Model Control
In this category we have two types of statements. First are the SUBMODEL and ENDSUBMODEL statements used to identify submodels, which are separate models contained within larger models. We also have the @SOLVE statement for use in solving submodels.
SUBMODEL and ENDSUBMODEL:
These two statements are used to bracket a submodel within a larger, composite model. The SUBMODEL statement must be followed immediately by a unique name of up to 32 characters that follows the normal LINGO naming conventions. The name must then be followed by a colon. You must also place a ENDSUBMODEL statement immediately after the last statement of your submodel. Submodels may only exist in the model section and are not allowed in data, init and calc sections. As an example, the following illustrates a submodel for solving a knapsack type model:
SUBMODEL Pattern_Gen:
[R_OBJ] MAX = @SUM( FG(i): PRICE(i)* Y(i));
[R_WIDTH] @SUM( FG(i): WIDTH(i)*Y(i)) <= RMWIDTH;
@FOR( FG(i): @GIN(Y(i)));
ENDSUBMODEL
In this example, the submodel is titled Pattern_Gen and contains one objective, R_OBJ, one constraint, R_WIDTH, and one @FOR loop to force the Y variables to be general integers via the @GIN function.
@DEBUG( [SUBMODEL_NAME[, …, SUBMODEL_NAME_N]])
Infeasible or unbounded submodels may be debugged in a calc section with the use of the @DEBUG statement. Refer to the Solver|Debug command for more information of model debugging.
If your model contains submodels, you can choose to debug a particular submodel by specifying its name as an argument to @DEBUG. If desired, you may also specify more than one submodel name, in which case, LINGO will simultaneously debug all the specified models as one combined model. If a submodel name is omitted, LINGO will solve all model statements occurring before the @DEBUG statement and not lying within a submodel section. It is the user’s responsibility to make sure the submodels together make sense, e.g., at most one submodel in an @DEBUG invocation can have an objective function.
In the following example, we solve a small submodel and then invoke the debugger if the solution is found to be non-optimal:
MODEL:
SUBMODEL M:
MIN = X + Y;
X>4;
Y<3;
Y>X;
ENDSUBMODEL
CALC:
@SOLVE( M);
@IFC( @STATUS() #NE# 0: @DEBUG( M));
ENDCALC
END
Note: | Submodels must be defined in the model prior to any references to them via the @DEBUG statement. |
@SOLVE( [SUBMODEL_NAME[, …, SUBMODEL_NAME_N]])
Submodels may be solved in a calc section with the use of the @SOLVE statement. If your model contains submodels, you can choose to solve a particular submodel by specifying its name as an argument to @SOLVE. If desired, you may also specify more than one submodel name, in which case, LINGO will simultaneously solve all the specified models as one combined model. If a submodel name is omitted, LINGO will solve all model statements occurring before the @SOLVE statement and not lying within a submodel section. It is the user’s responsibility to make sure the submodels together make sense, e.g., at most one submodel in an @SOLVE invocation can have an objective function.
As an example, to solve the submodel Pattern_Gen listed immediately above, you would add the following statement to a calc section:
@SOLVE( Pattern_Gen);
Note: | Submodels must be defined in the model prior to any references to them via the @SOLVE statement. |
@NEXTKBEST()
@NEXTKBEST can be used in a calc section to find the "next best" solutions to binary integer programs. First you must call @SOLVE (see above) to perform an initial solve of the model, which yields a solution with the best objective value. At this point, you may iteratively call @NEXTKBEST to generate one or more additional solutions ranked by objective value. This gives you the ability to determine if there are solutions close or equal in value to the optimal solution that might be preferred due to some secondary criteria. An example would be in a staff scheduling model, where there might be two solutions of equal cost, however, one of the solutions requires fewer workers on Sundays.
The LINGO sample model set includes the model LOOPKBEST. This model generates the 5 best solutions to a knapsack problem. The code of interest that generates these solutions is:
CALC:
! Reduce the amount of output;
@SET( 'TERSEO', 2);
NBEST = 0;
MXBEST = 5;
! Solve original model;
@SOLVE( KNAPSACK);
! Loop to display additional K-Best solutions;
! Stop when we either have a infeasible solution
or we reach MXBEST solutions.;
@WHILE( @STATUS() #EQ# 0 #AND# NBEST #LT# MXBEST:
NBEST = NBEST + 1;
! Print summary of current solution;
REPORT;
!Solve for next best solution;
@NEXTKBEST();
);
ENDCALC
Model: CHARTSTAFF
As mentioned, @SOLVE is called first to get an optimal solution to the model. We then have a @WHILE loop that call @NEXTKBEST until we either have an infeasible solutions, or we've generated 5 total solutions. Note that the initial @SOLVE call counts as one solution. We also make use of a procedure, REPORT, to print a summary report of each solution. You may open the model file in LINGO if you care to view this reporting procedure.
Note: | Calling @NEXTKBEST indefinitely can yield all the feasible solutions to a 0/1 program. However, for some models this may entail a very large number of solutions. |
Note: | If the model is not convex and you are not using the global solver, then the K-Best solutions may not be generated according to objective rank due to finding locally optimal solutions along the way. |