2. Problem#

2.1. What is the Problem#

Problem is the foundational interface for UQPyL. It integrates all elements needed to define and solve an analysis or optimization problem.

A problem instance includes:

  1. Decision Variables: Information about the decision dimension, variable names, ranges, and types.

  2. Problem Function: Python functions that map decision variables to output values, including objectives and/or constraints.

2.2. Overview of Problem class#

The UQPyL.problems module provides a Problem class as a container for all essential information required to define a problem instance.

Here is the API reference of the Problem class.


2.3. Class Problem#

The Problem class is designed to define optimization problems. It extends the abstract base class ProblemABC and allows users to specify custom objective and constraint functions.

Constructor

__init__(nInput, nOutput, ub, lb, objFunc, conFunc, evaluate,
         conWgt, varType, varSet, optType, xLabels, yLabels, name)

Parameters

  • nInput (int): Number of input variables

  • nOutput (int): Number of output variables

  • ub (int, float, list, ndarray): Upper bounds

  • lb (int, float, list, ndarray): Lower bounds

  • objFunc (callable): User objective function

  • conFunc (callable): User constraint function

  • evaluate (callable): User evaluation function

  • conWgt (list): Constraint weights

  • varType (list): Variable types (0: continuous, 1: int, 2: discrete)

  • varSet (dict): Discrete variable sets

  • optType (str/list): Optimization type (‘min’ or ‘max’)

  • xLabels (list): Input variable labels

  • yLabels (list): Objective labels

  • name (str): Problem name

Methods

2.3.1. objFunc#

Compute objective values for a batch of samples.

Parameters

  • X (2D ndarray): Input samples

Returns

  • 2D ndarray: Objective values

2.3.2. conFunc#

Compute constraint values.

Parameters

  • X (2D ndarray): Input samples

Returns

  • 2D ndarray: Constraint values

2.3.3. evaluate#

Calculate both objective and constraints.

Returns

  • dict: {'objs': ndarray, 'cons': ndarray}

2.4. How to define a problem#

Below is a modified Rosenbrock function with constraints:

../_images/Problem1.svg

Compared to the original Rosenbrock:

  • It adds a constraint: \(x_1^2 + x_2^2 + x_3^2 ≥ 4\)

  • It changes variable types: - x1: continuous - x2: integer - x3: discrete

Example code:

from UQPyL.problems import Problem

# Objective function (vectorized)
def objFunc(X):
    objs = (100 * (X[:, 2] - X[:, 1]**2)**2
            + 100 * (X[:, 1] - X[:, 0]**2)**2
            + (1 - X[:, 1])**2
            + (1 - X[:, 0])**2)
    return objs[:, None]


# Single-run version using decorator
from UQPyL.problems import singleFunc

@singleFunc
def objFunc_(X):
    obj = (100 * (X[2] - X[1]**2)**2
           + 100 * (X[1] - X[0]**2)**2
           + (1 - X[1])**2
           + (1 - X[0])**2)
    return obj

# Constraint function (vectorized)
def conFunc(X):
    cons = X[:, 0]**2 + X[:, 1]**2 + X[:, 2]**2 - 4
    return cons[:, None]

# Variable settings
nInput = 3
nOutput = 1
ub = [10, 10, 10]
lb = [0, 0, 0]
varType = [0, 1, 2]
varSet = {2: [2, 3.4, 5.1, 7]}
optType = 'min'
xLabels = ['x1', 'x2', 'x3']
yLabels = ['obj1']
name = 'Rosenbrock'

# Build problem instance
problem = Problem(
    nInput=nInput,
    nOutput=nOutput,
    objFunc=objFunc,
    conFunc=conFunc,
    ub=ub,
    lb=lb,
    varType=varType,
    varSet=varSet,
    optType=optType,
    xLabels=xLabels,
    yLabels=yLabels,
    name=name
)

# Optimization example using GA
from UQPyL.optimization.single_objective import GA

ga = GA()
ga.run(problem=problem)

2.5. Using evaluate to replace objFunc and conFunc#

Some practical problems may not be convenient to separate into objFunc and conFunc. In such cases, UQPyL recommends defining everything inside the evaluate function.

Example:

