Skip to content

Problem definition

Wrap an objective function with make_problem, or implement the Problem interface. The guide explains scalar and vectorized evaluation, bounds, encodings, and constraints.

Stable public API. The 1.x compatibility policy defines the supported surface; import from the public facade shown below.

from vamos import Problem, make_problem

Solve your own problem · Built-in problem catalogue · Problem discovery

make_problem(fn, *, n_var, n_obj, bounds=None, xl=None, xu=None, vectorized=False, encoding, name=None, constraints=None, n_constraints=0)

Create a VAMOS-compatible problem from a plain Python function.

This is the friendliest way to define a custom optimization problem. Your function receives decision variables and returns objective values -- VAMOS handles bounds, protocol adaptation, and optional batched execution.

Parameters:

Name Type Description Default
fn callable

Objective function.

  • Scalar mode (default, vectorized=False): receives a 1-D array of shape (n_var,) and returns a list or array of n_obj objective values.
  • Vectorized mode (vectorized=True): receives a 2-D array of shape (N, n_var) and returns an array of shape (N, n_obj).
required
n_var int

Number of decision variables.

required
n_obj int

Number of objectives to minimize.

required
bounds sequence of (lower, upper) tuples

Per-variable bounds, e.g. [(0, 1), (0, 5)]. Must have length n_var. Mutually exclusive with xl / xu.

None
xl float or array - like

Lower / upper bounds for all variables. A scalar applies the same bound to every variable. Mutually exclusive with bounds.

None
xu float or array - like

Lower / upper bounds for all variables. A scalar applies the same bound to every variable. Mutually exclusive with bounds.

None
vectorized bool

If False VAMOS evaluates your scalar function one row at a time for compatibility. Set True only when your function already handles batches directly for real vectorized performance.

False
encoding str

Variable encoding: "real", "binary", "integer", "permutation", or "mixed".

required
name str

Human-readable name shown in logs and results. Defaults to the function name.

None
constraints callable

Constraint function following the same signature convention as fn. Must return n_constraints values where g(x) <= 0 is feasible.

None
n_constraints int

Number of constraint values. Required when constraints is provided.

0

Returns:

Type Description
FunctionalProblem

A problem object ready to pass to vamos.optimize().

Raises:

Type Description
TypeError

If fn is not callable.

ValueError

If bounds and xl/xu are both provided, if bounds length does not match n_var, or if n_constraints > 0 but no constraints callable is given.

Examples:

Minimal two-objective problem::

from vamos import make_problem, optimize

problem = make_problem(
    lambda x: [x[0], 1 - x[0] ** 0.5],
    n_var=2, n_obj=2,
    bounds=[(0, 1), (0, 1)],
    encoding="real",
)
result = optimize(problem, algorithm="nsgaii", max_evaluations=2000)

Vectorized for better performance::

import numpy as np

def my_objectives(X):
    f1 = X[:, 0]
    f2 = 1 - np.sqrt(X[:, 0])
    return np.column_stack([f1, f2])

problem = make_problem(
    my_objectives,
    n_var=2, n_obj=2,
    bounds=[(0, 1), (0, 1)],
    vectorized=True,
    encoding="real",
)

With constraints (g(x) <= 0 is feasible)::

problem = make_problem(
    lambda x: [x[0] + x[1], x[0] * x[1]],
    n_var=2, n_obj=2,
    bounds=[(0, 5), (0, 5)],
    encoding="real",
    constraints=lambda x: [x[0] + x[1] - 4],
    n_constraints=1,
)

Problem

Base class for class-based custom optimization problems.

Subclass this when your problem needs state — a dataset, distance matrix, simulator, or any data set up in __init__.

Required: set n_var, n_obj, xl, xu in __init__. Optional: override encoding and n_constraints as class-level attributes (not in __init__).

Example — unconstrained::

import numpy as np
from vamos import Problem, optimize

class MyProblem(Problem):
    def __init__(self):
        self.n_var = 3
        self.n_obj = 2
        self.xl = np.zeros(3)
        self.xu = np.ones(3)

    def objectives(self, X: np.ndarray) -> np.ndarray:
        # X: (N, n_var) batch of candidate solutions
        f1 = np.sum(X ** 2, axis=1)
        f2 = np.sum((X - 1) ** 2, axis=1)
        return np.column_stack([f1, f2])

result = optimize(MyProblem(), algorithm="nsgaii", max_evaluations=5000)

Example — constrained::

class MyConstrainedProblem(Problem):
    n_constraints = 1          # declare at class level

    def __init__(self):
        self.n_var = 3
        self.n_obj = 2
        self.xl = np.zeros(3)
        self.xu = np.ones(3)

    def objectives(self, X):
        f1 = np.sum(X ** 2, axis=1)
        f2 = np.sum((X - 1) ** 2, axis=1)
        return np.column_stack([f1, f2])

    def constraints(self, X):
        # Sign convention: g(x) <= 0 means feasible.
        g = np.sum(X, axis=1) - 2.0   # sum(x) <= 2
        return g.reshape(-1, 1)

encoding = 'real' class-attribute instance-attribute

Variable encoding. Supported values: "real", "integer", "binary", "permutation", "mixed". Default: "real".

n_constraints = 0 class-attribute instance-attribute

Number of inequality constraints. Default: 0 (unconstrained).

constraints(X)

Compute constraint violations for a batch of solutions.

Override this method when your problem has inequality constraints.

Parameters:

Name Type Description Default
X ndarray

Decision matrix of shape (N, n_var).

required

Returns:

Type Description
ndarray | None

Constraint array of shape (N, n_constraints) where negative values indicate feasibility, or None for unconstrained problems.

evaluate(X, out)

Framework evaluation entry point. Override :meth:objectives (and optionally :meth:constraints) instead of this method.

objectives(X)

Compute objective values for a batch of solutions.

Override this method in your subclass.

Parameters:

Name Type Description Default
X ndarray

Decision matrix of shape (N, n_var).

required

Returns:

Type Description
ndarray

Objective array of shape (N, n_obj) to minimize. A single-objective problem may return a 1-D array of length N.