Problem Module

The problem module provides the core problem type classes for representing different types of optimization problems in the OptiX framework. It implements a hierarchical structure supporting Constraint Satisfaction Problems (CSP), Linear Programming (LP), and Goal Programming (GP).

Problem Types

class problem.OXCSPProblem(id: ~uuid.UUID = <factory>, class_name: str = '', db: ~data.OXDatabase.OXDatabase = <factory>, variables: ~variables.OXVariableSet.OXVariableSet = <factory>, constraints: ~constraints.OXConstraintSet.OXConstraintSet = <factory>, specials: list[~constraints.OXSpecialConstraints.OXSpecialConstraint] = <factory>, constraints_in_special_constraints: list[~uuid.UUID] = <factory>)[source]

Bases: OXObject

Base class for Constraint Satisfaction Problems (CSP).

This class represents a constraint satisfaction problem where the goal is to find values for variables that satisfy a set of constraints. It provides the fundamental structure for optimization problems in the OptiX framework.

db

Database containing data objects used in the problem.

Type:

OXDatabase

variables

Set of decision variables in the problem.

Type:

OXVariableSet

constraints

List of linear constraints.

Type:

list[OXConstraint]

specials

List of special (non-linear) constraints.

Type:

list[OXSpecialConstraint]

constraints_in_special_constraints

List of constraint IDs used in special constraints to avoid duplication.

Type:

list[UUID]

Examples

>>> problem = OXCSPProblem()
>>> problem.create_decision_variable("x", lower_bound=0, upper_bound=10)
>>> problem.create_decision_variable("y", lower_bound=0, upper_bound=10)
>>> problem.create_constraint(
...     variables=[problem.variables[0].id, problem.variables[1].id],
...     weights=[1, 1],
...     operator=RelationalOperators.LESS_THAN_EQUAL,
...     value=15
... )

See also

OXLPProblem: Linear Programming extension of CSP. OXGPProblem: Goal Programming extension of LP.

db: OXDatabase
variables: OXVariableSet
constraints: OXConstraintSet
specials: list[OXSpecialConstraint]
constraints_in_special_constraints: list[UUID]
create_special_constraint(*, constraint_type: SpecialConstraintType = SpecialConstraintType.MultiplicativeEquality, **kwargs)[source]

Create a special (non-linear) constraint for the problem.

This method creates various types of special constraints that handle non-linear operations such as multiplication, division, modulo, summation, and conditional logic.

Parameters:
  • constraint_type (SpecialConstraintType) – The type of special constraint to create. Defaults to MultiplicativeEquality.

  • **kwargs – Additional keyword arguments specific to the constraint type. See individual constraint creation functions for details.

Returns:

The created special constraint object.

Return type:

OXSpecialConstraint

Raises:

OXception – If an unknown constraint type is provided.

Examples

>>> # Create a multiplication constraint: z = x * y
>>> constraint = problem.create_special_constraint(
...     constraint_type=SpecialConstraintType.MultiplicativeEquality,
...     input_variables=[var_x, var_y]
... )
>>>
>>> # Create a division constraint: z = x // 3
>>> constraint = problem.create_special_constraint(
...     constraint_type=SpecialConstraintType.DivisionEquality,
...     input_variable=var_x,
...     divisor=3
... )

See also

_create_multiplicative_equality_constraint(): For multiplication constraints. _create_division_or_modulus_equality_constraint(): For division/modulo constraints. _create_summation_equality_constraint(): For summation constraints. _create_conditional_constraint(): For conditional constraints.

create_variables_from_db(*args, var_name_template: str = '', var_description_template: str = '', upper_bound: float | int = inf, lower_bound: float | int = 0)[source]

Create decision variables from database objects using Cartesian product.

This method creates decision variables by taking the Cartesian product of specified database object types. For each combination of objects, a new variable is created with the specified bounds and template-based naming.

Parameters:
  • *args – Variable number of database object types to use for variable creation. Each argument should be a type that exists in the problem’s database.

  • var_name_template (str, optional) – Template string for variable names. Can use database object type names as format keys, as well as individual field values with format “{type_name}_{field_name}”. Defaults to “”.

  • var_description_template (str, optional) – Template string for variable descriptions. Can use database object type names as format keys, as well as individual field values with format “{type_name}_{field_name}”. Defaults to “”.

  • upper_bound (float | int, optional) – Upper bound for all created variables. Defaults to positive infinity.

  • lower_bound (float | int, optional) – Lower bound for all created variables. Defaults to 0.

