Constraints Module

The constraints module provides comprehensive constraint definition capabilities for optimization problems. It includes linear constraints, goal programming constraints, special non-linear constraints, and mathematical expressions.

Constraint Classes

Linear Constraints

class constraints.OXConstraint(id: ~uuid.UUID = <factory>, class_name: str = '', expression: ~constraints.OXpression.OXpression = <factory>, relational_operator: ~constraints.OXConstraint.RelationalOperators = RelationalOperators.EQUAL, rhs: float | int = 0, name: str = '', active_scenario: str = 'Default', scenarios: dict[str, dict[str, ~typing.Any]] = <factory>)[source]

Bases: OXObject

A constraint in an optimization problem with scenario support.

A constraint represents a relationship between an expression and a value, such as “2x + 3y <= 10”. This class supports multiple scenarios, allowing different constraint parameters (RHS values, names, operators) to be defined for different optimization scenarios.

The scenario system enables sensitivity analysis and what-if modeling by maintaining multiple constraint configurations within the same constraint object.

expression

The left-hand side of the constraint.

Type:

OXpression

relational_operator

The operator (>, >=, =, <, <=).

Type:

RelationalOperators

rhs

The right-hand side value.

Type:

float | int

name

A descriptive name for the constraint.

Type:

str

active_scenario

The name of the currently active scenario.

Type:

str

scenarios

Dictionary mapping scenario names to dictionaries of attribute values for that scenario.

Type:

dict[str, dict[str, Any]]

Examples

Basic constraint creation:

>>> from constraints.OXpression import OXpression
>>> expr = OXpression(variables=[x.id, y.id], weights=[2, 3])
>>> constraint = OXConstraint(
...     expression=expr,
...     relational_operator=RelationalOperators.LESS_THAN_EQUAL,
...     rhs=10,
...     name="Capacity constraint"
... )

Scenario-based constraint management:

>>> # Create constraint with base values
>>> constraint = OXConstraint(
...     expression=expr,
...     relational_operator=RelationalOperators.LESS_THAN_EQUAL,
...     rhs=100,
...     name="Production capacity"
... )
>>>
>>> # Create scenarios with different RHS values
>>> constraint.create_scenario("High_Capacity", rhs=150, name="High capacity scenario")
>>> constraint.create_scenario("Low_Capacity", rhs=80, name="Reduced capacity scenario")
>>>
>>> # Switch between scenarios
>>> print(constraint.rhs)  # 100 (Default scenario)
>>>
>>> constraint.active_scenario = "High_Capacity"
>>> print(constraint.rhs)  # 150
>>> print(constraint.name)  # "High capacity scenario"
>>>
>>> constraint.active_scenario = "Low_Capacity"
>>> print(constraint.rhs)  # 80
expression: OXpression
relational_operator: RelationalOperators = '='
rhs: float | int = 0
name: str = ''
active_scenario: str = 'Default'
scenarios: dict[str, dict[str, Any]]
__getattribute__(item)[source]

Custom attribute access that checks the active scenario first.

When an attribute is accessed, this method first checks if it exists in the active scenario, and if not, falls back to the object’s own attribute. This enables transparent scenario switching for constraint parameters.

Parameters:

item (str) – The name of the attribute to access.

Returns:

The value of the attribute in the active scenario, or the

object’s own attribute if not found in the active scenario.

Return type:

Any

Examples

>>> constraint = OXConstraint(rhs=100)
>>> constraint.create_scenario("High_RHS", rhs=150)
>>> print(constraint.rhs)  # 100 (Default)
>>> constraint.active_scenario = "High_RHS"
>>> print(constraint.rhs)  # 150 (from scenario)
create_scenario(scenario_name: str, **kwargs)[source]

Create a new scenario with the specified constraint attribute values.

If the “Default” scenario doesn’t exist yet, it is created first, capturing the constraint’s current attribute values. This enables systematic scenario-based analysis while preserving the original constraint configuration.

Parameters:
  • scenario_name (str) – The name of the new scenario.

  • **kwargs – Constraint attribute-value pairs for the new scenario. Common attributes include: - rhs (float | int): Right-hand side value - name (str): Constraint name for this scenario - relational_operator (RelationalOperators): Constraint operator

Raises:

OXception – If an attribute in kwargs doesn’t exist in the constraint object.

Examples

Creating RHS scenarios for sensitivity analysis:

>>> constraint = OXConstraint(
...     expression=expr,
...     relational_operator=RelationalOperators.LESS_THAN_EQUAL,
...     rhs=100,
...     name="Base capacity"
... )
>>>
>>> # Create scenarios with different RHS values
>>> constraint.create_scenario("High_Demand", rhs=150, name="Peak capacity")
>>> constraint.create_scenario("Low_Demand", rhs=75, name="Reduced capacity")
>>> constraint.create_scenario("Critical", rhs=200, name="Emergency capacity")
>>>
>>> # Switch scenarios and access values
>>> constraint.active_scenario = "High_Demand"
>>> print(f"RHS: {constraint.rhs}, Name: {constraint.name}")
>>> # Output: RHS: 150, Name: Peak capacity

