"If" statement on a variable

2,749 views
Skip to first unread message

Billie

unread,
Jan 28, 2009, 1:12:59 PM1/28/09
to AMPL Modeling Language
Dear All,

I'd be grateful if someone could give some advice promptly.

Simply I have a question: by using AMPL, is it possible to have an
"if" statement on a variable? More precisely, I was wondering if it
were possible to use a code like the following in an AMPL model:

var var_name =
if a < var_1 < b then formula(1) for "var_name";
else if b < var_1 < c then formula(2) for var_name";

where
- var_name is a function (which I need to define as a variable)
- var_1 is a variable
- a,b,c are known "limit" values for var_1
- formula(i) is an algebraic expression for the variable "var_name".

Looking forward to receiving your prompt reply.

Thanks in advance for your help.

Cheers,
Claudia

Robert Fourer

unread,
Jan 29, 2009, 11:18:09 AM1/29/09
to am...@googlegroups.com, Billie

You can use variables in the expression after "if", but unfortunately none of
the solvers currently hooked to AMPL will know what to do with the resulting
if-then-else expression. So as a practical matter, you will have to introduce
some zero-one variables and convert your model to a form that can be handled by
a solver for mixed-integer programming. I can't say how this can best be done
in your case, however, as it would depend on the values of a, b, and c and on
what the expressions for the formulas are.

Bob Fourer
4...@ampl.com

C B

unread,
Jan 29, 2009, 4:20:25 PM1/29/09
to 4...@ampl.com, am...@googlegroups.com
Hello Robert,

Thanks for your reply.

What about applying the following method: declaring the variable, and
then using a constraint - which includes an "if-then-else" statement -
to define it? My code would be as follows:

var Falfa {t in SBC};

subject to Falfa_polynomial {t in SBC}:
Falfa[t] = if (a0[t]<=PG_A<=a1[t]) then
b0[t]+(PG_A-a0[t])*(b1[t]-b0[t])/(a1[t]-a0[t])
else if (a1[t]<PG_A<=a2[t]) then b1[t]+(PG_A-a1[t])*(b2[t]-b1[t])/(a2[t]-a1[t])
else if (a2[t]<PG_A<=a3[t]) then b2[t]+(PG_A-a2[t])*(b3[t]-b2[t])/(a3[t]-a2[t]);

where:
- SBC is a set
- ai[t] and bi[t] are parameters defined in SBC
- PG_A is an indipendent variable (one of the outputs of my optimization probem)
- Falfa is a function of PG_A, which should be mathematically
represented by means of different polynomials depending on the values
PG_A assumes

May the above-mentioned code be correct and well- managed by AMPL, in
the context of a main optimization model (it's an OPTIMAL POWER FLOW
model)?

Looking forward to hearing back from you again soon.

Thanks in advance for your help.

Regards,
Claudia


2009/1/29, Robert Fourer <4...@ampl.com>:


--
Claudia Battistelli

St. Paul's United College at the University of Waterloo
196 Westmount Road North
Waterloo, Ontario, Canada N2L 3G5

Home Phone: (+1) 519-772-8666
Cell Phone: (+1) 519-498-7940

e-mail: claudia.b...@unina.it,
claudia.b...@gmail.com

Robert Fourer

unread,
Feb 1, 2009, 10:48:44 AM2/1/09
to am...@googlegroups.com, C B
Claudia,

A variable in the expression after "if" is not going to work in a
constraint, for the same reason that it does not work in a var declaration.
However, it appears you're trying to write a piecewise-linear function of
the variable PG_A, which is such a common case that AMPL has a special
expression for it, in terms of the breakpoints and slopes of the function.
You could say

var PG_A >= a0, <= a3;

var Falfa {t in SBC} = b0[t] + <<a1[t],a2[t];
(b1[t]-b0[t])/(a1[t]-a0),
(b2[t]-b1[t])/(a2[t]-a1[t]),
(b3[t]-b2[t])/(a3-a2[t])>> (PG_A,a0);

Inside the delimiters <<...>> are a list of breakpoints and a list of slopes
surrounding the breakpoints. The argument "(PG_A,a0)" indicates that this
is a piecewise-linear function of the variable PG_A, and that the function
has value 0 at a0; adding b0[t] causes it to have value b0[t] at a0, as
required.

