@@ -140,8 +140,10 @@ public void reset() {
140140 doneProblems .clear ();
141141 }
142142
143- public static IExpr computePredExpr (Expression ap , IntMatrixCol sumMatrix , List <Integer > representative ,
144- ISparsePetriNet sr ) {
143+ public static IExpr computePredExpr (Expression ap , IntMatrixCol sumMatrix , List <Integer > representative , ISparsePetriNet sr ) {
144+ // Constants for explosion detection
145+ final int MAX_TOTAL_WEIGHT = 10000 ; // Maximum allowed cumulative weight
146+
145147 // we know that s satisfies ap
146148 // we want to force existence of an immediate predecessor of s satisfying !ap
147149
@@ -153,55 +155,67 @@ public static IExpr computePredExpr(Expression ap, IntMatrixCol sumMatrix, List<
153155 // * t was selected in the Parikh solution to reach s; |t|>0
154156
155157 // a map from index in reduced flow to set of transitions with this effect
156- Map <Integer , List <Integer >> revMap = SMTUtils .computeImages (representative );
157-
158- SparseIntArray supp = SMTUtils .computeSupport (ap );
159-
160- IFactory ef = SMT .instance .smtConfig .exprFactory ;
161-
162- List <IExpr > allPotentialPred = new ArrayList <>();
163-
164- int selected = 0 ;
165- // scan transition *effects* in sumMatrix
166- for (int tid = 0 , tide = sumMatrix .getColumnCount (); tid < tide ; tid ++) {
167- SparseIntArray t = sumMatrix .getColumn (tid );
168- if (!SparseIntArray .keysIntersect (supp , t )) {
169- // guaranteed to stutter : this is not a candidate
170- continue ;
171- } else {
172- if (selected ++ > 1000 ) {
173- // whatever...
174- return null ;
175- }
176- // more subtle we do touch the target AP
177- // compute if firing t would go from !ap to ap
178- // * the predecessor by t of s satisfies !ap; this depends only on the effect of
179- // t, not it's precise definition
180- IExpr apFalseBeforeT = SMTUtils .rewriteAfterEffect (Expression .not (ap ), t , true )
181- .accept (new ExprTranslator ());
182-
183- // * t was selected in the Parikh solution to reach s; |t|>0
184- IExpr tselected = ef .fcn (ef .symbol (">=" ), ef .symbol ("t" + tid ), ef .numeral (1 ));
185-
186- // * t was feasibly the last fired transition, i.e. there is a transition t'
187- // that t represents such that s >= post(t')
188- List <IExpr > alternatives = new ArrayList <>();
189- for (Integer ti : revMap .get (tid )) {
190- alternatives .add (buildFeasible (ef , sr .getFlowTP ().getColumn (ti )));
191- }
158+ Map <Integer , List <Integer >> revMap = SMTUtils .computeImages (representative );
159+ SparseIntArray supp = SMTUtils .computeSupport (ap );
160+ IFactory ef = SMT .instance .smtConfig .exprFactory ;
161+
162+ List <IExpr > allPotentialPred = new ArrayList <>();
163+ int cumulativeWeight = 0 ; // Track total weight of the expression tree
164+
165+ // scan transition *effects* in sumMatrix
166+ for (int tid = 0 , tide = sumMatrix .getColumnCount (); tid < tide ; tid ++) {
167+ SparseIntArray t = sumMatrix .getColumn (tid );
168+ if (!SparseIntArray .keysIntersect (supp , t )) {
169+ // guaranteed to stutter : this is not a candidate
170+ continue ;
171+ }
172+ // more subtle we do touch the target AP
173+ // compute if firing t would go from !ap to ap
174+ // * the predecessor by t of s satisfies !ap; this depends only on the effect of
175+ // t, not it's precise definition
176+ // Compute predecessor condition
177+ IExpr apFalseBeforeT = SMTUtils .rewriteAfterEffect (Expression .not (ap ), t , true ).accept (new ExprTranslator ());
178+ cumulativeWeight += SMTUtils .computeWeight (apFalseBeforeT );
179+ // Check if cumulative weight exceeds threshold
180+ if (cumulativeWeight > MAX_TOTAL_WEIGHT ) {
181+ System .err .println ("Excessive predecessor constraint size, skipping predecessor." );
182+ return null ; // Bail out completely
183+ }
184+
185+ // * t was selected in the Parikh solution to reach s; |t|>0
186+ IExpr tselected = ef .fcn (ef .symbol (">=" ), ef .symbol ("t" + tid ), ef .numeral (1 ));
192187
193- // combine
194- List <IExpr > toAnd = new ArrayList <>();
195- toAnd .add (apFalseBeforeT );
196- toAnd .add (tselected );
197- toAnd .add (SMTUtils .makeOr (alternatives ));
198- allPotentialPred .add (SMTUtils .makeAnd (toAnd ));
199- }
200- }
201- // assert an OR of one of the candidates
202- IExpr predicate = SMTUtils .makeOr (allPotentialPred );
203- return predicate ;
188+ // * t was feasibly the last fired transition, i.e. there is a transition t'
189+ // that t represents such that s >= post(t')
190+ List <IExpr > alternatives = new ArrayList <>();
191+ for (Integer ti : revMap .get (tid )) {
192+ IExpr elt = buildFeasible (ef , sr .getFlowTP ().getColumn (ti ));
193+ cumulativeWeight += SMTUtils .computeWeight (elt );
194+ // Check if cumulative weight exceeds threshold
195+ if (cumulativeWeight > MAX_TOTAL_WEIGHT ) {
196+ System .err .println ("Excessive predecessor constraint size, skipping predecessor." );
197+ return null ; // Bail out completely
198+ }
199+ alternatives .add (elt );
200+ }
201+ IExpr alternativesOr = SMTUtils .makeOr (alternatives );
202+
203+ // Combine into AND expression
204+ List <IExpr > toAnd = new ArrayList <>();
205+ toAnd .add (apFalseBeforeT );
206+ toAnd .add (tselected );
207+ toAnd .add (alternativesOr );
208+ IExpr conjunct = SMTUtils .makeAnd (toAnd );
209+
210+ // Add the conjunct to the list
211+ allPotentialPred .add (conjunct );
212+ }
213+
214+ // assert an OR of one of the candidates
215+ IExpr predicate = SMTUtils .makeOr (allPotentialPred );
216+ return predicate ;
204217 }
218+
205219
206220 private static IExpr buildFeasible (IFactory ef , SparseIntArray tp ) {
207221 List <IExpr > tojoin = new ArrayList <>();
0 commit comments