Creating operator scenarios for constraint type analysis:

>>> constraint.create_scenario("Equality",
...     relational_operator=RelationalOperators.EQUAL,
...     name="Exact capacity requirement"
... )
>>> constraint.create_scenario("Lower_Bound",
...     relational_operator=RelationalOperators.GREATER_THAN_EQUAL,
...     name="Minimum capacity requirement"
... )
reverse()[source]

Reverse the relational operator of the constraint.

This method changes the relational operator to its opposite: - GREATER_THAN becomes LESS_THAN - GREATER_THAN_EQUAL becomes LESS_THAN_EQUAL - EQUAL remains EQUAL - LESS_THAN becomes GREATER_THAN - LESS_THAN_EQUAL becomes GREATER_THAN_EQUAL

Returns:

A new constraint with the reversed operator.

Return type:

OXConstraint

property rhs_numerator

Get the numerator of the right-hand side as a fraction.

Returns:

The numerator of the right-hand side.

Return type:

int

property rhs_denominator

Get the denominator of the right-hand side as a fraction.

Returns:

The denominator of the right-hand side.

Return type:

int

to_goal(upper_bound: int | float | Fraction = 100) OXGoalConstraint[source]

Convert this constraint to a goal constraint for goal programming.

The conversion sets the relational operator to EQUAL and sets the desired deviation variables based on the original operator.

Returns:

A new goal constraint based on this constraint.

Return type:

OXGoalConstraint

See also

OXGoalConstraint

__init__(id: ~uuid.UUID = <factory>, class_name: str = '', expression: ~constraints.OXpression.OXpression = <factory>, relational_operator: ~constraints.OXConstraint.RelationalOperators = RelationalOperators.EQUAL, rhs: float | int = 0, name: str = '', active_scenario: str = 'Default', scenarios: dict[str, dict[str, ~typing.Any]] = <factory>) None
class constraints.OXGoalConstraint(id: ~uuid.UUID = <factory>, class_name: str = '', expression: ~constraints.OXpression.OXpression = <factory>, relational_operator: ~constraints.OXConstraint.RelationalOperators = RelationalOperators.EQUAL, rhs: float | int = 0, name: str = '', active_scenario: str = 'Default', scenarios: dict[str, dict[str, ~typing.Any]] = <factory>, positive_deviation_variable: ~variables.OXDeviationVar.OXDeviationVar = <factory>, negative_deviation_variable: ~variables.OXDeviationVar.OXDeviationVar = <factory>)[source]

Bases: OXConstraint

A goal constraint for goal programming.

A goal constraint extends a regular constraint by adding deviation variables that measure how much the constraint is violated. In goal programming, the objective is typically to minimize undesired deviations.

positive_deviation_variable

The variable representing positive deviation from the goal.

Type:

OXDeviationVar

negative_deviation_variable

The variable representing negative deviation from the goal.

Type:

OXDeviationVar

Examples

>>> goal = constraint.to_goal()
>>> print(goal.positive_deviation_variable.desired)
False
>>> print(goal.negative_deviation_variable.desired)
True
positive_deviation_variable: OXDeviationVar
negative_deviation_variable: OXDeviationVar
property desired_variables: list[OXDeviationVar]

Get the list of desired deviation variables.

Returns:

A list of deviation variables marked as desired.

Return type:

list[OXDeviationVar]

property undesired_variables: list[OXDeviationVar]

Get the list of undesired deviation variables.

Returns:

A list of deviation variables not marked as desired.

Return type:

list[OXDeviationVar]

__init__(id: ~uuid.UUID = <factory>, class_name: str = '', expression: ~constraints.OXpression.OXpression = <factory>, relational_operator: ~constraints.OXConstraint.RelationalOperators = RelationalOperators.EQUAL, rhs: float | int = 0, name: str = '', active_scenario: str = 'Default', scenarios: dict[str, dict[str, ~typing.Any]] = <factory>, positive_deviation_variable: ~variables.OXDeviationVar.OXDeviationVar = <factory>, negative_deviation_variable: ~variables.OXDeviationVar.OXDeviationVar = <factory>) None

Constraint Collections

class constraints.OXConstraintSet(id: ~uuid.UUID = <factory>, class_name: str = '', objects: list[~base.OXObject.OXObject] = <factory>)[source]

Bases: OXObjectPot

A specialized container for managing OXConstraint objects.

OXConstraintSet extends OXObjectPot to provide a type-safe container specifically designed for managing collections of OXConstraint objects. It ensures that only OXConstraint instances can be added or removed from the set, and provides specialized query functionality for finding constraints based on their metadata.

