Skip to content

Model API Reference

Model

A symbolic optimization model combining an objective and constraints.

The Model class represents a structured symbolic optimization problem. It contains an objective, a collection of Constraint objects, and an Environment that scopes all variables used in the model.

Models can be constructed implicitly by allowing the model to create its own private environment, or explicitly by passing an environment. If constructed inside an active Environment context, that context is used automatically.

Parameters:

  • name (str, default: None ) –

    An optional name assigned to the model for identification and debugging.

  • sense (Sense, default: Sense.MIN ) –

    The optimization sense - Sense.MIN to minimize or Sense.MAX to maximize the objective function.

  • env (Environment, default: None ) –

    The environment in which variables and expressions are created. If not provided, the model will either use the current context (if active), or create a new private environment.

Attributes:

Examples:

Basic usage:

>>> from luna_model import Model, Variable, Sense
>>> model = Model("MyModel", sense=Sense.MAX)
>>> x = model.add_variable("x")
>>> y = model.add_variable("y")
>>> model.objective = x * y + x
>>> model.constraints += x >= 0
>>> model.constraints += y <= 5
>>> print(model)
Model: MyModel
Maximize
  x * y + x
Subject To
  c0: x >= 0
  c1: y <= 5
Binary
  x y

With explicit environment:

>>> from luna_model import Environment
>>> env = Environment()
>>> model = Model("ScopedModel", env=env)
>>> x = model.add_variable("x")
>>> model.objective = x * x
>>> print(model)
Model: ScopedModel
Minimize
  x
Binary
  x

Serialization:

>>> blob = model.encode()
>>> restored = Model.decode(blob)
>>> print(restored.name)
ScopedModel

name: str property writable

Get or set the model's name.

Returns:

  • str

    The name of the model.

Examples:

>>> model = Model("MyModel")
>>> model.name
'MyModel'
>>> model.name = "UpdatedModel"
>>> model.name
'UpdatedModel'

sense: Sense property writable

Get or set the model's optimization sense.

The sense indicates whether the objective function is to be minimized or maximized.

Returns:

  • Sense

    The optimization sense (Sense.MIN or Sense.MAX).

Examples:

>>> model = Model(sense=Sense.MIN)
>>> model.sense
<Sense.MIN: 'Minimize'>
>>> model.sense = Sense.MAX
>>> model.sense
<Sense.MAX: 'Maximize'>

objective: Expression property writable

Get or set the model's objective function.

The objective function is the expression to be optimized (minimized or maximized).

Returns:

  • Expression

    The objective function expression.

Examples:

>>> model = Model()
>>> x = model.add_variable("x")
>>> y = model.add_variable("y")
>>> model.objective = 2 * x + 3 * y
>>> model.objective.degree()
1

constraints: ConstraintCollection property writable

Get or set the model's constraint collection.

Returns:

Examples:

>>> model = Model()
>>> x = model.add_variable("x")
>>> model.constraints += x <= 5
>>> len(model.constraints)
1

environment: Environment property

Get the model's environment.

Returns:

  • Environment

    The environment containing all variables in this model.

num_variables: int property

Get the number of variables in the model.

Returns:

  • int

    The total number of variables.

Examples:

>>> model = Model()
>>> x = model.add_variable("x")
>>> y = model.add_variable("y")
>>> model.objective += x + y
>>> model.num_variables
2

num_constraints: int property

Get the number of constraints in the model.

Returns:

  • int

    The total number of constraints.

Examples:

>>> model = Model()
>>> x = model.add_variable("x")
>>> model.constraints += x <= 5
>>> model.num_constraints
1

variables() -> list[Variable]

Get all variables in the model.

Returns:

Examples:

>>> model = Model()
>>> x = model.add_variable("x")
>>> y = model.add_variable("y")
>>> model.objective += x + y
>>> vars = model.variables()
>>> len(vars)
2

vtypes() -> list[Vtype]

Get the types of all variables in the model.

Returns:

  • list[Vtype]

    A list of variable types in the same order as variables().

