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

Commit b09cd39

Browse files
authored
Merge branch 'master' into noah/anti-unify-sort-fix
2 parents c782d0f + 66e1af2 commit b09cd39

File tree

3 files changed

+80
-24
lines changed

3 files changed

+80
-24
lines changed

src/pyk/proof/reachability.py

Lines changed: 52 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
from pyk.kore.rpc import LogEntry
99

1010
from ..cterm import CTerm
11-
from ..kast.inner import KRewrite, KSort
11+
from ..kast.inner import KInner, KRewrite, KSort, Subst
1212
from ..kast.manip import flatten_label, ml_pred_to_bool
1313
from ..kast.outer import KClaim
1414
from ..kcfg import KCFG
@@ -23,7 +23,6 @@
2323
from pathlib import Path
2424
from typing import Any, Final, TypeVar
2525

26-
from ..kast.inner import KInner
2726
from ..kast.outer import KDefinition
2827
from ..kcfg import KCFGExplore
2928
from ..kcfg.kcfg import NodeIdLike
@@ -781,27 +780,61 @@ def lines(self) -> list[str]:
781780

782781
@dataclass(frozen=True)
783782
class APRFailureInfo:
784-
failing_nodes: FrozenDict[int, tuple[str, str]]
785783
pending_nodes: frozenset[int]
784+
failing_nodes: frozenset[int]
785+
path_conditions: FrozenDict[int, str]
786+
failure_reasons: FrozenDict[int, str]
787+
models: FrozenDict[int, frozenset[tuple[str, str]]]
786788

787-
def __init__(self, failing_nodes: Mapping[int, tuple[str, str]], pending_nodes: Iterable[int]):
788-
object.__setattr__(self, 'failing_nodes', FrozenDict(failing_nodes))
789+
def __init__(
790+
self,
791+
failing_nodes: Iterable[int],
792+
pending_nodes: Iterable[int],
793+
path_conditions: Mapping[int, str],
794+
failure_reasons: Mapping[int, str],
795+
models: Mapping[int, Iterable[tuple[str, str]]],
796+
):
797+
object.__setattr__(self, 'failing_nodes', frozenset(failing_nodes))
789798
object.__setattr__(self, 'pending_nodes', frozenset(pending_nodes))
799+
object.__setattr__(self, 'path_conditions', FrozenDict(path_conditions))
800+
object.__setattr__(self, 'failure_reasons', FrozenDict(failure_reasons))
801+
object.__setattr__(
802+
self, 'models', FrozenDict({node_id: frozenset(model) for (node_id, model) in models.items()})
803+
)
790804

791805
@staticmethod
792-
def from_proof(proof: APRProof, kcfg_explore: KCFGExplore) -> APRFailureInfo:
806+
def from_proof(proof: APRProof, kcfg_explore: KCFGExplore, counterexample_info: bool = False) -> APRFailureInfo:
793807
target = proof.kcfg.node(proof.target)
794808
pending_nodes = {node.id for node in proof.pending}
795-
failing_nodes = {}
809+
failing_nodes = {node.id for node in proof.failing}
810+
path_conditions = {}
811+
failure_reasons = {}
812+
models = {}
796813
for node in proof.failing:
797814
simplified_node, _ = kcfg_explore.cterm_simplify(node.cterm)
798815
simplified_target, _ = kcfg_explore.cterm_simplify(target.cterm)
799816
node_cterm = CTerm.from_kast(simplified_node)
800817
target_cterm = CTerm.from_kast(simplified_target)
801818
_, reason = kcfg_explore.implication_failure_reason(node_cterm, target_cterm)
802819
path_condition = kcfg_explore.kprint.pretty_print(proof.path_constraints(node.id))
803-
failing_nodes[node.id] = (reason, path_condition)
804-
return APRFailureInfo(failing_nodes=failing_nodes, pending_nodes=pending_nodes)
820+
failure_reasons[node.id] = reason
821+
path_conditions[node.id] = path_condition
822+
if counterexample_info:
823+
model_subst = kcfg_explore.cterm_get_model(node.cterm)
824+
if type(model_subst) is Subst:
825+
model: list[tuple[str, str]] = []
826+
for var, term in model_subst.to_dict().items():
827+
term_kast = KInner.from_dict(term)
828+
term_pretty = kcfg_explore.kprint.pretty_print(term_kast)
829+
model.append((var, term_pretty))
830+
models[node.id] = model
831+
return APRFailureInfo(
832+
failing_nodes=failing_nodes,
833+
pending_nodes=pending_nodes,
834+
path_conditions=path_conditions,
835+
failure_reasons=failure_reasons,
836+
models=models,
837+
)
805838

