Added 08/09/2025
Textbook
lu_deb_sinha
Datasets
Description
A. Unconstrained and sensitive objective functions at both levels;
Dimension
{
"x": 1,
"y": 1,
"F": 1,
"G": 4,
"H": 0,
"f": 1,
"g": 0,
"h": 0
}
Solution
{
"optimality": "best_known",
"x": [0.2],
"y": [1.4],
"F": 1.13595399,
"G": [0.2,0.8,1.4,0.6],
"f": 1.18382613,
"g": []
}
Description
B. Unconstrained and sensitive objective function at lower-level alone;
Dimension
{
"x": 1,
"y": 1,
"F": 1,
"G": 4,
"H": 0,
"f": 1,
"g": 0,
"h": 0
}
Solution
{
"optimality": "best_known",
"x": [0.5],
"y": [1],
"F": 0,
"G": [0.5,0.5,1,1],
"f": 1.664544,
"g": []
}
Description
C. Unconstrained and sensitive objective function at upper-level alone;
Dimension
{
"x": 1,
"y": 1,
"F": 1,
"G": 4,
"H": 0,
"f": 1,
"g": 0,
"h": 0
}
Solution
{
"optimality": "best_known",
"x": [0.26],
"y": [1],
"F": 1.11826956,
"G": [0.26,0.74,1,1],
"f": 0.0576,
"g": []
}
Description
D. Constraint functions at both levels;
Dimension
{
"x": 2,
"y": 2,
"F": 1,
"G": 11,
"H": 0,
"f": 1,
"g": 3,
"h": 0
}
Solution
{
"optimality": "best_known",
"x": [10,192],
"y": [10,192],
"F": -192,
"f": -192,
"g": [0,4.5,633]
}
Description
E. Constraint functions at lower-level only;
Dimension
{
"x": 1,
"y": 2,
"F": 1,
"G": 6,
"H": 0,
"f": 1,
"g": 3,
"h": 0
}
Solution
{
"optimality": "unknown"
}
$title lu_deb_sinha
$onText
Finding Reliable Solutions in Bilevel Optimization Problems Under Uncertainties.
Zhichao Lu, Kalyanmoy Deb, Ankur Sinha.
In Proceedings of the Genetic and Evolutionary Computation Conference 2016.
https://www.egr.msu.edu/~kdeb/papers/c2016026.pdf
https://doi.org/10.1145/2908812.2908925
$offText
variables obj_val_upper, obj_val_lower, x, y;
equations obj_eq_upper, obj_eq_lower;
* Upper-level objective: F(x, y)
obj_eq_upper.. obj_val_upper =e=
2
- exp(-(((0.2*y - x + 0.6)/0.055)**0.4))
- 0.8*exp(-(sqr((0.15*y - 0.4 + x)/0.3)));
* Lower-level objective: f(x, y)
obj_eq_lower.. obj_val_lower =e=
2
- exp(-(((1.5*y - x)/0.055)**0.4))
- 0.8*exp(-(sqr((2*y - 3 + x)/0.5)));
* Bounds
x.lo = 0;
x.up = 1;
y.lo = 0;
y.up = 2;
* Solve
model lu_deb_sinha / all /;
$echo bilevel x min obj_val_lower y obj_eq_lower > "%emp.info%"
solve lu_deb_sinha using emp min obj_val_upper;
\subsection{lu\_deb\_sinha}
\label{subsec:lu_deb_sinha}
% Description
These are the six bilevel programs presented by Lu, Deb and Sinha~\cite{Lu2016}.
The first three test problems are unconstrained, but have sensitive objective functions.
The final three test problems are constrained such that the deterministic optimal solution(s) lie on one or more constraint boundary. Below we enumerate these problems and give the equation for case \texttt{a}.
% Cases
\begin{itemize}
\itemsep0em
\item[\texttt{a:}] Unconstrained and sensitive objective functions at both levels;
\item[\texttt{b:}] Unconstrained and sensitive objective function at lower-level alone;
\item[\texttt{c:}] Unconstrained and sensitive objective function at upper-level alone;
\item[\texttt{d:}] Uncertainty constraint functions at both levels;
\item[\texttt{e:}] Uncertainty constraint functions at lower-level only;
\item[\texttt{f:}] Uncertainty constraint functions at upper-level only;
\end{itemize}
% Equation
\begin{flalign*}
\minimise_{x, y} \quad
& 2
- \exp\left(-\left(\frac{0.2y-x+0.6}{0.055}\right)^{0.4}\right)
- 0.8\exp\left(-\left(\frac{0.15y-0.4+x}{0.3}\right)^{2}\right)\\
\subjectto \quad
& 0 \leq x \leq 1,\\
& 0 \leq y \leq 2,\\
& y \in \argmin_{y}
\left(
2
- \exp\left(-\left(\frac{1.5y-x}{0.055}\right)^{0.4}\right)
- 0.8\exp\left(-\left(\frac{2y-3+x}{0.5}\right)^{2}\right)
\right).
\end{flalign*}
classdef lu_deb_sinha
%{
Finding Reliable Solutions in Bilevel Optimization Problems Under Uncertainties.
Zhichao Lu, Kalyanmoy Deb, Ankur Sinha.
In Proceedings of the Genetic and Evolutionary Computation Conference 2016.
https://www.egr.msu.edu/~kdeb/papers/c2016026.pdf
https://doi.org/10.1145/2908812.2908925
%}
properties(Constant)
name = 'lu_deb_sinha';
category = 'textbook';
subcategory = '';
datasets = {
'lu_deb_sinha_a.txt'; % Unconstrained and sensitive objective functions at both levels;
'lu_deb_sinha_b.txt'; % Unconstrained and sensitive objective function at lower-level alone;
'lu_deb_sinha_c.txt'; % Unconstrained and sensitive objective function at upper-level alone;
'lu_deb_sinha_d.txt'; % Constraint functions at both levels;
'lu_deb_sinha_e.txt'; % Constraint functions at lower-level only;
'lu_deb_sinha_f.txt'; % Constraint functions at upper-level only;
};
paths = fullfile('bolib3', 'data', 'nonlinear', lu_deb_sinha.datasets);
end
methods(Static)
% Upper-level objective function
function obj = F(x, y, data)
switch data
case {'a','c'}
obj = 2.0 ...
- exp(-(((0.2*y(1) - x(1) + 0.6)/0.055) .^ 0.4)) ...
- 0.8 * exp(-(((0.15*y(1) - 0.4 + x(1))/0.3) .^ 2));
case 'b'
obj = (x(1) - 0.5).^2 + (y(1) - 1.0).^2;
case {'d','f'}
obj = -x(2);
case 'e'
obj = (( (y(2) - 50) / 30 ) .^ 2) ...
+ ((( (x(1) - 2.5) / 0.2 ) .^ 2));
otherwise
error('lu_deb_sinha must be parameterised by one of the six cases ''a'',''b'',''c'',''d'',''e'',''f''.');
end
end
% Upper-level inequality constraints
function val = G(x, y, data)
switch data
case {'a','b','c'}
val = [
x(1);
1 - x(1);
y(1);
2 - y(1)
];
case 'd'
t = (y(1)/14) + (16/7);
val = [
t*((x(1)-2)^2) - x(2);
x(2) - 12.5*t*(x(1)-5);
5*(x(1)+4 - t)*(x(1)+8 - t) - x(2);
4 + x(1);
10 - x(1);
100 + x(2);
200 - x(2);
4 + y(1);
10 - y(1);
100 + y(2);
200 - y(2)
];
case 'e'
val = [
x(1) - 2;
-x(1) + 3;
y(1) + 4;
-y(1) + 10;
y(2) + 100;
-y(2) + 200
];
case 'f'
t = x(1)/20;
val = [
y(1)*((t - 2)^2) + x(2);
x(2) - 12.5*y(1)*(t - 5);
5*(t + 4 - y(1))*(t + 8 - y(1)) - x(2);
x(1) + 80;
-x(1) + 200;
x(2) + 100;
-x(2) + 200;
y(1) - 2;
-y(1) + 4
];
otherwise
error('lu_deb_sinha must be parameterised by one of the six cases ''a'',''b'',''c'',''d'',''e'',''f''.');
end
end
% Upper-level equality constraints
function val = H(~, ~, ~)
val = [];
end
% Lower-level objective function
function obj = f(x, y, data)
switch data
case {'a','b'}
obj = 2.0 ...
- exp(-(((1.5*y(1) - x(1))/0.055) ^ 0.4)) ...
- 0.8 * exp(-(((2*y(1) - 3 + x(1))/0.5) ^ 2));
case 'c'
obj = (x(1) - 0.5)^2 ...
+ (y(1) - 1)^2;
case {'d','e'}
obj = -y(2);
case 'f'
obj = (((x(1) - 50)/28) ^ 2) ...
+ (((y(1) - 2.5)/0.2) ^ 2);
otherwise
error('lu_deb_sinha must be parameterised by one of the six cases ''a'',''b'',''c'',''d'',''e'',''f''.');
end
end
% Lower-level inequality constraints
function gvals = g(x, y, data)
switch data
case {'a','b','c','f'}
gvals = [];
case 'd'
t = (x(1)/14) + (16/7);
gvals = [
t*((x(1)-2)^2) - y(2);
y(2) - 12.5*t*(y(1)-5);
5*(y(1)+4 - t)*(y(1)+8 - t) - y(2)
];
case 'e'
gvals = [
x(1)*(y(1)-2)^2 - y(2);
y(2) - 12.5*x(1)*(y(1)-5);
5*(y(1)+4 - x(1))*(y(1)+8 - x(1)) - y(2)
];
otherwise
error('lu_deb_sinha must be parameterised by one of the six cases ''a'',''b'',''c'',''d'',''e'',''f''.');
end
end
% Lower-level equality constraints
function val = h(~, ~, ~)
val = [];
end
% read_data loads the Lu–Deb–Sinha case identifier from a text file.
function data = read_data(filepath)
% Validate the input is a valid filepath
if ~(ischar(filepath) || isstring(filepath))
error('read_data:InvalidPathType', ...
'filepath must be a character vector or string.');
end
filepath = char(filepath);
if isempty(strtrim(filepath))
error('read_data:EmptyPath', 'filepath is empty.');
end
if ~exist(filepath, 'file')
error('read_data:FileNotFound', 'File not found: %s', filepath);
end
% Read the data
try
raw = fileread(filepath);
catch ME
error('read_data:ReadError', ...
'Unable to read file "%s": %s', filepath, ME.message);
end
% Strip surrounding matching quotes if present
s = strtrim(raw);
if ~isempty(s) && numel(s) >= 2
if (s(1) == '"' && s(end) == '"') || (s(1) == '''' && s(end) == '''')
s = strtrim(s(2:end-1));
end
end
s = lower(s);
% Validate
valid = ['a','b','c','d','e','f'];
if isempty(s) || numel(s) ~= 1 || ~ismember(s, valid)
error('read_data:InvalidData', ...
'File "%s" must contain exactly one of {a,b,c,d,e,f}. Found: "%s"', ...
filepath, s);
end
% Return the case identifier
data = s;
end
% Dimension
function n = dimension(key, data)
% ---- Base dimensions ----
dims = struct( ...
'x', 1, ... % upper-level variables
'y', 1, ... % lower-level variables
'F', 1, ... % upper-level objective
'G', 4, ... % upper-level inequality constraints
'H', 0, ... % upper-level equality constraints
'f', 1, ... % lower-level objective
'g', 0, ... % lower-level inequality constraints
'h', 0); % lower-level equality constraints
% ---- Adjust for case ----
switch data
case 'd'
dims.x = 2; dims.y = 2; dims.G = 11; dims.g = 3;
case 'e'
dims.y = 2; dims.G = 6; dims.g = 3;
case 'f'
dims.x = 2; dims.G = 9;
end
% ---- Return result ----
if isempty(key)
n = dims;
else
if ~isfield(dims, key)
error('dimension:InvalidKey', ...
'Invalid key "%s". Must be one of x,y,F,G,H,f,g,h.', key);
end
n = dims.(key);
end
end
end
end
import os.path
import numpy as np
"""
Finding Reliable Solutions in Bilevel Optimization Problems Under Uncertainties.
Zhichao Lu, Kalyanmoy Deb, Ankur Sinha.
In Proceedings of the Genetic and Evolutionary Computation Conference 2016.
https://www.egr.msu.edu/~kdeb/papers/c2016026.pdf
https://doi.org/10.1145/2908812.2908925
"""
# Properties
name: str = "lu_deb_sinha"
category: str = "textbook"
subcategory: str = ""
datasets: list = [
'lu_deb_sinha_a.txt', # Unconstrained and sensitive objective functions at both levels;
'lu_deb_sinha_b.txt', # Unconstrained and sensitive objective function at lower-level alone;
'lu_deb_sinha_c.txt', # Unconstrained and sensitive objective function at upper-level alone;
'lu_deb_sinha_d.txt', # Constraint functions at both levels;
'lu_deb_sinha_e.txt', # Constraint functions at lower-level only;
'lu_deb_sinha_f.txt', # Constraint functions at upper-level only;
]
paths: list = [os.path.join('bolib3', 'data', 'nonlinear', dataset) for dataset in datasets]
case_error = TypeError("lu_deb_sinha must be parameterised by one of the six cases 'a', 'b', 'c', 'd', 'e', 'f'.")
# Methods
def F(x, y, data):
"""Upper-level objective function"""
match data:
case 'a' | 'c':
return (
2.0
- np.exp(-((0.2*y[0] - x[0] + 0.6)/0.055)**0.4)
- 0.8*np.exp(-((0.15*y[0] - 0.4 + x[0])/0.3)**2)
)
case 'b':
return (
(x[0] - 0.5)**2
+ (y[0] - 1.0)**2
)
case 'd' | 'f':
return -x[1]
case 'e':
return (
(((y[1] - 50)/30)**2)
+ (((x - 2.5)/0.2)**2)
)
raise case_error
def G(x, y, data):
"""Upper-level inequality constraints"""
match data:
case 'a' | 'b' | 'c':
return np.array([
x[0],
1 - x[0],
y[0],
2 - y[0]
])
case 'd':
t = (y[0]/14) + (16/7)
return np.array([
t*((x[0] - 2)**2) - x[1],
x[1] - 12.5*t*(x[0] - 5),
5*(x[0] + 4 - t)*(x[0] + 8 - t) - x[1],
4 + x[0],
10 - x[0],
100 + x[1],
200 - x[1],
4 + y[0],
10 - y[0],
100 + y[1],
200 - y[1],
])
case 'e':
return np.array([
+ x[0] - 2,
- x[0] + 3,
+ y[0] + 4,
- y[0] + 10,
+ y[1] + 100,
- y[1] + 200,
])
case 'f':
t = x[0]/20
return np.array([
y[0]*((t - 2)**2) + x[1],
x[1] - 12.5*y[0]*(t - 5),
5*(t + 4 - y[0])*(t + 8 - y[0]) - x[1],
+ x[0] + 80,
- x[0] + 200,
+ x[1] + 100,
- x[1] + 200,
+ y[0] - 2,
- y[0] + 4,
])
raise case_error
def H(x, y, data=None):
"""Upper-level equality constraints"""
return np.empty(0)
def f(x, y, data):
"""Lower-level objective function"""
match data:
case 'a' | 'b':
return (
2.0
- np.exp(-((1.5*y[0] - x[0])/0.055)**0.4)
- 0.8*np.exp(-((2*y[0] - 3 + x[0])/0.5)**2)
)
case 'c':
return (
(x[0] - 0.5)**2 +
(y[0] - 1)**2
)
case 'd' | 'e':
return -y[1]
case 'f':
return (
((x[0] - 50)/28)**2 +
((y[0] - 2.5)/0.2)**2
)
raise case_error
def g(x, y, data):
"""Lower-level inequality constraints"""
match data:
case 'a' | 'b' | 'c' | 'f':
return np.empty(0)
case 'd':
t = (x[0]/14) + (16/7)
return np.array([
t*(x[0] - 2)**2 - y[1],
y[1] - 12.5*t*(y[0] - 5),
5*(y[0] + 4 - t)*(y[0] + 8 - t) - y[1],
])
case 'e':
return np.array([
x[0]*(y[0] - 2)**2 - y[1],
y[1] - 12.5*x[0]*(y[0] - 5),
5*(y[0] + 4 - x[0])*(y[0] + 8 - x[0]) - y[1],
])
raise case_error
def h(x, y, data=None):
"""Lower-level equality constraints"""
return np.empty(0)
def read_data(filepath=''):
"""This problem must be parameterized by one of the six cases 'a', 'b', 'c', 'd', 'e', 'f' from the paper."""
with open(filepath, 'r') as file:
data = str(file.read()).lower().strip()
assert (data in ('a', 'b', 'c', 'd', 'e', 'f')), \
"The data for lu_deb_sinha must be one of the four cases ('a', 'b', 'c', 'd', 'e', 'f')."
return data
def dimension(key='', data='a'):
"""
If the argument 'key' is not specified, then:
- a dictionary mapping variable/function names (str) to the corresponding dimension (int) is returned.
If the first argument 'key' is specified, then:
- a single integer representing the dimension of the variable/function with the name {key} is returned.
"""
n = {
"x": 1, # Upper-level variables
"y": 1, # Lower-level variables
"F": 1, # Upper-level objective functions
"G": 4, # Upper-level inequality constraints
"H": 0, # Upper-level equality constraints
"f": 1, # Lower-level objective functions
"g": 0, # Lower-level inequality constraints
"h": 0, # Lower-level equality constraints
}
match data:
case 'd':
n["x"] = 2
n["y"] = 2
n["G"] = 11
n["g"] = 3
case 'e':
n["y"] = 2
n["G"] = 6
n["g"] = 3
case 'f':
n["x"] = 2
n["G"] = 9
if key in n:
return n[key]
return n