Initializing help system before first use

Nominal values: centered and uncentered uncertainty

The nominal value of an uncertain represents its default value, a real-valued number which is the expected or non-robust version of the uncertain. In the examples so far, all uncertainty has been treated so that the nominal value of each uncertain is zero, and in effect the uncertain has been treated as an error term. The default value or center of an uncertain can be shifted by specifying a nominal value that is different from zero. Using nominal values has the advantage that they allow one to work on both the robust optimization model and on a deterministic one obtained by fixing the uncertains (to their nominal values) in the same model.

Before detailing the use cases and rules when working with nominal values of uncertains, let us give an example on centered and uncentered uncertains.

I. Using zero centered uncertainty, where an uncertain is modelled as a zero centered error, i.e., uncertainty with zero nominal value:

(5+uncertain) x ≤ 1

is expressed as:

declarations
  x : mpvar
  u : uncertain
end-declarations

(5+u)*x <= 1

II. Uncertainty as coefficient, where the uncertain is modelled as a coefficient, i.e. an uncertain coefficient with 5 as its nominal value:

(5+uncertain) x ≤ 1

can also be expressed as:

declarations
  x : mpvar
  u : uncertain
end-declarations

u:= 5                             ! Setting the nominal value
u*x <= 1

As the example above shows, a nominal value is set using the assignment operator ':='. It is important to distinguish this from the equal operator '=', which would fix the value of the uncertain to the given value instead.

The price of robustness

Either when using zero-centered uncertains or when setting up nominal values, it is possible to solve the model with the uncertainty removed, i.e. all uncertain coefficients being fixed to their nominal values. This makes it possible to calculate the cost of having uncertainty in the model (often referred to as the price of robustness), as well as to check whether the model is feasible without the added uncertainty. The next example shows how to solve with all uncertains fixed to their nominal values.

  declarations
    x : mpvar
    u : uncertain
  end-declarations

  0 <= u
  u <= 3

  (1+u)*x <= 1

  maximize(XPRS_NOMINAL, x)
  nominal_objective := getobjval
  writeln("Objective at nominal values:", nominal_objective );

  maximize(x)
  robust_objective := getobjval
  writeln("Robust objective:", robust_objective );
  writeln("Price of robustness:", nominal_objective - robust_objective );
  writeln("Worst value of uncertain:", u.sol)

The output of the model is:

Objective at nominal values: 1
Robust objective: 0.25
Price of robustness: 0.75

When no nominal value is defined for an uncertain, the default nominal value of zero is used.

Working with nominal values

The workings of nominal values are defined by two simple rules.

Rule 1: setting a nominal value is shifting the domain of the uncertain.

Setting a nominal value for an uncertain to u:=a replaces all later occurrences of u with u+a.

The following simple model solves to x = 0.5:

declarations
 x : mpvar
 u : uncertain
end-declarations

0 <= u
     u <= 1

(1+u)*x <= 1

maximize(x)

as the worst case is when u takes its upper bound of 1.

Changing the nominal value of u to say 2, u is replaced by u+2 and the model solves to 0.25 instead.

declarations
 x : mpvar
 u : uncertain
end-declarations

0 <= u
     u <= 1

u := 2                   ! Shifts the center of the uncertain

(1+u)*x <= 1

maximize(x)

The uncertain u still takes its upper bound of 1, but the constraint loaded now reads (1+u+2)x≤1 with u taking on its upper bound of 1.

Rule2: a changed nominal value only affects robust and uncertainty set constraints that are defined after it has been assigned.

This behavior is best understood when put into analogy with how real-valued parameters behave. Looking at the example of rule 1, this behavior is already observed: changing the nominal value has only affected the robust constraint but not the bounds declared before this point.

declarations
 x : mpvar
 r : real
end-declarations

r := 3

C1 := (1+r)*x <= 1

r := 5

maximize(x)

The model solves to x = 0.25, that is the actual value of r at the time of declaring the constraint C1 has been used (3), and redefining it later had no effect on the constraint. This behavior is reproduced when working with the nominal values of uncertains.

