Skip to content

Built-in Transformations

LunaModel provides built-in pipelines and passes for common model analysis and transformations.

Available Pipelines

ToUnconstrainedBinaryPipeline

Convert a model to an unconstrained binary model.

This pipeline transforms any model with constraints to an unconstrained binary model. It allows the input model to contain binary, spin or integer variables. Spin and integer variables are automatically converted to a binary representation. If the input model has linear constraints they are added to the model's objective as quadratic penalties scaled by the the maximum bias of the input model's objective times the penalty_scaling paramter.

Warning

If the model's constraints are not linear, an error is raised.

Available Transformation Passes

BinarySpinPass

Convert between Binary and Spin variable types.

Purpose: Transform variables between {0, 1} (binary) and {-1, +1} (spin) domains.

Usage:

Python
from luna_model.transformation.passes import BinarySpinPass
from luna_model import Vtype

# Binary → Spin
pass_to_spin = BinarySpinPass(vtype=Vtype.SPIN, prefix=None)

# Spin → Binary  
pass_to_binary = BinarySpinPass(vtype=Vtype.BINARY, prefix=None)

Example:

Python
from luna_model import Model, Vtype
from luna_model.transformation.passes import BinarySpinPass
from luna_model.transformation import PassManager

# Model with binary variables
model = Model()
x = model.add_variable("x", vtype=Vtype.BINARY)
y = model.add_variable("y", vtype=Vtype.BINARY)
model.objective = x * y + x - 2 * y

# Convert to spin
pm = PassManager([BinarySpinPass(Vtype.SPIN, prefix=None)])
ir = pm.run(model)
spin_model = ir.model

ChangeSensePass

Change optimization sense between minimization and maximization.

Purpose: Convert MIN ↔ MAX by negating the objective function.

Usage:

Python
from luna_model.transformation.passes import ChangeSensePass
from luna_model import Sense

# To minimization
pass_min = ChangeSensePass(sense=Sense.MIN)

# To maximization
pass_max = ChangeSensePass(sense=Sense.MAX)

Example:

Python
from luna_model import Model, Sense
from luna_model.transformation import PassManager

# Maximization model
model = Model(sense=Sense.MAX)
x = model.add_variable("x")
y = model.add_variable("y")
model.objective = 3 * x + 2 * y

# Convert to minimization
pm = PassManager([ChangeSensePass(Sense.MIN)])
ir = pm.run(model)
min_model = ir.model

assert min_model.sense == Sense.MIN

EqualityConstraintsToQuadraticPenaltyPass

Move all equality constraints to the model's objective as a quadratic penalties.

Purpose: Make the model unconstrained by moving all equality constraints to the objective as quadratic penalties.

Note

This pass requires the MaxBiasAnalysis pass to be executed before this pass is executed.

Caution

Less-equal (<=) or greater-equal (>=) constraints are not respected by this transformation and have to be handled before this pass using, e.g., the GeToLeConstraintsPass and the LeToEqConstraintsPass.

Example:

Python
from luna_model import Model, Vtype, Sense
from luna_model.transformation import PassManager
from luna_model.transformation.passes import MaxBiasAnalysis
from luna_model.transformation.passes import EqualityConstraintsToQuadraticPenaltyPass
model = Model(sense=Sense.MAX)
x = model.add_variable("x", vtype=Vtype.BINARY)
y = model.add_variable("y", vtype=Vtype.BINARY)
model.objective = x * y + x - 2 * y
model.constraints += x + y == 0
pm = PassManager(
    [
        MaxBiasAnalysis(),
        EqualityConstraintsToQuadraticPenaltyPass(),
    ]
)
ir = pm.run(model)
print(ir.model.objective)
# 41 x y + 21 x + 18 y

GeToLeConstraintsPass

Convert the model's constraints by chaning all greater-equal (>=) constraints to less-equal (<=) constraints.

Purpose: Simplify the kind of constraints used in the model.

Example:

Python
from luna_model import Model, Vtype, Sense
from luna_model.transformation import PassManager
from luna_model.transformation.passes import GeToLeConstraintsPass
model = Model(sense=Sense.MAX)
x = model.add_variable("x", vtype=Vtype.BINARY)
y = model.add_variable("y", vtype=Vtype.BINARY)
model.objective = x * y + x - 2 * y
model.constraints += x + y >= 0, "ge_constr"
pm = PassManager([GeToLeConstraintsPass()])
ir = pm.run(model)
ir.model.constraints["ge_constr"]
# -x - y <= 0

LeToEqConstraintsPass

Convert the model's constraints by chaning all less-equal (<=) constraints to equality (==) constraints.

Purpose: Simplify the kind of constraints used in the model.

Example:

Python
from luna_model import Model, Vtype, Sense
from luna_model.transformation import PassManager
from luna_model.transformation.passes import MinValueForConstraintAnalysis
from luna_model.transformation.passes import LeToEqConstraintsPass
model = Model(sense=Sense.MAX)
x = model.add_variable("x", vtype=Vtype.BINARY)
y = model.add_variable("y", vtype=Vtype.BINARY)
model.objective = x * y + x - 2 * y
model.constraints += x + y <= 3, "le_constr"
pm = PassManager([MinValueForConstraintAnalysis(), LeToEqConstraintsPass()])
ir = pm.run(model)
ir.model.constraints["le_constr"]
# x + y + slack_le_constr == 0
print(ir.model.get_variable("slack_le_constr"))
# slack_le_constr: Integer(lower=0, upper=3)

IntegerToBinaryPass

Convert integer variables to a binary representation.

Purpose: Transform the variables of type integer to be represented by binary typed variables.

Example:

Python
from luna_model import Model, Vtype
from luna_model.transformation import PassManager
from luna_model.transformation.passes import BinarySpinPass
model = Model()
x = model.add_variable("x", vtype=Vtype.INTEGER, lower=0, upper=3)
y = model.add_variable("y", vtype=Vtype.BINARY)
model.objective = x * y + x - 2 * y
pm = PassManager([IntegerToBinaryPass()])
ir = pm.run(model)
print(ir.model.objective)
# y x_b0 + 2 y x_b1 - 2 y + x_b0 + 2 x_b1

Available Analysis Passes

MaxBiasAnalysis

Analysis pass that computes the maximum absolute coefficient value in the objective.

Purpose: Analyze objective coefficients to determine scaling needs.

Usage:

Python
from luna_model.transformation.passes import MaxBiasAnalysis

# Create analysis pass
analysis = MaxBiasAnalysis()

Example:

Python
from luna_model import Model
from luna_model.transformation import PassManager
from luna_model.transformation.passes import MaxBiasAnalysis

model = Model()
x = model.add_variable("x")
y = model.add_variable("y")
model.objective = 1000 * x + 500 * y

# Run analysis
pm = PassManager([MaxBiasAnalysis()])
ir = pm.run(model)

CheckModelSpecsAnalysis

Analysis pass that checks the model's specs for correctness.

Purpose: Ensures the input model satisfies the specifications expected by any following passes.

Example

Python
from luna_model import Model, Vtype
from luna_model.transformation import PassManager
from luna_model.transformation.passes import CheckModelSpecsAnalysis
model = Model()
x = model.add_variable("x", vtype=Vtype.BINARY)
y = model.add_variable("y", vtype=Vtype.BINARY)
model.objective = x * y + x - 2 * y
specs = ModelSpecs(max_degree=2)
pm = PassManager([CheckModelSpecsAnalysis(specs)])
ir = pm.run(model)

MinValueForConstraintAnalysis

Analysis pass that computes the min value possible for all constraints.

Purpose: Specific information on the model's constraints that can be used by other passes in the model's transformation.

Example

Python
from luna_model import Model, Vtype
from luna_model.transformation import PassManager
from luna_model.transformation.passes import CheckModelSpecsAnalysis
model = Model()
x = model.add_variable("x", vtype=Vtype.BINARY)
y = model.add_variable("y", vtype=Vtype.BINARY)
model.objective = x * y + x - 2 * y
model.constraints += -5 * x + y <= 2, "my-constraint"
pm = PassManager([MinValueForConstraintAnalysis()])
ir = pm.run(model)
print(ir.cache["min-value-for-constraint"].vals)
# {'my-constraint': -5.0}

SpecsAnalysis

Analysis pass that computes the model's specs and stores them in the cache.

Purpose: This analysis pass can, for example, be used in combination with the IfElsePass to guide the transformation depending on the specifications (ModelSpecs) of a model.

Note

This pass is not to be confused with the CheckModelSpecsAnalysis, which checks if an input model's specs satisfy a given set of ModelSpecs.

Example

Python
from luna_model import Model, Vtype
from luna_model.transformation import PassManager
from luna_model.transformation.passes import SpecsAnalysis
model = Model()
x = model.add_variable("x", vtype=Vtype.BINARY)
y = model.add_variable("y", vtype=Vtype.BINARY)
model.objective = x * y + x - 2 * y
pm = PassManager([SpecsAnalysis()])
ir = pm.run(model)
print(ir.cache["specs"])
# ModelSpecs(sense=Minimize, vtype=Binary, constraints=, max_degree=2, max_constraint_degree=0, max_num_variables=2)

Combining Passes

Python
from luna_model.transformation import PassManager
from luna_model.transformation.passes import (
    ChangeSensePass,
    BinarySpinPass,
)
from luna_model import Sense, Vtype

# Example: prepare for quantum annealer
pm = PassManager([
    ChangeSensePass(Sense.MIN),
    BinarySpinPass(Vtype.SPIN, prefix=None),
])

ir = pm.run(model)
transformed_model = ir.model

See Also