Model Generation
The commands in this category are related to the model generator, i.e., the component in LINGO that translates your model’s statements into a format compatible with the solver.
@GEN( [SUBMODEL_NAME[, …, SUBMODEL_NAME_N]])
The @GEN statement generates a model and displays the generated equations. @GEN converts the model into the appropriate format for the solver engine; however, it does not actually call the solver. You will primarily use @GEN for debugging your models.
@GEN produces a report showing all the equations in the expanded model. This report is identical to the report created by the Solver|Generate command. By default, the report will be sent to the terminal output window. You may use the @DIVERT statement to route the report to a file.
The @GEN statement accepts an optional argument of one or more submodel names. If a submodel is specified, LINGO will only generate the model contained within the specified submodel section. If multiple submodel names are specified, LINGO will combine them all into a single, larger model. If submodel names are omitted entirely, then LINGO will generate only those model statements occurring before the @GEN statement and not contained in any submodels.
As an example, below is a small staffing model that uses the @GEN statement in a calc section:
MODEL:
SETS:
DAY / MON, TUE, WED, THU,
FRI, SAT, SUN/ :
NEED, START, COST;
ENDSETS
! Minimize total staffing costs;
[OBJ] MIN = @SUM( DAY( TODAY) :
START( TODAY) * COST( TODAY));
! Subject to meeting daily needs;
@FOR( DAY( TODAY): [CONS]
@SUM( DAY( COUNT)| COUNT #LE# 5:
START( @WRAP(TODAY - COUNT+1,
@SIZE( DAY)))) >= NEED( TODAY));
DATA:
NEED = 18 15 12 16 19 14 12;
COST = 400;
ENDDATA
CALC:
@GEN();
ENDCALC
END
Running this sample model yields the following generated model report:
MODEL:
[OBJ] MIN= 400 * START_MON + 400 * START_TUE +
400 * START_WED + 400 * START_THU + 400 * START_FRI +
400 * START_SAT + 400 * START_SUN ;
[CONS_MON] START_MON + START_THU + START_FRI +
START_SAT + START_SUN >= 18 ;
[CONS_TUE] START_MON + START_TUE + START_FRI +
START_SAT + START_SUN >= 15 ;
[CONS_WED] START_MON + START_TUE + START_WED +
START_SAT + START_SUN >= 12 ;
[CONS_THU] START_MON + START_TUE + START_WED +
START_THU + START_SUN >= 16 ;
[CONS_FRI] START_MON + START_TUE + START_WED +
START_THU + START_FRI >= 19 ;
[CONS_SAT] START_TUE + START_WED + START_THU +
START_FRI + START_SAT >= 14 ;
[CONS_SUN] START_WED + START_THU + START_FRI +
START_SAT + START_SUN >= 12 ;
END
@GENDUAL( [SUBMODEL_NAME[, …, SUBMODEL_NAME_N]])
The @GENDUAL statement generates the dual formulation of a linear programming model and displays the generated equations. Every linear programming model has a corresponding, mirror-image formulation called the dual. If the original model has M constraints and N variables, then its dual will have N constraints and M variables.
Some interesting properties of the dual are that any feasible solution to the dual model provides a bound on the objective to the original, primal model, while the optimal solution to the dual has the same objective value as the optimal solution to the primal problem. It's also true that the dual of the dual model is, once again, the original primal model. You may wish to refer to any good linear programming text for a further discussion of duality theory.
For instance, replacing the @GEN statement with an @GENDUAL statement in the staffing model above, we’d have the following calc section:
CALC:
@GENDUAL();
ENDCALC
Running this sample model yields the following generated model report showing the original model's dual formulation:
MODEL:
MAX = 18 * CONS_MON + 15 * CONS_TUE + 12 * CONS_WED + 16 *
CONS_THU + 19 * CONS_FRI + 14 * CONS_SAT + 12 * CONS_SUN;
[ START_MON] CONS_MON + CONS_TUE + CONS_WED + CONS_THU +
CONS_FRI <= 400;
[ START_TUE] CONS_TUE + CONS_WED + CONS_THU + CONS_FRI +
CONS_SAT <= 400;
[ START_WED] CONS_WED + CONS_THU + CONS_FRI + CONS_SAT +
CONS_SUN <= 400;
[ START_THU] CONS_MON + CONS_THU + CONS_FRI + CONS_SAT +
CONS_SUN <= 400;
[ START_FRI] CONS_MON + CONS_TUE + CONS_FRI + CONS_SAT +
CONS_SUN <= 400;
[ START_SAT] CONS_MON + CONS_TUE + CONS_WED + CONS_SAT +
CONS_SUN <= 400;
[ START_SUN] CONS_MON + CONS_TUE + CONS_WED + CONS_THU +
CONS_SUN <= 400;
END
Note that the dual is the transpose of the original linear program, with variables becoming the new row names and row names becoming the new variable names.
@PIC( [SUBMODEL_NAME[, …, SUBMODEL_NAME_N]])
The @PIC statement works much like @GEN, with the exception that it displays a matrix picture rather than the generated equations. For instance, replacing the @GEN statement with an @PIC statement in the staffing model above, we’d have the following calc section:
CALC:
@PIC();
ENDCALC
Running the modified model will generate the following matrix picture:
S S S S S S S
T T T T T T T
A A A A A A A
R R R R R R R
T T T T T T T
( ( ( ( ( ( (
M T W T F S S
O U E H R A U
N E D U I T N
) ) ) ) ) ) )
OBJ: C C C C C C C MIN
CONS(MON): 1 1 1 1 1 > B
CONS(TUE): 1 1' ' 1'1 1 > B
CONS(WED): 1 1 1 ' 1 1 > B
CONS(THU): 1 1 1 1 1 > B
CONS(FRI): 1 1'1 1 1' ' > B
CONS(SAT): ' 1 1 1 1 1 ' > B
CONS(SUN): ' 1 1 1 1 1 > B
Refer to the PICTURE command for a discussion on how to interpret matrix picture reports.
@RELEASE( VARIABLE_NAME)
When a variable is assigned a value in a calc section, that variable is marked as being fixed at the value, i.e., subsequent optimization via @SOLVE will not affect the variable’s value. The @RELEASE statement is used to release such a fixed variable so that it may once again be optimizable.
The following calc section, developed for the staff scheduling model presented above, will help to illustrate the use of @RELEASE:
CALC:
@SOLVE();
@FOR( DAY( D):
! Force starts to 0 for today;
START( D) = 0;
@SOLVE();
OBJ0( D) = OBJ;
! Allow START( D) to be optimizable again;
@RELEASE( START( D));
);
@FOR( DAY( D):
@WRITE( DAY( D), 10*' ', OBJ0( D), @NEWLINE( 1));
);
ENDCALC
This calc section loops through each day of the week and does the following:
1. | Sets the number of employees starting on the day to zero: START( D) = 0 |
2. | Solves for the low-cost staffing pattern given that the current day will have no starting employees: @SOLVE() |
3. | Stores the objective for a later report: OBJ0( D) = OBJ |
4. | Releases the number of employee starts for the current day so that it can be optimized in the next solve: RELEASE( DAY( D)) |
The last part of the calc section writes the following report summarizing the results:
MON 9800
TUE 9000
WED 8600
THU 9600
FRI 9200
SAT 8800
SUN 8600
@SMPI( ‘FILE_NAME’[, SUBMODEL_NAME[, …, SUBMODEL_NAME_N]])
The @SMPI statement generates the model and then writes it to a specified file in MPI format. MPI is a special format developed by LINDO Systems for representing all classes of mathematical programs: linear, integer, and nonlinear. This format is not intended for permanent storage of your models. LINDO API users may be interested in this format for exporting models to the LINDO API.
The @SMPI statement also accepts an optional argument of one or more submodel names. If a single submodel is specified, LINGO will only generate and save the model contained within the specified submodel section. If multiple submodel names are specified, LINGO will group them all together as one larger, combined model before writing the MPI file. If no submodel name is specified, then only the model statements occurring before the @GEN statement and not contained in any submodels will be used in generating the MPI file.
As an example, we could write the staffing example listed above to an MPI file by modifying the calc section to be:
CALC:
@SMPI( ’MYMPIFILE.MPI’);
ENDCALC
@SMPS( ‘FILE_NAME’[, SUBMODEL_NAME[, …, SUBMODEL_NAME_N]])
The @SMPS statement generates the model and then writes it to a specified file in MPS format file. The MPS file format is an industry standard format developed by IBM, and is useful for passing models from one solver or platform to another. LINDO API users may be interested in this format for exporting models to the LINDO API.
The @SMPS statement also accepts an optional argument of one or more submodel names. If a single submodel is specified, LINGO will only generate and save the model contained within the specified submodel section. If multiple submodel names are specified, LINGO will group them all together as one larger, combined model before writing the MPS file. If no submodel name is specified, then only the model statements occurring before the @GEN statement and not contained in any submodels will be used in generating the MPS file.
As an example, we could write the staffing example listed above to an MPS file by modifying the calc section to be:
CALC:
@SMPS( ’MYMPSFILE.MPS');
ENDCALC
Note: | A model must be linear or quadratic to successfully export it in MPS format. |
Note: | When exporting an MPS file, LINGO truncates all variable names to 8 characters. For instance, the two distinct LINGO names SHIP( WH1, C1) and SHIP( WH1, C2) would both be truncated to the single 8 character name SHIPWH1C under MPS. Either choose names to avoid collisions of truncated names, or enable the option for converting names to RC format when doing MPS I/O. LINGO will display an error message if potential collisions exist. |
Note: | The MPS file format is intended primarily for exporting models to other applications or platforms. The MPS format is purely scalar in nature—all set-based information is lost upon converting a LINGO model to MPS format. Thus, when saving copies of a model on your own machine, you should always use the File|Save command in order to preserve your model in its entirety. |
@STATS( [SUBMODEL_NAME[, …, SUBMODEL_NAME_N]])
The @STATS statement works much like @GEN, with the exception that it displays a report containing summary statistics about the size of the generated model. Please refer to the Solver|Model Statistics command for more information on the fields of a STATS report.