This class is particularly useful for organizing constraints in optimization problems by category, type, or other metadata attributes stored in the constraint’s related_data dictionary.

Inherits all attributes from OXObjectPot
- objects

List of constraint objects in the set

Type:

list[OXObject]

- id

Unique identifier for the constraint set

Type:

str

- name

Human-readable name for the constraint set

Type:

str

add_object(obj)[source]

Add an OXConstraint to the set

remove_object(obj)[source]

Remove an OXConstraint from the set

query(**kwargs)

Find constraints by metadata attributes

Raises:

OXception – When attempting to add/remove non-OXConstraint objects

Examples

>>> # Create a constraint set for capacity constraints
>>> capacity_set = OXConstraintSet(name="Capacity Constraints")
>>>
>>> # Add constraints with metadata
>>> for i, constraint in enumerate(capacity_constraints):
...     constraint.related_data["category"] = "capacity"
...     constraint.related_data["priority"] = "high"
...     capacity_set.add_object(constraint)
>>>
>>> # Query by metadata
>>> high_priority = capacity_set.query(priority="high")
>>> capacity_constraints = capacity_set.query(category="capacity")
>>>
>>> # Check set size
>>> print(f"Total constraints: {len(capacity_set)}")
>>>
>>> # Iterate through constraints
>>> for constraint in capacity_set:
...     print(f"Constraint: {constraint.name}")
add_object(obj: OXObject)[source]

Add an OXConstraint object to the constraint set.

This method provides type-safe addition of constraint objects to the set. Only OXConstraint instances are allowed to be added to maintain the integrity of the constraint set.

Parameters:

obj (OXObject) – The constraint object to add. Must be an instance of OXConstraint.

Raises:

OXception – If the object is not an instance of OXConstraint.

Examples

>>> constraint_set = OXConstraintSet()
>>> constraint = OXConstraint(...)
>>> constraint_set.add_object(constraint)
>>> print(len(constraint_set))  # 1
remove_object(obj: OXObject)[source]

Remove an OXConstraint object from the constraint set.

This method provides type-safe removal of constraint objects from the set. Only OXConstraint instances are allowed to be removed to maintain the integrity of the constraint set.

Parameters:

obj (OXObject) – The constraint object to remove. Must be an instance of OXConstraint.

Raises:

OXception – If the object is not an instance of OXConstraint.

Examples

>>> constraint_set = OXConstraintSet()
>>> constraint = OXConstraint(...)
>>> constraint_set.add_object(constraint)
>>> constraint_set.remove_object(constraint)
>>> print(len(constraint_set))  # 0
__init__(id: ~uuid.UUID = <factory>, class_name: str = '', objects: list[~base.OXObject.OXObject] = <factory>) None

Mathematical Expressions

class constraints.OXpression(id: ~uuid.UUID = <factory>, class_name: str = '', variables: list[~uuid.UUID] = <factory>, weights: list[float | int | ~fractions.Fraction] = <factory>)[source]

Bases: OXObject

Mathematical expression representing linear combinations of optimization variables.

OXpression is a fundamental component of the OptiX optimization framework that represents linear mathematical expressions in the form: c₁x₁ + c₂x₂ + … + cₙxₙ, where cᵢ are coefficients (weights) and xᵢ are decision variables.

This class is designed to handle expressions used in both constraint definitions and objective functions within optimization problems. It provides precise arithmetic handling through fraction-based calculations to avoid floating-point precision errors that can occur in mathematical optimization.

The class maintains variable references using UUIDs rather than direct object references, enabling serialization, persistence, and cross-system compatibility. This design pattern supports distributed optimization scenarios and model persistence.

Key Features:
  • UUID-based variable referencing for serialization safety

  • Automatic conversion between floating-point and integer coefficient representations

  • Fraction-based arithmetic for mathematical precision

  • Iterator support for easy traversal of variable-coefficient pairs

  • Integration with OptiX constraint and objective function systems

  • Support for multiple numeric types (int, float, Fraction, Decimal)

variables

Ordered list of variable UUIDs that participate in this expression. The order corresponds to the order of coefficients in the weights list.

Type:

list[UUID]

weights

Ordered list of coefficients (weights) for each variable. Supports mixed numeric types with automatic conversion.

Type:

list[float | int | Fraction]

Type Parameters:

The class inherits from OXObject, providing UUID-based identity and serialization capabilities.

Example

Basic usage of OXpression for creating mathematical expressions:

from uuid import UUID
from constraints import OXpression
from variables import OXVariable

# Create some optimization variables
x = OXVariable(name="production_x", lower_bound=0, upper_bound=100)
y = OXVariable(name="production_y", lower_bound=0, upper_bound=50)
z = OXVariable(name="production_z", lower_bound=0)

# Create expression: 2.5x + 1.75y + 3z (production cost function)
cost_expr = OXpression(
    variables=[x.id, y.id, z.id],
    weights=[2.5, 1.75, 3.0]
)

