Skip to content

Commit 9e7056e

Browse files
committed
Dump a bunch of notes on applying a single rewrite rule
1 parent a8e56bb commit 9e7056e

File tree

1 file changed

+41
-0
lines changed

1 file changed

+41
-0
lines changed

docs/2024-10-18-booster-description.md

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,3 +31,44 @@ Over time, as the booster was able to pass more tests and handle more inputs, th
3131
To date, the most work has been put into making the `execute` endpoint of the booster as complete and performant as possible, as that is where the bulk of time on long-running proofs is spent.
3232
Necessarily, as part of the `execute` endpoints reasoning, simplification reasoning of the booster needs to be improved too, which means the `simplify` endpoint has improved as well.
3333
Only a very rudimentary `implies` endpoint has been implemented, to handle most of the failure cases as fast as possible, and usually the more complicated reasoning is still delegated to the Kore `implies` endpoint.
34+
35+
## [Rewriting Algorithm](#rewriting)
36+
37+
### [Single Rewrite Rule](#rewriting-apply-single-rule)
38+
39+
[applyRule](https://github.com/runtimeverification/haskell-backend/blob/3956-booster-rewrite-rule-remainders/booster/library/Booster/Pattern/Rewrite.hs#L329)
40+
41+
Steps to apply a rewrite rule include:
42+
43+
- Matching with the rule, i.e. does the current configuration looks like a rule's left-hand side. Successful matching produces a substitution `RULE_SUBSTITUTION`, assigning the left-hand side rule variables with the stuff from the configuration. See [#rule-matching](#rule-matching) for more details.
44+
- Checking the rule's requires clause. Unclear conditions may produce a remainder predicate, which affects the wider rewriting step process. See [#checking-requires](#checking-requires).
45+
- Checking the rule's ensures clause, and extracting the possible new substitution items from the ensured constraints. See [#checking-ensures](#checking-ensures).
46+
- Constructing the final rewritten configuration.
47+
48+
**TODO**: list abort conditions.
49+
50+
#### [Matching the configuration with the rule's left-hand side](#rule-matching)
51+
52+
See the [Booster.Pattern.Match](https://github.com/runtimeverification/haskell-backend/blob/3956-booster-rewrite-rule-remainders/booster/library/Booster/Pattern/Match.hs#L48) module, specifically the [matchTerms](https://github.com/runtimeverification/haskell-backend/blob/3956-booster-rewrite-rule-remainders/booster/library/Booster/Pattern/Match.hs#L132), [match](https://github.com/runtimeverification/haskell-backend/blob/3956-booster-rewrite-rule-remainders/booster/library/Booster/Pattern/Match.hs#L171) and [match1](https://github.com/runtimeverification/haskell-backend/blob/3956-booster-rewrite-rule-remainders/booster/library/Booster/Pattern/Match.hs#L191) functions
53+
- rules are indexed by the head symbol of the `<k>` cell (or other index-cells), i.e. we only try the rules that have the same head symbol that the configuration
54+
- rules can fail matching, usually that means that the rule and the configuration have different constructor symbols or domains values in some cells.
55+
This means that the rule does not apply and we can proceed to trying other rules.
56+
- rule matching can be indeterminate. We really do not want this to happen, as it will abort rewriting and cause a fallback to Kore (or a full-stop of using the `booster-dev` server).
57+
Common cases include unevaluated function symbols. See [match1](https://github.com/runtimeverification/haskell-backend/blob/3956-booster-rewrite-rule-remainders/booster/library/Booster/Pattern/Match.hs#L191) and look for `addIndetermiante` for the exhaustive list.
58+
59+
### [Checking `requires` --- the rule's pre-condition](#checking-requires)
60+
61+
- now we have to check the rule's side-condition, aka the `requires` and `ensures` clauses. Booster represents the `requires` and `ensures` clauses as a set of boolean predicates, constituting the conjuncts, i.e. they are implicitly connected by `_andBool_`, but Booster works with them independently, which makes filtering, de-duplication and other operations straightforward. Write your requires clauses in CNF!
62+
- the requires clause check is encapsulated by the [checkRequires](https://github.com/runtimeverification/haskell-backend/blob/3956-booster-rewrite-rule-remainders/booster/library/Booster/Pattern/Rewrite.hs#L496) function in applyRule. It will:
63+
- substitute the rule's requires clause with the matching substitution
64+
- check if we already have any of the conjuncts verbatim in the pattern's constrains. If so, we filter them out as known truth
65+
- simplify every conjunct individually by applying equations. This is where Petar is welcome to take over with his 4 hours workshop on simplifications.
66+
- filter again
67+
- if any clauses remain, it's time to fire-up Z3 and check them for validity.
68+
- some rule will be rejected at that point, as their pre-condition P (the `requires` clause) is invalid, which means that the rule is applicable statically, but the dynamic conditions makes it inapplicable.
69+
- some rules may have an indeterminate pre-condition P, which means that both P and its negation are satisfiable, i.e. the solver said (SAT, SAT) for (P, not P).
70+
In this case we can apply this rule conditionally, but add P into the path condition.
71+
We effectively do the same we cannot establish the validity of P due to a solver timeout, i.e. we add the predicate as an assumption. This may potentially lead to a vacuous branch.
72+
- some rules will have a valid requires clause, which means they definitely do apply and we do need to add anything else into the path condition as an assumption.
73+
74+
### [Checking `ensures` --- the rule's post-condition](#checking-ensures)

0 commit comments

Comments
 (0)