You can specify a0[t] and a3[t] in place of a0 and a3, because each Falfa[t]
needs to be defined over the full range of possible values of PG_A.

See chapter 17 of the AMPL book for more on piecewise-linear functions.

Robert Fourer

unread,
May 1, 2013, 2:55:12 PM5/1/13
to am...@googlegroups.com

It doesn't work to use expressions like

 

   var phiZ {i in 1..dimx, j in 1..dimy, k in 1..n} =

      if (pz[k] < minz) then ...

 

where there is a variable in the condition between the "if" and the "then".  Some nonlinear solvers will attempt to evaluate the if-expressions and solve such a problem, but they will not be able to deal with the discontinuities in the slopes of these functions.

 

I should have said, "... you will have to introduce some zero-one variables and convert your model to a form that can be handled by a solver for linear mixed-integer programming."  This means replacing definitions like

 

   var zi {i in 1..n, j in 1..dimz} =

      if (pz[i] >= i + minz and pz[i] < i + 1 + minz) then 1 else 0;

 

with linear constraints on "var zi {...} binary;".  When you use one-dimensional piecewise-linear notation, AMPL does this for you, but that does not help when you are doing 3D interpolation.  Instead you might extend the ideas in the following post concerning 2D interpolation:

 

   http://groups.google.com/group/ampl/browse_thread/thread/ce5d9a5b57868f20/099a400a4a6176ea?lnk=gst&q=anyhow+to+specify+the+sos2#099a400a4a6176ea

 

The "SOS2" mentioned there is a way of specifying that out of an ordered set of variables, at most two adjacent ones can be nonzero.

 

Bob Fourer

am...@googlegroups.com

 

 

From: ying...@gmail.com [mailto:ying...@gmail.com]
Sent: Sunday, April 28, 2013 10:00 PM
To: am...@googlegroups.com
Cc: 'C B'; 4...@ampl.com
Subject: Re: [AMPL 2194] Re: "If" statement on a variable

 

Hi Robert,

 

I was having a similar problem with AMPL's if statements and I found this post. I'll really appreciate it if you could give me some helpful information.

 

In the code below, there is a 3D grid with dimensions: dimx, dimy, dimz and a phi value in each cell. px, py, pz are the coordinates of n points. What I want to do is to get the phi value at each point by interpolation.

 

param dimx;

param dimy;

param dimz;

param minx;

param miny;

param minz;

param phi {1..dimx, 1..dimy, 1..dimz};

param n;

 

var px;

var py;

var pz;

 

var phiZ {i in 1..dimx, j in 1..dimy, k in 1..n} =

if (pz[k] < minz) then phi[i,j,1]

else if (pz[k] >= minz and pz[k] < 1+minz) then phi[i,j,1] * (1-(pz[k]-minz)) + phi[i,j,2] * (pz[k]-minz)

etc.

 

var phiYZ {i in 1..dimx, j in 1..n} =

if (py[j] < miny) then phiZ[i,1,j]

else if (py[j] >= miny and py[j] < 1+miny) then phiZ[i,1,j] * (1-(py[i]-miny)) + phiZ[i,2,j] * (py[j]-miny)

etc.

 

However, this doesn't work. phiZ and phiYZ seem to be fixed after pz and py are initialized. I saw you saying "none of the solvers currently hooked to AMPL will know what to do with the resulting if-then-else expression", but I don't know how exactly AMPL treats these expressions. And you said "So as a practical matter, you will have to introduce some zero-one variables and convert your model to a form that can be handled by a solver for mixed-integer programming." Did you mean this:

 

var zi {i in 1..n, j in 1..dimz} =

if (pz[i] >= i + minz and pz[i] < i + 1 + minz) then 1

else 0;

 

var phiZ {i in 1..dimx, j in 1..dimy, k in 1..n} = sum (expression[k] * zi[k]);

 

I also tried the piecewise-linear function approach. It works for phiZ but not for phiYZ since the piecewise-linear function has variable phiZ in it.

 

Could you think of any solution to my problem? Thanks for your attention!

 

Best,

Lucy

Reply all
Reply to author
Forward
0 new messages