# Access expression properties
print(f"Variables in expression: {cost_expr.number_of_variables}")  # 3
print(f"Integer weights: {cost_expr.integer_weights}")              # [10, 7, 12]
print(f"Common denominator: {cost_expr.integer_denominator}")       # 4

# Iterate through variable-coefficient pairs
for var_uuid, coefficient in cost_expr:
    print(f"Variable {var_uuid}: coefficient = {coefficient}")

# Example with mixed coefficient types
mixed_expr = OXpression(
    variables=[x.id, y.id],
    weights=[Fraction(1, 3), 0.75]  # Mixed Fraction and float
)

Note

  • Variables are referenced by UUID to support serialization and persistence

  • The weights list must have the same length as the variables list

  • Automatic fraction conversion ensures mathematical precision for optimization solvers

  • The class supports empty expressions (no variables/weights) for initialization

  • All weight types are converted to fractions internally for consistent arithmetic

Warning

Ensure that the variables and weights lists maintain corresponding order and equal length. Mismatched lengths will result in undefined behavior during iteration and calculations.

See also

OXVariable: Decision variables used in expressions OXConstraint: Constraints that use OXpression for left-hand sides calculate_fraction: Internal function for precise fraction conversion get_integer_numerator_and_denominators: Utility for solver-compatible representations

variables: list[UUID]
weights: list[float | int | Fraction]
property number_of_variables: int

Get the total count of variables participating in this mathematical expression.

This property provides a convenient way to determine the dimensionality of the linear expression, which is useful for validation, debugging, and solver setup. The count represents the number of decision variables that have non-zero coefficients in this expression.

Returns:

The total number of variables in the expression. Returns 0 for empty

expressions (expressions with no variables or coefficients).

Return type:

int

Note

  • The count is based on the length of the variables list

  • Empty expressions return 0, which is valid for initialization scenarios

  • The count should match the length of the weights list for consistency

Example

# Create expression with three variables
expr = OXpression(
    variables=[var1_id, var2_id, var3_id],
    weights=[1.0, 2.5, 0.75]
)
print(expr.number_of_variables)  # Output: 3

# Empty expression
empty_expr = OXpression()
print(empty_expr.number_of_variables)  # Output: 0
property integer_weights: list[int]

Convert expression coefficients to integer representations with common denominator.

This property transforms all variable coefficients from their original numeric types (float, int, Fraction, Decimal) into integer values by finding a common denominator and scaling appropriately. This conversion is essential for optimization solvers that require integer coefficients while maintaining mathematical precision.

The conversion process: 1. Converts each weight to its exact fractional representation 2. Finds the least common multiple (LCM) of all denominators 3. Scales all numerators to use the common denominator 4. Returns the scaled integer numerators

Returns:

Integer representations of all coefficients, scaled by the common

denominator. The order corresponds to the variables list order. Returns empty list if no weights are present.

Return type:

list[int]

Note

  • Maintains exact mathematical precision through fraction arithmetic

  • The integer values represent numerators when using the common denominator

  • Use integer_denominator property to get the corresponding denominator

  • Essential for solvers like CPLEX or Gurobi that prefer integer coefficients

Example

# Expression with decimal coefficients
expr = OXpression(
    variables=[x_id, y_id, z_id],
    weights=[0.5, 1.25, 2.0]
)

print(expr.integer_weights)      # [2, 5, 8]
print(expr.integer_denominator)  # 4

# Verification: 2/4 = 0.5, 5/4 = 1.25, 8/4 = 2.0

See also

integer_denominator: Get the common denominator for these integer weights get_integer_numerator_and_denominators: The underlying conversion function

property integer_denominator: int

Get the common denominator used for integer weight representation.

This property returns the least common multiple (LCM) of all denominators in the fractional representations of the expression coefficients. When combined with the integer_weights property, it allows for exact reconstruction of the original coefficient values while providing integer representations suitable for optimization solvers.

The denominator represents the scaling factor applied to convert floating-point or fractional coefficients into integers. This approach maintains mathematical precision and avoids floating-point arithmetic errors in optimization calculations.

Returns:

The common denominator for all coefficients in the expression.

Returns 1 if all weights are integers, or the LCM of all fractional denominators if floating-point weights are present. Returns 1 for empty expressions.

Return type:

int

Note

  • Always returns a positive integer value

  • The LCM approach ensures the smallest possible common denominator

  • Combined with integer_weights, provides exact coefficient representation

  • Essential for maintaining precision in constraint and objective definitions

Example

# Expression with fractional coefficients
expr = OXpression(
    variables=[x_id, y_id, z_id],
    weights=[0.5, 0.25, 1.75]  # 1/2, 1/4, 7/4
)

print(expr.integer_denominator)  # 4 (LCM of 2, 4, 4)
print(expr.integer_weights)      # [2, 1, 7]