Raises:

OXception – If any of the provided argument types don’t exist in the database.

Examples

>>> # Create variables for all combinations of buses and routes
>>> problem.create_variables_from_db(
...     Bus, Route,
...     var_name_template="bus_{bus_id}_route_{route_id}",
...     var_description_template="Assignment of bus {bus_name} to route {route_name}",
...     upper_bound=1,
...     lower_bound=0
... )
>>>
>>> # Create variables for single object type using field values
>>> problem.create_variables_from_db(
...     Driver,
...     var_name_template="driver_{driver_id}_active",
...     var_description_template="Driver {driver_name} is active",
...     upper_bound=1
... )

Note

The method uses the Cartesian product of all specified object types, so the number of created variables equals the product of the counts of each object type. Template strings can now access both object type names and individual field values from dataclass objects.

create_decision_variable(var_name: str = '', description: str = '', upper_bound: float | int = inf, lower_bound: float | int = 0, **kwargs)[source]

Create a decision variable for the optimization problem.

Creates a new decision variable with the specified bounds and properties, and adds it to the problem’s variable set. The variable can be linked to database objects through keyword arguments.

Parameters:
  • var_name (str, optional) – Name of the variable. Defaults to “”.

  • description (str, optional) – Description of the variable. Defaults to “”.

  • upper_bound (float | int, optional) – Upper bound for the variable. Defaults to positive infinity.

  • lower_bound (float | int, optional) – Lower bound for the variable. Defaults to 0.

  • **kwargs – Additional keyword arguments linking the variable to database objects. Keys must match database object types.

Raises:

OXception – If any keyword argument key doesn’t match a database object type.

Examples

>>> # Create a simple bounded variable
>>> problem.create_decision_variable(
...     var_name="x",
...     description="Production quantity",
...     upper_bound=100,
...     lower_bound=0
... )
>>>
>>> # Create a variable linked to database objects
>>> problem.create_decision_variable(
...     var_name="assignment_bus_1_route_2",
...     description="Bus 1 assigned to route 2",
...     upper_bound=1,
...     lower_bound=0,
...     bus=bus_1_id,
...     route=route_2_id
... )

Note

The variable is automatically added to the problem’s variable set and can be accessed through the variables attribute.

create_constraint(variable_search_function: Callable[[OXObject], bool] = None, weight_calculation_function: Callable[[UUID, Self], float | int | Fraction] = None, variables: list[UUID] = None, weights: list[float | int | Fraction] = None, operator: RelationalOperators = RelationalOperators.LESS_THAN_EQUAL, value: float | int = None, name: str = None)[source]

Create a linear constraint for the optimization problem.

Creates a linear constraint of the form: w1*x1 + w2*x2 + … + wn*xn {operator} value

Variables and weights can be specified either directly or through search and calculation functions.

Parameters:
  • variable_search_function (Callable[[OXObject], bool], optional) – Function to search for variables in the problem. If provided, variables parameter must be None.

  • weight_calculation_function (Callable[[UUID, Self], float | int], optional) – Function to calculate weights for each variable. If provided, weights parameter must be None.

  • variables (list[UUID], optional) – List of variable IDs to include in the constraint. If provided, variable_search_function must be None.

  • weights (list[float | int], optional) – List of weights for each variable. If provided, weight_calculation_function must be None.

  • operator (RelationalOperators, optional) – Relational operator for the constraint. Defaults to LESS_THAN_EQUAL.

  • value (float | int, optional) – Right-hand side value of the constraint.

  • name (str, optional) – A descriptive name for the constraint. If None, an auto-generated name will be created based on the constraint terms.

Raises:

OXception – If parameter combinations are invalid (see _check_parameters).

Examples

>>> # Using direct variable and weight specification
>>> problem.create_constraint(
...     variables=[var1.id, var2.id, var3.id],
...     weights=[1, 2, 3],
...     operator=RelationalOperators.LESS_THAN_EQUAL,
...     value=100
... )
>>>
>>> # Using search and calculation functions
>>> problem.create_constraint(
...     variable_search_function=lambda v: v.name.startswith("x"),
...     weight_calculation_function=lambda v, p: 1.0,
...     operator=RelationalOperators.EQUAL,
...     value=1
... )

Note

The constraint is automatically added to the problem’s constraint list. Exactly one of variable_search_function/variables and one of weight_calculation_function/weights must be provided.

