Skip to content

Problem ABC and native conversion

sezgi.Problem is the subclassable ABC for authoring your own search problem; as_native_problem converts any Problem subclass instance (or an already-native handle, unchanged) into the native handle every entry point (solve, Algorithm.run, EvalSession.for_problem, ...) accepts.

problem

sezgi.Problem -- subclassable Python ABC for a search-space problem (M4-1 Task 1).

Sits on top of the block-typed callable-problem bridge (_sezgi.from_callable_spaced, py-sezgi/src/lib.rs), the widening of the existing sezgi.from_callable(...) bridge to any sezgi.Space (not just a single Float block). A subclass declares its search space (space()) and objective (evaluate(x)); _to_native() builds the native Problem handle every existing entry point (sezgi.solve, EvalSession.for_problem, ...) already accepts.

Genotype -> Python conversion table (PINNED; block_value_to_py/ genotype_to_py in py-sezgi/src/lib.rs):

Float block        -> list[float]
Int block           -> list[int]
Categorical block    -> list[int]   (category INDICES 0..k, not labels)
Binary block         -> list[bool]
Permutation block     -> list[int]

A single-block space's x is that one block's own converted value, passed BARE. A multi-block space's x is a Python tuple of per-block converted values, in space()'s block order.

Problem

Bases: abc.ABC

Subclass and implement evaluate/space; optimum/batch_evaluate are optional overrides.

Genotype -> Python conversion table (PINNED; block_value_to_py/ genotype_to_py in py-sezgi/src/lib.rs), applied to evaluate's own x argument:

Float block          -> list[float]
Int block             -> list[int]
Categorical block      -> list[int]   (category INDICES 0..k, not labels)
Binary block           -> list[bool]
Permutation block       -> list[int]

A single-block space's x is that one block's own converted value, passed BARE. A multi-block space's x is a Python tuple of per-block converted values, in space()'s block order.

A subclass instance is usable anywhere a native Problem handle is (sezgi.solve, EvalSession.for_problem, Algorithm.run, ...) -- every such entry point routes it through as_native_problem, which calls _to_native() once to build the actual handle passed to the Rust engine.

__abstractmethods__ class-attribute

__abstractmethods__ = frozenset({'evaluate', 'space'})

frozenset() -> empty frozenset object frozenset(iterable) -> frozenset object

Build an immutable unordered collection of unique elements.

__doc__ class-attribute

__doc__ = "Subclass and implement `evaluate`/`space`; `optimum`/`batch_evaluate`\n    are optional overrides.\n\n    Genotype -> Python conversion table (PINNED; `block_value_to_py`/\n    `genotype_to_py` in `py-sezgi/src/lib.rs`), applied to `evaluate`'s own\n    `x` argument:\n\n        Float block          -> list[float]\n        Int block             -> list[int]\n        Categorical block      -> list[int]   (category INDICES 0..k, not labels)\n        Binary block           -> list[bool]\n        Permutation block       -> list[int]\n\n    A single-block space's `x` is that one block's own converted value,\n    passed BARE. A multi-block space's `x` is a Python tuple of per-block\n    converted values, in `space()`'s block order.\n\n    A subclass instance is usable anywhere a native `Problem` handle is\n    (`sezgi.solve`, `EvalSession.for_problem`, `Algorithm.run`, ...) --\n    every such entry point routes it through `as_native_problem`, which\n    calls `_to_native()` once to build the actual handle passed to the\n    Rust engine."

str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str

Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.str() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'.

__module__ class-attribute

__module__ = 'sezgi.problem'

str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str

Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.str() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'.

__weakref__ property

__weakref__

list of weak references to the object

evaluate

evaluate(x)

x -> float (the fitness/objective value at x).

For a single-block space, x is that block's own converted value, passed bare. For a multi-block space, x is a tuple of per-block values, in space()'s block order. See the module docstring's conversion table for each block kind's exact Python type.

space

space()

Declares the search space: a sezgi.Space(...), or a bare block (sezgi.Float(...), sezgi.Binary(...), ...) -- see as_space, which accepts either.

Called once, from _to_native(), when this Problem is converted to a native handle (e.g. at the start of sezgi.solve(...) or Algorithm.run(...)) -- not re-evaluated per generation, so the returned space must not depend on mutable instance state that changes during a run.

optimum

optimum()

The problem's known optimum (a float), or None (default) if it has none.

Design decision (M4-1 Task 1): plumbed through to the native handle's own .optimum() accessor (_to_native() passes this value to _sezgi.from_callable_spaced(..., optimum=...)), so problem._to_native().optimum() and problem.optimum() agree -- the native surface DOES support carrying an arbitrary Python- supplied optimum for a callable-bridge handle (a one-field addition to Inner::CallableSpaced, no core change), so there was no reason to leave it Python-side only.

batch_evaluate

batch_evaluate(xs)

xs -> list[float], one entry per x in xs (default: loop evaluate). Override for a vectorized objective; called ONCE per generation with the whole population as xs (see _sezgi.from_callable_spaced's own doc).

as_native_problem

as_native_problem(obj)

Accepts anything sezgi's entry points (solve, future .run() methods, ...) should accept as "a problem": a native Problem handle passes through unchanged; a sezgi.Problem subclass instance is converted via _to_native(); anything else raises TypeError.