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:
OXObjectBase 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:
- variables
Set of decision variables in the problem.
- Type:
- constraints
List of linear constraints.
- Type:
- specials
List of special (non-linear) constraints.
- Type:
- 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]
- 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:
- 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:
OXCSPProblemLinear 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:
- objective_type
Whether to minimize or maximize the objective.
- Type:
- db
Inherited from OXCSPProblem.
- Type:
- variables
Inherited from OXCSPProblem.
- Type:
- constraints
Inherited from OXCSPProblem.
- Type:
- specials
Inherited from OXCSPProblem.
- Type:
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:
OXLPProblemGoal 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:
- objective_function
Inherited from OXLPProblem.
- Type:
- objective_type
Inherited from OXLPProblem.
- Type:
- db
Inherited from OXCSPProblem.
- Type:
- variables
Inherited from OXCSPProblem.
- Type:
- constraints
Inherited from OXCSPProblem.
- Type:
- specials
Inherited from OXCSPProblem.
- Type:
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.
Available objective types:
MINIMIZE- Minimize the objective functionMAXIMIZE- 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.
Available special constraint types:
MultiplicativeEquality- Multiplication: result = var1 * var2 * … * varNDivisionEquality- Integer division: result = var // divisorModulusEquality- Modulo operation: result = var % divisorSummationEquality- Summation: result = var1 + var2 + … + varNConditionalConstraint- 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
Constraints Module - Constraint definitions and operators
Variables Module - Variable management and types
Data Module - Database objects and scenario management
Solvers Module - Solver interfaces and implementations
Examples - Complete example problems