Commit Graph

111 Commits

Author SHA1 Message Date
chriseth
1ecfbf5484 Booleanize changed constraints. (#3208)
The boolean extractor currently handles newly incoming algebraic
constraints. Substitutions that are performed during solving can lead to
constraints being boolean-extractable where we were not able to do
boolean extraction before. This PR tries to perform boolean extraction
on all constraints that potentially changed because of a substitution.

---------

Co-authored-by: schaeff <thibaut@powdrlabs.com>
2025-08-21 15:01:45 +00:00
chriseth
b5aa6759b4 Avoid running boolean extraction twice. (#3200)
In a future PR (#3208) we will try to run boolean extraction on any
newly changed constraint. This can have the risk that we perform boolean
extraction on a constraint where we already have run boolean extraction.
This PR stores a map of substitutions we performed to avoid introducing
a new boolean variable that then just turns out to be equivalent to an
already existing one.

Closes 3202

---------

Co-authored-by: schaeff <thibaut@powdrlabs.com>
2025-08-21 13:56:15 +00:00
chriseth
8701951b47 Collapse solvers (#3199)
The layered trait-based solver structure does provide a clean separation
but if we want to implement #3106 we have to call the boolean extractor
component from the innermost component which is quite difficult to
achieve. Also, most of the layers were just a simple pass-through for
most of the functions.

So this PR collapses the boolean extractor, linearizer and base solver
into one solver. It still keeps the VarTransform layer because it is
convenient to keep the type generic.
2025-08-20 16:27:57 +00:00
chriseth
5e83a8a93a Do not use bus field variables. (#3171)
Removes the special introduction and removal of bus variables because
the solver can now handle this on its own through the `LinearizedSolver`
component. It also has the benefit that we do not need to run the
optimizer twice any more (once with bus interaction variables and once
without).

Previously we would introduce a new variable type outside of the solver
and replace all bus interactions `bus_interaction(1, x + y * z)` by
`bus_interaction(1, bus_var_1)` and the algebraic constraint `bus_var_1
= x + y * z`.

Now the `LinearizedSolver` is a component inside the solver that
replaces all bus interaction fields (that are not already constants or
simple variables) and also replaces all non-linear components:

`bus_interaction(1, x + y * z)`

becomes

```
bus_interaction(1, v1)
v1 = x + v2
v2 = y * z
```

The reason behind also replacing non-linear parts is because range
constraints are only stored for variables, not for all sub-expressions.
Also if we find the same non-linear sub-expression multiple times, we
can now replace it directly by the same variable.

---------

Co-authored-by: Georg Wiese <georgwiese@gmail.com>
2025-08-20 14:20:15 +00:00
chriseth
f4c99197f9 Introduce range constraint size. (#3177)
Introduce the concept of `size` for range constraint. It provides an
upper bound for the number of values in the rang econstraint and can be
different from the range width.
2025-08-18 07:07:05 +00:00
chriseth
5d0d97a269 Linearizing solver. (#3140)
Adds a solver that introduces new variables for every non-linear
component in an algebraic constraint and also for every bus interaction
field that is not a constant or a variable already.

---------

Co-authored-by: Georg Wiese <georgwiese@gmail.com>
2025-08-15 13:21:11 +00:00
Georg Wiese
bdf3a5fefa Low-degree bus interaction optimizer (#3130)
This PR adds a new optimizer: If a stateless bus interaction (a.k.a.
lookup) implements a low-degree function, it is replaced by a polynomial
constraint (and range constraints).

Some examples include:
- `xor(a, 0xff)` (logical `not` on bytes): This is a linear function
(`255 - a`)
- `xor(a, b)`, where `a` and `b` are known to not have the same bits
set: This equals `a + b`
- `xor(a, b)`, where `a` and `b` are known to be bit-valued: This is
equal to `a + b - 2 * a * b`

Doing this replacement has several advantages:
- A bus interaction is replaced with a polynomial constraint (which is
usually much cheaper)
- Because the output is equal to a low-degree expression of the inputs
(often linear), the inliner can inline it, so we don't have to commit to
it

Note that in addition to the linear function, a lookup always *also*
enforces a range constraint. These are added to the system by using the
API added with the range constraint optimizer (#3151). In many cases,
these constraints are redundant and can be removed again by the range
constraint optimizer (e.g. the inputs might come from memory, which can
be assumed to store byte-constrained words.

---------

Co-authored-by: Leo <leo@powdrlabs.com>
Co-authored-by: chriseth <chris@ethereum.org>
2025-08-15 10:47:55 +00:00
chriseth
32fc857c57 Optimize exhaustive search. (#3181)
Optimize exhaustive search by directly applying assignments and doing it
in the solver, so further exhaustive searches profit from the new
information.

- Initial time for solver optimization in `test_optimize` (release):
 4.0 seconds
- Directly apply assignments to the variable sets and constraint system
 2.6 seconds
- Directly apply assignments inside the solver (i.e. also update the
range constraints)
 2.57 seconds
2025-08-14 22:01:51 +00:00
chriseth
9e08aa9016 Introduce var transformation. (#3146)
This introduces a single solver layer that does the variable
transformations. This way the trait bounds are much easier to state.
2025-08-11 15:48:30 +00:00
chriseth
92e3a79f10 Add test for bit decomposition bug (#3157)
This is not a proper fix, but we would like to replace the routine by a
better one soon anyway.
2025-08-11 10:16:19 +00:00
Georg Wiese
71d821c427 Range constraint optimizer (#3151)
Fixes #3128

---------

Co-authored-by: Leo <leo@powdrlabs.com>
2025-08-08 14:05:05 +00:00
chriseth
356ceba690 Use solver directly for memory (#3111)
Co-authored-by: Georg Wiese <georgwiese@gmail.com>
2025-08-05 19:04:18 +00:00
chriseth
24ddce250d Prefer inlining last variable. (#3136) 2025-08-05 19:03:23 +00:00
chriseth
ea3e10d686 Move solvers into their own files. (#3145)
This just moves code without modification.
2025-08-05 17:01:58 +00:00
chriseth
648b308e9c Remove leftover code relating to bus field assignments. (#3144)
Closes #2980
2025-08-05 16:18:53 +00:00
chriseth
4544897d58 Boolean extracted solver (#3094)
Extracts boolean variables as alternative constraints for all
constraints in the solver.

The exact implementation adds a layer of the Solver trait on top of an
existing solver where we try to extract a boolean variable for all
constraints that are added to the solver.

The interface is also simplified a little in that we always start out
with an "empty" solver and use the `add_algebraic_constraints` and
`add_bus_interaction` functions to fill it with the system.
2025-08-01 08:21:20 +00:00
chriseth
5166625cf5 Do not extract variables that are already boolean. (#3112)
Fixes https://github.com/powdr-labs/powdr/issues/3095
2025-07-31 16:00:06 +00:00
chriseth
7485dbf829 Improve boolean extraction (#3107)
Co-authored-by: Georg Wiese <georgwiese@gmail.com>
2025-07-31 15:04:46 +00:00
Georg Wiese
5c8ecd2a46 Remove free variables (#3098)
This PR adds a new optimizer step:

5568270f77/autoprecompiles/src/constraint_optimizer.rs (L96-L108)

This can be useful to remove "left-over" range constraints, e.g. from
removed memory bus interactions:
- Imagine a memory bus interaction receiving a previous time stamp and
then having a range constraint like `[current_timestamp - prev_timestamp
- 1] in [BIT16]` to enforce that it is smaller than the current
timestamp.
- Then, `prev_timestamp` would only be mentioned in this stateless bus
interaction after the memory bus interaction is removed by the memory
optimizer.
- The `remove_disconnected_columns` step would not remove it, because
`current_timestamp` is also mentioned and it is connected to a stateful
bus interaction.
- The constraint is still redundant: For any value of
`current_timestamp`, the prover could pick a satisfying value for
`current_timestamp - prev_timestamp - 1` (e.g. $0$) and solve for
`prev_timestamp`

---------

Co-authored-by: Thibaut Schaeffer <schaeffer.thibaut@gmail.com>
2025-07-30 15:03:39 +00:00
chriseth
ef97650646 Use negative numbers in range constraints. (#3115) 2025-07-30 08:53:22 +00:00
chriseth
581a9916fe Group into btreeset directly (#3105)
Co-authored-by: Georg Wiese <georgwiese@gmail.com>
2025-07-29 13:58:45 +00:00
Thibaut Schaeffer
4700c1815f Rename extract_boolean to try_extract_boolean (#3110)
It can fail and returns an Option, so `try_` seems appropriate.
2025-07-29 12:26:23 +00:00
Georg Wiese
92429bf364 Variable Occurrences: Use BTreeSet (#3102)
This way, we guarantee that there are no duplicates, which can cause
performance issues.

Although, it seems like on the OpenVM Keccak test case (#3104), there
are not many duplicates and performance decreases slightly:
```
$ cargo bench --bench optimizer_benchmark
Benchmarking optimize-keccak/optimize: Warming up for 3.0000 s
Warning: Unable to complete 10 samples in 5.0s. You may wish to increase target time to 45.8s.
optimize-keccak/optimize
                        time:   [4.5420 s 4.5712 s 4.6035 s]
                        change: [+3.5320% +4.2324% +5.0959%] (p = 0.00 < 0.05)
                        Performance has regressed.
```
2025-07-29 09:33:27 +00:00
chriseth
448debf109 Solver queue (#3092)
Implements a queue over constraint system items such that items are
re-queued when their variables are updated.

---------

Co-authored-by: Georg Wiese <georgwiese@gmail.com>
2025-07-29 07:26:23 +00:00
chriseth
0d43b411b3 Turn solver into trait. (#3087)
Turns `Solver` into a trait to abstract away the bus interaction handler
and also allow other implementations in the future.

It also makes the solver persistent across optimization loops so that we
do not have to derive the same range constraints all over again.

This is also a preparatory PR to make the solver more independent from
the constraint system: The constraint system inside the solver will have
way more redundancies in the future.

---------

Co-authored-by: Georg Wiese <georgwiese@gmail.com>
2025-07-28 14:18:02 +00:00
chriseth
5aaa375a70 Move derive_more... to exhaustive search module. (#3090)
It is not really an intrinsic task of the constraint system to derive
assignments.
2025-07-26 10:55:15 +00:00
chriseth
362d3f9fdb Remove redundant constraints. (#3074)
Removes algebraic constraints that are implied by other algebraic
constraints.

In order to do that, grouped expressions are turned into products of
factors such that these factors are as much normalized as possible. Then
we try to find algebraic constraints that are divisors of other
algebraic constraints (i.e. the factors are subsets).
2025-07-26 10:54:15 +00:00
chriseth
c79e4c17f0 Substitute bus vars at start and end. (#3078) 2025-07-25 11:08:22 +00:00
chriseth
993a1ac81b Avoid quadratic terms that sum to zero. (#3084) 2025-07-25 09:25:23 +00:00
chriseth
9a97fca7c6 Take other bus interactions into account when computing xor range constraints (#3012) 2025-07-22 09:32:46 +00:00
chriseth
ad9c6c0b3e Also return determined range constraints. (#3068)
Sometimes we want to run an optimization that depends on range
constraints. Using the solver is the best way to determine range
constraints, so it should also return them.
2025-07-21 18:59:07 +00:00
chriseth
57ed5b9bba Detect unsatisfiable first. (#3047) 2025-07-15 13:26:25 +00:00
chriseth
8d11daa952 Rename effect. (#3029) 2025-07-10 08:13:34 +00:00
chriseth
3281eb57ac Rename / remove QuadraticSymbolicExpression. (#3028) 2025-07-10 07:50:52 +00:00
chriseth
2793df62a1 Rename constraint system. (#3025) 2025-07-09 22:28:18 +00:00
chriseth
65371114f9 Field elements in autoprecompiles (#2996) 2025-07-09 08:08:20 +00:00
chriseth
c6caf5a8fa Generic solver (#2991) 2025-07-08 12:25:23 +00:00
chriseth
7ca7a2b3f1 Generic exhaustive search. (#2992) 2025-07-03 13:03:11 +00:00
chriseth
d209dedef5 Generic inliner (#2990) 2025-07-03 13:01:14 +00:00
chriseth
a5d648e856 Generic journaling constraint system. (#2987) 2025-07-03 11:56:46 +00:00
chriseth
c32ff3b640 Refactor the use of bus interaction variables. (#2970) 2025-07-03 10:49:10 +00:00
chriseth
84602425e4 Make utils generic. (#2969) 2025-07-03 10:09:24 +00:00
chriseth
718ea2b6b3 Generic indexed constraint system (#2981) 2025-07-03 10:02:05 +00:00
chriseth
80c65532b5 Var transformable (#2975)
Yet another trait we need to make GroupedExpression generic.
2025-07-02 17:18:22 +00:00
chriseth
737fcb44fa Generic constraint system (#2976) 2025-07-02 17:14:45 +00:00
chriseth
e964c9edfb Generic quadratic equiv (#2972) 2025-07-02 15:06:16 +00:00
chriseth
b96fe393ab Remove empty file. (#2977) 2025-07-02 14:11:57 +00:00
chriseth
d833216549 Rename quadratic symbolic expression. (#2968)
Renames QuadraticSymbolicExpression to GroupedExpression. The advantage
of doing it his way is also that we can slowly change what is called
`QuadraticSymbolicExpression` afer this PR, namely the one with
SymbolicExpression as RuntimeConstant to GroupedExpression and easily
see which on is generic already and which is not.
2025-07-02 13:03:54 +00:00
chriseth
55d2955156 Require field inverse for runtime constant (#2971) 2025-07-02 11:35:35 +00:00
Georg Wiese
a22065ee2d Refactor QuadraticSymbolicExpression (#2923)
This PR refactors `QuadraticSymbolicExpression`: I removed the reference
to
[`SymbolicExpression`](f60e9d9f69/constraint-solver/src/quadratic_symbolic_expression.rs (L70)).
It can represent values that are known at runtime, represented as an
expression. We don't need this in the context of APC: Variables are
either unknown or known at compile time, and therefore can be
represented as a `FieldElement` instead.

The idea is to introduce [this
trait](4989be08f3/constraint-solver/src/runtime_constant.rs (L11)),
which is implemented by `SymbolicExpression` and any `T: FieldElement`.
This way, we can continue to use the solver with
`QuadraticSymbolicExpression<SymbolicExpression<T, V>, V>` (equivalent
to the current `QuadraticSymbolicExpression<T, V>`) in the old JIT
pipeline and use the simpler `QuadraticSymbolicExpression<T, V>` in the
APC pipeline.

---------

Co-authored-by: chriseth <chriseth.github@gmail.com>
2025-06-30 15:47:12 +00:00