Definition of subroutines
We now show a package (file solarraypkg.mos) that defines several versions of a subroutine, solarray, which copies the solution values of an array of decision variables of type mpvar into an array of real of the same size. For each desired number (1-3) and type (integer or string) of array indices we need to define a new version of this subroutine.
package solarraypkg
! **** Integer indices (including ranges) ****
public procedure solarray(x:array(R:set of integer) of mpvar,
s:array(set of integer) of real)
forall(i in R) s(i):=getsol(x(i))
end-procedure
public procedure solarray(x:array(R1:set of integer,
R2:set of integer) of mpvar,
s:array(set of integer,
set of integer) of real)
forall(i in R1, j in R2) s(i,j):=getsol(x(i,j))
end-procedure
public procedure solarray(x:array(R1:set of integer,
R2:set of integer,
R3:set of integer) of mpvar,
s:array(set of integer,
set of integer,
set of integer) of real)
forall(i in R1, j in R2, k in R3) s(i,j,k):=getsol(x(i,j,k))
end-procedure
! ****String indices ****
public procedure solarray(x:array(R:set of string) of mpvar,
s:array(set of string) of real)
forall(i in R) s(i):=getsol(x(i))
end-procedure
public procedure solarray(x:array(R1:set of string,
R2:set of string) of mpvar,
s:array(set of string,
set of string) of real)
forall(i in R1, j in R2) s(i,j):=getsol(x(i,j))
end-procedure
public procedure solarray(x:array(R1:set of string,
R2:set of string,
R3:set of string) of mpvar,
s:array(set of string,
set of string,
set of string) of real)
forall(i in R1, j in R2, k in R3) s(i,j,k):=getsol(x(i,j,k))
end-procedure
end-package Using the package in a Mosel model (file solarr_test.mos):
model "Test solarray package"
uses "solarraypkg", "mmxprs"
declarations
R1=1..2
R2={6,7,9}
R3={5,-1}
x: array(R1,R2,R3) of mpvar
sol: array(R1,R2,R3) of real
end-declarations
! Define and solve a small problem
sum(i in R1, j in R2, k in R3) (i+j+2*k) * x(i,j,k) <= 20
forall(i in R1, j in R2, k in R3) x(i,j,k)<=1
maximize(sum(i in R1, j in R2, k in R3) (i+2*j+k) * x(i,j,k))
! Get the solution array
solarray(x,sol)
! Print the solution
forall(i in R1, j in R2, k in R3)
writeln(" (", i, ",", j, ",", k, ") ", sol(i,j,k), " ", getsol(x(i,j,k)))
writeln(sol)
end-model Output produced by this model:
(1,6,-1) 1 1 (1,6,5) 0 0 (1,7,-1) 1 1 (1,7,5) 0 0 (1,9,-1) 1 1 (1,9,5) 0 0 (2,6,-1) 0,167 0,167 (2,6,5) 0 0 (2,7,-1) 0 0 (2,7,5) 0 0 (2,9,-1) 0 0 (2,9,5) 0 0 [1,0,1,0,1,0,0.166667,0,0,0,0,0]
This example may be classified as a `utility function' that eases tasks occurring in a similar way in several of your models. Another example of such a utility function could be a printing function that simply outputs the solution value of a decision variable with some fixed format (if you apply write/writeln to a decision variable of type mpvar you obtain the pointer of the variable, and not its solution value).
If we again make the comparison with the implementation as a module we see that both ways have their positive and negative points: the implementation as a module is clearly more technical, requiring a considerable amount of C code not immediately related to the implementation of the function itself. However, at the C level we simply check that the two arguments have the same index sets, without having to provide a separate implementation for every case, thus making the definition more general.