Examples:

>>> model = Model()
>>> x = model.add_variable("x", vtype=Vtype.BINARY)
>>> y = model.add_variable("y", vtype=Vtype.INTEGER)
>>> model.objective += x + y
>>> model.vtypes()
[<Vtype.BINARY: 'Binary'>, <Vtype.INTEGER: 'Integer'>]

set_sense(sense: Sense) -> None

Set the model's sense.

Deprecated in favor of the direct attribute setter. Will be removed in a following release.

add_variable(name: str, vtype: Vtype = Vtype.BINARY, lower: float | type[Unbounded] | None = None, upper: float | type[Unbounded] | None = None, with_fallback: bool = False) -> Variable

Add a variable to the model.

Creates a new variable and adds it to the model's environment. If the variable name already exists and with_fallback=True, a unique name will be generated.

Parameters:

  • name (str) –

    The name of the variable.

  • vtype (Vtype, default: Vtype.BINARY ) –

    The type of the variable (BINARY, SPIN, INTEGER, or REAL).

  • lower (float or Unbounded, default: None ) –

    The lower bound for the variable. Only applicable for INTEGER and REAL types.

  • upper (float or Unbounded, default: None ) –

    The upper bound for the variable. Only applicable for INTEGER and REAL types.

  • with_fallback (bool, default: False ) –

    If True and the name exists, a unique fallback name is generated.

Returns:

  • Variable

    The newly created variable.

Raises:

  • VariableExistsError

    If a variable with the same name already exists and with_fallback=False.

  • VariableNameInvalidError

    If the variable name is invalid.

  • InvalidBoundsError

    If bounds are invalid or incompatible with the variable type.

Examples:

>>> model = Model()
>>> x = model.add_variable("x", vtype=Vtype.BINARY)
>>> y = model.add_variable("y", vtype=Vtype.INTEGER, lower=0, upper=10)
>>> z = model.add_variable("z", vtype=Vtype.REAL, lower=-1.5, upper=1.5)

Using fallback for duplicate names:

>>> x1 = model.add_variable("x", with_fallback=True)

add_variable_with_fallback(name: str, vtype: Vtype = Vtype.BINARY, lower: float | type[Unbounded] | None = None, upper: float | type[Unbounded] | None = None) -> Variable

Add a variable to the model with a fallback name in case it already exists.

Deprecated in favor of the :meth:add_variable(..., with_fallback=True) method.

get_variable(name: str) -> Variable

Get a variable from the model by its name.

Parameters:

  • name (str) –

    The name of the variable to retrieve.

Returns:

  • Variable

    The variable with the specified name.

Raises:

  • VariableNotExistingError

    If no variable with the given name exists in the model.

Examples:

>>> model = Model()
>>> x = model.add_variable("x")
>>> retrieved = model.get_variable("x")
>>> retrieved.name
'x'

get_specs() -> ModelSpecs

Get the model's specifications.

Returns the specifications describing the model's structure, including variable types, degree of expressions, and constraint properties.

Returns:

Examples:

>>> model = Model()
>>> specs = model.get_specs()
>>> specs.max_num_variables
0

add_constraint(constraint: Constraint, name: str | None = None) -> None

Add a constraint to the model.

Parameters:

  • constraint (Constraint) –

    The constraint to add to the model.

  • name (str, default: None ) –

    An optional name for the constraint. If not provided, an automatic name will be generated.

Raises:

  • DuplicateConstraintNameError

    If a constraint with the same name already exists.

  • ConstraintNameInvalidError

    If the constraint name is invalid. Constraint names cannot be empty strings and must start with an alphabetical character. Additionally, constraint names cannot start with inf or nan due to limitations of other modeling software.

Examples:

>>> model = Model()
>>> x = model.add_variable("x")
>>> constraint = x <= 5
>>> model.add_constraint(constraint, name="x_upper_bound")

set_objective(expression: Expression, sense: Sense | None = None) -> None

Set the model's objective function.