__init__(id: ~uuid.UUID = <factory>, class_name: str = '', db: ~data.OXDatabase.OXDatabase = <factory>, variables: ~variables.OXVariableSet.OXVariableSet = <factory>, constraints: ~constraints.OXConstraintSet.OXConstraintSet = <factory>, specials: list[~constraints.OXSpecialConstraints.OXSpecialConstraint] = <factory>, constraints_in_special_constraints: list[~uuid.UUID] = <factory>) None
class problem.OXLPProblem(id: ~uuid.UUID = <factory>, class_name: str = '', db: ~data.OXDatabase.OXDatabase = <factory>, variables: ~variables.OXVariableSet.OXVariableSet = <factory>, constraints: ~constraints.OXConstraintSet.OXConstraintSet = <factory>, specials: list[~constraints.OXSpecialConstraints.OXSpecialConstraint] = <factory>, constraints_in_special_constraints: list[~uuid.UUID] = <factory>, objective_function: ~constraints.OXpression.OXpression = <factory>, objective_type: ~problem.OXProblem.ObjectiveType = ObjectiveType.MINIMIZE)[source]

Bases: OXCSPProblem

Linear Programming Problem class.

This class extends OXCSPProblem to add support for linear programming by introducing an objective function that can be minimized or maximized.

objective_function

The objective function to optimize.

Type:

OXpression

objective_type

Whether to minimize or maximize the objective.

Type:

ObjectiveType

db

Inherited from OXCSPProblem.

Type:

OXDatabase

variables

Inherited from OXCSPProblem.

Type:

OXVariableSet

constraints

Inherited from OXCSPProblem.

Type:

list[OXConstraint]

specials

Inherited from OXCSPProblem.

Type:

list[OXSpecialConstraint]

Examples

>>> problem = OXLPProblem()
>>> problem.create_decision_variable("x", lower_bound=0, upper_bound=10)
>>> problem.create_decision_variable("y", lower_bound=0, upper_bound=10)
>>> problem.create_constraint(
...     variables=[problem.variables[0].id, problem.variables[1].id],
...     weights=[1, 1],
...     operator=RelationalOperators.LESS_THAN_EQUAL,
...     value=15
... )
>>> problem.create_objective_function(
...     variables=[problem.variables[0].id, problem.variables[1].id],
...     weights=[3, 2],
...     objective_type=ObjectiveType.MAXIMIZE
... )

See also

OXCSPProblem: Base constraint satisfaction problem class. OXGPProblem: Goal Programming extension of LP.

objective_function: OXpression
objective_type: ObjectiveType = 'minimize'
create_objective_function(variable_search_function: Callable[[OXObject], bool] = None, weight_calculation_function: Callable[[OXVariable, Self], float | int] = None, variables: list[UUID] = None, weights: list[float | int] = None, objective_type: ObjectiveType = ObjectiveType.MINIMIZE)[source]

Create an objective function for the linear programming problem.

Creates an objective function of the form: {minimize|maximize} w1*x1 + w2*x2 + … + wn*xn

Variables and weights can be specified either directly or through search and calculation functions.

Parameters:
  • variable_search_function (Callable[[OXObject], bool], optional) – Function to search for variables in the problem. If provided, variables parameter must be None.

  • weight_calculation_function (Callable[[OXVariable, Self], float | int], optional) – Function to calculate weights for each variable. If provided, weights parameter must be None.

  • variables (list[UUID], optional) – List of variable IDs to include in the objective function. If provided, variable_search_function must be None.

  • weights (list[float | int], optional) – List of weights for each variable. If provided, weight_calculation_function must be None.

  • objective_type (ObjectiveType, optional) – Whether to minimize or maximize the objective function. Defaults to MINIMIZE.

Examples

>>> # Maximize profit: 3*x + 2*y
>>> problem.create_objective_function(
...     variables=[x_id, y_id],
...     weights=[3, 2],
...     objective_type=ObjectiveType.MAXIMIZE
... )
>>>
>>> # Minimize cost using search function
>>> problem.create_objective_function(
...     variable_search_function=lambda v: "cost" in v.name,
...     weight_calculation_function=lambda v, p: v.get_cost(),
...     objective_type=ObjectiveType.MINIMIZE
... )

Note

This method sets both the objective_function and objective_type attributes of the problem.

