I have recently been introduced to AMPL in a class and I am currently working on an optimization problem that requires me to find the minimal cost for the demands required. The actual lines I have in question are these:
1. This is in my model file:
minimize Total_Cost:
sum{i in GENS, j in LOADS} cost[i,j] * Allocate[i,j];
subject to GenConst {i in GENS}:
sum {j in LOADS} Allocate[i,j] <= Generation[i];
subject to DemConst {j in LOADS}:
sum {i in GENS} Allocate [i,j] >= Demand[j];
in my data file:
param: GENS:
GenerationMin GenerationMax := #defines set "GENS" and param "Generation"
GEN1 10 90
GEN2 10 100
GEN3 5 85 ;
We have only ever worked with having problems where our demand=generation, but none with having minimum, maximum along with demand != supply. I get the following error when running my data file within ampl GenerationMin is not a subscripted param . When running this script with only the max value it runs fine. The issue, and I am only guessing, are with the lines above. Could someone explain to me where I am going wrong and how to fix this issue?
EDIT: I can include all of my code, although in case anyone wants to reproduce the problem. .mod file:
set GENS;
set LOADS;
param Generation {GENS} >=0;
param Demand {LOADS} >=0;
param cost {GENS, LOADS} >= 0;
var Allocate {GENS, LOADS} >= 0; #{GEN1, LOAD1}, {GEN1, LOAD2... etc}
minimize Total_Cost:
sum{i in GENS, j in LOADS} cost[i,j] * Allocate[i,j];
subject to GenConst {i in GENS}:
sum {j in LOADS} Allocate[i,j] <= Generation[i];
subject to DemConst {j in LOADS}:
sum {i in GENS} Allocate [i,j] >= Demand[j];
.data file:
data;
param: GENS:
GenerationMin GenerationMax := #defines set "GENS" and param "Generation"
GEN1 10 90
GEN2 10 100
GEN3 5 85 ;
param: LOADS: Demand := #Defining set "LOADS" and param "Demand"
Load1 70
Load2 20
Load3 30
Load4 60;
param cost:
Load1 Load2 Load3 Load4 :=
GEN1 39 14 11 14
GEN2 27 9 12 9
GEN3 24 14 17 13;
option solver cplex;
solve;
display Allocate;
display Allocate, Total_Cost > Output.txt
The correct AMPL syntax is:
set GENS;
param GenerationMin {GENS} >=0;
param GenerationMax {GENS} >=0;
data;
param: GENS:
GenerationMin GenerationMax :=
GEN1 10 90
GEN2 10 100
GEN3 5 85 ;
display GENS,GenerationMin,GenerationMax;
i.e. use both GenerationMin,GenerationMax in the model and in the data section.
Related
I am trying to solve the exercises from AMPL: A Modeling Language for Math Programming Package, but I am stuck on Exercise 1-4(e). My code so far looks like this:
.mod-file:
# Set of cars we can produce
set CAR;
# Parameters
param amount {CAR} > 0; # Amount of cars produced (for each car in CAR)
param time {CAR} > 0; # Time it takes to produce (for each car in CAR) in hours
param fac_time > 0; # Factory-time to use next week
param profit {CAR} > 0; # Profit (for each car in CAR)
param lower {CAR} >= 0; # Lower limit of amount of cars to be produced (for each car in CAR)
# Define var
var Make {c in CAR} >= lower[c];
# Obj. function
maximize Total_Cars: sum {c in CAR} Make[c];
# Constraits
s.t. Time: sum {c in CAR} time[c] * Make[c] = fac_time;
.dat-file:
set CAR := T C L;
param: time profit lower :=
T 1 200 10
C 2 500 20
L 3 700 15 ;
param fac_time := 120;
The task:
Each kind of car achieves a certain fuel efficiency, and the manufacturer is required by law to
maintain a certain ‘‘fleet average’’ efficiency. The fleet average is computed by multiplying the
efficiency of each kind of car times the number of that kind produced, summing all of the resulting
products, and dividing by the total of all cars produced. Extend your AMPL model to contain a
minimum fleet average efficiency constraint. Rearrange the constraint as necessary to make it linear — no variables divided into other variables.
So I changed my code to this:
.mod-file:
# Set of cars we can produce
set CAR;
# Parameters
param amount {CAR} > 0; # Amount of cars produced (for each car in CAR)
param time {CAR} > 0; # Time it takes to produce (for each car in CAR) in hours
param fac_time > 0; # Factory-time to use next week
param profit {CAR} > 0; # Profit (for each car in CAR)
param lower {CAR} >= 0; # Lower limit of amount of cars to be produced (for each car in CAR)
param fuel_eff {CAR} > 0; # Fuel efficiency (for each car in CAR)
param fleet_avg > 0; # Fleet average efficiency
# Define var
var Make {c in CAR} >= lower[c];
# Obj. function
maximize Total_Cars: sum {c in CAR} Make[c];
# Constraits
s.t. Time: sum {c in CAR} time[c] * Make[c] = fac_time;
s.t. Efficiency: **HERE** >= fleet_avg;
.dat-file:
set CAR := T C L;
param: time profit lower fuel_eff:=
T 1 200 10
C 2 500 20
L 3 700 15 ;
param fac_time := 120;
param fleet_eff := (sum {c in CAR} amount[c] * fuel_eff[c])/Total_Cars;
I do not have access to the solutions so my question here is: What should be written inside the constraint for efficiency? Have I defined the parameter fleet_avg correctly? If not, what is the proper way to solve this?
You are on the right track.
Your efficiency constraint is mathematically correct. You don't say so in the problem, but I think it is assumed that Total Cars is a variable, just the sum of Make[c], correct?
So what's the problem then?
Well you have just made your linear program non-linear by dividing by total cars because you have a variable divided by another variable in that fraction. (Aside: remember we are only talking about "linear" in terms of the variables so we want to avoid dividing, multiply variables with each other... parameters are fixed and are fair game).
So what's the fix?
They hint at this in the text by reminding you not to do what you just did above. Realize that with a little algebra, we can multiply both sides of that equation by Total Cars (or more accurately sum(Make[c]) to get rid of the division... So I would expect something like this (in pseudocode):
sum(Make[c]) * fleet_efficiency >= sum(Make[c] * fuel_eff[c])
Which is linear in terms of the variables.
I've been experiencing with GAMS but I still haven't got a clue what I'm doing.
Can someone take a look at this short model and try to point me in the right direction?
I have problems in the compilation at the equations, getting a few of these:
Dimension different - The symbol is referenced with more/less
indices as declared
Uncontrolled set entered as constant
Sets
i months / 1, 2, 3 /
j months / 1, 2, 3 /;
Parameters
cp(i) production cost in month i
/ 1 1.08
2 1.11
3 1.10
/
rh(i) number of necessary workers in month i
/ 1 3
2 4
3 6
/
cap(i) production capacity in month i
/ 1 25
2 20
3 25
/
q(j) number of motors to deliver in month j
/ 1 10
2 15
3 25
/
Scalar ca cost to store motors for a month /0.15/ ;
variables
mc(i,j) cost of production of motors in month i to be delivered in month j
x(i,j) number of motors produced in month i to be delivered in month j;
free variables
wf workforce
z cost of production
hr human resources;
Equations
cost cost
human_resources human resources
r1 restriction1
r2 restriction2 ;
cost .. z =e= sum((i,j), (cp(i)+(j-i)*ca)*x(i,j)) ;
human_resources .. hr =e= sum(i, sum(j, rh(i)*x(i, j))) ;
*lower than
r1.. sum(j, x(i,j)) =l= cap(i) ;
*greater than
r2.. sum(i, x(i,j)) =g= q(j) ;
Model
motors 'temp' /all/;
Solve motors using mip minimizing mc;
Display mc, x;
This works but check the solution. I added the positive variable x because otherwise you would have negative productions.
The main problem was the fact that you were optimizing a variable that is declared but that you never use in the equations. Also, the variable you are optimizing cannot have to dimensions (I think).
Then, for constraints r1 and r2 you need to add an index because they must be verified for each month, so r1(i) and r2(j). They are actually a "family of constraints".
You cannot subtract the indexes of the months (can't explain why), but you can subtract their order in the set.
And finally, calculate the mc(i,j) as a parameter after you have obtained the solution.
Sets
i months / 1, 2, 3 /
j months / 1, 2, 3 /;
Parameters
cp(i) production cost in month i
/ 1 1.08
2 1.11
3 1.10
/
rh(i) number of necessary workers in month i
/ 1 3
2 4
3 6
/
cap(i) production capacity in month i
/ 1 25
2 20
3 25
/
q(j) number of motors to deliver in month j
/ 1 10
2 15
3 25
/
Scalar ca cost to store motors for a month /0.15/ ;
variables
* mc(i,j) cost of production of motors in month i to be delivered in month j
x(i,j) number of motors produced in month i to be delivered in month j;
positive variable x;
free variables
wf workforce
z cost of production
hr human resources;
Equations
cost cost
human_resources human resources
r1(i) restriction1
r2(j) restriction2 ;
cost .. z =e= sum((i,j), (cp(i)+(ord(j)-ord(i))*ca)*x(i,j)) ;
human_resources .. hr =e= sum(i, sum(j, rh(i)*x(i, j))) ;
*lower than
r1(i).. sum(j, x(i,j)) =l= cap(i) ;
*greater than
r2(j).. sum(i, x(i,j)) =g= q(j) ;
Model
motors 'temp' /all/;
Solve motors using mip minimizing z;
Parameter mc(i,j);
mc(i,j)= (cp(i)+(ord(j)-ord(i))*ca)*x.l(i,j);
Display mc, x.l;
I this example is used
# random locations for the cities
param cx{i in N} := Uniform01();
param cy{i in N} := Uniform01();
for generate random locations for the cities
How to read data file with coordinates in GLPK and how format?
1 2 3 4
1,2,3,4
(1,2),(3,4)
{1,2},{3,4}
Glpk uses GNU MathProg, a subset of AMPL, so given the following parameter and set declarations:
set N := 1..2;
param cx{i in N};
param cy{i in N};
you can read the data as follows
data;
param:
cx cy :=
1 1 2
2 3 4;
Note that in this case parameters cx and cy shouldn't be defined in the model, so you should either remove the := Uniform01() part or change it to default Uniform01().
I have a data set that looks like this (SAS 9.4):
data opt_test;
input ID GRP $ x1 MIN MAX y z;
cards;
2 F 10 9 11 1.5 100
3 F 10 9 11 1.2 50
4 F 11 9 11 .9 20
8 G 5 4 6 1.2 300
9 G 6 4 6 .9 200
;
run;
I want to create a new variable x2 that maximizes a function based on x1, x2, y, and z.
I am having two main problems:
The syntax on my proc optmodel has some errors that I have not been able to fix "Subscript 1 may not be a set" and constraint has incomplete declaration". UPDATE: I figured this part out.
I need for the value of x2 to be the same for all members of the same GRP. So, id 2,3,4 would have same x2. ID 8 and 9 would have same x2.
Below is my attempt. This will ultimately be able to run with sevarl different GRP of varying numbers of ID.
Thanks in advance for any assistance.
proc optmodel;
set<num> ID;
var x2{ID} >= 0;
string GRP{ID};
number x1{ID};
number MIN{ID};
number MAX{ID};
number y{ID};
number z{ID};
max sales=sum{i in ID}(x2[i])*(1-(x2[i]-x1[i])*y[i]/x1[i])*z[i];
con floor_METRIC1{i in ID}: x2[i]>=MIN[i];
con ceiling_METRIC1{i in ID}: x2[i]<=MAX[i];
read data opt_test into
ID=[ID]
GRP
x1
MIN
MAX
y
z
;
solve;
print x2;
quit;
If you want the value of x2 to be the same for all ids in the same group, then you only need one variable x2 per group. To keep track of which ids are in which group you could use an array of sets indexed by group:
set<num> ID;
string GRP{ID};
set GRPS = setof{i in ID} GRP[i];
set IDperGRP{gi in GRPS} = {i in ID: GRP[i] = gi};
When you use = (as opposed to init), you provide OPTMODEL with a function you don't need to update later. If you change any of the GRP or ID data, optmodel will recompute GRPS and IDperGRP as needed.
Now you can use the GRPS set and the IDperGRP array of sets to rewrite your objective to more closely match your business rule:
max sales = sum{gi in GRPS} sum{i in IDperGRP[gi]}
(x2[gi]) * (1-(x2[gi]-x1[i])*y[i]/x1[i]) * z[i];
Writing the expression this way makes it clearer (to me at least) that it can be simplified further as long as x1, y, and z are constants.
Adding the new sets also makes it clearer (to me at least) that the bounds from floor_METRIC1 and ceiling_METRIC1 can be combined to tighten the domain of x2. Since MIN and MAX are constants, you can move the constraints into direct variable bounds by adding >= and <= clauses to the declaration of x2. Since x2 will now depend on MIN and MAX, you will have to declare those before x2. IMHO that makes your intent clearer:
number MIN{ID};
number MAX{ID};
var x2{gi in GRPS} >= max{i in IDperGRP[gi]} MIN[i]
<= min{i in IDperGRP[gi]} MAX[i]
;
I am struggling with a seemingly simple model in MathProg. The model is as follows:
set W;
set V;
param b {W, V} binary;
param p;
var w {j in W} <= 0, >= 1;
minimize obj: 0;
subject to within_radius_of {i in V}:
sum {j in W} b[i,j] * w[j] >= 1;
subject to p_limit:
sum {j in W} w[j] <= p;
end;
When I run it, it gives me the error feasibility.glp:11: b[v1,w1] out of domain. I have no idea what is going wrong. Even more strange to me, if I change the relevant line to b[j,i] it keeps giving the exact same error (not b[w1,v1] as I expected).
I inspected the AMPL Diet Example carefully, and despite me seeing no difference in the relevant part of my model it still doesn't work. What is wrong?
Parameter b is declared as binary so it can only take values 0 or 1. You haven't provided a data file, but the error message suggests that the data for b is out of domain (not 0 or 1), for example:
data;
set W := w1;
set V := v1;
param b := w1 v1 0.5;
AMPL gives a more detailed error message in this case:
error processing param b['w1','v1']:
failed check: param b['w1','v1'] = 0.5
is not binary (0 or 1);
The reason why the order of indices doesn't matter in this case is that the data for b is checked completely before the model is actually instantiated. So it seems that w1 and v1 may be swapped in the data file.