# Verification: 2/4 = 0.5, 1/4 = 0.25, 7/4 = 1.75

# Expression with integer coefficients
int_expr = OXpression(
    variables=[x_id, y_id],
    weights=[2, 3]
)
print(int_expr.integer_denominator)  # 1

See also

integer_weights: Get the integer numerators for these coefficients get_integer_numerator_and_denominators: The underlying conversion function

__iter__()[source]

Enable iteration over variable-coefficient pairs in the mathematical expression.

This method implements the iterator protocol, allowing the OXpression object to be used in for-loops and other iteration contexts. It yields tuples of (variable_uuid, coefficient) pairs, maintaining the order defined in the variables and weights lists.

The iterator is particularly useful for: - Traversing expression terms for solver setup - Debugging and validation of expression contents - Serialization and persistence operations - Constructing string representations of expressions

Yields:

tuple[UUID, float | int | Fraction]

Each iteration yields a tuple containing:
  • UUID: The unique identifier of the variable

  • float | int | Fraction: The coefficient (weight) for that variable

Note

  • Iteration order matches the order of variables and weights lists

  • Empty expressions will not yield any items

  • The yielded coefficients maintain their original numeric types

  • Supports standard Python iteration protocols (for loops, list comprehension, etc.)

Example

from uuid import uuid4
from fractions import Fraction

# Create expression with mixed coefficient types
expr = OXpression(
    variables=[uuid4(), uuid4(), uuid4()],
    weights=[2.5, 3, Fraction(1, 2)]
)

# Iterate over variable-coefficient pairs
for var_uuid, coefficient in expr:
    print(f"Variable {var_uuid}: coefficient = {coefficient}")

# Use in list comprehension
terms = [(str(var_id)[:8], coef) for var_id, coef in expr]
print(f"Expression terms: {terms}")

# Convert to dictionary
expr_dict = dict(expr)

# Count terms
term_count = len(list(expr))
Raises:

ValueError – If variables and weights lists have different lengths (this would indicate a malformed expression)

__init__(id: ~uuid.UUID = <factory>, class_name: str = '', variables: list[~uuid.UUID] = <factory>, weights: list[float | int | ~fractions.Fraction] = <factory>) None
constraints.get_integer_numerator_and_denominators(numbers: list[float | int]) tuple[int, list[int]][source]

Convert a list of floating-point or integer weights to integer representations.

This function takes a collection of numeric values (which may include floating-point numbers and integers) and converts them to exact integer representations by finding a common denominator. This is essential for optimization solvers that require integer coefficients while maintaining mathematical precision.

The function works by: 1. Converting each number to its fractional representation using calculate_fraction() 2. Finding the least common multiple (LCM) of all denominators 3. Scaling all numerators by appropriate factors to use the common denominator 4. Returning both the common denominator and the scaled integer numerators

Parameters:

numbers (list[float | int]) – A list of numeric values to convert to integer representations. Can contain floating-point numbers, integers, or a mix of both types.

Returns:

A tuple containing:
  • int: The common denominator for all converted values

  • list[int]: List of integer numerators corresponding to each input number

    when expressed with the common denominator

Return type:

tuple[int, list[int]]

Raises:
  • ValueError – If the input list is empty or contains non-numeric values.

  • ZeroDivisionError – If any input number results in a zero denominator.

Note

  • All calculations maintain exact precision through Fraction arithmetic

  • The LCM approach ensures the smallest possible common denominator

  • Integer inputs are handled efficiently as Fraction(value, 1)

  • Useful for preparing coefficients for linear programming solvers

Example

# Convert mixed numeric types
numbers = [0.5, 1.5, 2, 0.25]
denominator, numerators = get_integer_numerator_and_denominators(numbers)
print(f"Common denominator: {denominator}")  # 4
print(f"Integer numerators: {numerators}")   # [2, 6, 8, 1]

# Verify the conversion
for i, num in enumerate(numbers):
    converted = numerators[i] / denominator
    print(f"{num} = {numerators[i]}/{denominator} = {converted}")

# Example with simple fractions
simple_fractions = [0.5, 1.5, 2.0]
denom, nums = get_integer_numerator_and_denominators(simple_fractions)
# Returns: (2, [1, 3, 4]) representing [1/2, 3/2, 4/2]

See also

calculate_fraction: Used internally to convert individual numbers to fractions math.lcm: Used to find the least common multiple of denominators

Special Constraints

class constraints.OXSpecialConstraint(id: ~uuid.UUID = <factory>, class_name: str = '')[source]

Bases: OXObject

Base class for special constraints in optimization problems.

Special constraints are non-linear constraints that cannot be expressed as simple linear relationships. They require special handling by solvers and often involve complex relationships between variables.

This class serves as a base for all special constraint types including multiplicative, division, modulo, summation, and conditional constraints.

