| Quintiq file version 2.0 | 
| #parent: #root | 
| Method CanRescueSolution ( | 
|   MathematicalProgram program, | 
|   LibOpt_Task task | 
| ) as Boolean | 
| { | 
|   Description: 'In MathematicalProgram Handle Infeasible tab, this method can be called to check if your infeasible solution has sufficient quality to try using it despite the reported infeasibility with CPLEX default settings.' | 
|   TextBody: | 
|   [* | 
|     // lauri Feb-24-2014 (created) | 
|     statistics := program.Statistics(); | 
|     feasabilitytolerance := 100 * guard( select( this.CurrentSubOptimizerLevel().GetStrategyLevelMacroPlan(), SolverSettingGroupMacroPlan.SolverSettingMacroPlan, s, s.ParameterNumber() = 1016 ).ParameterValue(),  | 
|                                         1e-6 ); // cplex default if 1016 is not set | 
|      | 
|     info( 'goal value:', guard( [String]program.GoalValue(), 'not available' ) );  | 
|     info(  'Feasibility tolerance = ', feasabilitytolerance );  | 
|     info( 'Solver has the following bound violation statistics:' ); | 
|     info( 'primal infeasibility: ', statistics.MaxPrimalInfeasibility().Format( 'N(Scientific)' ), 'scaled:', statistics.MaxScaledPrimalInfeasibility().Format( 'N(Scientific)' ) ); | 
|     info( 'primal residual: ', statistics.MaxPrimalResidual().Format( 'N(Scientific)' ), 'scaled:', statistics.MaxScaledPrimalResidual().Format( 'N(Scientific)' ) ); | 
|      | 
|     info( 'dual infeasibility: ', statistics.MaxDualInfeasibility().Format( 'N(Scientific)' ), 'scaled:', statistics.MaxScaledDualInfeasibility().Format( 'N(Scientific)' ) ); | 
|     info( 'dual residual: ', statistics.MaxDualResidual().Format( 'N(Scientific)' ), 'scaled:', statistics.MaxScaledDualResidual().Format( 'N(Scientific)' ) ); | 
|      | 
|     info( 'max integer infeasibility: ', statistics.MaxIntInfeasibility().Format( 'N(Scientific)' ), '[tolerance=', program.MIPIntegralityTolerance(), ']' ); | 
|      | 
|     maxboundviolation := maxvalue( statistics.MaxScaledPrimalInfeasibility(), | 
|                                    statistics.MaxScaledPrimalResidual(), | 
|                                    statistics.MaxScaledDualInfeasibility(),   //only for LP | 
|                                    statistics.MaxScaledDualResidual() );         //only for LP | 
|      | 
|      | 
|      | 
|      | 
|     canberescued := program.HasSolution() and maxboundviolation <= feasabilitytolerance and statistics.MaxIntInfeasibility() <= program.MIPIntegralityTolerance(); | 
|      | 
|     task.Log( 'hassoln=' + [String] program.HasSolution() + 'feas(scaled)='+ [String] maxboundviolation + 'intfeas=' + [String] statistics.MaxIntInfeasibility() );  | 
|      | 
|     info(  ifexpr(  canberescued, 'Solution accepted', 'Solution discarded' ) );  | 
|      | 
|     if(  not canberescued  | 
|          and this.GetRunContextConst().IsMetaIteration()  | 
|          and this.GetRunContextMeta().OptionDebugCPLEXVariablesConstraints() )  | 
|     { | 
|       snapshot := task.Run().Snapshot( relnew, SnapshotMacroPlannerOptimizer );  | 
|       OptimizerDebugCPLEXLogEntry::CheckVariables( snapshot, program.astype( CapacityPlanningSuboptimizer_CapacityPlanningAlgorithm ) );  | 
|       OptimizerDebugCPLEXLogEntry::CheckConstraints( snapshot, program.astype( CapacityPlanningSuboptimizer_CapacityPlanningAlgorithm ) );  | 
|     } | 
|      | 
|     return canberescued; | 
|   *] | 
|   InterfaceProperties { Accessibility: 'Module' } | 
| } |