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

Commit 8c1b2bb

Browse files
Add cterm_get_model to KCFGExplore for counterexample generation (#519)
Closes the pyk-related part of runtimeverification/evm-semantics#1927, which is aimed to generate and output concrete assignment to variables corresponding to the failed Foundry test. Adds `cterm_get_model(cterm: CTerm) -> Subst | None` function to `KCFGExplore`, which returns a variable substitution identified via the `get-model` RPC request. Also adds two IMP tests that check the output of `cterm_get_model(cterm)` (one of a successful call, one of an unsuccessful). --------- Co-authored-by: devops <[email protected]>
1 parent 6c28b66 commit 8c1b2bb

File tree

4 files changed

+80
-3
lines changed

4 files changed

+80
-3
lines changed

package/version

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
0.1.357
1+
0.1.358

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.357"
7+
version = "0.1.358"
88
description = ""
99
authors = [
1010
"Runtime Verification, Inc. <[email protected]>",

src/pyk/kcfg/explore.py

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
)
1919
from ..kast.outer import KRule
2020
from ..konvert import krule_to_kore
21-
from ..kore.rpc import KoreClient, KoreServer, StopReason
21+
from ..kore.rpc import KoreClient, KoreServer, SatResult, StopReason, UnknownResult, UnsatResult
2222
from ..kore.syntax import Import, Module
2323
from ..ktool.kprove import KoreExecLogFormat
2424
from ..prelude import k
@@ -176,6 +176,32 @@ def kast_simplify(self, kast: KInner) -> tuple[KInner, tuple[LogEntry, ...]]:
176176
kast_simplified = self.kprint.kore_to_kast(kore_simplified)
177177
return kast_simplified, logs
178178

179+
def cterm_get_model(self, cterm: CTerm, module_name: str | None = None) -> Subst | None:
180+
_LOGGER.info(f'Getting model: {cterm}')
181+
kore = self.kprint.kast_to_kore(cterm.kast, GENERATED_TOP_CELL)
182+
_, kore_client = self._kore_rpc
183+
result = kore_client.get_model(kore, module_name=module_name)
184+
if type(result) is UnknownResult:
185+
_LOGGER.debug('Result is Unknown')
186+
return None
187+
elif type(result) is UnsatResult:
188+
_LOGGER.debug('Result is UNSAT')
189+
return None
190+
elif type(result) is SatResult:
191+
_LOGGER.debug('Result is SAT')
192+
model_subst = self.kprint.kore_to_kast(result.model)
193+
_subst: dict[str, KInner] = {}
194+
for subst_pred in flatten_label('#And', model_subst):
195+
subst_pattern = mlEquals(KVariable('###VAR'), KVariable('###TERM'))
196+
m = subst_pattern.match(subst_pred)
197+
if m is not None and type(m['###VAR']) is KVariable:
198+
_subst[m['###VAR'].name] = m['###TERM']
199+
else:
200+
raise AssertionError(f'Received a non-substitution from get-model endpoint: {subst_pred}')
201+
return Subst(_subst)
202+
else:
203+
raise AssertionError('Received an invalid response from get-model endpoint')
204+
179205
def cterm_implies(
180206
self,
181207
antecedent: CTerm,

src/tests/integration/kcfg/test_imp.py

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,36 @@
263263
),
264264
)
265265

266+
GET_MODEL_TEST_DATA: Final = (
267+
(
268+
'get-model-sat',
269+
(
270+
'int $n ; $n = X ;',
271+
'.Map',
272+
mlAnd(
273+
[
274+
mlEqualsTrue(KApply('_==Int_', [KVariable('X'), intToken(3)])),
275+
]
276+
),
277+
),
278+
Subst({'X': intToken(3)}),
279+
),
280+
(
281+
'get-model-unsat',
282+
(
283+
'int $n ; $n = X ;',
284+
'.Map',
285+
mlAnd(
286+
[
287+
mlEqualsTrue(KApply('_<Int_', [KVariable('X'), intToken(4)])),
288+
mlEqualsTrue(KApply('_>Int_', [KVariable('X'), intToken(4)])),
289+
]
290+
),
291+
),
292+
None,
293+
),
294+
)
295+
266296
APR_PROVE_TEST_DATA: Iterable[tuple[str, Path, str, str, int | None, int | None, Iterable[str], ProofStatus, int]] = (
267297
(
268298
'imp-simple-addition-1',
@@ -707,6 +737,27 @@ def test_execute(
707737
assert actual_depth == expected_depth
708738
assert set(actual_next_states) == set(expected_next_states)
709739

740+
@pytest.mark.parametrize(
741+
'test_id,cterm,expected',
742+
GET_MODEL_TEST_DATA,
743+
ids=[test_id for test_id, *_ in GET_MODEL_TEST_DATA],
744+
)
745+
def test_get_model(
746+
self,
747+
kcfg_explore: KCFGExplore,
748+
cterm: CTerm,
749+
test_id: str,
750+
expected: Subst | None,
751+
) -> None:
752+
# Given
753+
cterm_term = self.config(kcfg_explore.kprint, *cterm)
754+
755+
# When
756+
actual = kcfg_explore.cterm_get_model(cterm_term)
757+
758+
# Then
759+
assert actual == expected
760+
710761
@pytest.mark.parametrize(
711762
'test_id,antecedent,consequent,expected',
712763
IMPLIES_TEST_DATA,

0 commit comments

Comments
 (0)