Source code for formulation_bench.reformulation
from dataclasses import dataclass
from pathlib import Path
from .formulation import Formulation
[docs]
@dataclass(frozen=True)
class Reformulation:
"""A pair of MILP formulations with a reformulation label.
Consists of two MILP formulations ``a`` and ``b`` and a boolean ``is_reformulation``
label indicating whether ``b`` is a reformulation of ``a``. The formal definition
of *reformulation* is given in :ref:`reformulation-definition`. Positive entries
(``is_reformulation=True``) are accompanied by a Lean 4 proof whose path is
accessible via the ``lean_proof_path`` attribute; negative entries have no proof
and ``lean_proof_path`` resolves to ``None``.
Attributes
----------
a : Formulation
The base formulation.
b : Formulation
The reformulation candidate.
is_reformulation : bool
``True`` iff ``b`` is a *reformulation* of ``a``.
lean_proof_path : pathlib.Path or None
For positive entries, the path to the accompanying Lean 4 proof file. For
negative entries, ``None`` since no proof exists.
Examples
--------
Formulation ``b`` of :doc:`/problems/p12` is a reformulation of formulation ``a``::
>>> from formulation_bench import Dataset
>>> ds = Dataset("dataset")
>>> reform = ds.reformulations[80] # corresponds to p12.a -> p12.b
>>> reform.a.problem.name
'Traveling Salesman Problem (TSP)'
>>> reform.b.problem.name
'Traveling Salesman Problem (TSP)'
>>> reform.b.constraints[-1].description # cutting plane added by p12.b
'Depot-Exit Position Bound (EC1)...'
>>> reform.is_reformulation
True
"""
a: Formulation
b: Formulation
is_reformulation: bool
@property
def lean_proof_path(self) -> Path | None:
if not self.is_reformulation:
return None
problem_dir = self.a.problem.path
dataset_root = problem_dir.parent.parent
return (
dataset_root
/ "reformulations"
/ problem_dir.name
/ f"{self.a.path.name}_{self.b.path.name}.lean"
)