Provide
The multiSolve library supports two modes for providing a GMP to the solver, called provide modes:
generate
In this mode, the callback procedures are responsible to create a GMP for every solve. This is easily achieved by calling
GMP::Instance::Generate()
after updating the model sets and parameters for the data instance at hand.An example of using this mode is given in the previous chapter Hello.
modify
In this mode, after updating the model sets and parameters the GMP is not generated afresh. Instead the last GMP is reused and the callback procedure is responsible for modifying this GMP to obtain a GMP that reflects the changes in the model sets and parameters.
An example of using this mode is presented in this chapter.
The story and results are the same as in the previous chapter.
The call
The call to multiSolve::pr_multiSolve
is almost the same.
The differences are highlighted and discussed below:
1Procedure pr_solveMultipleModify {
2 Body: {
3 ep_baseGMP := gmp::Instance::Generate( mp_transport );
4 gmp::Instance::Solve( ep_baseGMP );
5
6 multiSolve::pr_multiSolve(
7 ep_onProvideGMP : 'pr_modifyInstance',
8 ep_onRetrieveSolution : 'pr_retrieveSolution',
9 ep_baseGMP : ep_baseGMP, ! Using the modify call back mode.
10 p_maxParallelGMPs : 2,
11 p_maxThreadsPerSolve : 1,
12 ep_startingSolutionMethod : multiSolve::ep_startingSolutionMethod_last);
13 }
14 ElementParameter ep_baseGMP {
15 Range: AllGeneratedMathematicalPrograms;
16 }
17}
Remarks:
Line 3,4: In modify provide mode, the multiSolve library makes modification upon modification. As a starting point, a base GMP needs to be provided. This is by making one call to
GMP::instance::Generate()
and solving it.Line 9: To indicate the use of
'modify'
provide mode, the GMP is passed that is constructed on lines 3,4.
Modify the instance
1Procedure pr_modifyInstance {
2 Arguments: (ep_gmp,ep_handle);
3 Body: {
4 p_iter += 1 ;
5 if p_iter > p_maxNoInstances then
6 ep_handle := '' ;
7
8 ! As there is no more data, this procedure can indicate to
9 ! the multiSolve library that it can stop new solve sequences.
10 p_procedureReturnCode := 0 ;
11 else
12 ! Which instance are going to solve.
13 ep_handle := element( s_instances, p_iter );
14
15 ! Update model parameters for this variation.
16 p_supply(i_src) := p_supplyInst(i_src, ep_handle) ;
17 p_demand(i_trgt) := p_demandInst(i_trgt, ep_handle) ;
18
19 ! The GMP to be solved is a small variation of the last solved GMP
20 ! Instead of regenerating the entire GMP, only some coefficients
21 ! are modified. This is significantly faster, but can be more involved.
22 gmp::Row::SetRightHandSideMulti(
23 GMP : ep_gmp,
24 binding : i_src,
25 row : c_respectSupply(i_src),
26 value : p_supply(i_src));
27 gmp::Row::SetRightHandSideMulti(
28 GMP : ep_gmp,
29 binding : i_trgt,
30 row : c_meetDemand(i_trgt),
31 value : p_demand(i_trgt));
32
33 ! Indicating there is data, and a GMP is created ready to solve.
34 p_procedureReturnCode := 1;
35 endif ;
36 return p_procedureReturnCode ;
37 }
38 DeclarationSection Argument_declarations {
39 ElementParameter ep_gmp {
40 Range: AllGeneratedMathematicalPrograms;
41 Property: InOut;
42 }
43 ElementParameter ep_handle {
44 Range: Integers;
45 Property: Output;
46 }
47 }
48 DeclarationSection Local_declarations {
49 Parameter p_procedureReturnCode;
50 }
51}
Remarks:
Lines 22-31 replace the single call to
gmp::instance::generate
. The RHS’s of two symbolic constraints need to be updated to the latest values of supply and demand.
Tip
From a software engineering point of view, it makes sense to start with the provide mode 'generate'
;
this mode permits the model builder to focus on adding code to update the model identifiers only.
If it turns out that relatively significant time is spent in the generation of GMP’s,
the alternative provide mode 'modify'
can be considered.