declarations
 y : mpvar
 u : uncertain
end-declarations

u := 3

(1+u)*y <= 1

u := 5

maximize(XPRS_NOMINAL, y)

The nominal version of the model where the uncertain coefficients are used solves (notice the nominal argument to maximize) to the same as when real valued coefficients are used: y = 0.25.

These rules offer significant flexibility on how to use the nominal values for uncertains, but care must be taken and the effects of rule 2 should always be kept in mind.

Using nominal values to shift the uncertainty set

Nominal values can be used to shift an uncertain coefficient while keeping its effect around the nominal values the same. Consider the following example:

declarations
 x,y : mpvar
 e,f : uncertain
end-declarations

e^2 + f^2 <= 2      ! An ellipsoidal uncertainty constraint

e*x + f*y <= 1

maximize(x + y)

The solution to the model is x=0.5, y=0.5. The values of uncertains e and f can take their value from a ball of radius sqrt() 2. When nominal values are added, the model becomes:

declarations
 x,y : mpvar
 e,f : uncertain
end-declarations

e^2 + f^2 <= 2

e := 1
f := 1

e*x + f*y <= 1

maximize(x + y)

The solution moves to x=0.25, y=0.25. To explore the reasons for this change, let us substitute the effect of the nominal values directly into the problem:

declarations
 x,y : mpvar
 e,f : uncertain
end-declarations

e^2 + f^2 <= 2

(e+1)*x + (f+1)*y <= 1

maximize(x + y)

The range of uncertains has remained the same, but in the robust constraint the values around which they are centered shift accordingly to the nominal values.

Using nominal valued uncertains as coefficients

Uncertains can be assigned a nominal value before the first time they are used, however they may behave in a way that is not expected. Consider three versions of the same model:

Case 1 Case 2 Case 3
No nominal values are set Nominal values are set to 1 Nominal values are set to different values
declarations
x,y : mpvar
e,f : uncertain
end-declarations
e + f ≤ 2
e*x + f*y ≤ 1
maximize(x + y)
 
 
declarations
x,y : mpvar
e,f : uncertain
end-declarations
e := 1
f := 1
e + f ≤ 2
e*x + f*y ≤ 1
maximize(x + y)
declarations
x,y : mpvar
e,f : uncertain
end-declarations
e := 2
f := 5
e + f ≤ 2
e*x + f*y ≤ 1
maximize(x + y)

All three versions of the model solve to the same solution of x = y = 0.5;

The reasons behind this may not be immediately obvious but become clear if we write out the effect of rule 1 on, say, the 3rd case:

Case 3 becomes which is
declarations
x,y : mpvar
e,f : uncertain
end-declarations
e := 2
f := 5
e + f ≤ 2
e*x + f*y ≤ 1
maximize(x + y)
declarations
x,y : mpvar
e,f : uncertain
end-declarations
e+2 + f+5 ≤ 2
(e+2)*x + (f+5)*y ≤ 1
maximize(x + y)
 
 
declarations
x,y : mpvar
e,f : uncertain
end-declarations
e + f ≤ -5
(e+2)*x + (f+5)*y ≤ 1
maximize(x + y)
 
 

As the shifts are also applied to the uncertain constraints (including bounds), in the example they cancel each other out: the linear robust constraints and the corresponding error constraints have been shifted together.

However, there is a very real difference should the model be solved using its nominal values. To demonstrate this, let us explicitly write out the nominal equivalent for the 3 cases:

The nominal equivalent of case 1: The nominal equivalent of case 2: The nominal equivalent of case 3:
declarations
x,y : mpvar
e,f : uncertain
end-declarations
0*x + 0*y ≤ 1
maximize(x + y)
declarations
x,y : mpvar
e,f : uncertain
end-declarations
1*x + 1*y ≤ 1
maximize(x + y)
declarations
x,y : mpvar
e,f : uncertain
end-declarations
2*x + 5*y ≤ 1
maximize(x + y)
is unbounded. solves to x=1 and y=0. solves to x=0.5 and y=0.