Date: 2025-11-20 Status: CRITICAL - Axiom statement may be incorrect Priority: HIGH - Affects correctness of main theorem
After deep analysis of Axiom 1 and its usage context, I've identified a fundamental issue: the axiom as currently stated appears to be unprovable and possibly incorrect.
The Problem: Axiom 1 claims that when find_first_match r_head s (length s) = Some pos for ANY r_head ∈ rules, then ALL rules in rules don't match before position pos. This is demonstrably false.
Impact: The main correctness theorem no_rules_match_before_first_match_preserved relies on this axiom at line 2817.
Recommendation: Reform Axiom 1 to accurately capture the intended execution semantics.
Axiom find_first_match_in_algorithm_implies_no_earlier_matches :
forall rules r_head s pos,
(forall r, In r rules -> wf_rule r) ->
In r_head rules ->
find_first_match r_head s (length s) = Some pos ->
no_rules_match_before rules s pos.
English: "If find_first_match returns position pos for rule r_head (where r_head ∈ rules), then no rules in the entire rules list match at any position before pos."
rules = [r1; r2]
s = "example string"
(* Suppose: *)
- r2 matches at position 3 in s
- r1 matches at position 5 in s
- find_first_match r1 s (length s) = Some 5
(* Axiom claims: *)
find_first_match r1 s (length s) = Some 5 (* TRUE by assumption *)
In r1 rules (* TRUE: r1 is in [r1; r2] *)
⟹ no_rules_match_before rules s 5 (* Axiom's conclusion *)
no_rules_match_before rules s 5 means:
forall r, In r rules -> forall p, (p < 5)%nat -> can_apply_at r s p = false
But:
can_apply_at r2 s 3 = true (* r2 matches at position 3 < 5 *)
In r2 rules (* r2 is in [r1; r2] *)
This contradicts no_rules_match_before rules s 5.
Conclusion: The axiom statement is INVALID as written.
The axiom is trying to capture the execution semantics of apply_rules_seq:
Fixpoint apply_rules_seq (rules : list RewriteRule) (s : PhoneticString) (fuel : nat) :=
match fuel with
| O => Some s
| S fuel' =>
match rules with
| [] => Some s
| r :: rest =>
match find_first_match r s (length s) with
| Some pos => (* Apply r at pos and restart *)
match apply_rule_at r s pos with
| Some s' => apply_rules_seq rules s' fuel'
| None => (* ... *)
end
| None => apply_rules_seq rest s fuel' (* Try next rule *)
end
end
end.
Key Observation: The algorithm restarts from the beginning after each application.
When apply_rules_seq finds a match for rule r at position pos:
Single-rule guarantee: r doesn't match at any position before pos
find_first_match r s (length s) = Some posMulti-rule guarantee (INTENDED but not captured): In the execution context where we find this match, we've been checking all rules sequentially from position 0, and no rules matched before pos
find_first_match r_head s (length s) = Some pos aloneTheorem no_rules_match_before_first_match_preserved :
forall rules r rest s pos s' p,
rules = r :: rest -> (* r is the FIRST rule in rules *)
(forall r0, In r0 rules -> wf_rule r0) ->
(forall r0, In r0 rules -> position_dependent_context (context r0) = false) ->
find_first_match r s (length s) = Some pos ->
apply_rule_at r s pos = Some s' ->
(p < pos)%nat ->
(forall r0, In r0 rules -> can_apply_at r0 s' p = false).
Proof.
intros rules r rest s pos s' p H_rules H_wf_all H_indep_all H_find H_apply H_p_lt.
(* Axiom usage: *)
assert (H_no_match_s: no_rules_match_before rules s pos).
{ eapply find_first_match_in_algorithm_implies_no_earlier_matches.
- intros r0 H_in. apply H_wf_all. exact H_in.
- subst rules. left. reflexivity. (* KEY: r is the HEAD of rules *)
- exact H_find.
}
(* Rest of proof... *)
At line 2819, subst rules. left. reflexivity proves that r is the head (first element) of rules.
So the axiom is being applied when:
rules = r :: restr is the first rulefind_first_match r s (length s) = Some posQuestion: Does this make the axiom valid for this specific case?
Answer: NO! Even if r is the first rule, other rules in rest could still match before position pos.
Replace the axiom with a weaker statement that's actually true:
Lemma find_first_match_implies_single_rule_no_earlier :
forall r s pos,
wf_rule r ->
find_first_match r s (length s) = Some pos ->
(* Only r doesn't match before pos *)
forall p, (p < pos)%nat -> can_apply_at r s p = false.
Advantage: Provable from existing infrastructure
Disadvantage: Doesn't give us no_rules_match_before rules s pos
Add a premise that captures the execution state:
Axiom find_first_match_with_execution_context :
forall rules r_head s pos,
(forall r, In r rules -> wf_rule r) ->
In r_head rules ->
find_first_match r_head s (length s) = Some pos ->
(* NEW: Execution context premise *)
(forall r, In r rules -> forall p, (p < pos)%nat -> can_apply_at r s p = false) ->
(* THEN: This holds (trivially) *)
no_rules_match_before rules s pos.
Problem: This makes the axiom trivial (conclusion is just restatement of premise).
Define an inductive predicate capturing apply_rules_seq execution:
Inductive ApplyRulesSeqStep : list RewriteRule -> PhoneticString -> nat -> Prop :=
| apply_seq_found : forall rules r rest s pos s',
rules = r :: rest ->
find_first_match r s (length s) = Some pos ->
apply_rule_at r s pos = Some s' ->
(* In this execution context, we know: *)
(* - We checked r from position 0 *)
(* - r matched first at pos *)
(* - So r doesn't match before pos *)
(* - Other rules in 'rest' weren't checked yet in this iteration *)
ApplyRulesSeqStep rules s pos
| apply_seq_not_found : forall rules r rest s,
rules = r :: rest ->
find_first_match r s (length s) = None ->
(* r doesn't match anywhere, try rest *)
ApplyRulesSeqStep rest s 0. (* Reset position for next rule *)
Then prove lemmas about this predicate and connect it to no_rules_match_before.
Advantage: Fully captures execution semantics Disadvantage: Complex, requires significant new infrastructure
Instead of trying to prove no_rules_match_before rules s pos, reformulate the preservation theorem to only claim what's actually provable:
Theorem single_rule_first_match_preserved :
forall r s pos s' p,
wf_rule r ->
position_dependent_context (context r) = false ->
find_first_match r s (length s) = Some pos ->
apply_rule_at r s pos = Some s' ->
(p < pos)%nat ->
(* Only claim about the specific rule r *)
can_apply_at r s' p = false.
Then lift this to multi-rule case by proving:
Lemma all_rules_preserved_independently :
forall rules r s pos s' p,
In r rules ->
(forall r0, In r0 rules -> wf_rule r0) ->
(forall r0, In r0 rules -> position_dependent_context (context r0) = false) ->
find_first_match r s (length s) = Some pos ->
apply_rule_at r s pos = Some s' ->
(p < pos)%nat ->
(* If each rule independently doesn't match at p in s *)
(forall r0, In r0 rules -> can_apply_at r0 s p = false) ->
(* Then each rule independently doesn't match at p in s' *)
(forall r0, In r0 rules -> can_apply_at r0 s' p = false).
Advantage: Avoids the unprovable axiom entirely Disadvantage: Changes the structure of the main theorem
Looking at no_rules_match_before_first_match_preserved (line 2803):
Theorem no_rules_match_before_first_match_preserved :
forall rules r rest s pos s' p,
rules = r :: rest ->
find_first_match r s (length s) = Some pos ->
apply_rule_at r s pos = Some s' ->
(p < pos)%nat ->
(* GOAL: Show all rules don't match at p in s' *)
(forall r0, In r0 rules -> can_apply_at r0 s' p = false).
Current approach (line 2816-2821):
no_rules_match_before rules s posr0, get can_apply_at r0 s p = falsecan_apply_at r0 s' p = falseProblem: Step 1 uses invalid axiom.
Alternative approach:
no_rules_match_before rules s pos
forall r0, In r0 rules -> can_apply_at r0 s p = falseforall r0, In r0 rules -> can_apply_at r0 s' p = falseThis would make the theorem more honest about its assumptions.
Recommendation: Option 4 (Reformulate main theorem)
Rationale:
Step 1: Change no_rules_match_before_first_match_preserved to accept premise:
Theorem no_rules_match_before_first_match_preserved :
forall rules r rest s pos s' p,
rules = r :: rest ->
(forall r0, In r0 rules -> wf_rule r0) ->
(forall r0, In r0 rules -> position_dependent_context (context r0) = false) ->
find_first_match r s (length s) = Some pos ->
apply_rule_at r s pos = Some s' ->
(p < pos)%nat ->
(* NEW PREMISE: Explicitly assume no rules match before pos in s *)
(forall r0, In r0 rules -> can_apply_at r0 s p = false) ->
(* CONCLUSION: Then no rules match at p in s' *)
(forall r0, In r0 rules -> can_apply_at r0 s' p = false).
Step 2: Update proof to use premise instead of axiom
Step 3: Check where this theorem is used and update callers
Step 4: Remove Axiom 1 entirely (replace with honest premises)
Search for usage of no_rules_match_before_first_match_preserved:
grep -n "no_rules_match_before_first_match_preserved" position_skipping_proof.v
Result: Need to check downstream usage.
The main theorem is position_skipping_optimization_correct. Need to verify:
no_rules_match_before_first_match_preserved?Status: Axiom 1 as currently stated is invalid and should be:
Next Action: Implement Option 4 (reformulate main theorem with explicit premises)
Time Estimate: 8-12 hours
Document Version: 1.0 Created: 2025-11-20 Author: Analysis by Claude Code Status: Awaiting user review and direction
Can you improve this documentation?Edit on GitHub
cljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |