- Function GMP::Instance::CreateBlockMatrices(GMP, colSet, blockValue, prefix)
GMP::Instance::CreateBlockMatrices
GMP::Instance::CreateBlockMatrices
generates a set
of generated mathematical programs that are independent block representations
of the specified generated mathematical program. In other words, the original
generated mathematical program will be partitioned into multiple generated
mathematical programs.GMP::Instance::CreateBlockMatrices(
GMP, ! (input) a generated mathematical program
colSet ! (input) a subset of Integers
blockValue ! (input) an integer parameter
prefix ! (input) a string expression
)
Arguments
- GMP
An element in the set
AllGeneratedMathematicalPrograms
.- colSet
A subset of the set
Integers
, representing a set of column numbers. This set may be empty.- blockValue
An integer parameter over colSet indicating the (nonnegative) block value for each column in colSet.
- prefix
A string that holds the prefix used to create the names of each generated mathematical program that is created by this function.
Return Value
A subset of the set
AllGeneratedMathematicalPrograms
. The subset will be empty in case of an error.
Note
The GMP must be linear.
The objective column will be copied to every block GMP. The objective row also, but it will only include the columns assigned to that block GMP.
The blockValue of the objective column will be ignored (because the objective column will be copied to every block GMP).
A blockValue of 0 for a certain column means that AIMMS will automatically assign that column to a block.
The user can specify the blockValue for every column in the GMP, in which case this function will create block GMP’s based on this partition. If a different non-zero blockValue is assigned to two columns, and it turns out that the two corresponding blocks are not independent, then this function will generate an error. If two columns are assigned the same non-zero blockValue then these columns will be assigned to the same block, even if this block could be partitioned into two blocks.
If colSet is empty, or if blockValue equals 0 for each column, then AIMMS will create block matrices automatically, and as many as possible. If the GMP cannot be partitioned in multiple block GMP’s then the returned subset of the set
AllGeneratedMathematicalPrograms
will only contain one element, namely a copy of the original GMP.It is possible to assign a positive blockValue for a subset of the columns. This function will then automatically assign the other columns to block GMP’s.
The prefix argument is used to create the names of the block GMP’s, which will consist of the prefix value followed by the block number. The block numbers correspond to the blockValue assigned to (a selection of) the columns. If extra block GMP’s are created (besides those specified through the blockValue argument) then their numbering will start at the largest blockValue plus one. (And if the colSet is empty, or if blockValue equals 0 for each column, then the numbering will start at one.)
If the objective row contains an objective constant then this will be added to the last block GMP only.
In the unusual situation that the GMP contains columns (besides the objective column) that only appear in the objective row, then these columns will be assigned to the last block GMP if their corresponding blockValue equals 0.
Example
Assume that ‘MP’ is a mathematical program with the following declaration (in ams format):
Set Periods { Index: t; Definition: { { 'per-1', 'per-2', 'per-3' } } } Variable x { IndexDomain: t; Range: nonnegative; } Variable y { IndexDomain: t; Range: nonnegative; } Variable obj { Definition: sum( t, 7 * x(t) - 2 * y(t) ); } Constraint c1 { IndexDomain: t; Definition: - x(t) + 2 * y(t) <= 4; } MathematicalProgram MP { Objective: obj; Direction: minimize; Type: LP; }To use
GMP::Instance::CreateBlockMatrices
we declare the following identifiers (in ams format):ElementParameter myGMP { Range: AllGeneratedMathematicalPrograms; } Set GMPset { SubsetOf: AllGeneratedMathematicalPrograms; Parameter: CurrentGMP; } ElementParameter session { Range: AllSolverSessions; } Set ColumnSet { SubsetOf: Integers; Index: cc; } Parameter BlockVals { IndexDomain: cc; } StringParameter ColumnName { IndexDomain: cc; } Parameter MergeSolution { Range: Binary; }To create block matrices and solve them to create a solution for the original model we can use:
myGMP := GMP::Instance::Generate( MP ); ColumnSet := GMP::Instance::GetColumnNumbers( myGMP, AllVariables ); for (cc) do ColumnName(cc) := GMP::Column::GetName( myGMP, cc ); endfor; BlockVals(cc) := 0; for (cc) do if ( FindString( ColumnName(cc), "per-1" ) ) then BlockVals(cc) := 1; elseif ( FindString( ColumnName(cc), "per-2" ) ) then BlockVals(cc) := 2; else BlockVals(cc) := 3; endif; endfor; GMPset := GMP::Instance::CreateBlockMatrices( myGMP, ColumnSet, BlockVals, "block-" ); MergeSolution := 0; while ( Card(GMPset) >= 1 ) do CurrentGMP := First(GMPset); session := GMP::Instance::CreateSolverSession( CurrentGMP ); GMP::SolverSession::Execute( session ); GMP::Solution::RetrieveFromSolverSession( session, 1 ); if ( Card(GMPset) = 1 ) then GMP::Solution::SendToModel( CurrentGMP, 1, merge : MergeSolution, evalInline : 1 ); else GMP::Solution::SendToModel( CurrentGMP, 1, merge : MergeSolution, evalInline : 0 ); endif; GMP::Instance::Delete( CurrentGMP ); ! Also deletes session MergeSolution := 1; endwhile; GMP::Instance::Delete( myGMP );The above piece of code creates three block GMP’s (with names “block-1”, “block-2” and “block-3”). This is also the case if ‘ColumnSet’ or ‘BlockVals’ would have been empty. If we assign the block values as follows then only two blocks will be created:
BlockVals(cc) := 0; for (cc) do if ( FindString( ColumnName(cc), "per-1" ) ) then BlockVals(cc) := 1; else BlockVals(cc) := 2; endif; endfor;In this case the columns corresponding to the periods “per-2” and “per-3” will be assigned to the same block GMP (with the name “block-2”).
The parameter ‘MergeSolution’ is set to 0 for the first block GMP, otherwise the solution will be merged with an old solution (if one exists).
Note: the first piece of code is optimized for mathematical programs with inline variables because it contains the following code snippet:
GMP::Solution::RetrieveFromSolverSession( session, 1 ); if ( Card(GMPset) = 1 ) then GMP::Solution::SendToModel( CurrentGMP, 1, merge : MergeSolution, evalInline : 1 ); else GMP::Solution::SendToModel( CurrentGMP, 1, merge : MergeSolution, evalInline : 0 ); endif;If your mathematical program does not contain any inline variables then you can use the following code instead:
GMP::Solution::RetrieveFromSolverSession( session, 1 ); GMP::Solution::SendToModel( CurrentGMP, 1, merge : MergeSolution );