__init__(id: ~uuid.UUID = <factory>, class_name: str = '') None
class constraints.OXNonLinearEqualityConstraint(id: ~uuid.UUID = <factory>, class_name: str = '', output_variable: ~uuid.UUID = <factory>)[source]

Bases: OXSpecialConstraint

Base class for non-linear equality constraints.

Non-linear equality constraints represent relationships that cannot be expressed as linear combinations of variables. They typically have the form f(x1, x2, …, xn) = output_variable, where f is a non-linear function.

output_variable

The UUID of the variable that stores the result of the non-linear operation.

Type:

UUID

Examples

This is a base class and should not be instantiated directly. Use specific subclasses like OXMultiplicativeEqualityConstraint.

output_variable: UUID
__init__(id: ~uuid.UUID = <factory>, class_name: str = '', output_variable: ~uuid.UUID = <factory>) None
class constraints.OXMultiplicativeEqualityConstraint(id: ~uuid.UUID = <factory>, class_name: str = '', output_variable: ~uuid.UUID = <factory>, input_variables: list[~uuid.UUID] = <factory>)[source]

Bases: OXNonLinearEqualityConstraint

A constraint representing multiplication of variables.

This constraint enforces that the output variable equals the product of all input variables: output_variable = input_variable_1 * input_variable_2 * … * input_variable_n

input_variables

The list of variable UUIDs to multiply.

Type:

list[UUID]

output_variable

The UUID of the variable that stores the product. Inherited from OXNonLinearEqualityConstraint.

Type:

UUID

Examples

>>> # Create a constraint: z = x * y
>>> constraint = OXMultiplicativeEqualityConstraint(
...     input_variables=[x.id, y.id],
...     output_variable=z.id
... )

Note

This constraint is typically handled by constraint programming solvers that support non-linear operations.

input_variables: list[UUID]
__init__(id: ~uuid.UUID = <factory>, class_name: str = '', output_variable: ~uuid.UUID = <factory>, input_variables: list[~uuid.UUID] = <factory>) None
class constraints.OXDivisionEqualityConstraint(id: ~uuid.UUID = <factory>, class_name: str = '', output_variable: ~uuid.UUID = <factory>, input_variable: ~uuid.UUID = <factory>, denominator: int = 1)[source]

Bases: OXNonLinearEqualityConstraint

A constraint representing integer division of a variable.

This constraint enforces that the output variable equals the integer division of the input variable by the denominator: output_variable = input_variable // denominator

input_variable

The UUID of the variable to divide.

Type:

UUID

denominator

The divisor for the division operation.

Type:

int

output_variable

The UUID of the variable that stores the quotient. Inherited from OXNonLinearEqualityConstraint.

Type:

UUID

Examples

>>> # Create a constraint: z = x // 3
>>> constraint = OXDivisionEqualityConstraint(
...     input_variable=x.id,
...     denominator=3,
...     output_variable=z.id
... )

Note

This constraint performs integer division (floor division), not floating-point division.

input_variable: UUID
denominator: int = 1
__init__(id: ~uuid.UUID = <factory>, class_name: str = '', output_variable: ~uuid.UUID = <factory>, input_variable: ~uuid.UUID = <factory>, denominator: int = 1) None
class constraints.OXModuloEqualityConstraint(id: ~uuid.UUID = <factory>, class_name: str = '', output_variable: ~uuid.UUID = <factory>, input_variable: ~uuid.UUID = <factory>, denominator: int = 1)[source]

Bases: OXNonLinearEqualityConstraint

A constraint representing modulo operation on a variable.

This constraint enforces that the output variable equals the remainder of the input variable divided by the denominator: output_variable = input_variable % denominator

input_variable

The UUID of the variable to apply modulo to.

Type:

UUID

denominator

The divisor for the modulo operation.

Type:

int

output_variable

The UUID of the variable that stores the remainder. Inherited from OXNonLinearEqualityConstraint.

Type:

UUID

Examples

>>> # Create a constraint: z = x % 5
>>> constraint = OXModuloEqualityConstraint(
...     input_variable=x.id,
...     denominator=5,
...     output_variable=z.id
... )

Note

The result is always non-negative and less than the denominator.

input_variable: UUID
denominator: int = 1
__init__(id: ~uuid.UUID = <factory>, class_name: str = '', output_variable: ~uuid.UUID = <factory>, input_variable: ~uuid.UUID = <factory>, denominator: int = 1) None
class constraints.OXSummationEqualityConstraint(id: ~uuid.UUID = <factory>, class_name: str = '', input_variables: list[~uuid.UUID] = <factory>, output_variable: ~uuid.UUID = <factory>)[source]

Bases: OXSpecialConstraint

A constraint representing summation of variables.

This constraint enforces that the output variable equals the sum of all input variables: output_variable = input_variable_1 + input_variable_2 + … + input_variable_n

