Persistent shared DAG for constraint propagation#225
Open
dpsanders wants to merge 8 commits into
Open
Conversation
…ompatibility Update compat bounds: IntervalArithmetic 1, IntervalBoxes 0.3, IntervalContractors 0.6, ReversePropagation 0.4, Symbolics 7. IntervalArithmetic v1.0 follows IEEE 1788 and deliberately does not define Base.isequal/Base.hash for Interval. This broke @register_symbolic x ∈ y::Interval since SymbolicUtils needs isequal/hash for hash-consing. Instead of type-pirating those methods, decompose x ∈ interval(a,b) into (x >= a) & (x <= b) at the symbolic level. Also fix pre-existing bug in separator() where & and | used Base.intersect/union instead of ⊓/⊔ (defined for AbstractSeparator in set_operations.jl). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Cherry-pick infrastructure changes from PR #220: - Update GitHub Actions versions (checkout v6, setup-julia v2, cache v3, codecov v6) - Test on Julia 1.11 instead of 1.10 - Set julia compat to 1.11 - Remove obsolete REQUIRE file (Pkg.jl era) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Switch from the old Documenter HTML backend to DocumenterVitepress for a modern VitePress-based documentation site. Add new pages explaining contractors/separators and the internal architecture, update index.md to the current API, add GitHub Actions workflow for doc deployment, and remove stale mkdocs.yml and Manifest.toml. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Implements an explicit DAG (directed acyclic graph) for forward-backward
interval constraint propagation (HC4Revise), inspired by Schichl & Neumaier.
This provides an inspectable, iterable alternative to the existing
ReversePropagation code-generation approach.
New types: DAGContractor, DAGSeparator, ConstraintDAG
New files: src/dag/{nodes,build,propagate,contractor}.jl
Tests: test/test_dag.jl (27 tests)
Benchmarks: benchmark/bench_dag_vs_codegen.jl
Both approaches produce identical paving results. The DAG approach is
currently ~10x slower due to DAG reconstruction per call and dynamic
dispatch, with clear optimization paths documented in CLAUDE.md.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Redesign the DAG engine so the graph is built once and reused: - SharedDAG: persistent DAG that accumulates constraints via add_expression!. Variable nodes and common subexpressions (CSE) are shared across all expressions added to the same DAG. - Multi-constraint propagation: forward-backward passes contract all constraints jointly, so narrowing from one constraint immediately benefits others through shared variable nodes. - DAGContractor/DAGSeparator accept an existing SharedDAG, allowing multiple separators to share the same graph. Benchmarks show ~30% speedup vs the previous rebuild-per-call approach, and shared DAGs use 33% fewer nodes than separate ones. Resolves Project.toml merge conflict from cherry-pick. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
3 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
SharedDAGis the central object that accumulates constraints viaadd_expression!. Variable nodes and common subexpressions are reused across all expressions added to the same DAG.propagate!(dag, X)contracts all constraints jointly each iteration, so narrowing from one constraint immediately benefits others through shared variable nodesDAGContractor(dag, expr, vars)andDAGSeparator(dag, expr, vars, constraint)accept an existing SharedDAG, letting multiple separators share the same graphKey results
Node sharing: Two expressions
x²+y²-1andx²-yon the same SharedDAG use 10 nodes vs 15 separate (33% fewer — thex²subexpression is shared).Joint propagation:
x²+y²≤1 AND x²-y≤0on[-10,10]²correctly narrows to[-1,1]×[0,1]in a singlepropagate!call, because the second constraint forcesy≥x²≥0.Benchmarks (persistent DAG vs code-generation):
Both approaches produce identical paving results on all test cases.
Usage
Test plan
test/test_dag.jl— SharedDAG construction, CSE node reuse, multi-constraint propagation, shared DAG contractors/separators, paving comparison with original, combined separators, 3Dtest/runtests.jlstill passbenchmark/bench_dag_vs_codegen.jl🤖 Generated with Claude Code