__init__(id: ~uuid.UUID = <factory>, class_name: str = '', db: ~data.OXDatabase.OXDatabase = <factory>, variables: ~variables.OXVariableSet.OXVariableSet = <factory>, constraints: ~constraints.OXConstraintSet.OXConstraintSet = <factory>, specials: list[~constraints.OXSpecialConstraints.OXSpecialConstraint] = <factory>, constraints_in_special_constraints: list[~uuid.UUID] = <factory>, objective_function: ~constraints.OXpression.OXpression = <factory>, objective_type: ~problem.OXProblem.ObjectiveType = ObjectiveType.MINIMIZE) None
class problem.OXGPProblem(id: ~uuid.UUID = <factory>, class_name: str = '', db: ~data.OXDatabase.OXDatabase = <factory>, variables: ~variables.OXVariableSet.OXVariableSet = <factory>, constraints: ~constraints.OXConstraintSet.OXConstraintSet = <factory>, specials: list[~constraints.OXSpecialConstraints.OXSpecialConstraint] = <factory>, constraints_in_special_constraints: list[~uuid.UUID] = <factory>, objective_function: ~constraints.OXpression.OXpression = <factory>, objective_type: ~problem.OXProblem.ObjectiveType = ObjectiveType.MINIMIZE, goal_constraints: ~constraints.OXConstraintSet.OXConstraintSet = <factory>)[source]

Bases: OXLPProblem

Goal Programming Problem class.

This class extends OXLPProblem to add support for goal programming by introducing goal constraints with deviation variables. Goal programming is used when there are multiple conflicting objectives that cannot be simultaneously satisfied.

goal_constraints

List of goal constraints with deviation variables.

Type:

list[OXGoalConstraint]

objective_function

Inherited from OXLPProblem.

Type:

OXpression

objective_type

Inherited from OXLPProblem.

Type:

ObjectiveType

db

Inherited from OXCSPProblem.

Type:

OXDatabase

variables

Inherited from OXCSPProblem.

Type:

OXVariableSet

constraints

Inherited from OXCSPProblem.

Type:

list[OXConstraint]

specials

Inherited from OXCSPProblem.

Type:

list[OXSpecialConstraint]

Examples

>>> problem = OXGPProblem()
>>> problem.create_decision_variable("x", lower_bound=0, upper_bound=10)
>>> problem.create_decision_variable("y", lower_bound=0, upper_bound=10)
>>> # Create a goal constraint: aim for x + y = 8
>>> problem.create_goal_constraint(
...     variables=[problem.variables[0].id, problem.variables[1].id],
...     weights=[1, 1],
...     operator=RelationalOperators.EQUAL,
...     value=8
... )
>>> # The objective function minimizes undesired deviations
>>> problem.create_objective_function()

See also

OXLPProblem: Base linear programming problem class. OXCSPProblem: Base constraint satisfaction problem class. constraints.OXConstraint.OXGoalConstraint: Goal constraint with deviation variables.

goal_constraints: OXConstraintSet
create_goal_constraint(variable_search_function: Callable[[OXObject], bool] = None, weight_calculation_function: Callable[[UUID, Self], float | int | Fraction] = None, variables: list[UUID] = None, weights: list[float | int] = None, operator: RelationalOperators = RelationalOperators.LESS_THAN_EQUAL, value: float | int = None, name: str = None)[source]

Create a goal constraint for the goal programming problem.

Creates a goal constraint with associated positive and negative deviation variables. Goal constraints represent targets that the problem should try to achieve, but may not be strictly satisfied.

The constraint is of the form: w1*x1 + w2*x2 + … + wn*xn + d- - d+ {operator} value

Where d- and d+ are negative and positive deviation variables respectively.

Parameters:
  • variable_search_function (Callable[[OXObject], bool], optional) – Function to search for variables in the problem. If provided, variables parameter must be None.

  • weight_calculation_function (Callable[[OXVariable, Self], float | int], optional) – Function to calculate weights for each variable. If provided, weights parameter must be None.

  • variables (list[UUID], optional) – List of variable IDs to include in the constraint. If provided, variable_search_function must be None.

  • weights (list[float | int], optional) – List of weights for each variable. If provided, weight_calculation_function must be None.

  • operator (RelationalOperators, optional) – Relational operator for the constraint. Defaults to LESS_THAN_EQUAL.

  • value (float | int, optional) – Target value for the goal constraint.

Examples