../_images/Problem1.svg
def evaluate(X):
    # Compute objective
    objs = (100 * (X[:, 2] - X[:, 1]**2)**2
            + 100 * (X[:, 1] - X[:, 0]**2)**2
            + (1 - X[:, 1])**2
            + (1 - X[:, 0])**2)

    # Compute constraint
    cons = X[:, 0]**2 + X[:, 1]**2 + X[:, 2]**2 - 4

    # Return dictionary
    return {'objs': objs[:, None], 'cons': cons[:, None]}

Single-run mode (using @singleEval):

from UQPyL.problems import singleEval

@singleEval
def evaluate(x):
    obj = (100 * (x[2] - x[1]**2)**2
           + 100 * (x[1] - x[0]**2)**2
           + (1 - x[1])**2
           + (1 - x[0])**2)
    con = x[0]**2 + x[1]**2 + x[2]**2 - 4

    return {'objs': obj, 'cons': con}

Remaining setup is the same:

nInput = 3
nOutput = 1
ub = [10, 10, 10]
lb = [0, 0, 0]

varType = [0, 1, 2]
varSet = {2: [2, 3.4, 5.1, 7]}
optType = 'min'

xLabels = ['x1', 'x2', 'x3']
yLabels = ['obj1']
name = 'Rosenbrock'

problem = Problem(
    nInput=nInput,
    nOutput=nOutput,
    evaluate=evaluate,
    ub=ub,
    lb=lb,
    varType=varType,
    varSet=varSet,
    optType=optType,
    xLabels=xLabels,
    yLabels=yLabels,
    name=name
)

Note

Problem.evaluate returns a Python dictionary with two keys: 'objs' and 'cons'. Access them as:

res['objs'], res['cons']

2.6. Benchmark Problems#

Optimization problems in real applications often lack known solutions. Benchmark problems provide standardized evaluation targets with known behavior.

UQPyL includes a wide set of benchmark problems.

2.7. Single-objective Benchmarks#

Name

Formula

Optimal Solution

Optima

Sphere

../_images/Sphere.svg

(0, 0, 0 … 0)

0.0

Schwefel_2_22

../_images/Schwefel_2_22.svg

(0, 0, 0 … 0)

0.0

Schwefel_1_22

../_images/Schwefel_1_22.svg

(0, 0, 0 … 0)

0.0

Schwefel_2_21

../_images/Schwefel_2_21.svg

(0, 0, 0 … 0)

0.0

Schwefel_2_26

../_images/Schwefel_2_26.svg

(420.9687 … 420.9687)

-12569.5

Rosenbrock

../_images/Rosenbrock.svg

(0, 0, 0 … 0)

0.0

Step

../_images/Step.svg

(1, 1, 1 … 1)

0.0

Quartic

../_images/Quartic.svg

(1, 1, 1 … 1)

0.0

Rastrigin

../_images/Rastrigin.svg

(0, 0, 0 … 0)

0.0

Ackley

../_images/Ackley.svg

(0, 0, 0 … 0)

0.0

Griewank

../_images/Griewank.svg

(0, 0, 0 … 0)

0.0

Bent_Cigar

../_images/Bent_Cigar.svg

(0, 0, 0 … 0)

0.0

Discus

../_images/Discus.svg

(0, 0, 0 … 0)

0.0

Weierstrass

../_images/Weierstrass.svg

(0, 0, 0 … 0)

0.0

2.8. Multi-objective Benchmarks#

Name

Objectives

Pareto Front

Feature

ZDT1

2

Line

Convex

ZDT2

2

Line

Concave

ZDT3

2

Line

Disconnected

ZDT4

2

Line

Convex

ZDT6

2

Line

Concave

DTLZ1

>=3

Surface

Multimodal

DTLZ2

>=3

Surface

Single-peaked

DTLZ3

>=3

Surface

Multimodal

DTLZ4

>=3

Surface

Multimodal

DTLZ5

>=3

Line

Multimodal

DTLZ6

>=3

Line

Multimodal

DTLZ7

>=3

Discrete Surface

Multimodal

All benchmark problems are available under:

  • UQPyL.problems.single_objective

  • UQPyL.problems.multi_objective

Example:

from UQPyL.problems.single_objective import Sphere

problem = Sphere(nInput=20, ub=10, lb=-10)