Transformations API Reference
Pass Management
PassManager
Manage and execute a sequence of passes on a model.
The PassManager implements a compiler-style pass pattern, enabling both general-purpose and algorithm-specific manipulations of optimization models. Each pass is an atomic operation that transforms the model or extracts information from the model. The PassManager runs each pass in order and produces an IR that records the transformations applied and supports back-transformations.
Parameters:
-
passes(Sequence[BasePass], default:None) –An ordered sequence of Pass instances to apply, default None.
add(pass_: BasePass) -> None
Append a pass to the configured passes.
Parameters:
-
pass_(BasePass) –The pass to add to this PassManager's configured passes.
run(model: Model) -> IR
backwards(solution: Solution, ir: IR) -> Solution
Apply the back transformation to the given solution.
Parameters:
-
solution(Solution) –The solution to transform back to a representation fitting the original (input) model of this
PassManager. -
ir(IR) –The intermediate representation (IR) resulted from the
runcall.
Returns:
-
Solution–A solution object representing a solution to the original problem passed to this
PassManager's run method.
__str__() -> str
Human readable string.
__repr__() -> str
Debug string.
IR
Intermediate representation of a transformed model.
The IR contains the resulting model after transformation along with the analysis cache and execution log generated during execution of the PassManager.
Notes
IR objects are typically created as the result of running the PassManager
on a model. Use the model, cache, and execution_log properties to
access the transformation results.
model: Model
property
cache: AnalysisCache
property
Get the analysis cache.
Returns:
-
AnalysisCache–The analysis cache containing analysis results from running the PassManager.
execution_log: list[LogElement]
property
Get the execution log.
Returns:
-
list[LogElement]–A list of log elements documenting the pass manager process.
Pipeline
Bases: PyPipeline, PipelineProto, BasePass
A pipeline for executing multiple transformation passes in sequence.
Pipelines organize and execute multiple passes, managing dependencies and ensuring they run in the correct order.
Parameters:
-
passes(list[BasePass]) –The transformation passes to include in the pipeline.
-
name(str, default:None) –A custom name for the pipeline. If not provided, a default name will be generated.
satisfies: set[str]
property
Get the set of pass requirements that this pipeline satisfies.
Returns:
-
set of str–Names of pass requirements satisfied by executing this pipeline.
passes: list[BasePass]
property
Get all passes that are part of the pipeline.
Returns:
-
list of BasePass–The transformation passes in this pipeline.
add(new_pass: BasePass) -> None
Add a new pass to the pipeline.
Parameters:
-
new_pass(BasePass) –The transformation pass to add to the pipeline.
clear() -> None
Clear all passes from the pipeline.
Removes all transformation passes, leaving an empty pipeline.
__len__() -> int
Get the number of passes in the pipeline.
Returns:
-
int–The number of transformation passes in this pipeline.
__str__() -> str
Get a string representation of the pipeline.
Returns:
-
str–A human-readable string describing the pipeline.
__repr__() -> str
Get a detailed string representation of the pipeline for debugging.
Returns:
-
str–A detailed string representation suitable for debugging.
Pass Types
TransformationPass
Bases: PyTransformationPass, BasePass
Base class for transformation passes that modify models.
Transformation passes apply changes to models and can also convert solutions backwards to match the input representation.
Notes
This is an abstract class. Subclasses must implement the name, run,
and backwards methods.
invalidates: list[str]
property
Get a list of passes that are invalidated by this pass.
Returns:
-
list of str–Names of passes whose results become invalid after this pass runs.
run(model: Model, cache: AnalysisCache) -> TransformationOutcome | tuple[PyModel, PyActionType] | tuple[PyModel, PyActionType, Any]
abstractmethod
Run/Execute this transformation pass.
Parameters:
-
model(Model) –The model to transform.
-
cache(AnalysisCache) –Cache containing analysis results.
Returns:
-
TransformationOutcome or tuple–The transformation result, either as a TransformationOutcome object or as a tuple of (model, action_type) or (model, action_type, analysis).
backwards(solution: Solution, cache: AnalysisCache) -> Solution
abstractmethod
Convert a solution back to fit this pass' input.
Converts a solution from a representation fitting this pass' output to a solution representation fitting this pass' input.
Parameters:
-
solution(Solution) –The solution in the output representation.
-
cache(AnalysisCache) –Cache containing analysis results.
Returns:
-
Solution–The solution converted to the input representation.
AnalysisPass
Bases: PyAnalysisPass, BasePass, Generic[T]
Base class for analysis passes that compute information about models.
Analysis passes inspect models and compute results without modifying them. They can depend on other analysis passes and cache their results for efficient access in subsequent passes.
run(model: Model, cache: AnalysisCache) -> T
abstractmethod
Execute this analysis pass on a model.
Parameters:
-
model(Model) –The model to analyze.
-
cache(AnalysisCache) –Cache containing results from previous analysis passes.
Returns:
-
T–The result of the analysis.
Built-in 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.
Notes
If the model's constraints are not linear, an error is raised.
Paramters
penalty_scaling : float The factor used to scale the quadratic penalties with, by default 10.
Raises:
-
AnalysisPassError–If the model's constraints are not all linear.
Example
from luna_model import Model, Vtype from luna_model.transformation import PassManager, pipelines model = Model() x = model.add_variable("x", vtype=Vtype.BINARY) y = model.add_variable("y", vtype=Vtype.SPIN) z = model.add_variable("z", vtype=Vtype.INTEGER, lower=0, upper=12) model.objective = x + y + z model.constraints += x + y + z <= 3, "c0" model.constraints += x - y - z >= 0, "c1" model.constraints += x + y == 2, "c2" pm = PassManager([pipelines.ToUnconstrainedBinaryPipeline()]) ir = pm.run(model)
__new__(penalty_scaling: float = 10.0) -> PipelineProto
Todo.
Built-in Passes
BinarySpinPass
Bases: ConcreteTransformationPass
Convert between Binary and Spin variable types.
Transform the variables of type binary to spin typed variables or vice versa.
Target vtype is set by the vtype parameter.
Parameters:
-
vtype(Literal[BINARY, SPIN]) –The target vtype to convert the variables to. If set to
Vtype.SPINall binary variables in the model are converted to spin variables. If set toVtype.BINARYall spin variables are converted to binary variables. -
prefix(str, default:None) –An optional prefix to prepend to the name of the new variables created. If none specified a default prefix is used.
Examples:
>>> 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.BINARY)
>>> y = model.add_variable("y", vtype=Vtype.BINARY)
>>> model.objective = x * y + x - 2 * y
>>> pm = PassManager([BinarySpinPass(vtype=Vtype.SPIN)])
>>> ir = pm.run(model)
>>> spin_model = ir.model
invalidates: list[str]
property
Get a list of passes that are invalidated by this pass.
Returns:
-
list of str–Names of passes whose results become invalid after this pass runs.
vtype: Vtype
property
Get the target variable type to convert to.
prefix: str | None
property
Get the optional naming prefix.
ChangeSensePass
Bases: ConcreteTransformationPass
Change the optimization sense between minimization and maximization.
Converts the optimization sense by negating the objective function.
Parameters:
-
sense(Sense) –The target sense to convert the optimization sense to.
Examples:
>>> from luna_model import Model, Vtype, Sense
>>> from luna_model.transformation import PassManager
>>> from luna_model.transformation.passes import ChangeSensePass
>>> 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
>>> pm = PassManager([ChangeSensePass(Sense.MIN)])
>>> ir = pm.run(model)
>>> min_model = ir.model
invalidates: list[str]
property
Get a list of passes that are invalidated by this pass.
Returns:
-
list of str–Names of passes whose results become invalid after this pass runs.
sense: Sense
property
Get the target optimization sense.
MaxBiasAnalysis
Bases: ConcreteAnalysisPass
Analysis pass that computes the maximum absolute coefficient value in the objective.
Examples:
>>> from luna_model import Model, Vtype
>>> from luna_model.transformation import PassManager
>>> from luna_model.transformation.passes import MaxBiasAnalysis
>>> 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([MaxBiasAnalysis()])
>>> ir = pm.run(model)
>>> ir.cache["max-bias"].val
2.0
CheckModelSpecsAnalysis
Bases: ConcreteAnalysisPass
Analysis pass that checks the model's specs for correctness.
This analysis pass checks if the input model satisfies the
specifications (ModelSpecs) this pass is initilized with. If the specs
are not satified by the model it raises an error during runtime.
Examples:
>>> 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)
>>> # no errors raised
MinValueForConstraintAnalysis
Bases: ConcreteAnalysisPass
Analysis pass that computes the min value possible for all constraints.
This analysis pass computes the minimal value possible for all constraints of the input model.
Examples:
>>> 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)
>>> ir.cache["min-value-for-constraint"].vals
{'my-constraint': -5.0}
SpecsAnalysis
Bases: ConcreteAnalysisPass
Analysis pass that computes the model's specs and stores them in the cache.
This analysis pass computes the ModelSpecs of the input model and writes it
to the AnalysisCache to be used by transformation passes following it during
the PassManager execution. 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.
Notes
This pass is not to be confused with the CheckModelSpecsAnalysis, which checks
if an input model's specs satisfy a given set of ModelSpecs.
Examples:
>>> 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)
>>> ir.cache["specs"]
ModelSpecs(sense=Minimize, vtype=Binary, constraints=, max_degree=2, max_constraint_degree=0, max_num_variables=2)
EqualityConstraintsToQuadraticPenaltyPass
Bases: ConcreteTransformationPass
Move all equality constraints to the model's objective as a quadratic penalties.
Converts the model by moving all equality constraints to the objective as quadratic penalties.
Requires the MaxBiasAnalysis pass to be executed before this pass.
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.
Notes
This pass requires the MaxBiasAnalysis pass to be executed before this pass.
Parameters:
-
penalty_scaling(float, default:10.0) –The factor used to scale the penalties with, default 10.0.
Examples:
>>> 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
invalidates: list[str]
property
Get a list of passes that are invalidated by this pass.
Returns:
-
list of str–Names of passes whose results become invalid after this pass runs.
GeToLeConstraintsPass
Bases: ConcreteTransformationPass
Convert the model's constraints by chaning all greater-equal (>=) constraints to less-equal (<=) constraints.
Examples:
>>> 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
invalidates: list[str]
property
Get a list of passes that are invalidated by this pass.
Returns:
-
list of str–Names of passes whose results become invalid after this pass runs.
IntegerToBinaryPass
Bases: ConcreteTransformationPass
Convert integer variables to a binary representation.
Transform the variables of type integer to be represented by binary typed variables.
Examples:
>>> 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
invalidates: list[str]
property
Get a list of passes that are invalidated by this pass.
Returns:
-
list of str–Names of passes whose results become invalid after this pass runs.
LeToEqConstraintsPass
Bases: ConcreteTransformationPass
Convert the model's constraints by chaning all less-equal (<=) constraints to equality (==) constraints.
Examples:
>>> 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)
invalidates: list[str]
property
Get a list of passes that are invalidated by this pass.
Returns:
-
list of str–Names of passes whose results become invalid after this pass runs.
Decorators
TransformationPass
Bases: PyTransformationPass, BasePass
Base class for transformation passes that modify models.
Transformation passes apply changes to models and can also convert solutions backwards to match the input representation.
Notes
This is an abstract class. Subclasses must implement the name, run,
and backwards methods.
invalidates: list[str]
property
Get a list of passes that are invalidated by this pass.
Returns:
-
list of str–Names of passes whose results become invalid after this pass runs.
run(model: Model, cache: AnalysisCache) -> TransformationOutcome | tuple[PyModel, PyActionType] | tuple[PyModel, PyActionType, Any]
abstractmethod
Run/Execute this transformation pass.
Parameters:
-
model(Model) –The model to transform.
-
cache(AnalysisCache) –Cache containing analysis results.
Returns:
-
TransformationOutcome or tuple–The transformation result, either as a TransformationOutcome object or as a tuple of (model, action_type) or (model, action_type, analysis).
backwards(solution: Solution, cache: AnalysisCache) -> Solution
abstractmethod
Convert a solution back to fit this pass' input.
Converts a solution from a representation fitting this pass' output to a solution representation fitting this pass' input.
Parameters:
-
solution(Solution) –The solution in the output representation.
-
cache(AnalysisCache) –Cache containing analysis results.
Returns:
-
Solution–The solution converted to the input representation.
AnalysisPass
Bases: PyAnalysisPass, BasePass, Generic[T]
Base class for analysis passes that compute information about models.
Analysis passes inspect models and compute results without modifying them. They can depend on other analysis passes and cache their results for efficient access in subsequent passes.
run(model: Model, cache: AnalysisCache) -> T
abstractmethod
Execute this analysis pass on a model.
Parameters:
-
model(Model) –The model to analyze.
-
cache(AnalysisCache) –Cache containing results from previous analysis passes.
Returns:
-
T–The result of the analysis.
Control Flow
IfElsePass
Bases: PyIfElsePass, BasePass
Conditional pass that executes different pipelines based on a runtime condition.
The IfElsePass evaluates a condition function against the analysis cache at runtime
and executes either the then pipeline or the otherwise pipeline based on the result.
This enables branching logic in transformation workflows, allowing different transformation
strategies based on model properties discovered during analysis.
Parameters:
-
requires(list[str]) –List of pass names that must be run before this pass. These passes provide the data used by the condition function.
-
condition(Callable[[AnalysisCache], bool]) –A function that takes an
AnalysisCacheand returns a boolean. IfTrue, thethenpipeline is executed; otherwise, theotherwisepipeline runs. -
then(Pipeline) –The pipeline to execute when the condition evaluates to
True. -
otherwise(Pipeline) –The pipeline to execute when the condition evaluates to
False. -
name(str, default:None) –Optional name for this pass. If not provided, a default name is generated.
Examples:
Execute different transformations based on the maximum bias:
>>> from luna_model import Model, Vtype
>>> from luna_model.transformation import PassManager, Pipeline, IfElsePass
>>> from luna_model.transformation.passes import MaxBiasAnalysis, BinarySpinPass
>>> # Create conditional pass
>>> conditional = IfElsePass(
... requires=["max-bias"],
... condition=lambda cache: cache["max-bias"].val > 10.0,
... then=Pipeline([BinarySpinPass(vtype=Vtype.BINARY)]),
... otherwise=Pipeline([]),
... name="conditional-spin-conversion",
... )
Let's create a model that satisfies the condition:
>>> model = Model("example")
>>> x = model.add_variable("x", vtype=Vtype.SPIN)
>>> y = model.add_variable("y")
>>> z = model.add_variable("z")
>>> model.objective = 2 * x + 12 * y * z
And use it in the pass manager:
>>> pm = PassManager([MaxBiasAnalysis(), conditional])
>>> result = pm.run(model)
>>> print(result.model)
Model: example
Minimize
12 * y * z - 4 * x_x + 2
Binary
y z x_x
And now a model that does not satisfy the condition:
>>> model = Model("example")
>>> x = model.add_variable("x", vtype=Vtype.SPIN)
>>> y = model.add_variable("y")
>>> z = model.add_variable("z")
>>> model.objective = 2 * x + 8 * y * z
And use it in the pass manager:
>>> pm = PassManager([MaxBiasAnalysis(), conditional])
>>> result = pm.run(model)
>>> print(result.model)
Model: example
Minimize
8 * y * z + 2 * x
Binary
y z
Spin
x
Notes
The condition function has access to all analysis results computed by the passes
listed in requires. Both pipelines can contain arbitrarily complex sequences
of transformations and analyses.
The condition is evaluated once per IfElsePass execution. If you need to
re-evaluate during pipeline execution, nest multiple IfElsePass instances.
LogElement
An element of the execution log of an intermediate representation (IR).
Log elements record information about transformation passes, including the pass name, timing information, and the type of action performed.
pass_name: str
property
timing: Timing
property
kind: ActionType | None
property
Get the type of transformation action performed.
Returns:
-
ActionType or None–The type of transformation action, or None if not available.