>>> # Goal: total production should be around 1000 units
>>> problem.create_goal_constraint(
...     variables=[prod1_id, prod2_id, prod3_id],
...     weights=[1, 1, 1],
...     operator=RelationalOperators.EQUAL,
...     value=1000
... )
>>>
>>> # Goal: minimize resource usage below 500
>>> problem.create_goal_constraint(
...     variable_search_function=lambda v: "resource" in v.name,
...     weight_calculation_function=lambda v, p: v.usage_rate,
...     operator=RelationalOperators.LESS_THAN_EQUAL,
...     value=500
... )

Note

This method creates a regular constraint first, then converts it to a goal constraint with deviation variables. The goal constraint is added to the goal_constraints list.

create_objective_function(variable_search_function: Callable[[OXObject], bool] = None, weight_calculation_function: Callable[[OXVariable, Self], float | int] = None, variables: list[UUID] = None, weights: list[float | int] = None, objective_type: ObjectiveType = ObjectiveType.MINIMIZE)[source]

Create an objective function for the goal programming problem.

Creates an objective function that minimizes the sum of undesired deviation variables from all goal constraints. This is the standard approach in goal programming where the objective is to minimize deviations from goals.

Parameters:
  • variable_search_function (Callable[[OXObject], bool], optional) – Not used in goal programming. Included for interface consistency.

  • weight_calculation_function (Callable[[OXVariable, Self], float | int], optional) – Not used in goal programming. Included for interface consistency.

  • variables (list[UUID], optional) – Not used in goal programming. Included for interface consistency.

  • weights (list[float | int], optional) – Not used in goal programming. Included for interface consistency.

  • objective_type (ObjectiveType, optional) – Not used in goal programming. Always set to MINIMIZE. Included for interface consistency.

Examples

>>> # Create goal constraints first
>>> problem.create_goal_constraint(
...     variables=[x_id, y_id],
...     weights=[1, 1],
...     operator=RelationalOperators.EQUAL,
...     value=100
... )
>>>
>>> # Create objective function to minimize deviations
>>> problem.create_objective_function()

Note

This method automatically collects all undesired deviation variables from existing goal constraints and creates an objective function that minimizes their sum. The objective is always set to MINIMIZE. Parameters are ignored as the objective is automatically determined from goal constraints.

__init__(id: ~uuid.UUID = <factory>, class_name: str = '', db: ~data.OXDatabase.OXDatabase = <factory>, variables: ~variables.OXVariableSet.OXVariableSet = <factory>, constraints: ~constraints.OXConstraintSet.OXConstraintSet = <factory>, specials: list[~constraints.OXSpecialConstraints.OXSpecialConstraint] = <factory>, constraints_in_special_constraints: list[~uuid.UUID] = <factory>, objective_function: ~constraints.OXpression.OXpression = <factory>, objective_type: ~problem.OXProblem.ObjectiveType = ObjectiveType.MINIMIZE, goal_constraints: ~constraints.OXConstraintSet.OXConstraintSet = <factory>) None

Enumerations

class problem.ObjectiveType(*values)[source]

Enumeration of objective types for optimization problems.

MINIMIZE

Minimize the objective function.

Type:

str

MAXIMIZE

Maximize the objective function.

Type:

str

Available objective types:

  • MINIMIZE - Minimize the objective function

  • MAXIMIZE - Maximize the objective function

MINIMIZE = 'minimize'
MAXIMIZE = 'maximize'
class problem.SpecialConstraintType(*values)[source]

Enumeration of special constraint types supported by the framework.

This enumeration defines the types of special (non-linear) constraints that can be created in optimization problems.

MultiplicativeEquality

Constraint for variable multiplication.

Type:

str

DivisionEquality

Constraint for integer division operations.

Type:

str

ModulusEquality

Constraint for modulo operations.

Type:

str

SummationEquality

Constraint for variable summation.

Type:

str

ConditionalConstraint

Constraint for conditional logic.

Type:

str

Available special constraint types:

  • MultiplicativeEquality - Multiplication: result = var1 * var2 * … * varN

  • DivisionEquality - Integer division: result = var // divisor

  • ModulusEquality - Modulo operation: result = var % divisor

  • SummationEquality - Summation: result = var1 + var2 + … + varN

  • ConditionalConstraint - Conditional logic: if condition then constraint1 else constraint2

MultiplicativeEquality = 'MultiplicativeEquality'
DivisionEquality = 'DivisionEquality'
ModulusEquality = 'ModulusEquality'
SummationEquality = 'SummationEquality'
ConditionalConstraint = 'ConditionalConstraint'