input_variables

The list of variable UUIDs to sum.

Type:

list[UUID]

output_variable

The UUID of the variable that stores the sum.

Type:

UUID

Examples

>>> # Create a constraint: z = x + y + w
>>> constraint = OXSummationEqualityConstraint(
...     input_variables=[x.id, y.id, w.id],
...     output_variable=z.id
... )

Note

While this could be expressed as a linear constraint, it’s included as a special constraint for consistency and solver optimization.

input_variables: list[UUID]
output_variable: UUID
__init__(id: ~uuid.UUID = <factory>, class_name: str = '', input_variables: list[~uuid.UUID] = <factory>, output_variable: ~uuid.UUID = <factory>) None
class constraints.OXConditionalConstraint(id: ~uuid.UUID = <factory>, class_name: str = '', indicator_variable: ~uuid.UUID = <factory>, input_constraint: ~uuid.UUID = <factory>, constraint_if_true: ~uuid.UUID = <factory>, constraint_if_false: ~uuid.UUID = <factory>)[source]

Bases: OXSpecialConstraint

A constraint representing conditional logic.

This constraint enforces different constraints based on the value of an indicator variable. If the indicator variable is true, constraint_if_true is enforced; otherwise, constraint_if_false is enforced.

indicator_variable

The UUID of the boolean variable that determines which constraint to enforce.

Type:

UUID

input_constraint

The UUID of the base constraint to evaluate.

Type:

UUID

constraint_if_true

The UUID of the constraint to enforce if the indicator variable is true.

Type:

UUID

constraint_if_false

The UUID of the constraint to enforce if the indicator variable is false.

Type:

UUID

Examples

>>> # Create a conditional constraint: if flag then x >= 5 else x <= 3
>>> constraint = OXConditionalConstraint(
...     indicator_variable=flag.id,
...     input_constraint=base_constraint.id,
...     constraint_if_true=upper_bound_constraint.id,
...     constraint_if_false=lower_bound_constraint.id
... )

Note

This constraint is used for modeling logical implications and conditional relationships in optimization problems.

indicator_variable: UUID
input_constraint: UUID
constraint_if_true: UUID
constraint_if_false: UUID
__init__(id: ~uuid.UUID = <factory>, class_name: str = '', indicator_variable: ~uuid.UUID = <factory>, input_constraint: ~uuid.UUID = <factory>, constraint_if_true: ~uuid.UUID = <factory>, constraint_if_false: ~uuid.UUID = <factory>) None

Enumerations

class constraints.RelationalOperators(*values)[source]

Enumeration of relational operators for constraints.

These operators define the relationship between the left-hand side (expression) and right-hand side (rhs) of a constraint.

GREATER_THAN

The “>” operator.

Type:

str

GREATER_THAN_EQUAL

The “>=” operator.

Type:

str

EQUAL

The “=” operator.

Type:

str

LESS_THAN

The “<” operator.

Type:

str

LESS_THAN_EQUAL

The “<=” operator.

Type:

str

Available operators:

  • GREATER_THAN - Greater than (>)

  • GREATER_THAN_EQUAL - Greater than or equal (>=)

  • EQUAL - Equal (=)

  • LESS_THAN - Less than (<)

  • LESS_THAN_EQUAL - Less than or equal (<=)

GREATER_THAN = '>'
GREATER_THAN_EQUAL = '>='
EQUAL = '='
LESS_THAN = '<'
LESS_THAN_EQUAL = '<='

Examples

Basic Linear Constraints

from constraints import OXConstraint, OXpression, RelationalOperators
from variables import OXVariable

# Create variables
x = OXVariable(name="x", lower_bound=0, upper_bound=100)
y = OXVariable(name="y", lower_bound=0, upper_bound=100)

# Create expression: 2x + 3y
expr = OXpression(variables=[x.id, y.id], weights=[2, 3])

# Create constraint: 2x + 3y <= 500
constraint = OXConstraint(
    expression=expr,
    relational_operator=RelationalOperators.LESS_THAN_EQUAL,
    rhs=500,
    name="Resource capacity constraint"
)

print(f"Constraint: {constraint}")

Goal Programming Constraints

from constraints import OXConstraint, RelationalOperators

# Create a regular constraint
constraint = OXConstraint(
    expression=expr,
    relational_operator=RelationalOperators.LESS_THAN_EQUAL,
    rhs=100,
    name="Production target"
)

# Convert to goal constraint
goal_constraint = constraint.to_goal()

# Check deviation variables
print(f"Positive deviation desired: {goal_constraint.positive_deviation_variable.desired}")
print(f"Negative deviation desired: {goal_constraint.negative_deviation_variable.desired}")

Constraint Sets

from constraints import OXConstraintSet, OXConstraint

# Create constraint set
constraint_set = OXConstraintSet(name="Production Constraints")

