Skip to content

Commit a2f5abf

Browse files
committed
protect against excessive predecessor constraint sizes
1 parent 27808a9 commit a2f5abf

File tree

2 files changed

+81
-49
lines changed

2 files changed

+81
-49
lines changed

smt/fr.lip6.move.gal.gal2smt/src/fr/lip6/move/gal/structural/smt/PredecessorConstraintRefiner.java

Lines changed: 63 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -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<>();

smt/fr.lip6.move.gal.gal2smt/src/fr/lip6/move/gal/structural/smt/SMTUtils.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -339,5 +339,23 @@ public static VarSet computeSupport(IExpr pred) {
339339
}
340340
return vc.support;
341341
}
342+
343+
// Helper method to compute syntactic weight of an IExpr
344+
public static int computeWeight(IExpr expr) {
345+
if (expr == null) {
346+
return 0;
347+
}
348+
if (expr instanceof IExpr.ISymbol || expr instanceof IExpr.INumeral) {
349+
return 1; // Leaf node
350+
} else if (expr instanceof IExpr.IFcnExpr) {
351+
IExpr.IFcnExpr fcn = (IExpr.IFcnExpr) expr;
352+
int weight = 1; // Count the function itself
353+
for (IExpr arg : fcn.args()) {
354+
weight += computeWeight(arg); // Recursively count arguments
355+
}
356+
return weight;
357+
}
358+
return 1; // Default for unhandled types
359+
}
342360

343361
}

0 commit comments

Comments
 (0)