Parameters:

  • expression (Expression) –

    The expression to use as the objective function.

  • sense (Sense, default: None ) –

    The optimization sense. If provided, also updates the model's sense. If None, the model's current sense is used.

Examples:

>>> model = Model()
>>> x = model.add_variable("x")
>>> y = model.add_variable("y")
>>> model.set_objective(x + 2 * y, sense=Sense.MAX)

evaluate(solution: Solution) -> Solution

Evaluate a solution against the model.

Computes objective values and checks constraint satisfaction for all samples in the solution.

Parameters:

  • solution (Solution) –

    The solution to evaluate.

Returns:

  • Solution

    A new solution with updated objective values and feasibility information.

Raises:

  • EvaluationError

    If evaluation fails due to incompatible solution format.

  • SampleIncorrectLengthError

    If samples have incorrect number of variables.

  • SampleUnexpectedVariableError

    If samples contain variables not in the model.

Examples:

>>> from luna_model import Model, Solution, Sense, Variable, Vtype
>>> model = Model(sense=Sense.MAX)
>>> x = model.add_variable("x", vtype=Vtype.INTEGER)
>>> y = model.add_variable("y", vtype=Vtype.INTEGER)
>>> model.objective = x + 2 * y
>>> model.constraints += x + y <= 5
>>> samples = [{"x": 1, "y": 2}]
>>> with model.environment:
...     solution = Solution(samples=samples)
>>> solution = model.evaluate(solution)
>>> solution.obj_values[0]  # Value of x + 2*y = 1 + 4 = 5
np.float64(5.0)
>>> solution[0].feasible  # x + y = 3 <= 5, so True
True

evaluate_sample(sample: Sample) -> Result

Evaluate a single sample against the model.

Computes the objective value and checks constraint satisfaction for a single variable assignment.

Parameters:

  • sample (Sample) –

    A dictionary mapping variable names to their values.

Returns:

  • Result

    Evaluation result containing objective value and feasibility information.

Raises:

  • SampleIncorrectLengthError

    If the sample has incorrect number of variables.

  • SampleUnexpectedVariableError

    If the sample contains variables not in the model.

violated_constraints(sample: Sample) -> ConstraintCollection

Get all constraints violated by a sample.

Parameters:

  • sample (Sample) –

    A dictionary mapping variable names to their values.

Returns:

  • ConstraintCollection

    Collection containing only the constraints that are violated by the sample.

substitute(target: Variable, replacement: Expression | Variable) -> None

Substitute a variable with an expression or another variable.

Replaces all occurrences of the target variable in the objective and constraints with the replacement expression or variable.

Parameters:

  • target (Variable) –

    The variable to be replaced.

  • replacement (Expression or Variable) –

    The expression or variable to substitute in place of the target.

Raises:

  • TypeError

    If replacement is neither an Expression nor a Variable.

  • DifferentEnvironmentsError

    If the replacement is from a different environment.

Examples:

>>> model = Model()
>>> x = model.add_variable("x")
>>> y = model.add_variable("y")
>>> z = model.add_variable("z")
>>> model.objective = x + 2 * y
>>> model.substitute(y, z + 1)  # Replace y with (z + 1)
>>> # Objective becomes: x + 2*(z + 1) = x + 2z + 2
Notes

This operation modifies the model in place. The target variable remains in the model's environment but is no longer used.

satisfies(specs: ModelSpecs) -> bool

Check if the model satisfies given specifications.

Parameters:

  • specs (ModelSpecs) –

    The specifications to check against.

Returns:

  • bool

    True if the model satisfies all specifications, False otherwise.

Examples:

>>> model = Model()
>>> specs = model.get_specs()
>>> model.satisfies(specs)
True

encode() -> bytes

Serialize the model into a compact binary format.

Returns:

  • bytes

    Encoded model representation.

Examples:

>>> model = Model("MyModel")
>>> blob = model.encode()
>>> restored = Model.decode(blob)
>>> restored.name
'MyModel'

serialize() -> bytes