# Add constraints to the set
for i, constraint in enumerate(production_constraints):
    # Add metadata for querying
    constraint.related_data["category"] = "production"
    constraint.related_data["priority"] = "high" if i < 3 else "medium"
    constraint_set.add_object(constraint)

print(f"Total constraints: {len(constraint_set)}")

# Query constraints by metadata
high_priority = constraint_set.query(priority="high")
production_constraints = constraint_set.query(category="production")

Mathematical Expressions

from constraints import OXpression
from variables import OXVariable

# Create variables
x = OXVariable(name="x", lower_bound=0)
y = OXVariable(name="y", lower_bound=0)
z = OXVariable(name="z", lower_bound=0)

# Create expression: 2.5x + 1.5y + 3z
expr = OXpression(
    variables=[x.id, y.id, z.id],
    weights=[2.5, 1.5, 3]
)

# Access variable coefficients
for var_id, weight in zip(expr.variables, expr.weights):
    print(f"Variable {var_id}: coefficient {weight}")

# Convert to integer coefficients
int_weights, denominator = expr.get_integer_weights()
print(f"Integer weights: {int_weights}, common denominator: {denominator}")

Special Constraints

from constraints import OXMultiplicativeEqualityConstraint, OXDivisionEqualityConstraint
from variables import OXVariable

# Create variables for multiplication
x = OXVariable(name="x", lower_bound=0, upper_bound=50)
y = OXVariable(name="y", lower_bound=0, upper_bound=50)
product = OXVariable(name="product", lower_bound=0, upper_bound=2500)

# Multiplication constraint: x * y = product
mult_constraint = OXMultiplicativeEqualityConstraint(
    left_variable_id=x.id,
    right_variable_id=y.id,
    result_variable_id=product.id,
    name="Product calculation"
)

# Division constraint: x / y = quotient (integer division)
quotient = OXVariable(name="quotient", lower_bound=0, upper_bound=100)
div_constraint = OXDivisionEqualityConstraint(
    left_variable_id=x.id,
    right_variable_id=y.id,
    result_variable_id=quotient.id,
    name="Division calculation"
)

Conditional Constraints

from constraints import OXConditionalConstraint
from variables import OXVariable

# Create binary variables
condition = OXVariable(name="use_machine", lower_bound=0, upper_bound=1, variable_type="binary")
production = OXVariable(name="production", lower_bound=0, upper_bound=100)
cost = OXVariable(name="cost", lower_bound=0, upper_bound=1000)

# Conditional constraint: if use_machine then production >= 10
conditional = OXConditionalConstraint(
    condition_variable_id=condition.id,
    implication_variable_id=production.id,
    threshold_value=10,
    name="Minimum production when machine is used"
)

Constraint Validation

def validate_constraint_satisfaction(constraint, variable_values):
    """Check if a constraint is satisfied by given variable values."""

    # Calculate left-hand side value
    lhs_value = 0
    for var_id, weight in zip(constraint.expression.variables, constraint.expression.weights):
        lhs_value += weight * variable_values.get(var_id, 0)

    # Check constraint satisfaction
    tolerance = 1e-6

    if constraint.relational_operator == RelationalOperators.LESS_THAN_EQUAL:
        return lhs_value <= constraint.rhs + tolerance
    elif constraint.relational_operator == RelationalOperators.GREATER_THAN_EQUAL:
        return lhs_value >= constraint.rhs - tolerance
    elif constraint.relational_operator == RelationalOperators.EQUAL:
        return abs(lhs_value - constraint.rhs) <= tolerance
    elif constraint.relational_operator == RelationalOperators.LESS_THAN:
        return lhs_value < constraint.rhs + tolerance
    elif constraint.relational_operator == RelationalOperators.GREATER_THAN:
        return lhs_value > constraint.rhs - tolerance

    return False

# Usage
is_satisfied = validate_constraint_satisfaction(constraint, solution_values)
print(f"Constraint satisfied: {is_satisfied}")

Precise Arithmetic with Fractions

from constraints import OXpression, get_integer_numerator_and_denominators

# Create expression with decimal coefficients
expr = OXpression(
    variables=[x.id, y.id, z.id],
    weights=[0.333, 0.667, 1.5]  # These will be converted to fractions
)

# Convert to integer representation for solver compatibility
int_weights, common_denom = get_integer_numerator_and_denominators(expr.weights)
print(f"Integer weights: {int_weights}")
print(f"Common denominator: {common_denom}")

# Access fraction properties
for i, weight in enumerate(expr.weights):
    frac_weight = expr.get_fraction_weight(i)
    print(f"Weight {i}: {frac_weight.numerator}/{frac_weight.denominator}")

See Also

  • Problem Module - Problem classes that use constraints

  • Variables Module - Variable definitions and management

  • Solvers Module - Solver implementations that handle constraints

  • ../user_guide/constraints - Advanced constraint modeling guide