Examples

Creating a Constraint Satisfaction Problem

from problem import OXCSPProblem
from constraints import RelationalOperators

# Create CSP
csp = OXCSPProblem()

# Add variables
csp.create_decision_variable("x1", lower_bound=0, upper_bound=10)
csp.create_decision_variable("x2", lower_bound=0, upper_bound=10)

# Add constraint: x1 + x2 <= 15
csp.create_constraint(
    variables=[csp.variables[0].id, csp.variables[1].id],
    weights=[1, 1],
    operator=RelationalOperators.LESS_THAN_EQUAL,
    value=15
)

Creating a Linear Programming Problem

from problem import OXLPProblem, ObjectiveType
from constraints import RelationalOperators

# Create LP problem
lp = OXLPProblem()

# Add variables
lp.create_decision_variable("production_a", lower_bound=0, upper_bound=1000)
lp.create_decision_variable("production_b", lower_bound=0, upper_bound=1000)

# Add resource constraint
lp.create_constraint(
    variables=[lp.variables[0].id, lp.variables[1].id],
    weights=[2, 3],  # Resource consumption per unit
    operator=RelationalOperators.LESS_THAN_EQUAL,
    value=500,  # Available resources
    name="Resource limitation"
)

# Set objective: maximize profit
lp.create_objective_function(
    variables=[lp.variables[0].id, lp.variables[1].id],
    weights=[10, 15],  # Profit per unit
    objective_type=ObjectiveType.MAXIMIZE
)

Creating a Goal Programming Problem

from problem import OXGPProblem
from constraints import RelationalOperators

# Create GP problem
gp = OXGPProblem()

# Add variables
gp.create_decision_variable("workers_day", lower_bound=0, upper_bound=100)
gp.create_decision_variable("workers_night", lower_bound=0, upper_bound=100)

# Add goal constraint: target 80 total workers
gp.create_goal_constraint(
    variables=[gp.variables[0].id, gp.variables[1].id],
    weights=[1, 1],
    operator=RelationalOperators.EQUAL,
    value=80,
    name="Target workforce size"
)

# Add goal constraint: prefer balanced shifts
gp.create_goal_constraint(
    variables=[gp.variables[0].id, gp.variables[1].id],
    weights=[1, -1],  # Difference between shifts
    operator=RelationalOperators.EQUAL,
    value=0,   # Equal shifts
    name="Balanced shift allocation"
)

# Create objective function to minimize deviations
gp.create_objective_function()

Working with Database Objects

from problem import OXLPProblem
from data import OXData, OXDatabase

# Create data objects
bus1 = OXData()
bus1.capacity = 50
bus1.cost_per_km = 2.5

bus2 = OXData()
bus2.capacity = 40
bus2.cost_per_km = 2.0

route1 = OXData()
route1.distance = 25
route1.demand = 35

route2 = OXData()
route2.distance = 30
route2.demand = 45

# Create problem
problem = OXLPProblem()

# Add data to database
problem.db.add_object(bus1)
problem.db.add_object(bus2)
problem.db.add_object(route1)
problem.db.add_object(route2)

# Create variables from database objects using custom types
class Bus:
    pass

class Route:
    pass

# Create variables for all bus-route combinations
problem.create_variables_from_db(
    Bus, Route,
    var_name_template="assign_{bus_id}_{route_id}",
    var_description_template="Assign bus {bus_id} to route {route_id}",
    upper_bound=1,
    lower_bound=0
)

Special Constraints

from problem import OXLPProblem, SpecialConstraintType

problem = OXLPProblem()

# Create variables
problem.create_decision_variable("x", lower_bound=0, upper_bound=100)
problem.create_decision_variable("y", lower_bound=0, upper_bound=100)

# Create multiplication constraint: z = x * y
mult_constraint = problem.create_special_constraint(
    constraint_type=SpecialConstraintType.MultiplicativeEquality,
    input_variables=[problem.variables[0], problem.variables[1]]
)

# Create division constraint: w = x // 5
div_constraint = problem.create_special_constraint(
    constraint_type=SpecialConstraintType.DivisionEquality,
    input_variable=[problem.variables[0]],
    divisor=5
)

# Create modulo constraint: r = x % 7
mod_constraint = problem.create_special_constraint(
    constraint_type=SpecialConstraintType.ModulusEquality,
    input_variable=[problem.variables[0]],
    divisor=7
)

