| Quintiq file version 2.0 | 
| #parent: #root | 
| Method LogDetailsCPLEX ( | 
|   MathematicalProgram program, | 
|   String comment, | 
|   const LibOpt_Scope scope | 
| ) | 
| { | 
|   TextBody: | 
|   [* | 
|     statistics := program.Statistics(); | 
|     msg2 := 'pml inf: ' + statistics.MaxPrimalInfeasibility().AsQUILL(); | 
|     msg3 := 'pml resdl: ' + statistics.MaxPrimalResidual().AsQUILL();  | 
|     msg4 := 'dual inf: ' + statistics.MaxDualInfeasibility().AsQUILL();  | 
|     msg5 := 'dual resdl: ' + statistics.MaxDualResidual().AsQUILL();  | 
|     msg6 := 'max int inf:' + statistics.MaxIntInfeasibility().AsQUILL();  | 
|     msg7 := 'kappa:' + statistics.Kappa().AsQUILL();  | 
|     msg8 := 'kappamax:' + statistics.KappaMax().AsQUILL(); | 
|     msg9 := 'illposed=' + statistics.KappaIllPosed().AsQUILL() + 'susp=' + statistics.KappaSuspicious().AsQUILL() + 'unstable=' + statistics.KappaUnstable().AsQUILL()  | 
|     + 'stable=' + statistics.KappaStable().AsQUILL() | 
|       | 
|     msgstats := msg2 + msg3 + msg4 + msg5 + msg6 + msg7 + msg8 + msg9;  | 
|      | 
|     lvlmsg := 'lvl'+ [String](this.CurrentSubOptimizerLevel().LevelNumber()) + ifexpr(  this.CurrentSubOptimizerLevel().IsExtraPTQTYLevelMetaOptimizer(), '[PTQTYmin] ', ' ' );  | 
|     nrgoalterms := ifexpr(  not this.UseHierarchicalCPLEXGoals(), counter(  program.Goal().Terms(), Elements, t, true, not t.Coefficient() = 0), Number::MaxNumber() );  | 
|     msg := lvlmsg + 'no solution';  | 
|      | 
|     if ( program.HasSolution() )  | 
|     { | 
|       if ( this.UseHierarchicalCPLEXGoals() )  | 
|       { | 
|         msg := '';  | 
|         maxlevel := this.GetMaxLevelNumberForHierarchicalGoals( this.GetRunContextConst(), scope );  | 
|         for ( i := 0; i <= maxlevel; i++ )  | 
|         { | 
|           nameofgoal := CapacityPlanningSuboptimizer::HierarchicalGoalLevelName( i );  | 
|           try | 
|           { | 
|             goalvalue := program.GoalValue( nameofgoal ); | 
|             goal := program.Goal( nameofgoal );   | 
|             //abstol := goal.AbsTolerance();  | 
|        | 
|             msg := msg + 'level='+ [String]i + 'goal=' + [String] goalvalue + 'goalterms=' + [ String] goal.Terms().Elements( relsize ) + String::NewLine();   | 
|             this.AllLevelsOptimal( this.AllLevelsOptimal() and program.Optimal() ) ;  | 
|           } | 
|           onerror | 
|           { | 
|             // we skip levels | 
|           } | 
|         } | 
|         optimal := ifexpr(  program.Optimal(), 'optimal', 'suboptimal' );  | 
|         msg := msg + optimal + ' absgap=' + program.AbsoluteGap().AsQUILL() + msgstats; | 
|         this.DetailsCPLEX( msg );  | 
|       } | 
|       else | 
|       { | 
|         msg := lvlmsg + 'goal=' + [String] program.GoalValue() + 'absgap=' + [String] program.AbsoluteGap();  | 
|         this.DetailsCPLEX( this.DetailsCPLEX() + comment + msg + 'gterms=' + [String] nrgoalterms + msgstats + String::NewLine() ); | 
|         this.AllLevelsOptimal( this.AllLevelsOptimal() and program.Optimal() ) ;  | 
|       } | 
|     } | 
|     else | 
|     { | 
|       this.DetailsCPLEX( this.DetailsCPLEX() + msg );  | 
|       this.AllLevelsOptimal( false );  | 
|     } | 
|      | 
|     msg_kpilowerbounds := guard( program.RetrieveString( 'message_kpilowerbound' ), '' );  | 
|     this.DetailsCPLEX( this.DetailsCPLEX() + msg_kpilowerbounds ); | 
|      | 
|     nrshiftbinaries := guard( [Number] program.RetrieveReal( 'NrShiftBinaries' ), 0 );  | 
|     this.DetailsCPLEXNrShiftBinaries( nrshiftbinaries );  | 
|     /* for debugging purpose. Example to log some variable values: | 
|     v1 := program.astype( CapacityPlanningSuboptimizer_CapacityPlanningAlgorithm ).TotalUnitPeriodCampaignUtilizationSlackVariables().Find(); | 
|     msg := '';  | 
|     if ( not isnull( v1 ) and program.HasSolution() )  | 
|     { | 
|       msg := msg + 'TotalUnitPeriodCampaignUtilizationSlackVariables=' + [String] v1.OptimalValue() + String::NewLine();     | 
|       v2 := program.astype( CapacityPlanningSuboptimizer_CapacityPlanningAlgorithm ).TotalCampaignSequencingCombiSlackVariables().Get(); | 
|       msg := msg + 'TotalCampaignSequencingCombiSlackVariables=' + [String] v2.OptimalValue() + String::NewLine();     | 
|       v3 := program.astype( CapacityPlanningSuboptimizer_CapacityPlanningAlgorithm ).TotalCampaignMinQtyUnderVariables().Get(); | 
|       msg := msg + 'TotalCampaignMinQtyUnderVariables=' + [String] v3.OptimalValue() + String::NewLine();     | 
|       v4 := program.astype( CapacityPlanningSuboptimizer_CapacityPlanningAlgorithm ).TotalCampaignMaxQtyOverVariables().Get(); | 
|       msg := msg + 'TotalCampaignMaxQtyOverVariables=' + [String] v4.OptimalValue() + String::NewLine();     | 
|       v5 := program.astype( CapacityPlanningSuboptimizer_CapacityPlanningAlgorithm ).TotalCampaignMinDurationUnderVariables().Get(); | 
|       msg := msg + 'TotalCampaignMinDurationUnderVariables=' + [String] v5.OptimalValue() + String::NewLine();     | 
|       v6 := program.astype( CapacityPlanningSuboptimizer_CapacityPlanningAlgorithm ).TotalCampaignMaxDurationOverVariables().Get(); | 
|       msg := msg + 'TotalCampaignMaxDurationOverVariables=' + [String] v6.OptimalValue() + String::NewLine(); | 
|       this.DetailsCPLEX( this.DetailsCPLEX() + msg );  | 
|     } | 
|     */ | 
|   *] | 
|   InterfaceProperties { Accessibility: 'Module' } | 
| } |