Skip to content
This repository was archived by the owner on Apr 25, 2024. It is now read-only.

Commit d7b05c1

Browse files
ehildenbrv-auditor
andauthored
Make advance proof functionality generic (#875)
~Blocked on: #878 In an attempt to make the prover interfaces simpler, we are making it so that `advance_proof` is a generic method among all `*Prover` classes. This will allow us to have a generic way to call subproofs and advance them, then call superproofs and advance them, which will allow simplifying some downstream logic a bit. - Makes it so that `mlEqualsTrue` and `mlEqualsFalse` can take sort arguments for their outer sort. - Moves all the `APRProof` specific arguments of `APRProof.advance_proof` to the constructor instead. - Adds an `abstractmethod Proof.step_proof(...)` which should take one step of executing a proof to completion. - Adds an `abstractmethod Proof.can_progress` which lets you know if it's possible to make progress on a given proof. - Implements generic `Proof.advance_proof(...)` which handles calling `step_proof` in a loop until either `max_iterations` is reached, the proof can no longer progress, or if `fail_fast` trigger hits. It also handles writing proof data each iteration. - Adjusts all the tests to the new interface. --------- Co-authored-by: devops <[email protected]>
1 parent 9453af7 commit d7b05c1

File tree

11 files changed

+90
-78
lines changed

11 files changed

+90
-78
lines changed

docs/conf.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@
99
project = 'pyk'
1010
author = 'Runtime Verification, Inc'
1111
copyright = '2024, Runtime Verification, Inc'
12-
version = '0.1.626'
13-
release = '0.1.626'
12+
version = '0.1.627'
13+
release = '0.1.627'
1414

1515
# -- General configuration ---------------------------------------------------
1616
# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration

package/version

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
0.1.626
1+
0.1.627

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build-backend = "poetry.core.masonry.api"
44

55
[tool.poetry]
66
name = "pyk"
7-
version = "0.1.626"
7+
version = "0.1.627"
88
description = ""
99
authors = [
1010
"Runtime Verification, Inc. <[email protected]>",

src/pyk/proof/equality.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,10 @@ def status(self) -> ProofStatus:
6262
else:
6363
return ProofStatus.PASSED
6464

65+
@property
66+
def can_progress(self) -> bool:
67+
return self.simplified_antecedent is None or self.simplified_consequent is None
68+
6569
def write_proof_data(self, subproofs: bool = False) -> None:
6670
super().write_proof_data()
6771
if not self.proof_dir:
@@ -352,7 +356,7 @@ def __init__(self, proof: ImpliesProof, kcfg_explore: KCFGExplore):
352356
super().__init__(kcfg_explore)
353357
self.proof = proof
354358

355-
def advance_proof(self) -> None:
359+
def step_proof(self) -> None:
356360
proof_type = type(self.proof).__name__
357361
_LOGGER.info(f'Attempting {proof_type} {self.proof.id}')
358362

@@ -388,4 +392,3 @@ def advance_proof(self) -> None:
388392
self.proof.csubst = result
389393

390394
_LOGGER.info(f'{proof_type} finished {self.proof.id}: {self.proof.status}')
391-
self.proof.write_proof_data()

src/pyk/proof/proof.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,11 @@ def subproofs_status(self) -> ProofStatus:
174174
def status(self) -> ProofStatus:
175175
...
176176

177+
@property
178+
@abstractmethod
179+
def can_progress(self) -> bool:
180+
...
181+
177182
@property
178183
def failed(self) -> bool:
179184
return self.status == ProofStatus.FAILED
@@ -283,6 +288,23 @@ def lines(self) -> list[str]:
283288

284289
class Prover:
285290
kcfg_explore: KCFGExplore
291+
proof: Proof
286292

287293
def __init__(self, kcfg_explore: KCFGExplore):
288294
self.kcfg_explore = kcfg_explore
295+
296+
@abstractmethod
297+
def step_proof(self) -> None:
298+
...
299+
300+
def advance_proof(self, max_iterations: int | None = None, fail_fast: bool = False) -> None:
301+
iterations = 0
302+
while self.proof.can_progress:
303+
if fail_fast and self.proof.failed:
304+
_LOGGER.warning(f'Terminating proof early because fail_fast is set: {self.proof.id}')
305+
return
306+
if max_iterations is not None and max_iterations <= iterations:
307+
return
308+
iterations += 1
309+
self.step_proof()
310+
self.proof.write_proof_data()

src/pyk/proof/reachability.py

Lines changed: 34 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,10 @@ def status(self) -> ProofStatus:
186186
else:
187187
return ProofStatus.PASSED
188188

189+
@property
190+
def can_progress(self) -> bool:
191+
return len(self.pending) > 0
192+
189193
@classmethod
190194
def from_dict(cls: type[APRProof], dct: Mapping[str, Any], proof_dir: Path | None = None) -> APRProof:
191195
kcfg = KCFG.from_dict(dct['kcfg'])
@@ -533,6 +537,9 @@ class APRProver(Prover):
533537
main_module_name: str
534538
dependencies_module_name: str
535539
circularities_module_name: str
540+
execute_depth: int | None
541+
cut_point_rules: Iterable[str]
542+
terminal_rules: Iterable[str]
536543
counterexample_info: bool
537544
always_check_subsumption: bool
538545
fast_check_subsumption: bool
@@ -545,6 +552,9 @@ def __init__(
545552
self,
546553
proof: APRProof,
547554
kcfg_explore: KCFGExplore,
555+
execute_depth: int | None = None,
556+
cut_point_rules: Iterable[str] = (),
557+
terminal_rules: Iterable[str] = (),
548558
counterexample_info: bool = False,
549559
always_check_subsumption: bool = True,
550560
fast_check_subsumption: bool = False,
@@ -559,6 +569,9 @@ def _inject_module(module_name: str, import_name: str, sentences: list[KRuleLike
559569
super().__init__(kcfg_explore)
560570
self.proof = proof
561571
self.main_module_name = self.kcfg_explore.kprint.definition.main_module_name
572+
self.execute_depth = execute_depth
573+
self.cut_point_rules = cut_point_rules
574+
self.terminal_rules = terminal_rules
562575
self.counterexample_info = counterexample_info
563576
self.always_check_subsumption = always_check_subsumption
564577
self.fast_check_subsumption = fast_check_subsumption
@@ -672,57 +685,33 @@ def advance_pending_node(
672685
module_name=module_name,
673686
)
674687

675-
def advance_proof(
676-
self,
677-
max_iterations: int | None = None,
678-
execute_depth: int | None = None,
679-
cut_point_rules: Iterable[str] = (),
680-
terminal_rules: Iterable[str] = (),
681-
fail_fast: bool = False,
682-
) -> None:
683-
iterations = 0
684-
688+
def step_proof(self) -> None:
685689
self._check_all_terminals()
686690

687-
while self.proof.pending:
688-
self.proof.write_proof_data()
689-
if fail_fast and self.proof.failed:
690-
_LOGGER.warning(
691-
f'Terminating proof early because fail_fast is set {self.proof.id}, failing nodes: {[nd.id for nd in self.proof.failing]}'
692-
)
693-
break
694-
695-
if max_iterations is not None and max_iterations <= iterations:
696-
_LOGGER.warning(f'Reached iteration bound {self.proof.id}: {max_iterations}')
697-
break
698-
iterations += 1
699-
curr_node = self.proof.pending[0]
700-
701-
self.advance_pending_node(
702-
node=curr_node,
703-
execute_depth=execute_depth,
704-
cut_point_rules=cut_point_rules,
705-
terminal_rules=terminal_rules,
706-
)
707-
708-
self._check_all_terminals()
691+
if not self.proof.pending:
692+
return
693+
curr_node = self.proof.pending[0]
709694

710-
for node in self.proof.terminal:
711-
if (
712-
not node.id in self._checked_for_subsumption
713-
and self.proof.kcfg.is_leaf(node.id)
714-
and not self.proof.is_target(node.id)
715-
):
716-
self._checked_for_subsumption.add(node.id)
717-
self._check_subsume(node)
695+
self.advance_pending_node(
696+
node=curr_node,
697+
execute_depth=self.execute_depth,
698+
cut_point_rules=self.cut_point_rules,
699+
terminal_rules=self.terminal_rules,
700+
)
718701

719-
if self.proof.failed:
720-
self.save_failure_info()
702+
self._check_all_terminals()
721703

722-
self.proof.write_proof_data()
704+
for node in self.proof.terminal:
705+
if (
706+
not node.id in self._checked_for_subsumption
707+
and self.proof.kcfg.is_leaf(node.id)
708+
and not self.proof.is_target(node.id)
709+
):
710+
self._checked_for_subsumption.add(node.id)
711+
self._check_subsume(node)
723712

724-
def save_failure_info(self) -> None:
725-
self.proof.failure_info = self.failure_info()
713+
if self.proof.failed:
714+
self.proof.failure_info = self.failure_info()
726715

727716
def failure_info(self) -> APRFailureInfo:
728717
return APRFailureInfo.from_proof(self.proof, self.kcfg_explore, counterexample_info=self.counterexample_info)

src/tests/integration/proof/test_cell_map.py

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -136,11 +136,8 @@ def test_all_path_reachability_prove(
136136
init = proof.kcfg.node(proof.init)
137137
new_init_term = kcfg_explore.cterm_assume_defined(init.cterm)
138138
proof.kcfg.replace_node(init.id, new_init_term)
139-
prover = APRProver(proof, kcfg_explore=kcfg_explore)
140-
prover.advance_proof(
141-
max_iterations=max_iterations,
142-
execute_depth=max_depth,
143-
)
139+
prover = APRProver(proof, kcfg_explore=kcfg_explore, execute_depth=max_depth)
140+
prover.advance_proof(max_iterations=max_iterations)
144141

145142
kcfg_show = KCFGShow(
146143
kcfg_explore.kprint, node_printer=APRProofNodePrinter(proof, kcfg_explore.kprint, full_printer=True)

src/tests/integration/proof/test_goto.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -116,13 +116,14 @@ def test_all_path_bmc_reachability_prove(
116116

117117
proof = APRProof.from_claim(kprove.definition, claim, logs={}, bmc_depth=bmc_depth)
118118
kcfg_explore.simplify(proof.kcfg, {})
119-
prover = APRProver(proof, kcfg_explore=kcfg_explore)
120-
prover.advance_proof(
121-
max_iterations=max_iterations,
119+
prover = APRProver(
120+
proof,
121+
kcfg_explore=kcfg_explore,
122122
execute_depth=max_depth,
123123
cut_point_rules=cut_rules,
124124
terminal_rules=terminal_rules,
125125
)
126+
prover.advance_proof(max_iterations=max_iterations)
126127

127128
kcfg_show = KCFGShow(
128129
kcfg_explore.kprint, node_printer=APRProofNodePrinter(proof, kcfg_explore.kprint, full_printer=True)

src/tests/integration/proof/test_imp.py

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -903,8 +903,8 @@ def test_all_path_reachability_prove(
903903
subproof.admit()
904904
subproof.write_proof_data()
905905

906-
prover = APRProver(proof, kcfg_explore=kcfg_explore)
907-
prover.advance_proof(max_iterations=max_iterations, execute_depth=max_depth, cut_point_rules=cut_rules)
906+
prover = APRProver(proof, kcfg_explore=kcfg_explore, execute_depth=max_depth, cut_point_rules=cut_rules)
907+
prover.advance_proof(max_iterations=max_iterations)
908908

909909
kcfg_show = KCFGShow(
910910
kcfg_explore.kprint, node_printer=APRProofNodePrinter(proof, kcfg_explore.kprint, full_printer=True)
@@ -944,13 +944,14 @@ def _node_printer(cterm: CTerm) -> list[str]:
944944
)
945945

946946
proof = APRProof.from_claim(kprove.definition, claim, logs={}, proof_dir=proof_dir)
947-
prover = APRProver(proof, kcfg_explore=kcfg_explore)
948-
prover.advance_proof(
949-
max_iterations=max_iterations,
947+
prover = APRProver(
948+
proof,
949+
kcfg_explore=kcfg_explore,
950950
execute_depth=max_depth,
951951
terminal_rules=terminal_rules,
952952
cut_point_rules=cut_rules,
953953
)
954+
prover.advance_proof(max_iterations=max_iterations)
954955

955956
assert len(proof.failing) == 1
956957
path_constraint = proof.path_constraints(proof.failing[0].id)
@@ -984,13 +985,14 @@ def test_all_path_bmc_reachability_prove(
984985

985986
proof = APRProof.from_claim(kprove.definition, claim, logs={}, bmc_depth=bmc_depth)
986987
kcfg_explore.simplify(proof.kcfg, {})
987-
prover = APRProver(proof, kcfg_explore=kcfg_explore)
988-
prover.advance_proof(
989-
max_iterations=max_iterations,
988+
prover = APRProver(
989+
proof,
990+
kcfg_explore=kcfg_explore,
990991
execute_depth=max_depth,
991992
terminal_rules=terminal_rules,
992993
cut_point_rules=cut_rules,
993994
)
995+
prover.advance_proof(max_iterations=max_iterations)
994996

995997
kcfg_show = KCFGShow(
996998
kcfg_explore.kprint, node_printer=APRProofNodePrinter(proof, kcfg_explore.kprint, full_printer=True)
@@ -1057,8 +1059,8 @@ def test_apr_prove_read_write_node_data(
10571059

10581060
proof = APRProof.from_claim(kprove.definition, claim, logs={}, proof_dir=proofs_dir)
10591061
kcfg_explore.simplify(proof.kcfg, {})
1060-
prover = APRProver(proof, kcfg_explore=kcfg_explore)
1061-
prover.advance_proof(execute_depth=1)
1062+
prover = APRProver(proof, kcfg_explore=kcfg_explore, execute_depth=1)
1063+
prover.advance_proof()
10621064

10631065
proof_from_disk = APRProof.read_proof_data(proof_dir=proofs_dir, id=proof.id)
10641066

@@ -1082,8 +1084,8 @@ def test_aprbmc_prove_read_write_node_data(
10821084

10831085
proof = APRProof.from_claim(kprove.definition, claim, logs={}, proof_dir=proofs_dir, bmc_depth=3)
10841086
kcfg_explore.simplify(proof.kcfg, {})
1085-
prover = APRProver(proof, kcfg_explore=kcfg_explore)
1086-
prover.advance_proof(execute_depth=1)
1087+
prover = APRProver(proof, kcfg_explore=kcfg_explore, execute_depth=1)
1088+
prover.advance_proof()
10871089

10881090
proof_from_disk = APRProof.read_proof_data(proof_dir=proofs_dir, id=proof.id)
10891091

@@ -1116,7 +1118,6 @@ def test_fail_fast(
11161118

11171119
proof = APRProof.from_claim(kprove.definition, claim, logs={}, proof_dir=proof_dir)
11181120
prover = APRProver(proof, kcfg_explore=kcfg_explore)
1119-
11201121
prover.advance_proof(fail_fast=True)
11211122

11221123
# First branch will be reached first and terminate the proof, leaving the second long branch pending (fail_fast=True)

src/tests/integration/proof/test_mini_kevm.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,8 +93,10 @@ def test_all_path_reachability_prove(
9393
prover = APRProver(
9494
proof,
9595
kcfg_explore=kcfg_explore,
96+
execute_depth=max_depth,
97+
cut_point_rules=cut_rules,
9698
)
97-
prover.advance_proof(max_iterations=max_iterations, execute_depth=max_depth, cut_point_rules=cut_rules)
99+
prover.advance_proof(max_iterations=max_iterations)
98100

99101
kcfg_show = KCFGShow(
100102
kcfg_explore.kprint,

src/tests/integration/proof/test_non_det.py

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -54,11 +54,8 @@ def test_all_path_reachability_prove(
5454
)
5555

5656
proof = APRProof.from_claim(kprove.definition, claim, logs={})
57-
prover = APRProver(proof, kcfg_explore=kcfg_explore)
58-
prover.advance_proof(
59-
max_iterations=max_iterations,
60-
execute_depth=max_depth,
61-
)
57+
prover = APRProver(proof, kcfg_explore=kcfg_explore, execute_depth=max_depth)
58+
prover.advance_proof(max_iterations=max_iterations)
6259

6360
kcfg_show = KCFGShow(
6461
kcfg_explore.kprint, node_printer=APRProofNodePrinter(proof, kcfg_explore.kprint, full_printer=True)

0 commit comments

Comments
 (0)