Docs / FAQ

When the run surprises you.

Heuristics are easier to debug when you can separate input problems, domain-contract bugs, and search-policy tradeoffs. Start with the closest symptom.

Is DeltaSearch on PyPI?

Not yet. This is an alpha release. Clone the repository and install it in editable mode with python -m pip install -e ".[dev]". A PyPI release will come after the API and packaging workflow stabilize.

Does it guarantee an optimal answer?

No. DeltaSearch is a heuristic framework. It can find useful solutions quickly, but a greedy or beam-based run does not prove global optimality. Compare against exact solvers or known bounds when correctness requires it.

Does Maximum Planar Subgraph prove planarity?

Not by itself. The current core feasibility helper applies Euler’s edge bound component by component. That is a necessary condition, not a complete planarity test, so it can admit non-planar graphs that stay under the bound. Use a complete planarity oracle such as NetworkX’s check_planarity when the guarantee matters.

Why is my state empty?

The default evaluate_initial_state creates an empty candidate graph. Built-in problems may override this. If your custom problem needs seeded nodes or terminals, return a state that contains them and test the initial state before enumerating actions.

Why does the solver stop without progress?

class DebugObserver:
    def on_iteration_complete(self, iteration, best_action, objective):
        print({"iteration": iteration,
               "action": best_action,
               "objective": objective})

result = solver.solve(max_iterations=25, observer=DebugObserver())
print(result.convergence_reason)

Why did a candidate mutation leak?

Mutate only through the problem’s action methods. A custom action must record every changed node, edge, and attribute in its undo entry. Write a test that snapshots the entire state, applies an action, undoes it, and compares the snapshot.

Why is the “O(1)” path still slow?

Local delta calculation is only one part of the loop. Candidate enumeration, defensive graph copies, planarity checks, observers, and dense action sets can dominate. Measure each component. Use incremental=True only inside a controlled solver loop that always unwinds with undo_action.

Why does an optional feature fail to import?

Install the matching extras from your local checkout:

python -m pip install -e ".[all]"

# Check the environment
python -c "import networkx, matplotlib, sklearn; print('optional deps ready')"

When should I use ThreadSafeGraph?

Use it when multiple threads share graph access or when a live graph is coordinated between workers. For a normal single-threaded solve, use Graph. Thread safety does not make a multi-step read atomic unless you hold the graph lock across the whole read.

How do I report a bug?

Open an issue with the Python version, commit SHA, minimal graph, problem class, solver configuration, expected result, actual result, and a short observer trace. Reproducers that run from a clean local checkout are easiest to diagnose.