Quick subscript question

60 views
Skip to first unread message

jors...@gmail.com

unread,
Jul 20, 2022, 2:43:41 PM7/20/22
to AMPL Modeling Language
Hello AMPL community! I really need your help to solve this one:

I need to determine the value of a decision variable in a certain condition. However, this condition is related to the state of another variable one step behind, like this:

s.t. d {n in V, j in T}:
if S[n,j-1] < S[n,j] then D[n,j]<=0;

However, this error appears because there is no j=0, since it starts at 1:

error processing constraint ddd[1,1]:    
invalid subscript S[1,0]

How could I solve this?

AMPL Google Group

unread,
Jul 21, 2022, 8:33:25 AM7/21/22
to AMPL Modeling Language
You can index the constraint like this:

s.t. ddd {n in V, j in T: j > 1}: ...

Even with this change, however, it won't work to write your constraint as "if S[n,j-1] < S[n,j] then D[n,j] <= 0;", because AMPL looks for an expression rather than a constraint after "then". To get help with writing the constraint expression, provide the following information:
  • the AMPL definitions of S and D
  • the solver (or solvers) that you would like to use


--
Robert Fourer
am...@googlegroups.com
{#HS:1954870913-111088#}

jors...@gmail.com

unread,
Jul 22, 2022, 9:30:03 AM7/22/22
to AMPL Modeling Language
param t;
set T := {1..t};  
param N;
set VE := {1..N};    
var S {n in VE, j in T} default 0;    
var D {n in VE, j in T} >=0, <= 1;    

var D is a decision variable, defined by optimization. var S is calulated as a constraint at each time step, depending on other variables and parameters:

s.t. s1 {n in VE, j in T}:
S[n,j] = (if j = pi[n] then Si[n]+((ef*PcM[n]*a[n,j]*C[n,j]*Ta)/(B[n])) else 0);

Since this is a Nonlinearly COnstrained Optimization, I'm using SNOPT solver. 

Thanks Robert!

Message has been deleted

jors...@gmail.com

unread,
Jul 22, 2022, 9:42:01 AM7/22/22
to AMPL Modeling Language
Actually my problem is: if C[n,j] is > 0 at any time step "j", then D[n,j] should be zero for the subsequent timesteps. I'm using S[n,j] because if C[n,j] is higher than zero, then S[n,j] will be increased. So that was the way I was trying to solve this issue. 

But if there is any possibility to solve this with C[n,j] related to D[n,j] it should be more simple. Like this:

param t;
set T := {1..t};  
param N;
set VE := {1..N};    
var C {n in VE, j in T} >=0, <= 1;    #decision variable
var D {n in VE, j in T} >=0, <= 1;    #decision variable

s.t. logic {n in VE, j in T}:
if C[n,j] > 0 then D[n,j..T] = 0;

But the syntax "j..T" ^^ doesn't exists. So, after C receive any value higher than zero, D should be zero for all next timesteps. But unfortunately I couldn't find a way to do that. I really appreciate your help on this one!! 

AMPL Google Group

unread,
Jul 24, 2022, 1:53:57 PM7/24/22
to AMPL Modeling Language
You will need to move j..T into the constraint's indexing. Also to say that one constraint implies another constraint, you'll need to use the ==> logical operator. (The if-then syntax only works when there is an expression -- not a constraint -- after "then".) Then your constraint becomes:

s.t. logic {n in VE, j in T, k in j..t}:
   C[n,j] > 0 ==> D[n,k] = 0;

There is an experimental version of Gurobi, called x-gurobi, that will try to automatically transform this constraint to something that Gurobi can handle. New solvers COPT and HiGHS also have this transformation code in their AMPL interfaces. (They are all available in our solver downloads.) But if you want to use the regular version of Gurobi, CPLEX, or Xpress, you will need to introduce a binary (zero-one) variable for each constraint:

var Cpos {n in VE, j in T} binary;

Then you can change the constraints to

s.t. logic1 {n in VE, j in T}:
   C[n,j] > 0 ==> Cpos[n,j] = 1;
s.t. logic2 {n in VE, j in T, k in j..t}:
   Cpos[n,j] = 1 ==> D[n,k] = 0;

or equivalently,

s.t. logic1 {n in VE, j in T}:
   Cpos[n,j] = 0 ==> C[n,j] = 0;
s.t. logic2 {n in VE, j in T, k in j..t}:
   Cpos[n,j] = 1 ==> D[n,k] = 0;

Because this formulation has only constraints of the form "binary-variable = 0 ==> constraint" and "binary-variable = 1 ==> constraint", these are "indicator constraints" that can be handled directly by Gurobi, Xpress, or CPLEX. For other solvers, you can easily linearize these constraints; for example, "Cpos[n,j] = 0 ==> C[n,j] = 0" can be written equivalently as C[n,j] <= Cpos[n,j].


--
Robert Fourer
am...@googlegroups.com
{#HS:1954870913-111088#}
On Fri, Jul 22, 2022 at 1:42 PM UTC, AMPL Modeling Language <am...@googlegroups.com> wrote:
Actually my problem is: if C[n,j] is > 0 at any time step "j", then D[n,j] should be zero for the subsequent timesteps. I'm using S[n,j] because if C[n,j] is higher than zero, then S[n,j] will be increased. So that was the way I was trying to solve this issue.

But if there is any possibility to solve this with C[n,j] related to D[n,j] it should be more simple. Like this:

param t;
set T := {1..t};
param N;
set VE := {1..N};
var C {n in VE, j in T} >=0, <= 1; #decision variable
var D {n in VE, j in T} >=0, <= 1; #decision variable

s.t. logic {n in VE, j in T}:
if C[n,j] > 0 then D[n,j..T] = 0;

But the syntax "j..T" ^^ doesn't exists. So, after C receive any value higher than zero, D should be zero for all next timesteps. But unfortunately I couldn't find a way to do that. I really appreciate your help on this one!!

On Thu, Jul 21, 2022 at 12:33 PM UTC, AMPL Google Group <am...@googlegroups.com> wrote:
You can index the constraint like this:

s.t. ddd {n in V, j in T: j > 1}: ...

Even with this change, however, it won't work to write your constraint as "if S[n,j-1] < S[n,j] then D[n,j] <= 0;", because AMPL looks for an expression rather than a constraint after "then". To get help with writing the constraint expression, provide the following information:
  • the AMPL definitions of S and D
  • the solver (or solvers) that you would like to use


--
Robert Fourer
am...@googlegroups.com

jors...@gmail.com

unread,
Jul 25, 2022, 12:53:41 PM7/25/22
to AMPL Modeling Language
Dear Robert, I am very thankfull for your attention and precious help. Now I better understand the if-then syntax limited to expressions. Also, the solution by introducing a binary variable worked perfectly. However, the solvers you've mentioned didn't worked for me because my objective is nonlinear.

My way out was doing this:

s.t. logic1 {n in VE, j in T}:                           # Binary variable Cpos[n,j] that assumes zero when C[n,j] > 0;
Cpos[n,j] = (if C[n,j] > 0 then 1 else 0);
   
s.t. logic2 {n in VE, j in T, k in j..t}:              # New variable D[n,k] that assumes zero for "k in j..t" when C[n,j] > 0 (i.e., when Cpos[n,j] = 1);
if Cpos[n,j] = 1 then D[n,k] = 0;

Altough COPT, Gurobi and CPLEX accept logical expressions, it didn't worked due to nonlinearity of objective function. Even though SNOPT can't handle logic expressions, it worked fine by forcing a constraint in the if-then syntax, which in turn should be limited to expressions. 
Probably this isn't the optimal way to go, but it converged and the results are as expected.

Thank you again!

AMPL Google Group

unread,
Jul 25, 2022, 4:40:49 PM7/25/22
to AMPL Modeling Language
SNOPT is designed to optimize "smooth" functions, which are continuous functions that also have continuous derivatives. Given some if-then functions, it will try to use them, but it may converge and declare a solution to be optimal even though it is not actually even locally optimal.

Also SNOPT does not recognize integer variables. Any binary variable is treated as just a continuous variable with bounds 0 and 1 -- although of its values may come out to be 0 or 1 in the solution that is returned.

If you can tell that SNOPT is giving you the desired results anyway, then you can go ahead and use SNOPT as your solver. But to check the results, you should linearize the ==> constraints as I suggested, and then use a mixed-integer nonlinear (MINLP) solver that can handle zero-one variables. There are both local MINLP solvers (Knitro) and global MINLP solvers (BARON, Octeract, Lindo Global).


--
Robert Fourer
am...@googlegroups.com
{#HS:1954870913-111088#}
On Mon, Jul 25, 2022 at 4:53 PM UTC, AMPL Modeling Language <am...@googlegroups.com> wrote:
Dear Robert, I am very thankfull for your attention and precious help. Now I better understand the if-then syntax limited to expressions. Also, the solution by introducing a binary variable worked perfectly. However, the solvers you've mentioned didn't worked for me because my objective is nonlinear.

My way out was doing this:

s.t. logic1 {n in VE, j in T}: # Binary variable Cpos[n,j] that assumes zero when C[n,j] > 0;
Cpos[n,j] = (if C[n,j] > 0 then 1 else 0);

s.t. logic2 {n in VE, j in T, k in j..t}: # New variable D[n,k] that assumes zero for "k in j..t" when C[n,j] > 0 (i.e., when Cpos[n,j] = 1);
if Cpos[n,j] = 1 then D[n,k] = 0;

Altough COPT, Gurobi and CPLEX accept logical expressions, it didn't worked due to nonlinearity of objective function. Even though SNOPT can't handle logic expressions, it worked fine by forcing a constraint in the if-then syntax, which in turn should be limited to expressions.

Probably this isn't the optimal way to go, but it converged and the results are as expected.

Thank you again!

On Sun, Jul 24, 2022 at 5:53 PM UTC, AMPL Google Group <am...@googlegroups.com> wrote:
You will need to move j..T into the constraint's indexing. Also to say that one constraint implies another constraint, you'll need to use the ==> logical operator. (The if-then syntax only works when there is an expression -- not a constraint -- after "then".) Then your constraint becomes:

s.t. logic {n in VE, j in T, k in j..t}:
   C[n,j] > 0 ==> D[n,k] = 0;

There is an experimental version of Gurobi, called x-gurobi, that will try to automatically transform this constraint to something that Gurobi can handle. New solvers COPT and HiGHS also have this transformation code in their AMPL interfaces. (They are all available in our solver downloads.) But if you want to use the regular version of Gurobi, CPLEX, or Xpress, you will need to introduce a binary (zero-one) variable for each constraint:

var Cpos {n in VE, j in T} binary;

Then you can change the constraints to

s.t. logic1 {n in VE, j in T}:
   C[n,j] > 0 ==> Cpos[n,j] = 1;
s.t. logic2 {n in VE, j in T, k in j..t}:
   Cpos[n,j] = 1 ==> D[n,k] = 0;

or equivalently,

s.t. logic1 {n in VE, j in T}:
   Cpos[n,j] = 0 ==> C[n,j] = 0;
s.t. logic2 {n in VE, j in T, k in j..t}:
   Cpos[n,j] = 1 ==> D[n,k] = 0;

Because this formulation has only constraints of the form "binary-variable = 0 ==> constraint" and "binary-variable = 1 ==> constraint", these are "indicator constraints" that can be handled directly by Gurobi, Xpress, or CPLEX. For other solvers, you can easily linearize these constraints; for example, "Cpos[n,j] = 0 ==> C[n,j] = 0" can be written equivalently as C[n,j] <= Cpos[n,j].


--
Robert Fourer
am...@googlegroups.com

jors...@gmail.com

unread,
Aug 6, 2022, 11:36:45 AM8/6/22
to AMPL Modeling Language
I'm trying to do that but by using your suggestion results in an error:

Caution: Treating strict inequality constraint as a logical constraint. context: D[n,k] < >>> Cpos[n,j]; <<<

s.t. logic {n in VE, j in T}:
Cpos[n,j] >= C[n,j];

s.t. logic1 {n in VE, j in T, k in j..t}:
D[n,k] < Cpos[n,j];

AMPL Google Group

unread,
Aug 7, 2022, 7:30:59 PM8/7/22
to AMPL Modeling Language
These constraints ("logic" and "logic1") are different from what I previously suggested. You do need to use >= or <= or = in your constraint, and not > or <. Notice that when I used a > in my (different) constraint logic1, I immediately rewrote it in an equivalent way that did not use a > operator.

Also if the variables are defined the same as before, as

var D {n in VE, j in T} >= 0, <= 1
var Cpos {n in VE, j in T} binary;

then if Cpos[n,j] equals 0, the constraint logic1 becomes "D[n,k] < 0", which is impossible since D is a nonnegative variable. Thus it is never feasible for Cpos[n,j] to equal 0. This suggests that "D[n,k] < Cpos[n,j]" is not really giving the constraint that you want.


--
Robert Fourer
am...@googlegroups.com
{#HS:1954870913-111088#}
On Sat, Aug 6, 2022 at 3:36 PM UTC, AMPL Modeling Language <am...@googlegroups.com> wrote:
I'm trying to do that but by using your suggestion results in an error:

Caution: Treating strict inequality constraint as a logical constraint. context: D[n,k] < >>> Cpos[n,j]; <<<

s.t. logic {n in VE, j in T}:
Cpos[n,j] >= C[n,j];

s.t. logic1 {n in VE, j in T, k in j..t}:
D[n,k] < Cpos[n,j];

On Mon, Jul 25, 2022 at 8:40 PM UTC, AMPL Google Group <am...@googlegroups.com> wrote:
SNOPT is designed to optimize "smooth" functions, which are continuous functions that also have continuous derivatives. Given some if-then functions, it will try to use them, but it may converge and declare a solution to be optimal even though it is not actually even locally optimal.

Also SNOPT does not recognize integer variables. Any binary variable is treated as just a continuous variable with bounds 0 and 1 -- although of its values may come out to be 0 or 1 in the solution that is returned.

If you can tell that SNOPT is giving you the desired results anyway, then you can go ahead and use SNOPT as your solver. But to check the results, you should linearize the ==> constraints as I suggested, and then use a mixed-integer nonlinear (MINLP) solver that can handle zero-one variables. There are both local MINLP solvers (Knitro) and global MINLP solvers (BARON, Octeract, Lindo Global).


--
Robert Fourer
am...@googlegroups.com
Reply all
Reply to author
Forward
0 new messages