Functional Constraint Creation

from problem import OXLPProblem
from constraints import RelationalOperators

problem = OXLPProblem()

# Create variables with meaningful names
for i in range(5):
    problem.create_decision_variable(
        f"production_{i}",
        lower_bound=0,
        upper_bound=100
    )

# Create constraint using search function
problem.create_constraint(
    variable_search_function=lambda v: v.name.startswith("production"),
    weight_calculation_function=lambda var_id, prob: 1.0,  # Equal weights
    operator=RelationalOperators.LESS_THAN_EQUAL,
    value=300,
    name="Total production capacity"
)

# Create objective using search function
problem.create_objective_function(
    variable_search_function=lambda v: v.name.startswith("production"),
    weight_calculation_function=lambda var_id, prob: 10.0,  # Profit per unit
    objective_type=ObjectiveType.MAXIMIZE
)

Advanced Goal Programming

from problem import OXGPProblem
from constraints import RelationalOperators

# Multi-criteria optimization problem
problem = OXGPProblem()

# Create variables for different departments
problem.create_decision_variable("dept_a_budget", lower_bound=0, upper_bound=1000000)
problem.create_decision_variable("dept_b_budget", lower_bound=0, upper_bound=1000000)
problem.create_decision_variable("dept_c_budget", lower_bound=0, upper_bound=1000000)

# Goal 1: Total budget should be around $2M
problem.create_goal_constraint(
    variables=[v.id for v in problem.variables],
    weights=[1, 1, 1],
    operator=RelationalOperators.EQUAL,
    value=2000000,
    name="Total budget target"
)

# Goal 2: Department A should get at least 40% of total budget
problem.create_goal_constraint(
    variables=[v.id for v in problem.variables],
    weights=[1, -0.4, -0.4],  # dept_a - 0.4*(dept_b + dept_c)
    operator=RelationalOperators.GREATER_THAN_EQUAL,
    value=0,
    name="Department A minimum share"
)

# Goal 3: Departments B and C should have similar budgets
problem.create_goal_constraint(
    variables=[problem.variables[1].id, problem.variables[2].id],
    weights=[1, -1],  # dept_b - dept_c
    operator=RelationalOperators.EQUAL,
    value=0,
    name="Balanced B and C budgets"
)

# Create objective to minimize undesired deviations
problem.create_objective_function()

Complex Special Constraints

from problem import OXCSPProblem, SpecialConstraintType

problem = OXCSPProblem()

# Create variables for a scheduling problem
problem.create_decision_variable("task_duration", lower_bound=1, upper_bound=10)
problem.create_decision_variable("num_workers", lower_bound=1, upper_bound=5)
problem.create_decision_variable("efficiency_factor", lower_bound=1, upper_bound=3)

# Total work = duration * workers * efficiency
work_constraint = problem.create_special_constraint(
    constraint_type=SpecialConstraintType.MultiplicativeEquality,
    input_variables=problem.variables.objects  # All variables
)

# Create summation constraint for resource allocation
for i in range(3):
    problem.create_decision_variable(f"resource_{i}", lower_bound=0, upper_bound=100)

# Total resources used
resource_sum = problem.create_special_constraint(
    constraint_type=SpecialConstraintType.SummationEquality,
    input_variables=lambda v: v.name.startswith("resource")
)

Working with Variable Templates

from problem import OXLPProblem
from data import OXData, OXDatabase

# Create a transportation problem
problem = OXLPProblem()

# Create supply and demand data
supply_points = []
for i in range(3):
    point = OXData()
    point.location = f"Factory_{i}"
    point.supply_capacity = (i + 1) * 100
    problem.db.add_object(point)
    supply_points.append(point)

demand_points = []
for i in range(4):
    point = OXData()
    point.location = f"Customer_{i}"
    point.demand = (i + 1) * 50
    problem.db.add_object(point)
    demand_points.append(point)

# Create classes for database query
class SupplyPoint:
    pass

class DemandPoint:
    pass

# Create transportation variables
problem.create_variables_from_db(
    SupplyPoint, DemandPoint,
    var_name_template="ship_{supplypoint_location}_{demandpoint_location}",
    var_description_template="Shipment from {supplypoint_location} to {demandpoint_location}",
    upper_bound=1000,
    lower_bound=0
)

print(f"Created {len(problem.variables)} transportation variables")

See Also