Inline index addition in gams - optimization

I want to use an index equation to iterate over a tensors, whereas I always want to extract the value at index i and index i+1. An example:
Variable x; x.up = 10;
Parameter T /1=1,2=2,3=3,4=4,5=5/;
Set a /1,2,4/;
equation eq(a); eq(a).. x =g= T[a+1];
*x ist restricted by the values of T at the indices 2,3 and 5.
Model dummy /all/;
solve dummy min x use lp;
I am aware that gams sees the indices as string-keys rather than numerical ones, so the addition is not intended. Is this possible anyway? This e.g. can be solved by defining another tensor, unfortunaly my given conditions require the index operation inline (i.e. I am not allowed to define additional parameters or sets.

Does this work for you?
Variable x; x.up = 10;
Set aa /1*6/;
Parameter T(aa) /1=1,2=2,3=3,4=4,5=5/;
Set a(aa) /1,2,4/;
equation eq(a); eq(a(aa)).. x =g= T[aa+1];
*x ist restricted by the values of T at the indices 2,3 and 5.
Model dummy /all/;
solve dummy min x use lp;

Related

GAMS modelation: how do i set an identifier as the last value of a set (index.last) on an equation

I'm modeling a VRP in GAMS language and one of my equations would ideally be:
SUM(i, x(i,n+1)) =e= 0;
with "n+1" being the last value of the set i /0*4/ (so it's 4)
I can't type x(i,"4") because this number (4) is just an example.
The software doesn't recognize this equation. the error says "unknown identifier set as index, which i understand is because "n" isn't a set.
so i put n as a set, just like i did with i, but then I'd have to give it a number (3, so that n+1 = 4) and i don't want that.
I just need a way to put "n+1" as a valid index for x(i,n+1)
Assuming that x is declared as x(i,i), you can do something like this:
Alias (i,i2);
Equation eq;
eq.. SUM((i,i2)$i2.last, x(i,i2)) =e= 0;

How to set the lower and upper bounds of a single variable in a single equation in gams

Is this possible?:
boundary_of_x..
19.0 =l= x =g= 22.1;
where x is a positive variable and boundary_of_x is an equation. Or do I have to do this in two equations?
You cannot do this in one equation, you need two, or (better) use the .lo and .up attribute of the variable:
x.lo = 19.0; x.up = 22.1;

Using the sum function in GAMS to sum over a subset of variables

I am working with maximazation problems in GAMS where I will choose
X=(x_1,x2,...,x_n) such that f(X)=c_1*x_1+...c_n*x_n is maximized. The c's are known scalars and I know n (10 in my case). I want my constraints to be such that the first (n-1)=9 x's should sum up to one and the last one should be less than 10. How do I use the sum to do so?
This is what I have tried:
SET C / c1 .... c2 /;
ALIAS(Assets,i)
Parameter Valuesforc(i) 'C values'/
*( here are my values typed in for all the C1)
POSITIVE VARIABLES
x(i);
EQUATIONS
Const1 First constraint
Const1 Second constraint
Obj The Object;
* here comes the trouble:
Const1 .. x(10) =l= 10
Const2 .. sum((i-1),x(i)) =e= 1
The code is not done all the way but I believe the essential setup is typed in. How do you make the summation to find x_1+x_1 + .... x_(n-1) and how do you refer to x_10?
Try this:
Const1 .. x('10') =l= 10;
Const2 .. sum(i$(ord(i)<card(i)),x(i)) =e= 1;
Edit: Here are some notes to explain what happens in Const2, especially in the "$(ord(i) < card(i))" part.
The "$" starts a condition, so it excludes certain elements of i from the sum (see: https://www.gams.com/latest/docs/UG_CondExpr.html#UG_CondExpr_TheDollarCondition)
The operator ord returns the relative position of a member in a set (see: https://www.gams.com/latest/docs/UG_OrderedSets.html#UG_OrderedSets_TheOrdOperator)
The operator card returns the number of elements in a set (see: https://www.gams.com/latest/docs/UG_OrderedSets.html#UG_OrderedSets_TheCardOperator)
So, all in all, there is a condition saying that all elements of i should be included in the sum except for the last one.

Summation under null set

I have a few collection ,and the intersection of these collections gives me a few new collection.
I want to have summation under these intersections , but some of these are null. And I get an error for my summation, for example
Set I/1*3/;
Set j/1*3/;
Set s(I,j)
1.(2,3)
2.(1,3)
3.(2);
Alias (I,i1,j);
Set intersection (I,i1,j);
Intersection (I,i1,j)= s(I,j)*s(i1,j);
Variable x(j) ,z;
Binary variable x;
Equation c1,c2;
C1(I)..sum(j$s(I,j),x(j))=e=z;
C2(I,i1)..sum(j$ intesection(i,I1,j),x(j))=g=1;
Model test /all/;
Solve test using lp minimizing z;
I have error for constraint 2 because intersection(2,3) is null ,and I have 0> 1
How can I write this summation?
I do not really understand, what you model here, but this way it runs without an error (there is still no feasible solution though because of equation C1('3')):
Set I/1*3/;
Set j/1*3/;
Set s(I,j) / 1.(2,3)
2.(1,3)
3.(2) /;
Alias (I,i1);
Set intersection (I,i1,j);
Intersection (I,i1,j)= s(I,j)*s(i1,j);
Variable x(j) ,z;
Binary variable x;
Equation c1,c2;
C1(I).. sum(j$s(I,j),x(j))=e=z;
C2(I,i1)$sum(j$ Intersection(i,I1,j),1)..
sum(j$ Intersection(i,I1,j),x(j))=g=1;
Model test /all/;
Solve test using mip minimizing z;

How to assign values randomly based on a percentage in SAS?

This question pertains to SAS. I need to generate a variable randomly, let's call it "species," for which 60% of the cases are 1's and the remaining 40% of cases are 0's. There are 15,000 cases of x_1 (where x_1 is a random, uniformly distributed variable) which need assignment of either 1 or 0. It's got to be generated with an if-then-do statement, right? So far, I have:
data species_list;
set work.species_list;
if x_1 <= 0.6 then do;
Species = 1;
end;
else if x_1 > 0.6 then do;
Species = 0;
end;
run;
This part is easy enough. But, I need the 1's and 0's to be randomly assigned to the 15,000 cases, not based on some inequality.
If x_1 is a random, uniformly distributed variable, then this inequality does distribute them 'randomly' (as much as can be done with a computer, anyway).
From what I recall, your inequality will work, more or less. It's not perfect; most likely your random number has a lower bound of 0 and an upper bound of 0.999999, so it's not quite going to give perfect 60/40 split, though with 15000 you probably will see a reasonably close match.
A somewhat better way is to use proc surveyselect. This doesn't require your x_1 variable.
proc surveyselect data=species_list out=species_out samprate=0.6 outall seed=12345;
run;
That would sample 60% and give them a 1, and the remaining 40% would be a 0. Easy as pie.
If you want to produce a random variable in SAS you can use the rand function.
You could use:
Species = ifn(rand("uniform") <= 0.6, 1, 0);
or:
x_1 = rand("uniform");
if x_1 <= 0.6 then Species = 1;
else Species = 0;
Depending on which one is more understandable to you.
rand(dist [, parameters]) produces a random number generated from one of several distributions.
ifn(condition, trueValue, falseValue) will return its second or third (numeric) argument depending on whether the condition evaluates to true or false.
It is not necessary to wrap your conditional statements in do; end; if you only want to run one statement.
If you want reproducable results you can provide a seed to the PRNG with call streaminit.