Skip to main content
Ctrl+K
lczerolens - Home lczerolens - Home
  • Getting Started
  • Features
  • Tutorials
  • API Reference
  • About
  • GitHub
  • Discord
  • PyPI
  • Getting Started
  • Features
  • Tutorials
  • API Reference
  • About
  • GitHub
  • Discord
  • PyPI

Section Navigation

  • End-to-end decision analysis
  • Load models and encode inputs
  • Evaluate positions and batches
  • Analyze chess evidence
  • Run and replay search
  • Complete decision analysis
  • Compare two evaluators
  • Analyze an authored puzzle collection
  • Tutorials
  • Run and replay search

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.

previous

Analyze chess evidence

next

Complete decision analysis

On this page
  • Use the official engine boundary

© Copyright 2024, Yoann Poupart.

Created using Sphinx 9.0.4.

Built with the PyData Sphinx Theme 0.20.0.