1
1
from __future__ import annotations
2
2
3
3
import logging
4
+ from abc import ABC , abstractmethod
4
5
from contextlib import contextmanager
6
+ from dataclasses import dataclass
5
7
from pathlib import Path
6
8
from typing import TYPE_CHECKING
7
9
22
24
from pyk .kore .rpc import KoreClient , KoreExecLogFormat , TransportType , kore_server
23
25
from pyk .proof import APRProof , APRProver
24
26
from pyk .proof .implies import EqualityProof , ImpliesProver
27
+ from pyk .proof .proof import parallel_advance_proof
25
28
from pyk .utils import single
26
29
27
30
if TYPE_CHECKING :
@@ -91,9 +94,116 @@ def get_apr_proof_for_spec(
91
94
return apr_proof
92
95
93
96
97
+ @dataclass
98
+ class RunProverParams :
99
+ execute_depth : int
100
+ terminal_rules : Iterable [str ]
101
+ cut_point_rules : Iterable [str ]
102
+ counterexample_info : bool
103
+ always_check_subsumption : bool
104
+ fast_check_subsumption : bool
105
+
106
+
107
+ class APRProofStrategy (ABC ):
108
+ params : RunProverParams
109
+
110
+ def __init__ (self , params : RunProverParams ) -> None :
111
+ self .params = params
112
+
113
+ @abstractmethod
114
+ def prove (self , proof : APRProof , max_iterations : int | None = None , fail_fast : bool = False ) -> None : ...
115
+
116
+
117
+ class ParallelStrategy (APRProofStrategy ):
118
+ _create_kcfg_explore : Callable [[], KCFGExplore ]
119
+ _max_workers = 1
120
+
121
+ def __init__ (
122
+ self ,
123
+ create_kcfg_explore : Callable [[], KCFGExplore ],
124
+ params : RunProverParams ,
125
+ max_workers : int = 1 ,
126
+ ) -> None :
127
+ self ._create_kcfg_explore = create_kcfg_explore
128
+ self ._max_workers = max_workers
129
+ super ().__init__ (params )
130
+
131
+ def prove (self , proof : APRProof , max_iterations : int | None = None , fail_fast : bool = False ) -> None :
132
+ def create_prover () -> APRProver :
133
+ return APRProver (
134
+ self ._create_kcfg_explore (),
135
+ execute_depth = self .params .execute_depth ,
136
+ terminal_rules = self .params .terminal_rules ,
137
+ cut_point_rules = self .params .cut_point_rules ,
138
+ counterexample_info = self .params .counterexample_info ,
139
+ always_check_subsumption = self .params .always_check_subsumption ,
140
+ fast_check_subsumption = self .params .fast_check_subsumption ,
141
+ )
142
+
143
+ parallel_advance_proof (
144
+ proof = proof ,
145
+ create_prover = create_prover ,
146
+ max_iterations = max_iterations ,
147
+ fail_fast = fail_fast ,
148
+ max_workers = self ._max_workers ,
149
+ )
150
+
151
+
152
+ class SequentialStrategy (APRProofStrategy ):
153
+ _kcfg_explore : KCFGExplore
154
+
155
+ def __init__ (self , kcfg_explore : KCFGExplore , params : RunProverParams ) -> None :
156
+ self ._kcfg_explore = kcfg_explore
157
+ super ().__init__ (params )
158
+
159
+ def prove (self , proof : APRProof , max_iterations : int | None = None , fail_fast : bool = False ) -> None :
160
+ prover = APRProver (
161
+ self ._kcfg_explore ,
162
+ execute_depth = self .params .execute_depth ,
163
+ terminal_rules = self .params .terminal_rules ,
164
+ cut_point_rules = self .params .cut_point_rules ,
165
+ counterexample_info = self .params .counterexample_info ,
166
+ always_check_subsumption = self .params .always_check_subsumption ,
167
+ fast_check_subsumption = self .params .fast_check_subsumption ,
168
+ )
169
+ prover .advance_proof (fail_fast = fail_fast , max_iterations = max_iterations , proof = proof )
170
+
171
+
172
+ def select_apr_strategy (
173
+ params : RunProverParams ,
174
+ max_frontier_parallel : int ,
175
+ kcfg_explore : KCFGExplore | None = None ,
176
+ create_kcfg_explore : Callable [[], KCFGExplore ] | None = None ,
177
+ ) -> APRProofStrategy :
178
+ strategy : APRProofStrategy
179
+
180
+ if max_frontier_parallel > 1 and create_kcfg_explore is not None :
181
+ strategy = ParallelStrategy (
182
+ max_workers = max_frontier_parallel ,
183
+ create_kcfg_explore = create_kcfg_explore ,
184
+ params = params ,
185
+ )
186
+ elif kcfg_explore is not None or create_kcfg_explore is not None :
187
+ if kcfg_explore is not None :
188
+ _kcfg_explore = kcfg_explore
189
+ else :
190
+ assert create_kcfg_explore is not None
191
+ _kcfg_explore = create_kcfg_explore ()
192
+ strategy = SequentialStrategy (
193
+ kcfg_explore = _kcfg_explore ,
194
+ params = params ,
195
+ )
196
+ else :
197
+ raise ValueError (
198
+ 'Must provide at least one of kcfg_explore or create_kcfg_explore, or provide create_kcfg_explore if using max_frontier_parallel > 1.'
199
+ )
200
+ return strategy
201
+
202
+
94
203
def run_prover (
95
204
proof : Proof ,
96
- kcfg_explore : KCFGExplore ,
205
+ kcfg_explore : KCFGExplore | None = None ,
206
+ create_kcfg_explore : Callable [[], KCFGExplore ] | None = None ,
97
207
max_depth : int = 1000 ,
98
208
max_iterations : int | None = None ,
99
209
cut_point_rules : Iterable [str ] = (),
@@ -102,22 +212,33 @@ def run_prover(
102
212
counterexample_info : bool = False ,
103
213
always_check_subsumption : bool = False ,
104
214
fast_check_subsumption : bool = False ,
215
+ max_frontier_parallel : int = 1 ,
105
216
) -> bool :
106
217
prover : APRProver | ImpliesProver
107
218
try :
108
219
if type (proof ) is APRProof :
109
- prover = APRProver (
110
- kcfg_explore ,
111
- execute_depth = max_depth ,
112
- terminal_rules = terminal_rules ,
113
- cut_point_rules = cut_point_rules ,
114
- counterexample_info = counterexample_info ,
115
- always_check_subsumption = always_check_subsumption ,
116
- fast_check_subsumption = fast_check_subsumption ,
220
+ strategy = select_apr_strategy (
221
+ create_kcfg_explore = create_kcfg_explore ,
222
+ kcfg_explore = kcfg_explore ,
223
+ max_frontier_parallel = max_frontier_parallel ,
224
+ params = RunProverParams (
225
+ always_check_subsumption = always_check_subsumption ,
226
+ counterexample_info = counterexample_info ,
227
+ cut_point_rules = cut_point_rules ,
228
+ execute_depth = max_depth ,
229
+ fast_check_subsumption = fast_check_subsumption ,
230
+ terminal_rules = terminal_rules ,
231
+ ),
117
232
)
118
- prover .advance_proof (proof , max_iterations = max_iterations , fail_fast = fail_fast )
233
+ strategy .prove (fail_fast = fail_fast , max_iterations = max_iterations , proof = proof )
234
+
119
235
elif type (proof ) is EqualityProof :
120
- prover = ImpliesProver (proof , kcfg_explore = kcfg_explore )
236
+ if kcfg_explore is not None :
237
+ prover = ImpliesProver (proof , kcfg_explore = kcfg_explore )
238
+ elif create_kcfg_explore is not None :
239
+ prover = ImpliesProver (proof , kcfg_explore = create_kcfg_explore ())
240
+ else :
241
+ raise ValueError ('Must provide at least one of kcfg_explore or create_kcfg_explore for EqualityProof.' )
121
242
prover .advance_proof (proof )
122
243
else :
123
244
raise ValueError (f'Do not know how to build prover for proof: { proof } ' )
@@ -293,6 +414,7 @@ def legacy_explore(
293
414
bug_report : BugReport | None = None ,
294
415
haskell_log_format : KoreExecLogFormat = KoreExecLogFormat .ONELINE ,
295
416
haskell_log_entries : Iterable [str ] = (),
417
+ haskell_threads : int | None = None ,
296
418
log_axioms_file : Path | None = None ,
297
419
trace_rewrites : bool = False ,
298
420
start_server : bool = True ,
@@ -315,6 +437,7 @@ def legacy_explore(
315
437
smt_tactic = smt_tactic ,
316
438
haskell_log_format = haskell_log_format ,
317
439
haskell_log_entries = haskell_log_entries ,
440
+ haskell_threads = haskell_threads ,
318
441
log_axioms_file = log_axioms_file ,
319
442
fallback_on = fallback_on ,
320
443
interim_simplification = interim_simplification ,
0 commit comments