Serialize the model into a compact binary format.

This is an alias for :meth:encode.

Returns:

  • bytes

    Encoded model representation.

decode(data: bytes) -> Model classmethod

Reconstruct a model from encoded bytes.

Parameters:

  • data (bytes) –

    Binary blob returned by :meth:encode or :meth:serialize.

Returns:

  • Model

    Deserialized model object.

Raises:

  • DecodingError

    If decoding fails due to corruption or incompatibility.

Examples:

>>> original = Model("MyModel")
>>> blob = original.encode()
>>> restored = Model.decode(blob)
>>> restored.name == original.name
True

deserialize(data: bytes) -> Model classmethod

Reconstruct a model from encoded bytes.

This is an alias for :meth:decode.

Parameters:

  • data (bytes) –

    Binary blob returned by encode().

Returns:

  • Model

    Deserialized model object.

deep_clone() -> Model

Create a deep copy of the model.

Returns:

  • Model

    A new model that is an independent copy of this model, including its own environment, variables, constraints, and objective.

Examples:

>>> from luna_model import Model
>>> original = Model("Original")
>>> x = original.add_variable("x")
>>> original.objective = 2 * x
>>> clone = original.deep_clone()
>>> clone.name = "Clone"
>>> original.name
'Original'

from_(other: ConstrainedQuadraticModel | BinaryQuadraticModel | str | Path | NDArray, name: str | None = None, **kwargs) -> Model classmethod

from_(other: ConstrainedQuadraticModel | BinaryQuadraticModel | str | Path, name: str | None = None) -> Model
from_(other: NDArray, name: str | None = None, *, offset: float | None = None, variable_names: list[str] | None = None, vtype: Vtype | None = None) -> Model

Create a model from other.

to(target: TranslationTarget, filepath: Path | None = None) -> Qubo | str | BinaryQuadraticModel | ConstrainedQuadraticModel | None

to(target: Literal[TranslationTarget.LP], filepath: Path) -> None
to(target: Literal[TranslationTarget.LP]) -> str
to(target: Literal[TranslationTarget.CQM]) -> ConstrainedQuadraticModel
to(target: Literal[TranslationTarget.BQM]) -> BinaryQuadraticModel
to(target: Literal[TranslationTarget.QUBO]) -> Qubo

Translate model to target.

equal_contents(other: Model) -> bool

Check if two models have equal contents.

__eq__(other: Model) -> bool

Check if two models are exactly equal.

Two models are equal if they have the same structure, variables, constraints, and objective.

Parameters:

  • other (Model) –

    The model to compare with.

Returns:

  • bool

    True if models are equal, False otherwise.

Examples:

>>> model1 = Model("A")
>>> model2 = Model("B")
>>> model1 == model2
False

__hash__() -> int

Compute hash value for the model.

Returns:

  • int

    Hash value based on the model's structure.

Examples:

>>> model = Model("MyModel")
>>> hash(model)
4726318758077234822

__reduce__() -> tuple[Callable[[bytes], Model], tuple[bytes]]

Support for pickle serialization.

Returns:

  • tuple

    A tuple of (decoder_function, encoded_data) for pickle.

Examples:

>>> import pickle
>>> model = Model("MyModel")
>>> pickled = pickle.dumps(model)
>>> restored = pickle.loads(pickled)
>>> restored.name
'MyModel'
Notes

This method is called automatically by Python's pickle module. It uses the model's encode/decode methods internally.

__str__() -> str

Get human-readable string representation of the model.

Returns:

  • str

    A formatted string showing the model's name, sense, objective, constraints, and variables.

Examples:

>>> from luna_model import Model, Sense
>>> model = Model("MyModel", sense=Sense.MAX)
>>> x = model.add_variable("x")
>>> model.objective = 2 * x
>>> print(model)
Model: MyModel
Maximize
  2 * x
Binary
  x

__repr__() -> str

Get detailed debug representation of the model.

Returns:

  • str

    A string representation suitable for debugging.

Examples:

>>> model = Model("MyModel")
>>> repr(model)
'Model(name=MyModel, sense=Minimize, objective=0, constraints={})'
Notes

This representation may include internal details useful for debugging but is not guaranteed to be stable across versions.

Sense

Bases: Enum

Optimization direction for the objective function.

Specifies whether the goal is to minimize or maximize the objective.

Attributes:

  • MIN (str) –

    Minimize the objective function.

  • MAX (str) –

    Maximize the objective function.

Examples:

>>> from luna_model import Model, Sense
>>> model = Model(sense=Sense.MIN)  # Minimization problem

ModelSpecs

Specifications and requirements for models.

Defines the characteristics and limitations of an optimization model, including optimization sense, allowed variable types, constraint types, maximum polynomial degree, and size limits.

Parameters:

  • sense (Sense, default: None ) –

    The optimization direction (MIN or MAX).

  • vtypes (set[Vtype], default: None ) –

    Set of allowed variable types (BINARY, INTEGER, REAL, SPIN).

  • constraints (set[Ctype], default: None ) –

    Set of allowed constraint types (UNCONSTRAINED, EQUALITY, INEQUALITY, LESS_EQUAL, GREATER_EQUAL).

  • max_degree (int, default: None ) –

    Maximum degree of objective polynomial.

  • max_constraint_degree (int, default: None ) –

    Maximum degree of constraint polynomials.

  • max_num_variables (int, default: None ) –

    Maximum number of variables allowed.

Attributes:

Examples:

Create specifications for a QUBO model:

>>> from luna_model import ModelSpecs, Sense, Ctype, Vtype
>>> target_specs = ModelSpecs(
...     sense=Sense.MIN, vtypes={Vtype.BINARY}, constraints={Ctype.UNCONSTRAINED}, max_degree=2
... )

Check if a model satisfies specifications:

>>> from luna_model import Model
>>> model = Model("test_model", sense=Sense.MIN)
>>> x = model.add_variable("x", vtype=Vtype.BINARY)
>>> model.objective = 10 * x
>>> model_specs = model.get_specs()
>>> if model_specs.satisfies(target_specs):
...     print("Model meets requirements")
Model meets requirements

sense: Sense | None property

Get the optimization sense.

max_degree: int | None property

Get the maximum objective polynomial degree.

max_constraint_degree: int | None property

Get the maximum constraint polynomial degree.

max_num_variables: int | None property

Get the maximum number of variables allowed.

vtypes: list[Vtype] | None property

Get the list of allowed variable types.

constraints: list[Ctype] | None property

Get the list of allowed constraint types.

__init__(sense: Sense | None = None, vtypes: set[Vtype] | None = None, constraints: set[Ctype] | None = None, max_degree: int | None = None, max_constraint_degree: int | None = None, max_num_variables: int | None = None) -> None

Initialize model specifications with requirements.

satisfies(other: ModelSpecs) -> bool

Check if these specifications satisfy another set of requirements.

Parameters:

  • other (ModelSpecs) –

    The required specifications to check against.

Returns:

  • bool

    True if this model satisfies all requirements in other.

__str__() -> str

Return human-readable string representation.

Returns:

  • str

    String representation of the model specs.

__repr__() -> str

Return detailed string representation.

Returns:

  • str

    Detailed representation of the model specs.

Ctype

Bases: Enum

Types of constraints in optimization models.

Categorizes constraints by their comparison operators and structure.

Attributes:

  • UNCONSTRAINED (str) –

    No constraints (unconstrained optimization).

  • EQUALITY (str) –

    Equality constraints (==).

  • INEQUALITY (str) –

    Inequality constraints (<= or >=).

  • LESS_EQUAL (str) –

    Less-than-or-equal constraints (<=).

  • GREATER_EQUAL (str) –

    Greater-than-or-equal constraints (>=).

Examples:

>>> from luna_model import Ctype, ModelSpecs
>>> specs = ModelSpecs(constraints={Ctype.LESS_EQUAL})