omnibias.discrete.proposers
Shared discrete-problem contracts, annealed relaxations, hard decoders, and optimality-gap evidence.
import omnibias.discrete.proposersModule contract & mathematical conventions
Optional discovery proposers that wrap anneal_descent.
Not registered on omnibias.core.proof.discovery.get_proposer. Pass an
instance to ~omnibias.core.proof.discovery.run_discovery. Missing torch
or jax makes AnnealDescentProposer.propose yield nothing so the caller
stays BLOCKED.
Shared formulas do not imply universal floating-point identity. Verify dtype, shape, derivative-order support, and the stated numerical assumptions for the path you use.
AnnealDescentProposer
omnibias.discrete.AnnealDescentProposerSource ↗class AnnealDescentProposerRelax -score with anneal_descent, then snap to a 0/1 vertex.
Parameters
| Name | Type & default | Contract |
|---|---|---|
backendkeyword-only | strDefault: 'torch' | See the operation contract and implementation below. |
seedkeyword-only | intDefault: 0 | See the operation contract and implementation below. |
Executed regression · anneal proposer hits toy via fallback
Recorded coverage confirms this test executed the API body. This example belongs to the pinned upstream test suite. It may use fixtures and imports from its full file. Run it from that checkout with its test dependencies installed.
def test_anneal_proposer_hits_toy_via_fallback() -> None:
pytest.importorskip("torch")
family = IntegerIntervalFamily(lo=-3, hi=3, target_square=4)
result = run_discovery(
family.statement,
family,
AnnealDescentProposer(),
budget=16,
)
assert result.status == "PROVED"
assert result.proposer == "anneal_descent"
assert result.candidate in (-2, 2)python -m pytest "packages/omnibias-discrete/tests/test_proposers.py::test_anneal_proposer_hits_toy_via_fallback" -qFields & methods
__init__method
__init__(self, *, backend: str='torch', seed: int=0) -> NoneSee the class contract above and the exact method implementation below.
Parameters
| Name | Type & default | Contract |
|---|---|---|
backendkeyword-only | strDefault: 'torch' | See the operation contract and implementation below. |
seedkeyword-only | intDefault: 0 | See the operation contract and implementation below. |
Returns: None
Executed regression · anneal proposer hits toy via fallback
Recorded coverage confirms this test executed the API body. This example belongs to the pinned upstream test suite. It may use fixtures and imports from its full file. Run it from that checkout with its test dependencies installed.
def test_anneal_proposer_hits_toy_via_fallback() -> None:
pytest.importorskip("torch")
family = IntegerIntervalFamily(lo=-3, hi=3, target_square=4)
result = run_discovery(
family.statement,
family,
AnnealDescentProposer(),
budget=16,
)
assert result.status == "PROVED"
assert result.proposer == "anneal_descent"
assert result.candidate in (-2, 2)python -m pytest "packages/omnibias-discrete/tests/test_proposers.py::test_anneal_proposer_hits_toy_via_fallback" -qMethod implementation
def __init__(self, *, backend: str = "torch", seed: int = 0) -> None:
self.backend = backend
self.seed = seedproposemethod
propose(self, family: FiniteFamily, budget: int) -> Iterator[Candidate]See the class contract above and the exact method implementation below.
Parameters
| Name | Type & default | Contract |
|---|---|---|
familypositional-or-keyword | FiniteFamilyRequired | See the operation contract and implementation below. |
budgetpositional-or-keyword | intRequired | See the operation contract and implementation below. |
Returns: Iterator[Candidate]
Executed regression · anneal proposer hits toy via fallback
Recorded coverage confirms this test executed the API body. This example belongs to the pinned upstream test suite. It may use fixtures and imports from its full file. Run it from that checkout with its test dependencies installed.
def test_anneal_proposer_hits_toy_via_fallback() -> None:
pytest.importorskip("torch")
family = IntegerIntervalFamily(lo=-3, hi=3, target_square=4)
result = run_discovery(
family.statement,
family,
AnnealDescentProposer(),
budget=16,
)
assert result.status == "PROVED"
assert result.proposer == "anneal_descent"
assert result.candidate in (-2, 2)python -m pytest "packages/omnibias-discrete/tests/test_proposers.py::test_anneal_proposer_hits_toy_via_fallback" -qMethod implementation
def propose(self, family: FiniteFamily, budget: int) -> Iterator[Candidate]:
if budget <= 0:
return
origin = family.origin()
bits = _bit_tuple(family, origin)
if bits is None:
yield from ScoreGuidedWalk().propose(family, budget)
return
snapped = self._anneal_bits(family, bits)
if snapped is None:
return
seen: set[Candidate] = set()
start = _from_bits(family, snapped, origin)
for candidate in (origin, start, *family.neighbors(start)):
if candidate in seen:
continue
seen.add(candidate)
yield candidate
if len(seen) >= budget:
return
leftover = budget - len(seen)
if leftover > 0:
for candidate in ScoreGuidedWalk().propose(family, leftover + len(seen)):
if candidate in seen:
continue
seen.add(candidate)
yield candidate
if len(seen) >= budget:
returnbackendattribute
backend: str = backendPublic instance attribute assigned by __init__. The source assignment is backend = backend; it describes instance state, not a literal constructor default.
seedattribute
seed: int = seedPublic instance attribute assigned by __init__. The source assignment is seed = seed; it describes instance state, not a literal constructor default.
Read the implementation
class AnnealDescentProposer:
"""Relax ``-score`` with ``anneal_descent``, then snap to a 0/1 vertex."""
name = "anneal_descent"
def __init__(self, *, backend: str = "torch", seed: int = 0) -> None:
self.backend = backend
self.seed = seed
def propose(self, family: FiniteFamily, budget: int) -> Iterator[Candidate]:
if budget <= 0:
return
origin = family.origin()
bits = _bit_tuple(family, origin)
if bits is None:
yield from ScoreGuidedWalk().propose(family, budget)
return
snapped = self._anneal_bits(family, bits)
if snapped is None:
return
seen: set[Candidate] = set()
start = _from_bits(family, snapped, origin)
for candidate in (origin, start, *family.neighbors(start)):
if candidate in seen:
continue
seen.add(candidate)
yield candidate
if len(seen) >= budget:
return
leftover = budget - len(seen)
if leftover > 0:
for candidate in ScoreGuidedWalk().propose(family, leftover + len(seen)):
if candidate in seen:
continue
seen.add(candidate)
yield candidate
if len(seen) >= budget:
return
def _anneal_bits(self, family: FiniteFamily, bits: tuple[int, ...]) -> tuple[int, ...] | None:
n = len(bits)
schedule = AnnealSchedule(beta0=0.5, beta_growth=2.0, stages=3, steps=4)
def energy_of(values: tuple[int, ...]) -> float:
origin = family.origin()
candidate = _from_bits(family, values, origin)
value = family.score(candidate)
score = value if isinstance(value, Fraction) else Fraction(value)
return -float(score)
if self.backend == "jax":
return self._anneal_jax(family, n, schedule, energy_of)
return self._anneal_torch(family, n, schedule, energy_of)
def _anneal_torch(
self,
family: FiniteFamily,
n: int,
schedule: AnnealSchedule,
energy_of: Any,
) -> tuple[int, ...] | None:
try:
import torch
from omnibias.discrete.torch import anneal_descent
except ImportError:
return None
def grad_x_fn(x: Any) -> Any:
grads = []
snapped = tuple(1 if float(v) >= 0.5 else 0 for v in x.detach().tolist())
base = energy_of(snapped)
for i in range(n):
flipped = list(snapped)
flipped[i] = 1 - flipped[i]
delta = energy_of(tuple(flipped)) - base
grads.append(delta)
return torch.tensor(grads, dtype=x.dtype)
vertex = anneal_descent(grad_x_fn, scale=1.0, n=n, schedule=schedule)
return tuple(1 if float(v) >= 0.5 else 0 for v in vertex.detach().tolist())
def _anneal_jax(
self,
family: FiniteFamily,
n: int,
schedule: AnnealSchedule,
energy_of: Any,
) -> tuple[int, ...] | None:
try:
import jax.numpy as jnp
from omnibias.discrete.jax import anneal_descent
except ImportError:
return None
def grad_x_fn(x: Any) -> Any:
snapped = tuple(1 if float(v) >= 0.5 else 0 for v in list(x))
base = energy_of(snapped)
grads = []
for i in range(n):
flipped = list(snapped)
flipped[i] = 1 - flipped[i]
grads.append(energy_of(tuple(flipped)) - base)
return jnp.asarray(grads, dtype=x.dtype)
vertex = anneal_descent(grad_x_fn, scale=1.0, n=n, schedule=schedule)
return tuple(1 if float(v) >= 0.5 else 0 for v in list(vertex))Other public import paths
omnibias.discrete.AnnealDescentProposeromnibias.discrete.proposers.AnnealDescentProposer