diff --git a/picat/diet2.pi b/picat/diet2.pi
new file mode 100644
index 00000000..e3e457b7
--- /dev/null
+++ b/picat/diet2.pi
@@ -0,0 +1,102 @@
+/*
+
+ Diet problem in Picat.
+
+ From the GLPK model diet.mod
+ """
+ STIGLER'S NUTRITION MODEL
+
+ This model determines a least cost diet which meets the daily
+ allowances of nutrients for a moderately active man weighing 154 lbs.
+
+ References:
+ Dantzig G B, "Linear Programming and Extensions."
+ Princeton University Press, Princeton, New Jersey, 1963,
+ Chapter 27-1.
+ """
+
+ This Picat model was created by Hakan Kjellerstrand, hakank@gmail.com
+ See also my Picat page: http://www.hakank.org/picat/
+
+*/
+
+
+import mip.
+
+
+main => go.
+
+
+go =>
+ a(A),
+ b(B),
+ NumNutr = A[1].length,
+ NumFood = A.length,
+
+ X = new_list(NumFood),
+ X :: 0.0..1.0,
+
+ Cost #= sum(X),
+ Cost #>= 0,
+
+ % nutrient balance (units)
+ foreach(N in 1..NumNutr)
+ sum([A[F,N] * X[F] : F in 1..NumFood]) #= B[N]
+ end,
+
+
+ solve($[min(Cost)], X),
+
+ printf("\nTotal cost: $%0.4f\n", Cost),
+ % println(x=X),
+ println("Dollars of food f to be purchased daily:"),
+ Food = ["Wheat", "Cornmeal", "Cannedmilk", "Margarine", "Cheese", "Peanut-B", "Lard",
+ "Liver", "Porkroast", "Salmon", "Greenbeans", "Cabbage", "Onions", "Potatoes", "Spinach",
+ "Sweet-Pot", "Peaches", "Prunes", "Limabeans", "Navybeans"],
+
+ foreach({F,C} in zip(Food, X))
+ printf("%-10w: $%0.4f\n", F, C)
+ end,
+
+ nl.
+
+
+
+% Calorie 3 % thousands
+% Protein 70 % grams
+% Calcium 0.8 % grams
+% Iron 12 % milligrams
+% Vitamin-A 5 % thousands IUs
+% Vitamin-B1 1.8 % milligrams
+% Vitamin-B2 2.7 % milligrams
+% Niacin 18 % milligrams
+% Vitamin-C 75 % milligrams ;
+
+b(B) => B = [3.0, 70.0, 0.8, 12.0, 5.0, 1.8, 2.7, 18.0, 75.0].
+
+
+a(A) =>
+A = [
+% Calorie Protein Calcium Iron Vitamin-A Vitamin-B1 Vitamin-B2 Niacin Vitamin-C
+% (1000) (g) (g) (mg) (1000IU) (mg) mg) (mg) (mg)
+[44.7, 1411.0, 2.0, 365.0, 0.0, 55.4, 33.3, 441.0, 0.0],
+[36.0, 897.0, 1.7, 99.0, 30.9, 17.4, 7.9, 106.0, 0.0],
+[ 8.4, 422.0, 15.1, 9.0, 26.0, 3.0, 23.5, 11.0, 60.0],
+[20.6, 17.0, 0.6, 6.0, 55.8, 0.2, 0.0, 0.0, 0.0],
+[ 7.4, 448.0, 16.4, 19.0, 28.1, 0.8, 10.3, 4.0, 0.0],
+[15.7, 661.0, 1.0, 48.0, 0.0, 9.6, 8.1, 471.0, 0.0],
+[41.7, 0.0, 0.0, 0.0, 0.2, 0.0, 0.5, 5.0, 0.0],
+[ 2.2, 333.0, 0.2, 139.0, 169.2, 6.4, 50.8, 316.0, 525.0],
+[ 4.4, 249.0, 0.3, 37.0, 0.0, 18.2, 3.6, 79.0, 0.0],
+[ 5.8, 705.0, 6.8, 45.0, 3.5, 1.0, 4.9, 209.0, 0.0],
+[ 2.4, 138.0, 3.7, 80.0, 69.0, 4.3, 5.8, 37.0, 862.0],
+[ 2.6, 125.0, 4.0, 36.0, 7.2, 9.0, 4.5, 26.0, 5369.0],
+[ 5.8, 166.0, 3.8, 59.0, 16.6, 4.7, 5.9, 21.0, 1184.0],
+[14.3, 336.0, 1.8, 118.0, 6.7, 29.4, 7.1, 198.0, 2522.0],
+[ 1.1, 106.0, 0.0, 138.0, 918.4, 5.7, 13.8, 33.0, 2755.0],
+[ 9.6, 138.0, 2.7, 54.0, 290.7, 8.4, 5.4, 83.0, 1912.0],
+[ 8.5, 87.0, 1.7, 173.0, 86.8, 1.2, 4.3, 55.0, 57.0],
+[12.8, 99.0, 2.5, 154.0, 85.7, 3.9, 4.3, 65.0, 257.0],
+[17.4, 1055.0, 3.7, 459.0, 5.1, 26.9, 38.2, 93.0, 0.0],
+[26.9, 1691.0, 11.4, 792.0, 0.0, 38.4, 24.6, 217.0, 0.0]].
+
diff --git a/picat/dirichlet.pi b/picat/dirichlet.pi
new file mode 100644
index 00000000..fb504491
--- /dev/null
+++ b/picat/dirichlet.pi
@@ -0,0 +1,52 @@
+/*
+
+ Triangle problem in Picat.
+
+ From the lecture notes Modelling with Constraints
+ http://www.cse.unsw.edu.au/~cs4418/2008/Lectures/Modelling2.ppt, page 45ff
+
+
+ This Picat model was created by Hakan Kjellerstrand, hakank@gmail.com
+ See also my Picat page: http://www.hakank.org/picat/
+
+*/
+
+import mip.
+
+main => go.
+
+go =>
+ temp(Temp),
+ N = Temp.length,
+
+ % Note .vars() here.
+ Temp.vars() :: 0.0..100.0,
+
+ foreach(I in 2..N-1,J in 2..N-1)
+ % Temp[I,J] #= 1.0/4.0*(Temp[I-1,J] + Temp[I+1,J] + Temp[I,J-1] + Temp[I,J+1])
+ Temp[I,J]*4.0 #= (Temp[I-1,J] + Temp[I+1,J] + Temp[I,J-1] + Temp[I,J+1])
+ end,
+
+ solve(Temp),
+
+ foreach(Row in Temp)
+ foreach(T in Row)
+ printf("%10.3f ", T)
+ end,
+ nl
+ end,
+
+ HalfN = N div 2,
+ printf("Tempature at Temp[%d,%d]: %0.3f\n", HalfN, HalfN, Temp[HalfN,HalfN]),
+
+ nl.
+
+temp(Temp) =>
+ Temp =
+ [[100.0,100.0,100.0,100.0,100.0,100.0,100.0],
+ [ 0.0, _, _, _, _, _, 0.0],
+ [ 0.0, _, _, _, _, _, 0.0],
+ [ 0.0, _, _, _, _, _, 0.0],
+ [ 0.0, _, _, _, _, _, 0.0],
+ [ 0.0, _, _, _, _, _, 0.0],
+ [ 0.0, _, _, _, _, _, 0.0]].
\ No newline at end of file
diff --git a/picat/index.html b/picat/index.html
index 0fe2b854..04c8fa68 100644
--- a/picat/index.html
+++ b/picat/index.html
@@ -36,7 +36,7 @@
My Picat programs/models
They are separated in different sections:
-
-
Project Euler problem
Here are some solutions for the Project Euler problems:
@@ -391,7 +401,7 @@ Project Euler problem
euler39.pi: Euler #39
euler40.pi: Euler #40
euler41.pi: Euler #41
- euler41.pi: Euler #42 (data file words.txt)
+ euler41.pi: Euler #42
euler43.pi: Euler #43
euler44.pi: Euler #44
euler45.pi: Euler #45
@@ -565,13 +575,12 @@ Miscellaneous programs
tic_tac_bench.pi
- allpartitions.pi: Generate all partitions of a number
arbitrage_loops.pi: Arbitrage loops. Cf bitcoin.pi
analogy.pi: Evan's Analogy program (ported from Sterling "The Art of Prolog")
apl_util.pi: APL utils. Some utilities inspired by APL and/or K. (Is now a module in Picat distribution.)
base_conversion.pi: Base conversion.
beds1.pi: Bunk beds puzzle
- bitcoind.pi: Reading bitcoin currency and make an optimal arbitrage loop. Cf arbitrage_loops.pi.
+ bitcoin.pi: Reading bitcoin currency and make an optimal arbitrage loop. Cf arbitrage_loops.pi.
bridge_party.pi: Bridge party
bubble_sort.pi: Bubble sort
carroll_symbolic_logic_60.pi: Lewis Carroll's symbolic logic problem #60
@@ -591,7 +600,7 @@ Miscellaneous programs
josephus.pi: Josephus problem
lace.pi: Lace problem (ported from B-Prolog's entry to 2012 Prolog Programming Contest)
lcs_tabling.pi: Longest Common Subsequence using tabling (ported from B-Prolog)
- lunc_problem.pi: Lunch problem
+ lunch_problem.pi: Lunch problem
mankell.pi: Generate all possible (right and wrong) spellings of 'Henning Mankell' and 'Kjellerstrand' (using a "grammar" etc)
matrix_slice.pi: Some list/array/matrix extraction functions. E.g. M.slice(1..3, 2..4)
for extracting a sub square
mcsam.pi: MicroSAM program (ported from Sterling "The Art of Prolog")
diff --git a/picat/knapsack_problem_mip.pi b/picat/knapsack_problem_mip.pi
new file mode 100644
index 00000000..bb1a2059
--- /dev/null
+++ b/picat/knapsack_problem_mip.pi
@@ -0,0 +1,90 @@
+/*
+
+ Knapsack problem (Rosetta Code) in Picat.
+
+ From
+ http://rosettacode.org/wiki/Knapsack_problem/Unbounded
+ """
+ A traveller gets diverted and has to make an unscheduled stop in what turns out to
+ be Shangri La. Opting to leave, he is allowed to take as much as he likes of the
+ following items, so long as it will fit in his knapsack, and he can carry it. He knows
+ that he can carry no more than 25 'weights' in total; and that the capacity of his
+ knapsack is 0.25 'cubic lengths'.
+
+ Looking just above the bar codes on the items he finds their weights and volumes.
+ He digs out his recent copy of a financial paper and gets the value of each item.
+
+ Item Explanation Value (each) weight Volume (each)
+ ------------------------------------------------------------
+ panacea (vials of) Incredible healing properties 3000 0.3 0.025
+ ichor (ampules of) Vampires blood 1800 0.2 0.015
+ gold (bars) Shiney shiney 2500 2.0 0.002
+ ----------------------------------------------------------------------------
+ Knapsack For the carrying of - <=25 <=0.25
+
+ He can only take whole units of any item,, but there is much more of any item than
+ he could ever carry
+
+ How many of each item does he take to maximise the value of items he is carrying
+ away with him?
+
+ Note:
+
+ 1. There are four solutions that maximise the value taken. Only one need be given.
+ """
+
+
+ This Picat model was created by Hakan Kjellerstrand, hakank@gmail.com
+ See also my Picat page: http://www.hakank.org/picat/
+
+*/
+
+
+import mip.
+
+
+main => go.
+
+
+go =>
+ Value = [3000.0, 1800.0, 2500.0 ],
+ Weight = [ 0.3, 0.2, 2.0 ],
+ Volume = [ 0.025, 0.015, 0.002],
+
+ N = Value.length,
+
+ X = new_list(N),
+ X :: 0..1000,
+
+ Z #= sum([X[I]*Value[I] : I in 1..N]),
+
+ foreach(I in 1..N)
+ X[I] #>= 0
+ end,
+
+ knapsack(Volume, X, 0.25),
+ knapsack(Weight, X, 25.0),
+
+ solve($[max(Z)], X),
+
+ println(z=Z),
+ println(x=X),
+ Items = ["panacea","ichor","gold"],
+ foreach({Item,Num} in zip(Items,X), Num > 0)
+ printf("Take %d of %w\n", Num,Item)
+ end,
+
+ println("\nTotal volume:"),
+ println(sum([X[I]*Volume[I] : I in 1..N])),
+
+ println("Total weight:"),
+ println(sum([X[I]*Weight[I] : I in 1..N])),
+
+ println("Total cost:"),
+ println(sum([X[I]*Value[I] : I in 1..N])),
+
+ nl.
+
+
+knapsack(W, Take, WTMax) =>
+ sum([W[I]*Take[I] : I in 1..W.length]) #<= WTMax.
\ No newline at end of file
diff --git a/picat/least_square_optimeringslara_286.pi b/picat/least_square_optimeringslara_286.pi
new file mode 100644
index 00000000..51fd8509
--- /dev/null
+++ b/picat/least_square_optimeringslara_286.pi
@@ -0,0 +1,47 @@
+/*
+
+ Least square in Picat.
+
+ Least square problem from the Swedish book
+ Optimeringslara, page 286f
+
+ This Picat model was created by Hakan Kjellerstrand, hakank@gmail.com
+ See also my Picat page: http://www.hakank.org/picat/
+
+*/
+
+
+import mip.
+
+
+main => go.
+
+go =>
+
+ % temperature
+ T = [20.0, 30.0, 80.0,125.0,175.0,225.0,275.0,325.0,360.0,420.0,495.0,540.0,630.0,700.0],
+ % percentage gas
+ F = [0.0,5.8 ,14.7,31.6,43.2,58.3,78.4,89.4,96.4,99.1,99.5,99.9,100.0,100.0],
+ N = T.length,
+
+ M = 4,
+ A = new_list(M+1), % equation (index 0..M)
+ A :: -100.0..100.0,
+
+ Z :: -1000.0..1000.0,
+ Z #= sum([F[I] - (A[0+1] + A[1+1]*T[I] + A[2+1]*T[I]*T[I] + A[3+1]*T[I]*T[I]*T[I] + A[4+1]*T[I]*T[I]*T[I]*T[I]) : I in 1..N]),
+
+
+ A[0+1] + 20.0*A[1+1] + 20.0*20.0*A[2+1] + 20.0*20.0*20.0*A[3+1] + 20.0*20.0*20.0*20.0*A[4+1] #= 0.0,
+ A[0+1] + 700.0*A[1+1] + 700.0*700.0*A[2+1] + 700.0*700.0*700.0*A[3+1] + 700.0*700.0*700.0*700.0*A[4+1] #= 100.0,
+ foreach(I in 1..N)
+ (A[1+1] + 2.0*A[2+1]*T[I] + 3.0*A[3+1]*T[I]*T[I] + 4.0*A[4+1]*T[I]*T[I]*T[I]) #>= 0.0
+ end,
+
+ solve($[min(Z)],A),
+
+ println(z=Z),
+ println(a=A),
+
+ nl.
+
diff --git a/picat/markov_chains.pi b/picat/markov_chains.pi
new file mode 100644
index 00000000..bda16958
--- /dev/null
+++ b/picat/markov_chains.pi
@@ -0,0 +1,122 @@
+/*
+
+ Markov chains in Picat.
+
+ From the (Swedish) book "Statistisk Dataanalys", page 299ff.
+
+ Transition matrix of market shares for three products A, B, and C.
+
+ From To
+ A B C
+ A 0.7 0.1 0,2
+ B 0.2 0.6 0.2
+ C 0.4 0.1 0.5
+
+ What is the stable state of the transitions?
+
+ Also, this model solves the reversed problem:
+ given a stable state, generate a transition matrix.
+
+
+ This Picat model was created by Hakan Kjellerstrand, hakank@gmail.com
+ See also my Picat page: http://www.hakank.org/picat/
+
+*/
+
+
+import mip.
+
+
+main => go.
+
+go =>
+ transitions(1,Transitions),
+ markov_chain(Transitions, X),
+ println(X),
+ nl.
+
+go2 =>
+ transitions(2,Transitions),
+ markov_chain(Transitions, X),
+ println(X),
+ nl.
+
+
+% reversed problem
+go3 =>
+ % This is the result from go/0
+ X = [ 0.514285714285714, 0.2, 0.285714285714286],
+ markov_chain_rev(X, Transitions),
+ foreach(Row in Transitions) println(Row) end,
+ nl.
+
+% reversed problem 2
+go4 =>
+ % This is the result from go2/0
+ X = [0.367182763904145,0.07548189012462,0.102060886308352,0.15336027885601,0.034415433900105,0.080532266138785,0.13700725112718,0.023360147677889,0.01100743321783,0.015591648745084],
+ markov_chain_rev(X, Transitions),
+
+ foreach(Row in Transitions) println(Row) end,
+ nl.
+
+
+
+%
+% Given a transition matrix, yield stable state X
+%
+markov_chain(Transitions, X) =>
+
+ N = Transitions.length,
+
+ X = new_list(N),
+ X :: 0.0..1.0,
+
+ foreach(I in 1..N)
+ X[I] #= sum([Transitions[I,J]*X[J] : J in 1..N])
+ end,
+
+ sum(X) #= 1.0,
+
+ solve(X).
+
+
+transitions(1,Transitions) =>
+ Transitions =
+ [[0.7,0.2,0.4],
+ [0.1,0.6,0.1],
+ [0.2,0.2,0.5]].
+
+% Another problem from the book "Optimieringslara":
+transitions(2,Transitions) =>
+ Transitions =
+[[0.01782,0.54024,0.46916,0.85467,0.30838,0.62996,0.42815,0.22189,0.37009,0.74681],
+ [0.04633,0.04427,0.14569,0.03971,0.50937,0.09334,0.01055,0.12776,0.36217,0.04528],
+ [0.12289,0.22650,0.12335,0.02186,0.10853,0.14409,0.05414,0.01577,0.01709,0.03761],
+ [0.28441,0.01805,0.09189,0.04428,0.00565,0.00538,0.16482,0.20185,0.15423,0.11391],
+ [0.00980,0.07623,0.03248,0.00753,0.01028,0.00424,0.12144,0.11167,0.05904,0.00009],
+ [0.15721,0.09004,0.07690,0.00448,0.03511,0.05270,0.00859,0.00057,0.00754,0.04810],
+ [0.29881,0.00202,0.00490,0.00909,0.00343,0.00296,0.17159,0.05433,0.00924,0.00041],
+ [0.02110,0.00004,0.02863,0.00255,0.01232,0.06338,0.02043,0.16868,0.00080,0.00129],
+ [0.01843,0.00002,0.02181,0.00453,0.00290,0.00011,0.00819,0.00118,0.00312,0.00163],
+ [0.02320,0.00259,0.00519,0.01130,0.00403,0.00384,0.01210,0.09630,0.01668,0.00487]].
+
+
+%
+% reversed problem: Given stable state X, yield a transition matrix.
+%
+markov_chain_rev(X, Transitions) =>
+
+ N = length(X),
+
+ Transitions = new_array(N,N),
+ Transitions.vars() :: 0.0..1.0,
+
+ % Transitions[1,1] #<= 0.99, % to make it more interesting...
+ foreach(I in 1..N)
+ X[I] #= sum([Transitions[I,J]*X[J] : J in 1..N])
+ end,
+
+ sum(X) #= 1.0,
+
+
+ solve(Transitions).
diff --git a/picat/markov_chains_taha.pi b/picat/markov_chains_taha.pi
new file mode 100644
index 00000000..84ed0d68
--- /dev/null
+++ b/picat/markov_chains_taha.pi
@@ -0,0 +1,75 @@
+/*
+
+ Markov chains in Picat.
+
+ From Hamdy Taha "Operations Research" (8th edition), page 649ff.
+ Fertilizer example.
+
+
+ This Picat model was created by Hakan Kjellerstrand, hakank@gmail.com
+ See also my Picat page: http://www.hakank.org/picat/
+
+*/
+
+
+import mip.
+
+
+main => go.
+
+
+go =>
+ Cost = [100.0, 125.0, 160.0],
+ Mat = [[0.3, 0.6, 0.1],
+ [0.1, 0.6, 0.3],
+ [0.05, 0.4, 0.55]],
+
+ % the transition matrix page 650
+ % Mat = [[0.35, 0.6, 0.05],
+ % [0.3 , 0.6, 0.1 ],
+ % [0.25, 0.4, 0.35]],
+
+
+ N = Cost.length,
+
+ %% Not used since it involves nonlinear *
+ % MeanFirstReturnTime = new_list(N),
+ % MeanFirstReturnTime :: 0.0..1.0,
+
+ P = new_list(N),
+ P :: 0.0..1.0,
+
+ TotCost #= sum([Cost[I]*P[I] : I in 1..N]),
+
+ steady_state_prob(Mat, P),
+ % get_mean_first_return_time(P, MeanFirstReturnTime),
+
+ % solve(P ++ MeanFirstReturnTime),
+ solve($[min(TotCost)], P),
+
+ println(p=P),
+ println(totCost=TotCost),
+ % println(meanFirstReturnTime=MeanFirstReturnTime),
+
+ nl.
+
+
+%
+% Calculates the steady state probablity of a transition matrix m
+%
+steady_state_prob(M, Prob) =>
+ Len = M.length,
+ foreach(I in 1..Len)
+ Prob[I] #= sum([Prob[J]* M[J,I] : J in 1..Len])
+ end,
+ sum(Prob) #= 1.0.
+
+
+%
+% calculate the mean first return time from a steady state probability array
+%
+% Gives error: nonlinear constraint,*
+get_mean_first_return_time(Prob, Mfrt) =>
+ foreach(I in 1..Prob.length)
+ Mfrt[I] * Prob[I] #= 1.0
+ end.
diff --git a/picat/mortgage.pi b/picat/mortgage.pi
new file mode 100644
index 00000000..aed6dc6f
--- /dev/null
+++ b/picat/mortgage.pi
@@ -0,0 +1,59 @@
+/*
+
+ Mortgage in Picat.
+
+ Marriot & Stuckey: Programming with Constraints, page 175f
+ (famous early example)
+
+ This Picat model was created by Hakan Kjellerstrand, hakank@gmail.com
+ See also my Picat page: http://www.hakank.org/picat/
+
+*/
+
+
+import mip.
+
+
+main => go.
+
+
+% b=203.128769950000162
+go =>
+ mortgage(1000.0,10,10.0/100.0,150.0,B),
+ println(b=B),
+ nl.
+
+% p=921.685065855701964
+go2 =>
+ mortgage(P,10,10.0/100.0,150.0,0),
+ println(p=P),
+ nl.
+
+% This give p=0.0,r=0.0,b=0.0
+% (book example: 0.3855*B + 6.1446*R)
+go3 =>
+ mortgage(P,10,10.0/100.0,R,B),
+ println([p=P,r=R,b=B]),
+ nl.
+
+go4 =>
+ B #= 10.0,
+ mortgage(1234,10,10.0/100.0,R,B),
+ println([r=R,b=B]),
+ nl.
+
+% P: principal (amount borrowed)
+% T: time periods
+% I: interest rate
+% R: repayment
+% B: balance (final amount owing)
+mortgage(P,T,I,R,B) ?=>
+ T = 0,
+ B #= P,
+ solve([P,T,I,R,B]).
+
+mortgage(P,T,I,R,B) =>
+ T >= 0,
+ NT #= T -1,
+ NP #= P + P*I -R,
+ mortgage(NP,NT,I,R,B).
diff --git a/picat/plan_mip.pi b/picat/plan_mip.pi
new file mode 100644
index 00000000..cbf47a6a
--- /dev/null
+++ b/picat/plan_mip.pi
@@ -0,0 +1,65 @@
+/*
+
+ Planning model (MIP) in Picat.
+
+ From GLPK:s example plan.mod
+
+
+ This Picat model was created by Hakan Kjellerstrand, hakank@gmail.com
+ See also my Picat page: http://www.hakank.org/picat/
+
+*/
+
+
+import mip.
+
+
+main => go.
+
+
+go =>
+ Bin1 :: 0.0..200.0,
+ Bin2 :: 0.0..2500.0,
+ Bin3 :: 400.0..800.0,
+ Bin4 :: 100.0..700.0,
+ Bin5 :: 0.0..1500.0,
+ Alum :: 0.0..1000.0,
+ Silicon :: 0.0..1000.0,
+
+ Value #= 0.03 * Bin1 + 0.08 * Bin2 + 0.17 * Bin3 + 0.12 * Bin4 + 0.15 * Bin5 + 0.21 * Alum + 0.38 * Silicon,
+
+ Alum #>= 0.0,
+ Silicon #>= 0.0,
+ Bin1 + Bin2 + Bin3 + Bin4 + Bin5 + Alum + Silicon #= 2000.0,
+ 0.15 * Bin1 + 0.04 * Bin2 + 0.02 * Bin3 + 0.04 * Bin4 + 0.02 * Bin5 +
+ 0.01 * Alum + 0.03 * Silicon #<= 60.0,
+
+ 0.03 * Bin1 + 0.05 * Bin2 + 0.08 * Bin3 + 0.02 * Bin4 + 0.06 * Bin5 +
+ 0.01 * Alum #<= 100.0,
+
+ 0.02 * Bin1 + 0.04 * Bin2 + 0.01 * Bin3 + 0.02 * Bin4 + 0.02 * Bin5 #<= 40.0,
+
+ 0.02 * Bin1 + 0.03 * Bin2 + 0.01 * Bin5 #<= 30.0,
+
+ 0.70 * Bin1 + 0.75 * Bin2 + 0.80 * Bin3 + 0.75 * Bin4 + 0.80 * Bin5 + 0.97 * Alum #>= 1500.0,
+
+ 250.0 #<= 0.02 * Bin1 + 0.06 * Bin2 + 0.08 * Bin3 + 0.12 * Bin4 + 0.02 * Bin5 + 0.01 * Alum + 0.97 * Silicon,
+
+ 0.02 * Bin1 + 0.06 * Bin2 + 0.08 * Bin3 + 0.12 * Bin4 + 0.02 * Bin5 +
+ 0.01 * Alum + 0.97 * Silicon #<= 300.0,
+
+
+ Vars = [Bin1,Bin2,Bin3,Bin4,Bin5,Alum,Silicon],
+ solve($[min(Value)], Vars),
+
+ println(bin1=Bin1),
+ println(bin2=Bin2),
+ println(bin3=Bin3),
+ println(bin4=Bin4),
+ println(bin5=Bin5),
+ println(alum=Alum),
+ println(silicon=Silicon),
+ println(value=Value),
+
+ nl.
+
diff --git a/picat/spreadsheet.pi b/picat/spreadsheet.pi
new file mode 100644
index 00000000..d3f8df30
--- /dev/null
+++ b/picat/spreadsheet.pi
@@ -0,0 +1,41 @@
+/*
+
+ Spreadsheet in Picat.
+
+ From Krzysztof Apt "Principles of Constraint Programming" page 16ff. Spreadsheet.
+ Cf Winston "Artificial Intelligence", 3rd edition, page 235
+ (not the same values though)
+
+ This Picat model was created by Hakan Kjellerstrand, hakank@gmail.com
+ See also my Picat page: http://www.hakank.org/picat/
+
+*/
+
+
+import mip.
+
+
+main => go.
+
+
+go =>
+
+ X = [B1,B4,B5,C4,C5,D4,D5,E7,E8],
+ X :: 0.0..1000.0,
+
+ B1 #= 0.17,
+ B4 #= 3.5,
+ B5 #= 1.7,
+ C4 #= 1.5,
+ C5 #= 4.5,
+ D4 #= B4 * C4,
+ D5 #= B5 * C5,
+ E7 #= D4 + D5,
+ E8 #= E7 * (1.0 + B1),
+
+ solve(X),
+
+ println(X),
+
+ nl.
+
diff --git a/picat/stigler.pi b/picat/stigler.pi
new file mode 100644
index 00000000..40aec2e8
--- /dev/null
+++ b/picat/stigler.pi
@@ -0,0 +1,374 @@
+/*
+
+ Original Stigler's 1939 diet problem in Picat.
+
+ From GLPK:s example stigler.mod
+ """
+ STIGLER, original Stigler's 1939 diet problem
+
+ The Stigler Diet is an optimization problem named for George Stigler,
+ a 1982 Nobel Laureate in economics, who posed the following problem:
+ For a moderately active man weighing 154 pounds, how much of each of
+ 77 foods should be eaten on a daily basis so that the man's intake of
+ nine nutrients will be at least equal to the recommended dietary
+ allowances (RDSs) suggested by the National Research Council in 1943,
+ with the cost of the diet being minimal?
+
+ The nutrient RDAs required to be met in Stigler's experiment were
+ calories, protein, calcium, iron, vitamin A, thiamine, riboflavin,
+ niacin, and ascorbic acid. The result was an annual budget allocated
+ to foods such as evaporated milk, cabbage, dried navy beans, and beef
+ liver at a cost of approximately $0.11 a day in 1939 U.S. dollars.
+
+ While the name "Stigler Diet" was applied after the experiment by
+ outsiders, according to Stigler, "No one recommends these diets for
+ anyone, let alone everyone." The Stigler diet has been much ridiculed
+ for its lack of variety and palatability, however his methodology has
+ received praise and is considered to be some of the earliest work in
+ linear programming.
+
+ The Stigler diet question is a linear programming problem. Lacking
+ any sophisticated method of solving such a problem, Stigler was
+ forced to utilize heuristic methods in order to find a solution. The
+ diet question originally asked in which quantities a 154 pound male
+ would have to consume 77 different foods in order to fulfill the
+ recommended intake of 9 different nutrients while keeping expense at
+ a minimum. Through "trial and error, mathematical insight and
+ agility," Stigler was able to eliminate 62 of the foods from the
+ original 77 (these foods were removed based because they lacked
+ nutrients in comparison to the remaining 15). From the reduced list,
+ Stigler calculated the required amounts of each of the remaining 15
+ foods to arrive at a cost-minimizing solution to his question.
+ According to Stigler's calculations, the annual cost of his solution
+ was $39.93 in 1939 dollars. When corrected for inflation using the
+ consumer price index, the cost of the diet in 2005 dollars is
+ $561.43. The specific combination of foods and quantities is as
+ follows:
+
+ Stigler's 1939 Diet
+
+ Food Annual Quantities Annual Cost
+ ---------------- ----------------- -----------
+ Wheat Flour 370 lb. $13.33
+ Evaporated Milk 57 cans 3.84
+ Cabbage 111 lb. 4.11
+ Spinach 23 lb. 1.85
+ Dried Navy Beans 285 lb. 16.80
+ ----------------------------------------------
+ Total Annual Cost $39.93
+
+ The 9 nutrients that Stigler's diet took into consideration and their
+ respective recommended daily amounts were:
+
+ Table of nutrients considered in Stigler's diet
+
+ Nutrient Daily Recommended Intake
+ ------------------------- ------------------------
+ Calories 3,000 Calories
+ Protein 70 grams
+ Calcium .8 grams
+ Iron 12 milligrams
+ Vitamin A 5,000 IU
+ Thiamine (Vitamin B1) 1.8 milligrams
+ Riboflavin (Vitamin B2) 2.7 milligrams
+ Niacin 18 milligrams
+ Ascorbic Acid (Vitamin C) 75 milligrams
+
+ Seven years after Stigler made his initial estimates, the development
+ of George Dantzig's Simplex algorithm made it possible to solve the
+ problem without relying on heuristic methods. The exact value was
+ determined to be $39.69 (using the original 1939 data). Dantzig's
+ algorithm describes a method of traversing the vertices of a polytope
+ of N+1 dimensions in order to find the optimal solution to a specific
+ situation.
+
+ (From Wikipedia, the free encyclopedia.)
+
+ Translated from GAMS by Andrew Makhorin .
+
+ For the original GAMS model stigler1939.gms see [3].
+
+ References:
+
+ 1. George J. Stigler, "The Cost of Subsistence," J. Farm Econ. 27,
+ 1945, pp. 303-14.
+
+ 2. National Research Council, "Recommended Daily Allowances," Reprint
+ and Circular Series No. 115, January, 1943.
+
+ 3. Erwin Kalvelagen, "Model building with GAMS," Chapter 2, "Building
+ linear programming models," pp. 128-34.
+ """
+
+
+ Solution according GLPK:
+ """
+
+ Commodity Unit Quantity Cost
+ ------------------------- ---------- ---------- ----------
+ Wheat Flour (Enriched) 10 lb. 29.95 $ 10.78
+ Liver (Beef) 1 lb. 2.58 $ 0.69
+ Cabbage 1 lb. 110.70 $ 4.10
+ Spinach 1 lb. 22.58 $ 1.83
+ Navy Beans, Dried 1 lb. 377.81 $ 22.29
+ -----------------
+ Total: $ 39.69
+ """
+
+ This Picat model was created by Hakan Kjellerstrand, hakank@gmail.com
+ See also my Picat page: http://www.hakank.org/picat/
+
+*/
+
+
+% import util.
+import mip.
+
+
+main => go.
+
+
+go =>
+
+ stigler,
+ nl.
+
+
+stigler =>
+ data(Data),
+ NumCommodities = Data.length,
+
+ % days in a year
+ Days = 365.25,
+
+ % nutrients
+ NumNutrients = 9,
+
+ allowance(Allowance),
+
+ % decision variables
+
+ % dollars of food to be purchased daily
+ X = new_list(NumCommodities),
+ X :: 0.0..1.0,
+
+ XCost = new_list(NumCommodities),
+ XCost :: 0.0..100.0,
+ Quant = new_list(NumCommodities),
+ Quant :: 0.0..1000.0,
+
+ % total food bill
+ TotalCost #= Days * sum(X),
+ Cost #= sum(X), % cost per day
+
+ % nutrient balance
+ foreach(N in 3..NumNutrients+2)
+ sum([Data[C,N] * X[C] : C in 1..NumCommodities]) #>= Allowance[N-2]
+ end,
+
+ foreach(C in 1..NumCommodities)
+ XCost[C] #= Days * X[C],
+ % Quant[C] #= 100.0*Days*X[C] / Data[C,1] % / is integer divistion
+ Quant[C]*Data[C,1] #= 100.0*Days*X[C]
+ end,
+
+ Vars = X ++ XCost ++ Quant,
+ solve($[min(Cost)], Vars),
+
+ % println(x=X),
+ println(cost=Cost),
+ % println(xcost=XCost),
+ % println(quant=Quant),
+ println(totalCost=TotalCost),
+
+ commodities(Commodities),
+ foreach({Comm,Q,C} in zip(Commodities,Quant,XCost), Q > 0)
+ printf("%-35w: %10.2f $ %5.2f\n", Comm,Q,C)
+ end,
+
+ nl.
+
+allowance(Allowance) =>
+ Allowance = [3.0, 70.0, 0.8, 12.0, 5.0, 1.8, 2.7, 18.0, 75.0].
+
+
+commodities(Commodities) =>
+ Commodities =
+[
+"Wheat Flour (Enriched) 10 lb.",
+"Macaroni 1 lb.",
+"Wheat Cereal (Enriched) 28 oz.",
+"Corn Flakes 8 oz.",
+"Corn Meal 1 lb.",
+"Hominy Grits 24 oz.",
+"Rice 1 lb.",
+"Rolled Oats 1 lb.",
+"White Bread (Enriched) 1 lb.",
+"Whole Wheat Bread 1 lb.",
+"Rye Bread 1 lb.",
+"Pound Cake 1 lb.",
+"Soda Crackers 1 lb.",
+"Milk 1 qt.",
+"Evaporated Milk (can) 14.5 oz.",
+"Butter 1 lb.",
+"Oleomargarine 1 lb.",
+"Eggs 1 doz.",
+"Cheese (Cheddar) 1 lb.",
+"Cream 1/2 pt.",
+"Peanut Butter 1 lb.",
+"Mayonnaise 1/2 pt.",
+"Crisco 1 lb.",
+"Lard 1 lb.",
+"Sirloin Steak 1 lb.",
+"Round Steak 1 lb.",
+"Rib Roast 1 lb.",
+"Chuck Roast 1 lb.",
+"Plate 1 lb.",
+"Liver (Beef) 1 lb.",
+"Leg of Lamb 1 lb.",
+"Lamb Chops (Rib) 1 lb.",
+"Pork Chops 1 lb.",
+"Pork Loin Roast 1 lb.",
+"Bacon 1 lb.",
+"Ham - smoked 1 lb.",
+"Salt Pork 1 lb.",
+"Roasting Chicken 1 lb.",
+"Veal Cutlets 1 lb.",
+"Salmon, Pink (can) 16 oz.",
+"Apples 1 lb.",
+"Bananas 1 lb.",
+"Lemons 1 doz.",
+"Oranges 1 doz.",
+"Green Beans 1 lb.",
+"Cabbage 1 lb.",
+"Carrots 1 bunch",
+"Celery 1 stalk",
+"Lettuce 1 head",
+"Onions 1 lb.",
+"Potatoes 15 lb.",
+"Spinach 1 lb.",
+"Sweet Potatoes 1 lb.",
+"Peaches (can) No. 2 1/2",
+"Pears (can) No. 2 1/2",
+"Pineapple (can) No. 2 1/2",
+"Asparagus (can) No. 2",
+"Grean Beans (can) No. 2",
+"Pork and Beans (can) 16 oz.",
+"Corn (can) No. 2",
+"Peas (can) No. 2",
+"Tomatoes (can) No. 2",
+"Tomato Soup (can) 10 1/2 oz.",
+"Peaches, Dried 1 lb.",
+"Prunes, Dried 1 lb.",
+"Raisins, Dried 15 oz.",
+"Peas, Dried 1 lb.",
+"Lima Beans, Dried 1 lb.",
+"Navy Beans, Dried 1 lb.",
+"Coffee 1 lb.",
+"Tea 1/4 lb.",
+"Cocoa 8 oz.",
+"Chocolate 8 oz.",
+"Sugar 10 lb.",
+"Corn Sirup 24 oz.",
+"Molasses 18 oz.",
+"Strawberry Preserve 1 lb."].
+
+
+
+% set N :=
+% calories % Calories, unit = 1000
+% protein % Protein, unit = grams
+% calcium % Calcium, unit = grams
+% iron % Iron, unit = milligrams
+% vitaminA % Vitamin A, unit = 1000 International Units
+% thiamine % Thiamine, Vit. B1, unit = milligrams
+% riboflavin % Riboflavin, Vit. B2, unit = milligrams
+% niacin % Niacin (Nicotinic Acid), unit = milligrams
+% ascorbicAcid % Ascorbic Acid, Vit. C, unit = milligrams
+% ;
+
+% price and weight is the two first columns
+data(Data) =>
+ % 1..num_nutrients+2,
+Data =
+[
+ [36.0, 12600.0, 44.7, 1411.0, 2.0, 365.0, 0.0, 55.4, 33.3, 441.0, 0.0],
+ [14.1, 3217.0, 11.6, 418.0, 0.7, 54.0, 0.0, 3.2, 1.9, 68.0, 0.0],
+ [24.2, 3280.0, 11.8, 377.0, 14.4, 175.0, 0.0, 14.4, 8.8, 114.0, 0.0],
+ [ 7.1, 3194.0, 11.4, 252.0, 0.1, 56.0, 0.0, 13.5, 2.3, 68.0, 0.0],
+ [ 4.6, 9861.0, 36.0, 897.0, 1.7, 99.0, 30.9, 17.4, 7.9, 106.0, 0.0],
+ [ 8.5, 8005.0, 28.6, 680.0, 0.8, 80.0, 0.0, 10.6, 1.6, 110.0, 0.0],
+ [ 7.5, 6048.0, 21.2, 460.0, 0.6, 41.0, 0.0, 2.0, 4.8, 60.0, 0.0],
+ [ 7.1, 6389.0, 25.3, 907.0, 5.1, 341.0, 0.0, 37.1, 8.9, 64.0, 0.0],
+ [ 7.9, 5742.0, 15.6, 488.0, 2.5, 115.0, 0.0, 13.8, 8.5, 126.0, 0.0],
+ [ 9.1, 4985.0, 12.2, 484.0, 2.7, 125.0, 0.0, 13.9, 6.4, 160.0, 0.0],
+ [ 9.2, 4930.0, 12.4, 439.0, 1.1, 82.0, 0.0, 9.9, 3.0, 66.0, 0.0],
+ [24.8, 1829.0, 8.0, 130.0, 0.4, 31.0, 18.9, 2.8, 3.0, 17.0, 0.0],
+ [15.1, 3004.0, 12.5, 288.0, 0.5, 50.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ [11.0, 8867.0, 6.1, 310.0, 10.5, 18.0, 16.8, 4.0, 16.0, 7.0, 177.0],
+ [ 6.7, 6035.0, 8.4, 422.0, 15.1, 9.0, 26.0, 3.0, 23.5, 11.0, 60.0],
+ [20.8, 1473.0, 10.8, 9.0, 0.2, 3.0, 44.2, 0.0, 0.2, 2.0, 0.0],
+ [16.1, 2817.0, 20.6, 17.0, 0.6, 6.0, 55.8, 0.2, 0.0, 0.0, 0.0],
+ [32.6, 1857.0, 2.9, 238.0, 1.0, 52.0, 18.6, 2.8, 6.5, 1.0, 0.0],
+ [24.2, 1874.0, 7.4, 448.0, 16.4, 19.0, 28.1, 0.8, 10.3, 4.0, 0.0],
+ [14.1, 1689.0, 3.5, 49.0, 1.7, 3.0, 16.9, 0.6, 2.5, 0.0, 17.0],
+ [17.9, 2534.0, 15.7, 661.0, 1.0, 48.0, 0.0, 9.6, 8.1, 471.0, 0.0],
+ [16.7, 1198.0, 8.6, 18.0, 0.2, 8.0, 2.7, 0.4, 0.5, 0.0, 0.0],
+ [20.3, 2234.0, 20.1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ [ 9.8, 4628.0, 41.7, 0.0, 0.0, 0.0, 0.2, 0.0, 0.5, 5.0, 0.0],
+ [39.6, 1145.0, 2.9, 166.0, 0.1, 34.0, 0.2, 2.1, 2.9, 69.0, 0.0],
+ [36.4, 1246.0, 2.2, 214.0, 0.1, 32.0, 0.4, 2.5, 2.4, 87.0, 0.0],
+ [29.2, 1553.0, 3.4, 213.0, 0.1, 33.0, 0.0, 0.0, 2.0, 0.0, 0.0],
+ [22.6, 2007.0, 3.6, 309.0, 0.2, 46.0, 0.4, 1.0, 4.0, 120.0, 0.0],
+ [14.6, 3107.0, 8.5, 404.0, 0.2, 62.0, 0.0, 0.9, 0.0, 0.0, 0.0],
+ [26.8, 1692.0, 2.2, 333.0, 0.2, 139.0, 169.2, 6.4, 50.8, 316.0, 525.0],
+ [27.6, 1643.0, 3.1, 245.0, 0.1, 20.0, 0.0, 2.8, 3.0, 86.0, 0.0],
+ [36.6, 1239.0, 3.3, 140.0, 0.1, 15.0, 0.0, 1.7, 2.7, 54.0, 0.0],
+ [30.7, 1477.0, 3.5, 196.0, 0.2, 80.0, 0.0, 17.4, 2.7, 60.0, 0.0],
+ [24.2, 1874.0, 4.4, 249.0, 0.3, 37.0, 0.0, 18.2, 3.6, 79.0, 0.0],
+ [25.6, 1772.0, 10.4, 152.0, 0.2, 23.0, 0.0, 1.8, 1.8, 71.0, 0.0],
+ [27.4, 1655.0, 6.7, 212.0, 0.2, 31.0, 0.0, 9.9, 3.3, 50.0, 0.0],
+ [16.0, 2835.0, 18.8, 164.0, 0.1, 26.0, 0.0, 1.4, 1.8, 0.0, 0.0],
+ [30.3, 1497.0, 1.8, 184.0, 0.1, 30.0, 0.1, 0.9, 1.8, 68.0, 46.0],
+ [42.3, 1072.0, 1.7, 156.0, 0.1, 24.0, 0.0, 1.4, 2.4, 57.0, 0.0],
+ [13.0, 3489.0, 5.8, 705.0, 6.8, 45.0, 3.5, 1.0, 4.9, 209.0, 0.0],
+ [ 4.4, 9072.0, 5.8, 27.0, 0.5, 36.0, 7.3, 3.6, 2.7, 5.0, 544.0],
+ [ 6.1, 4982.0, 4.9, 60.0, 0.4, 30.0, 17.4, 2.5, 3.5, 28.0, 498.0],
+ [26.0, 2380.0, 1.0, 21.0, 0.5, 14.0, 0.0, 0.5, 0.0, 4.0, 952.0],
+ [30.9, 4439.0, 2.2, 40.0, 1.1, 18.0, 11.1, 3.6, 1.3, 10.0, 1993.0],
+ [ 7.1, 5750.0, 2.4, 138.0, 3.7, 80.0, 69.0, 4.3, 5.8, 37.0, 862.0],
+ [ 3.7, 8949.0, 2.6, 125.0, 4.0, 36.0, 7.2, 9.0, 4.5, 26.0, 5369.0],
+ [ 4.7, 6080.0, 2.7, 73.0, 2.8, 43.0, 188.5, 6.1, 4.3, 89.0, 608.0],
+ [ 7.3, 3915.0, 0.9, 51.0, 3.0, 23.0, 0.9, 1.4, 1.4, 9.0, 313.0],
+ [ 8.2, 2247.0, 0.4, 27.0, 1.1, 22.0, 112.4, 1.8, 3.4, 11.0, 449.0],
+ [ 3.6, 11844.0, 5.8, 166.0, 3.8, 59.0, 16.6, 4.7, 5.9, 21.0, 1184.0],
+ [34.0, 16810.0, 14.3, 336.0, 1.8, 118.0, 6.7, 29.4, 7.1, 198.0, 2522.0],
+ [ 8.1, 4592.0, 1.1, 106.0, 0.0, 138.0, 918.4, 5.7, 13.8, 33.0, 2755.0],
+ [ 5.1, 7649.0, 9.6, 138.0, 2.7, 54.0, 290.7, 8.4, 5.4, 83.0, 1912.0],
+ [16.8, 4894.0, 3.7, 20.0, 0.4, 10.0, 21.5, 0.5, 1.0, 31.0, 196.0],
+ [20.4, 4030.0, 3.0, 8.0, 0.3, 8.0, 0.8, 0.8, 0.8, 5.0, 81.0],
+ [21.3, 3993.0, 2.4, 16.0, 0.4, 8.0, 2.0, 2.8, 0.8, 7.0, 399.0],
+ [27.7, 1945.0, 0.4, 33.0, 0.3, 12.0, 16.3, 1.4, 2.1, 17.0, 272.0],
+ [10.0, 5386.0, 1.0, 54.0, 2.0, 65.0, 53.9, 1.6, 4.3, 32.0, 431.0],
+ [ 7.1, 6389.0, 7.5, 364.0, 4.0, 134.0, 3.5, 8.3, 7.7, 56.0, 0.0],
+ [10.4, 5452.0, 5.2, 136.0, 0.2, 16.0, 12.0, 1.6, 2.7, 42.0, 218.0],
+ [13.8, 4109.0, 2.3, 136.0, 0.6, 45.0, 34.9, 4.9, 2.5, 37.0, 370.0],
+ [ 8.6, 6263.0, 1.3, 63.0, 0.7, 38.0, 53.2, 3.4, 2.5, 36.0, 1253.0],
+ [ 7.6, 3917.0, 1.6, 71.0, 0.6, 43.0, 57.9, 3.5, 2.4, 67.0, 862.0],
+ [15.7, 2889.0, 8.5, 87.0, 1.7, 173.0, 86.8, 1.2, 4.3, 55.0, 57.0],
+ [ 9.0, 4284.0, 12.8, 99.0, 2.5, 154.0, 85.7, 3.9, 4.3, 65.0, 257.0],
+ [ 9.4, 4524.0, 13.5, 104.0, 2.5, 136.0, 4.5, 6.3, 1.4, 24.0, 136.0],
+ [ 7.9, 5742.0, 20.0, 1367.0, 4.2, 345.0, 2.9, 28.7, 18.4, 162.0, 0.0],
+ [ 8.9, 5097.0, 17.4, 1055.0, 3.7, 459.0, 5.1, 26.9, 38.2, 93.0, 0.0],
+ [ 5.9, 7688.0, 26.9, 1691.0, 11.4, 792.0, 0.0, 38.4, 24.6, 217.0, 0.0],
+ [22.4, 2025.0, 0.0, 0.0, 0.0, 0.0, 0.0, 4.0, 5.1, 50.0, 0.0],
+ [17.4, 652.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2.3, 42.0, 0.0],
+ [ 8.6, 2637.0, 8.7, 237.0, 3.0, 72.0, 0.0, 2.0, 11.9, 40.0, 0.0],
+ [16.2, 1400.0, 8.0, 77.0, 1.3, 39.0, 0.0, 0.9, 3.4, 14.0, 0.0],
+ [51.7, 8773.0, 34.9, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ [13.7, 4996.0, 14.7, 0.0, 0.5, 74.0, 0.0, 0.0, 0.0, 5.0, 0.0],
+ [13.6, 3752.0, 9.0, 0.0, 10.3, 244.0, 0.0, 1.9, 7.5, 146.0, 0.0],
+ [20.5, 2213.0, 6.4, 11.0, 0.4, 7.0, 0.2, 0.2, 0.4, 3.0, 0.0]
+].
+
+
diff --git a/picat/transp.pi b/picat/transp.pi
new file mode 100644
index 00000000..40c7d0f5
--- /dev/null
+++ b/picat/transp.pi
@@ -0,0 +1,92 @@
+/*
+
+ Transportation problem in Picat.
+
+ From GLPK:s example transp.mod
+
+ """
+ A TRANSPORTATION PROBLEM
+
+ This problem finds a least cost shipping schedule that meets
+ requirements at markets and supplies at factories.
+
+ References:
+ Dantzig G B, "Linear Programming and Extensions."
+ Princeton University Press, Princeton, New Jersey, 1963,
+ Chapter 3-3.
+ """
+
+ This Picat model was created by Hakan Kjellerstrand, hakank@gmail.com
+ See also my Picat page: http://www.hakank.org/picat/
+
+*/
+
+
+import mip.
+
+
+main => go.
+
+
+go =>
+
+ % canning plants
+ % set I := Seattle San-Diego;
+ NumPlants = 2,
+
+ % markets
+ % set J := New-York Chicago Topeka;
+ NumMarkets = 3,
+
+
+ % capacity of plant i in cases
+ A = [350.0, 600.0],
+
+ % demand at market j in cases
+ B = [325.0, 300.0, 275.0],
+
+ % distance in thousands of miles
+ D = [
+ [2.5, 1.7, 1.8],
+ [2.5, 1.8, 1.4]
+ ],
+
+ % freight in dollars per case per thousand miles
+ F = 90.0,
+
+
+ % transport cost in thousands of dollars per case
+ % param c{i in I, j in J} := f * d[i,j] / 1000;
+ % array[I,J] of float: c = array2d(I,J, [f*d[i,j] / 1000.0 | i in I, j in J]);
+ C = [ [F*D[I,J] : J in 1..NumMarkets] : I in 1..NumPlants],
+
+
+ X = new_array(NumPlants,NumMarkets),
+ X.vars() :: 0.0..1000.0,
+
+ Cost * 1000.0 #= sum([C[I,J]*X[I,J] : I in 1..NumPlants, J in 1..NumMarkets]),
+
+ % observe supply limit at plant i
+ foreach(I in 1..NumPlants)
+ sum([X[I,J] : J in 1..NumMarkets]) #<= A[I]
+ end,
+
+
+ % satisfy demand at market j
+ foreach(J in 1..NumMarkets)
+ sum([X[I,J] : I in 1..NumPlants]) #>= B[J]
+ end,
+
+ solve($[min(Cost)],X),
+
+ printf("cost: %0.3f\n", Cost),
+ println("X:"),
+ foreach(Row in X)
+ foreach(R in Row)
+ printf("%8.2f ",R)
+ end,
+ nl
+ end,
+
+ nl.
+
diff --git a/picat/transp1.pi b/picat/transp1.pi
new file mode 100644
index 00000000..aed39656
--- /dev/null
+++ b/picat/transp1.pi
@@ -0,0 +1,136 @@
+/*
+
+ Transportation problem in Picat.
+
+ This is in princple the same model as in
+ Pascal Van Hentenryck "The OPL Optimization Programming Language",
+ page 116.
+
+ Data from OPL example transp1.dat
+
+
+ This Picat model was created by Hakan Kjellerstrand, hakank@gmail.com
+ See also my Picat page: http://www.hakank.org/picat/
+
+*/
+
+
+import mip.
+
+
+main => go.
+
+
+go =>
+ capacity(Capacity),
+ supply(Supply),
+ demand(Demand),
+ cost(Cost),
+
+ NumProducts = Supply.length,
+ NumCities = Supply[1].length,
+
+ % decision variables
+ Trans = new_array(NumProducts,NumCities,NumCities),
+ % Trans.vars() :: 0.0..1000000.0,
+
+ % Z :: 0.0..10000000.0,
+ Z #= sum([ Cost[P,O,D] * Trans[P,O,D] : P in 1..NumProducts , O in 1..NumCities, D in 1..NumCities]),
+
+
+ foreach(P in 1..NumProducts , O in 1..NumCities)
+ sum([Trans[P,O,D] : D in 1..NumCities]) #= Supply[P,O]
+ end,
+
+ foreach(P in 1..NumProducts , D in 1..NumCities)
+ sum([Trans[P,O,D] : O in 1..NumCities]) #= Demand[P,D]
+ end,
+
+ foreach(O in 1..NumCities, D in 1..NumCities)
+ sum([Trans[P,O,D] : P in 1..NumProducts]) #<= Capacity
+ end,
+
+
+ solve($[min(Z)],Trans),
+
+ println(z=Z),
+ println("Trans:"),
+ foreach(T in Trans)
+ foreach(R in T)
+ foreach(S in R)
+ printf("%6.1f ", S)
+ end,
+ nl
+ end
+ end,
+
+
+ nl.
+
+
+capacity(Capacity) => Capacity = 625.0.
+
+% 1..NumProducts,1..NumCities
+supply(Supply) =>
+ Supply =
+ [
+ [400.0, 700.0, 800.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ [800.0, 1600.0, 1800.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ [200.0, 300.0, 300.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
+ ].
+
+% 1..NumProducts,1..NumCities
+demand(Demand) =>
+ Demand =
+ [
+ [0, 0, 0,300,300,100, 75,650,225,250], % bands
+ [0, 0, 0,500,750,400,250,950,850,500], % coils
+ [0, 0, 0,100,100, 0, 50,200,100,250] % plate
+ ].
+
+% 1..NumProducts, 1..NumCities,1..NumCities
+cost(Cost) =>
+ Cost =
+ [
+ % bands
+ [
+ [0, 0, 0, 30, 10, 8, 10, 11, 71, 6],
+ [0, 0, 0, 22, 7, 10, 7, 21, 82, 13],
+ [0, 0, 0, 19, 11, 12, 10, 25, 83, 15],
+ [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+ [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+ [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+ [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+ [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+ [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+ [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ ]
+ ,
+ % coils
+ [
+ [0, 0, 0, 39, 14, 11, 14, 16, 82, 8],
+ [0, 0, 0, 27, 9, 12, 9, 26, 95, 17],
+ [0, 0, 0, 24, 14, 17, 13, 28, 99, 20],
+ [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+ [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+ [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+ [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+ [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+ [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+ [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ ]
+ ,
+ % plate
+ [
+ [0, 0, 0, 41, 15, 12, 16, 17, 86, 8],
+ [0, 0, 0, 29, 9, 13, 9, 28, 99, 18],
+ [0, 0, 0, 26, 14, 17, 13, 31, 104, 20],
+ [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+ [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+ [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+ [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+ [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+ [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+ [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ ]
+ ].