Skip to main content

  | मौसम…

411 समाचार
Public archive edition · Attributed source reporting with original dates · AI drafts are excluded

411 REFERENCE · Wikibooks

GLPK/GMPL Workarounds

Reference material by Wikibooks contributors. This retains its source identity and is not 411 news reporting.

This page offers alternative constructions for features that are not specifically supported by GMPL (MathProg). __FORCETOC__ If–then–else conditional GLPK does not provide an IF–THEN–ELSE syntax, often useful when post-processing results. Instead use the following syntax: for {{0}: condition}{ # IF condition THEN } for {{0}: not condition} { # ELSE } # ENDIF The {0} could be replaced by any set with one element. The for statement will iterate only once over the expression inside the subsequent braces. The following minimal example creates output with differing line formats, dependent on whether a number is even or odd: for{ c in {1..10} } { for {{0}: c mod 2 == 0} { printf "even\t%d\n", c; } for {{0}: c mod 2 != 0} { printf "odd\t%d\n", c; } } end; Sorted output It may be desirable to output a sorted sequence. The following example shows how: # sorting_symbolic.mod - how to sort arrays in MathProg # based on code by Andrew Makhorin # Sometimes it is necessary to print parameters or variables in the # order of ascending or descending their values. Suppose, for example, # that we have the following subscripted parameter: set I; param a{i in I} := Uniform(2, 7); # If we print all its members: printf{i in I} "a[%2s] = %g\n", i, a[i]; # the output may look like follows: # # a[a] = 2.64156 # a[b] = 2.04798 # a[c] = 2.14843 # a[d] = 4.76896 # a[e] = 6.09132 # a[f] = 3.27780 # a[g] = 4.06113 # a[h] = 4.05898 # a[i] = 6.63120 # a[j] = 6.50318 # a[k] = 3.46065 # a[l] = 4.69845 # # However, we would like the parameter members to appear in the order # of ascending values. # # Introduce the following auxiliary parameter: param pos{i in I} := card({j in I: a[j] < a[i] or a[j] = a[i] and j < i}); # where pos[i] = k - 1 means that in the sorted list member a[i] has # k-th position, 1 <= k <= |I|. Then introduce another auxiliary # parameter: set ind{k in 1..card(I)} := setof{i in I: pos[i] = k - 1} i; # where ind[k] = {i} iff pos[k] = i. # # Now, the following statement: printf "\n"; printf{k in 1..card(I), l in ind[k]} "a[%2s] = %g\n", l, a[l]; # prints the parameter members in the desired order: # # a[b] = 2.04798 # a[c] = 2.14843 # a[a] = 2.64156 # a[f] = 3.27780 # a[k] = 3.46065 # a[h] = 4.05898 # a[g] = 4.06113 # a[l] = 4.69845 # a[d] = 4.76896 # a[e] = 6.09132 # a[j] = 6.50318 # a[i] = 6.63120 solve; data; set I := a b c d e f g h i j k l; #set I := 1 2 3 4 5 6 7 8 9 10 11 12; end; Mimicking an AMPL defined variable The AMPL language has a construct called defined variables. Robert Fourer David M. Gay Brian W. Kerningham AMPL : a modeling language for mathematical programming 2nd 2002 Duxbury Press 978-0534388096 131 Available as a downloadable PDF. A defined variable consists of a variable declaration with an equals sign and a term on the right-hand side. Take for example: var f{k in 1..K} = sum{i in 1..I, j in 1..J} x[i,j,k]*w[i]; Here f is a defined variable. The statement above does not actually declare a structural variable but rather works like a kind of a macro — so that each occurrence of f[k] is replaced by: sum{i in 1..I, j in 1..J} x[i,j,k]*w[i] This construct is not supported in GMPL. But you can use a structural variable and a constraint instead to achieve the same effect — the downside being that this formulation may render your problem harder to solve: var f{k in 1..K}; s.t. c1{k in 1..K} : f[k] = sum{i in 1..I, j in 1..J} x[i,j,k]*w[i]; Sets of sets Sets of sets do not exist in GMPL. Instead an indexing set and an indexed set can be used. The example below shows how to enumerate all subsets of given size of a superset. /********************************************** * * For a set of superset S determine all subsets * of size m * **********************************************/ # Superset set S; # Number of elements in subset param m; # Number of elements in superset param n := card(S); # Set of subset sizes less or equal to m set I := {1 .. m}; # Set of indices for a subset of size i of set S set J{i in I} := { 1 .. round((prod{a in {1..n}}a) / (prod{a in {1..i}}a) / (prod{a in {1..n-i}}a)) }; # Set of indices for S set K := {1 .. n}; # Set containing the kth member of S set L{k in K} := setof{s in S : k == sum{t in S : t <= s} 1} s; # Set of integers in [i, n] set M{i in I} := {i .. n}; # Number of subsets of size i of a set of size j - 1 param ji{i in I, j in M[i]} := if i==j then 0 else round((prod{a in {1..j-1}}a) / (prod{a in {1..i}}a) / (prod{a in {1..j-1-i}}a)) ; # Subsets j of size i set N{i in I, j in J[i]} := if i == 1 then L[j] else N[i-1,j - ji[i,max{k in M[i] : ji[i,k] < j} k]] union L[max{k in M[i] : ji[i,k] < j} k]; # Set of subsets of size m set C := J[m]; # Elements in subset c set Sc{c in C} := N[m, c]; solve; printf "Last 100 subsets\n"; for {c in C: c > card(C) - 100} { printf "[%d]: ", c; printf {s in Sc[c]} "%s ", s; printf "\n"; } printf "\nChecking cardinality\n"; printf {c in C} "%s", if card(Sc[c]) != m then "Wrong cardinality! " else ""; printf "\n"; printf "Checking disjunctness\n"; for {c in C} printf {d in C: d > c} "%s", if card(Sc[c] union Sc[d]) <= m then "Two subsets are the same!" else ""; printf "\n"; printf "Number of subsets = %d\n\n", card(C); data; param m:= 4; set S := A B C D E F G H I J K L; end; References