22
33import json
44import logging
5+ from itertools import chain
56from typing import TYPE_CHECKING
67
78from pyk .kore .rpc import LogEntry
@@ -51,8 +52,9 @@ def __init__(
5152 logs : dict [int , tuple [LogEntry , ...]],
5253 terminal_nodes : Iterable [NodeIdLike ] | None = None ,
5354 proof_dir : Path | None = None ,
55+ subproof_ids : Iterable [str ] = (),
5456 ):
55- super ().__init__ (id , proof_dir = proof_dir )
57+ super ().__init__ (id , proof_dir = proof_dir , subproof_ids = subproof_ids )
5658 self .kcfg = kcfg
5759 self .init = init
5860 self .target = target
@@ -90,24 +92,36 @@ def read_proof(id: str, proof_dir: Path) -> APRProof:
9092 def status (self ) -> ProofStatus :
9193 if len (self .terminal ) > 0 :
9294 return ProofStatus .FAILED
93- elif len (self .pending ) > 0 :
95+ elif len (self .pending ) > 0 or self . subproofs_status == ProofStatus . PENDING :
9496 return ProofStatus .PENDING
9597 else :
96- return ProofStatus .PASSED
98+ if self .subproofs_status == ProofStatus .PASSED :
99+ return ProofStatus .PASSED
100+ else :
101+ return ProofStatus .FAILED
97102
98103 @classmethod
99104 def from_dict (cls : type [APRProof ], dct : Mapping [str , Any ], proof_dir : Path | None = None ) -> APRProof :
100105 cfg = KCFG .from_dict (dct ['cfg' ])
101- terminal_nodes = dct ['terminal_nodes' ]
102106 init_node = dct ['init' ]
107+ terminal_nodes = dct ['terminal_nodes' ]
103108 target_node = dct ['target' ]
104109 id = dct ['id' ]
110+ subproof_ids = dct ['subproof_ids' ] if 'subproof_ids' in dct else []
105111 if 'logs' in dct :
106112 logs = {k : tuple (LogEntry .from_dict (l ) for l in ls ) for k , ls in dct ['logs' ].items ()}
107113 else :
108114 logs = {}
109-
110- return APRProof (id , cfg , init_node , target_node , logs , terminal_nodes = terminal_nodes , proof_dir = proof_dir )
115+ return APRProof (
116+ id ,
117+ cfg ,
118+ init_node ,
119+ target_node ,
120+ logs ,
121+ terminal_nodes = terminal_nodes ,
122+ proof_dir = proof_dir ,
123+ subproof_ids = subproof_ids ,
124+ )
111125
112126 @staticmethod
113127 def from_claim (defn : KDefinition , claim : KClaim , * args : Any , ** kwargs : Any ) -> APRProof :
@@ -130,29 +144,34 @@ def path_constraints(self, final_node_id: NodeIdLike) -> KInner:
130144
131145 @property
132146 def dict (self ) -> dict [str , Any ]:
147+ dct = super ().dict
148+ dct ['type' ] = 'APRProof'
149+ dct ['cfg' ] = self .kcfg .to_dict ()
150+ dct ['init' ] = self .init
151+ dct ['target' ] = self .target
152+ dct ['terminal_nodes' ] = self ._terminal_nodes
133153 logs = {k : [l .to_dict () for l in ls ] for k , ls in self .logs .items ()}
134- return {
135- 'type' : 'APRProof' ,
136- 'id' : self .id ,
137- 'cfg' : self .kcfg .to_dict (),
138- 'init' : self .init ,
139- 'target' : self .target ,
140- 'terminal_nodes' : self ._terminal_nodes ,
141- 'logs' : logs ,
142- }
154+ dct ['logs' ] = logs
155+ return dct
143156
144157 def add_terminal (self , nid : NodeIdLike ) -> None :
145158 self ._terminal_nodes .append (self .kcfg ._resolve (nid ))
146159
147160 @property
148161 def summary (self ) -> Iterable [str ]:
149- return [
162+ subproofs_summaries = chain (subproof .summary for subproof in self .subproofs )
163+ yield from [
150164 f'APRProof: { self .id } ' ,
151165 f' status: { self .status } ' ,
152166 f' nodes: { len (self .kcfg .nodes )} ' ,
167+ f' frontier: { len (self .kcfg .frontier )} ' ,
168+ f' stuck: { len (self .kcfg .stuck )} ' ,
169+ 'Subproofs:' if len (self .subproof_ids ) else '' ,
153170 f' pending: { len (self .pending )} ' ,
154171 f' terminal: { len (self .terminal )} ' ,
155172 ]
173+ for summary in subproofs_summaries :
174+ yield from summary
156175
157176
158177class APRBMCProof (APRProof ):
@@ -171,8 +190,9 @@ def __init__(
171190 bmc_depth : int ,
172191 bounded_nodes : Iterable [int ] | None = None ,
173192 proof_dir : Path | None = None ,
193+ subproof_ids : Iterable [str ] = (),
174194 ):
175- super ().__init__ (id , kcfg , init , target , logs , proof_dir = proof_dir )
195+ super ().__init__ (id , kcfg , init , target , logs , proof_dir = proof_dir , subproof_ids = subproof_ids )
176196 self .bmc_depth = bmc_depth
177197 self ._bounded_nodes = list (bounded_nodes ) if bounded_nodes is not None else []
178198
@@ -202,26 +222,40 @@ def is_bounded(self, node_id: NodeIdLike) -> bool:
202222
203223 @property
204224 def status (self ) -> ProofStatus :
205- if len (self .terminal ) > 0 :
225+ if (
226+ any (nd .id not in self ._bounded_nodes for nd in self .kcfg .stuck )
227+ or self .subproofs_status == ProofStatus .FAILED
228+ ):
206229 return ProofStatus .FAILED
207- elif len (self .pending ) > 0 :
230+ elif len (self .pending ) > 0 or self . subproofs_status == ProofStatus . PENDING :
208231 return ProofStatus .PENDING
209232 else :
210233 return ProofStatus .PASSED
211234
212235 @classmethod
213236 def from_dict (cls : type [APRBMCProof ], dct : Mapping [str , Any ], proof_dir : Path | None = None ) -> APRBMCProof :
214237 cfg = KCFG .from_dict (dct ['cfg' ])
215- id = dct ['id' ]
216238 init = dct ['init' ]
217239 target = dct ['target' ]
218240 bounded_nodes = dct ['bounded_nodes' ]
219241 bmc_depth = dct ['bmc_depth' ]
242+ id = dct ['id' ]
243+ subproof_ids = dct ['subproof_ids' ] if 'subproof_ids' in dct else []
220244 if 'logs' in dct :
221245 logs = {k : tuple (LogEntry .from_dict (l ) for l in ls ) for k , ls in dct ['logs' ].items ()}
222246 else :
223247 logs = {}
224- return APRBMCProof (id , cfg , init , target , logs , bmc_depth , bounded_nodes = bounded_nodes , proof_dir = proof_dir )
248+ return APRBMCProof (
249+ id ,
250+ cfg ,
251+ init ,
252+ target ,
253+ logs ,
254+ bmc_depth ,
255+ bounded_nodes = bounded_nodes ,
256+ proof_dir = proof_dir ,
257+ subproof_ids = subproof_ids ,
258+ )
225259
226260 @staticmethod
227261 def from_claim_with_bmc_depth (defn : KDefinition , claim : KClaim , bmc_depth : int ) -> APRBMCProof :
@@ -243,14 +277,21 @@ def add_bounded(self, nid: NodeIdLike) -> None:
243277
244278 @property
245279 def summary (self ) -> Iterable [str ]:
246- return [
280+ subproofs_summaries = chain (subproof .summary for subproof in self .subproofs )
281+ yield from [
247282 f'APRBMCProof(depth={ self .bmc_depth } ): { self .id } ' ,
248283 f' status: { self .status } ' ,
249284 f' nodes: { len (self .kcfg .nodes )} ' ,
285+ f' frontier: { len (self .kcfg .frontier )} ' ,
286+ f' stuck: { len ([nd for nd in self .kcfg .stuck if nd .id not in self ._bounded_nodes ])} ' ,
287+ f' bmc-depth-bounded: { len (self ._bounded_nodes )} ' ,
288+ 'Subproofs' if len (self .subproof_ids ) else '' ,
250289 f' pending: { len (self .pending )} ' ,
251290 f' terminal: { len (self .terminal )} ' ,
252291 f' bounded: { len (self .bounded )} ' ,
253292 ]
293+ for summary in subproofs_summaries :
294+ yield from summary
254295
255296
256297class APRProver :
0 commit comments