Run and replay search#
ReferenceSearch is a deterministic, sequential evidence producer. It is useful for testing analysis and replay logic, but it is not algorithmically equivalent to the official lc0 engine. This offline demo uses the versioned fixture rather than trained weights.
[1]:
import chess
from examples.decision_analysis_tutorial import load_fixture_evaluator
from lczerolens import (
ReferenceSearch,
Simulations,
replay_retained_events,
replay_search_trace,
)
from lczerolens.search.trace import SearchCapability
board = chess.Board()
runtime = load_fixture_evaluator()
result = ReferenceSearch(runtime.evaluator, c_puct=1.0).run(board, Simulations(4))
(result.move.uci(), result.capability, len(result.trace.events))
[1]:
('e2e4', <SearchCapability.REPLAYABLE: 'replayable'>, 4)
Capability checks are part of the contract. A replayable reference trace exposes full simulation events; an official-engine trace may expose only root snapshots, and consumers must not infer missing events.
[2]:
result.trace.require(SearchCapability.REPLAYABLE)
root_rows = [
{"move": move, "prior": round(action.prior, 4), "visits": action.visits}
for move, action in result.root.items()
if action.visits
]
root_rows
[2]:
[{'move': 'a2a3', 'prior': 0.0, 'visits': 1},
{'move': 'e2e4', 'prior': 1.0, 'visits': 3}]
Semantic replay reconstructs the deterministic tree from recorded events instead of trusting the recorded final snapshot. Retained-event replay answers a different question: what root decision is represented by an explicit subset of the original simulations?
[3]:
semantic = replay_search_trace(result.trace)
retained = replay_retained_events(result.trace, ("simulation-0", "simulation-2"))
assert semantic.selected_move == result.move.uci()
{
"semantic_move": semantic.selected_move,
"retained_move": retained.selected_move,
"retained_events": retained.plan.retained_event_ids,
"observed_costs": retained.costs,
}
[3]:
{'semantic_move': 'e2e4',
'retained_move': 'a2a3',
'retained_events': ('simulation-0', 'simulation-2'),
'observed_costs': RetainedEventReplayCosts(simulations=2, evaluator_calls=2, expansions=2, backup_updates=3, path_steps=3)}
Use the official engine boundary#
For production lc0 output, construct LczeroSearch(executable=..., network=..., engine_version=...) and run it with Nodes(...) or Time(...). That process-backed adapter is intentionally not executed in this hermetic notebook. It records only public root evidence and advertises at most root-snapshot capability; use the opt-in pinned live conformance test to validate a particular binary and network.