Skip to content

Commit 1209847

Browse files
committed
introducing "auto add_*" to scripts.
1 parent 835497a commit 1209847

2 files changed

Lines changed: 131 additions & 0 deletions

File tree

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
package de.uka.ilkd.key.scripts;
2+
3+
import org.jspecify.annotations.Nullable;
4+
import org.key_project.prover.rules.Rule;
5+
import de.uka.ilkd.key.macros.FilterStrategy;
6+
import de.uka.ilkd.key.proof.Goal;
7+
import de.uka.ilkd.key.rule.Taclet;
8+
import de.uka.ilkd.key.strategy.Strategy;
9+
import org.key_project.logic.Name;
10+
import org.key_project.prover.rules.RuleApp;
11+
import org.key_project.prover.rules.RuleSet;
12+
import org.key_project.prover.sequent.PosInOccurrence;
13+
import org.key_project.prover.strategy.costbased.NumberRuleAppCost;
14+
import org.key_project.prover.strategy.costbased.RuleAppCost;
15+
import org.key_project.util.collection.Pair;
16+
17+
import java.util.ArrayList;
18+
import java.util.List;
19+
import java.util.Map;
20+
import java.util.Optional;
21+
22+
class AdditionalRulesStrategy extends FilterStrategy {
23+
/** Name of that strategy */
24+
private static final Name NAME = new Name(
25+
AdditionalRulesStrategy.class.getSimpleName());
26+
27+
private static final Map<String, String> TRANSLATIONS =
28+
Map.of("high", "-50", "medium", "1000", "low", "10000");
29+
private static final int DEFAULT_PRIORITY = 1000;
30+
31+
private final List<Pair<String, Integer>> additionalRules;
32+
33+
public AdditionalRulesStrategy(Strategy delegate, String additionalRules) {
34+
super(delegate);
35+
this.additionalRules = parseAddRules(additionalRules);
36+
}
37+
38+
private List<Pair<String, Integer>> parseAddRules(String additionalRules) {
39+
List<Pair<String, Integer>> result = new ArrayList<>();
40+
for (String entry : additionalRules.trim().split(" *, *")) {
41+
String[] parts = entry.split(" *= *", 2);
42+
int prio;
43+
if (parts.length == 2) {
44+
String prioStr = parts[1];
45+
prioStr = TRANSLATIONS.getOrDefault(prioStr, prioStr);
46+
try {
47+
prio = Integer.parseInt(prioStr);
48+
} catch (NumberFormatException e) {
49+
throw new IllegalArgumentException("Invalid value for additional rule: " + parts[1]);
50+
}
51+
} else {
52+
prio = DEFAULT_PRIORITY;
53+
}
54+
55+
result.add(new Pair<>(parts[0], prio));
56+
}
57+
return result;
58+
}
59+
60+
@Override
61+
public Name name() {
62+
return NAME;
63+
}
64+
65+
@Override
66+
public RuleAppCost computeCost(RuleApp app, PosInOccurrence pio, Goal goal) {
67+
RuleAppCost localCost = computeLocalCost(app.rule());
68+
if (localCost != null) {
69+
return localCost;
70+
}
71+
return super.computeCost(app, pio, goal);
72+
}
73+
74+
@Override
75+
public boolean isApprovedApp(RuleApp app, PosInOccurrence pio, Goal goal) {
76+
RuleAppCost localCost = computeLocalCost(app.rule());
77+
if (localCost != null) {
78+
return true;
79+
}
80+
return super.isApprovedApp(app, pio, goal);
81+
}
82+
83+
private @Nullable RuleAppCost computeLocalCost(Rule rule) {
84+
String name = rule.name().toString();
85+
Optional<Integer> cost = lookup(name);
86+
if(cost.isPresent()) {
87+
return NumberRuleAppCost.create(cost.get());
88+
}
89+
90+
if (rule instanceof Taclet taclet) {
91+
for (RuleSet rs : taclet.getRuleSets()) {
92+
String rname = rs.name().toString();
93+
cost = lookup(rname);
94+
if(cost.isPresent()) {
95+
return NumberRuleAppCost.create(cost.get());
96+
}
97+
}
98+
}
99+
100+
return null;
101+
}
102+
103+
private Optional<Integer> lookup(String name) {
104+
return additionalRules.stream()
105+
.filter(nameAndPrio -> name.matches(nameAndPrio.first))
106+
.findFirst()
107+
.map(p -> p.second);
108+
}
109+
110+
@Override
111+
public boolean isStopAtFirstNonCloseableGoal() {
112+
return false;
113+
}
114+
115+
116+
}

key.core/src/main/java/de/uka/ilkd/key/scripts/AutoCommand.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import de.uka.ilkd.key.prover.impl.ApplyStrategy;
1515
import de.uka.ilkd.key.scripts.meta.*;
1616
import de.uka.ilkd.key.strategy.FocussedBreakpointRuleApplicationManager;
17+
import de.uka.ilkd.key.strategy.Strategy;
1718
import de.uka.ilkd.key.strategy.StrategyProperties;
1819

1920
import org.key_project.prover.engine.ProverCore;
@@ -92,6 +93,11 @@ public void execute(ScriptCommandAst args) throws ScriptException, InterruptedEx
9293

9394
SetCommand.updateStrategySettings(state(), activeStrategyProperties);
9495

96+
final Strategy originalStrategy = state.getProof().getActiveStrategy();
97+
if (arguments.additionalRules != null) {
98+
state.getProof().setActiveStrategy(new AdditionalRulesStrategy(originalStrategy, arguments.additionalRules));
99+
}
100+
95101
// Give some feedback
96102
applyStrategy.addProverTaskObserver(uiControl);
97103

@@ -113,6 +119,7 @@ public void execute(ScriptCommandAst args) throws ScriptException, InterruptedEx
113119
activeStrategyProperties.setProperty(ov.settingName, ov.oldValue);
114120
}
115121
}
122+
state.getProof().setActiveStrategy(originalStrategy);
116123
SetCommand.updateStrategySettings(state(), activeStrategyProperties);
117124
}
118125
}
@@ -215,6 +222,14 @@ may be a showstopper (if expansion increases the complexity on the sequent too m
215222
Enable dependency reasoning. In modular reasoning, the value of symbols may stay the same, \
216223
without that its definition is known. May be an enabler, may be a showstopper.""")
217224
public boolean dependencies;
225+
226+
@Option(value = "add")
227+
@Documentation("""
228+
Additional rules to be used by the auto strategy. The rules have to be given as a
229+
comma-separated list of rule names and rule set names. Each entry can be assigned to a priority
230+
(high, low, medium or a natural number) using an equals sign.
231+
""")
232+
public @Nullable String additionalRules;
218233
}
219234

220235
private static final class OriginalValue {

0 commit comments

Comments
 (0)