806839
def print(self) -> list[str]:
807840
res_lines: list[str] = []
@@ -819,10 +852,9 @@ def print(self) -> list[str]:
819852
if num_failing > 0:
820853
res_lines.append('')
821854
res_lines.append('Failing nodes:')
822-
print(self.failing_nodes)
823-
for node_id, info in self.failing_nodes.items():
824-
print(info)
825-
(reason, path_condition) = info
855+
for node_id in self.failing_nodes:
856+
reason = self.failure_reasons[node_id]
857+
path_condition = self.path_conditions[node_id]
826858
res_lines.append('')
827859
res_lines.append(f' Node id: {str(node_id)}')
828860

@@ -832,6 +864,13 @@ def print(self) -> list[str]:
832864
res_lines.append(' Path condition:')
833865
res_lines += [f' {path_condition}']
834866

867+
if node_id in self.models:
868+
res_lines.append(' Model:')
869+
for var, term in self.models[node_id]:
870+
res_lines.append(f' {var} = {term}')
871+
else:
872+
res_lines.append(' Failed to generate a model.')
873+
835874
res_lines.append('')
836875
res_lines.append('Join the Runtime Verification Discord server for support: https://discord.gg/CurfmXNtbN')
837876
return res_lines

src/tests/integration/kcfg/test_imp.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1033,7 +1033,7 @@ def test_failure_info(
10331033
assert expected_pending == actual_pending
10341034
assert expected_failing == actual_failing
10351035

1036-
actual_path_conds = set({path_condition for _, (_, path_condition) in failure_info.failing_nodes.items()})
1036+
actual_path_conds = set({path_condition for _, path_condition in failure_info.path_conditions.items()})
10371037
expected_path_conds = set({kprove.pretty_print(condition) for condition in path_conditions})
10381038

10391039
assert actual_path_conds == expected_path_conds

src/tests/unit/test_proof.py

Lines changed: 27 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -270,17 +270,31 @@ def test_aprbmc_proof_from_dict_heterogeneous_subproofs(proof_dir: Path) -> None
270270

271271

272272
def test_print_failure_info() -> None:
273-
failing_nodes: dict[int, tuple[str, str]] = {}
274-
failing_nodes[3] = (
275-
'Structural matching failed, the following cells failed individually (antecedent #Implies consequent):\nSTATE_CELL: $n |-> 2 #Implies 1',
276-
'true #Equals X <=Int 100',
277-
)
278-
failing_nodes[5] = (
279-
'Structural matching failed, the following cells failed individually (antecedent #Implies consequent):\nSTATE_CELL: $n |-> 5 #Implies 6',
280-
'#Top',
281-
)
273+
failing_nodes = [3, 5]
282274
pending_nodes = [6, 7, 8]
283-
failure_info = APRFailureInfo(failing_nodes=failing_nodes, pending_nodes=pending_nodes)
275+
276+
path_conditions = {}
277+
path_conditions[3] = 'true #Equals X <=Int 100'
278+
path_conditions[5] = '#Top'
279+
280+
failure_reasons = {}
281+
failure_reasons[
282+
3
283+
] = 'Structural matching failed, the following cells failed individually (antecedent #Implies consequent):\nSTATE_CELL: $n |-> 2 #Implies 1'
284+
failure_reasons[
285+
5
286+
] = 'Structural matching failed, the following cells failed individually (antecedent #Implies consequent):\nSTATE_CELL: $n |-> 5 #Implies 6'
287+
288+
models: dict[int, list[tuple[str, str]]] = {}
289+
models[5] = [('X', '101')]
290+
291+
failure_info = APRFailureInfo(
292+
failing_nodes=failing_nodes,
293+
pending_nodes=pending_nodes,
294+
failure_reasons=failure_reasons,
295+
path_conditions=path_conditions,
296+
models=models,
297+
)
284298

285299
actual_output = '\n'.join(failure_info.print())
286300
expected_output = r"""5 Failure nodes. (3 pending and 2 failing)
@@ -295,13 +309,16 @@ def test_print_failure_info() -> None:
295309
STATE_CELL: $n |-> 2 #Implies 1
296310
Path condition:
297311
true #Equals X <=Int 100
312+
Failed to generate a model.
298313
299314
Node id: 5
300315
Failure reason:
301316
Structural matching failed, the following cells failed individually (antecedent #Implies consequent):
302317
STATE_CELL: $n |-> 5 #Implies 6
303318
Path condition:
304319
#Top
320+
Model:
321+
X = 101
305322
306323
Join the Runtime Verification Discord server for support: https://discord.gg/CurfmXNtbN"""
307324

0 commit comments

Comments
 (0)