diff --git a/.gitignore b/.gitignore index 894015b1c6c..df03685c259 100644 --- a/.gitignore +++ b/.gitignore @@ -67,6 +67,7 @@ key/key.ui/examples/**/**.proof # generated by the antlr plugin of IntelliJ key.core/src/main/antlr4/gen/ +*.tokens scripts/tools/checkstyle/key_checks_incremental.xml checkstyle-diff.txt diff --git a/key.core.infflow/src/main/java/de/uka/ilkd/key/informationflow/macros/PrepareInfFlowContractPreBranchesMacro.java b/key.core.infflow/src/main/java/de/uka/ilkd/key/informationflow/macros/PrepareInfFlowContractPreBranchesMacro.java index 7670258d45d..c8a18c337a8 100644 --- a/key.core.infflow/src/main/java/de/uka/ilkd/key/informationflow/macros/PrepareInfFlowContractPreBranchesMacro.java +++ b/key.core.infflow/src/main/java/de/uka/ilkd/key/informationflow/macros/PrepareInfFlowContractPreBranchesMacro.java @@ -10,12 +10,12 @@ import de.uka.ilkd.key.proof.Node; import de.uka.ilkd.key.proof.Proof; import de.uka.ilkd.key.strategy.AbstractFeatureStrategy; -import de.uka.ilkd.key.strategy.Strategy; import org.key_project.logic.Name; import org.key_project.prover.proof.ProofGoal; import org.key_project.prover.rules.RuleApp; import org.key_project.prover.sequent.PosInOccurrence; +import org.key_project.prover.strategy.Strategy; import org.key_project.prover.strategy.costbased.MutableState; import org.key_project.prover.strategy.costbased.NumberRuleAppCost; import org.key_project.prover.strategy.costbased.RuleAppCost; @@ -138,17 +138,9 @@ private String getAppRuleName(Node parent) { return parentRuleName; } - - @Override - protected RuleAppCost instantiateApp(RuleApp app, PosInOccurrence pio, Goal goal, - MutableState mState) { - return computeCost(app, pio, goal, mState); - } - @Override public boolean isStopAtFirstNonCloseableGoal() { return false; } } - } diff --git a/key.core.infflow/src/main/java/de/uka/ilkd/key/informationflow/macros/SelfcompositionStateExpansionMacro.java b/key.core.infflow/src/main/java/de/uka/ilkd/key/informationflow/macros/SelfcompositionStateExpansionMacro.java index 0c0da931f76..51cc1b7a38c 100644 --- a/key.core.infflow/src/main/java/de/uka/ilkd/key/informationflow/macros/SelfcompositionStateExpansionMacro.java +++ b/key.core.infflow/src/main/java/de/uka/ilkd/key/informationflow/macros/SelfcompositionStateExpansionMacro.java @@ -12,10 +12,7 @@ import de.uka.ilkd.key.proof.Goal; import de.uka.ilkd.key.proof.Proof; import de.uka.ilkd.key.proof.init.ProofOblInput; -import de.uka.ilkd.key.strategy.JavaCardDLStrategyFactory; -import de.uka.ilkd.key.strategy.RuleAppCostCollector; -import de.uka.ilkd.key.strategy.Strategy; -import de.uka.ilkd.key.strategy.StrategyProperties; +import de.uka.ilkd.key.strategy.*; import org.key_project.logic.Name; import org.key_project.prover.proof.ProofGoal; @@ -65,7 +62,7 @@ protected Set getAdmittedRuleNames() { } @Override - protected Strategy<@NonNull Goal> createStrategy(Proof proof, + protected org.key_project.prover.strategy.Strategy<@NonNull Goal> createStrategy(Proof proof, PosInOccurrence posInOcc) { return new SelfCompExpansionStrategy(getAdmittedRuleNames()); } @@ -113,7 +110,7 @@ protected boolean allowOSS() { * This strategy accepts all rule apps for which the rule name is in the admitted set or has * INF_FLOW_UNFOLD_PREFIX as a prefix and rejects everything else. */ - private class SelfCompExpansionStrategy implements Strategy { + private class SelfCompExpansionStrategy implements JavaStrategy { private final Name NAME = new Name( SelfcompositionStateExpansionMacro.SelfCompExpansionStrategy.class.getSimpleName()); @@ -136,10 +133,10 @@ public Name name() { String name = ruleApp.rule().name().toString(); if ((admittedRuleNames.contains(name) || name.startsWith(INF_FLOW_UNFOLD_PREFIX)) && ruleApplicationInContextAllowed(ruleApp, pio, goal)) { - JavaCardDLStrategyFactory strategyFactory = new JavaCardDLStrategyFactory(); - Strategy<@NonNull Goal> javaDlStrategy = + ModularJavaDLStrategyFactory strategyFactory = new ModularJavaDLStrategyFactory(); + org.key_project.prover.strategy.Strategy<@NonNull Goal> dlStrategy = strategyFactory.create(goal.proof(), new StrategyProperties()); - RuleAppCost costs = javaDlStrategy.computeCost(ruleApp, pio, goal, mState); + RuleAppCost costs = dlStrategy.computeCost(ruleApp, pio, goal, mState); if ("orLeft".equals(name)) { costs = costs.add(NumberRuleAppCost.create(100)); } @@ -157,7 +154,7 @@ public boolean isApprovedApp(RuleApp app, PosInOccurrence pio, @Override public void instantiateApp(RuleApp app, PosInOccurrence pio, Goal goal, - RuleAppCostCollector collector) { + org.key_project.prover.strategy.RuleAppCostCollector collector) { } @Override diff --git a/key.core.infflow/src/main/java/de/uka/ilkd/key/informationflow/macros/UseInformationFlowContractMacro.java b/key.core.infflow/src/main/java/de/uka/ilkd/key/informationflow/macros/UseInformationFlowContractMacro.java index c29e48d2882..b495ea6e849 100644 --- a/key.core.infflow/src/main/java/de/uka/ilkd/key/informationflow/macros/UseInformationFlowContractMacro.java +++ b/key.core.infflow/src/main/java/de/uka/ilkd/key/informationflow/macros/UseInformationFlowContractMacro.java @@ -14,13 +14,13 @@ import de.uka.ilkd.key.proof.Goal; import de.uka.ilkd.key.proof.Node; import de.uka.ilkd.key.proof.Proof; -import de.uka.ilkd.key.strategy.RuleAppCostCollector; -import de.uka.ilkd.key.strategy.Strategy; +import de.uka.ilkd.key.strategy.JavaStrategy; import org.key_project.logic.Name; import org.key_project.prover.proof.ProofGoal; import org.key_project.prover.rules.RuleApp; import org.key_project.prover.sequent.PosInOccurrence; +import org.key_project.prover.strategy.RuleAppCostCollector; import org.key_project.prover.strategy.costbased.MutableState; import org.key_project.prover.strategy.costbased.NumberRuleAppCost; import org.key_project.prover.strategy.costbased.RuleAppCost; @@ -166,7 +166,7 @@ private String getAppRuleName(Node parent) { * This strategy accepts all rule apps for which the rule name starts with a string in the * admitted set and rejects everything else. */ - protected class PropExpansionStrategy implements Strategy { + protected class PropExpansionStrategy implements JavaStrategy { private final Name NAME = new Name(UseInformationFlowContractMacro.PropExpansionStrategy.class.getSimpleName()); diff --git a/key.core.infflow/src/main/java/de/uka/ilkd/key/informationflow/rule/InfFlowBlockContractInternalRule.java b/key.core.infflow/src/main/java/de/uka/ilkd/key/informationflow/rule/InfFlowBlockContractInternalRule.java index 1fbee05a4d6..9ee7886a1ba 100644 --- a/key.core.infflow/src/main/java/de/uka/ilkd/key/informationflow/rule/InfFlowBlockContractInternalRule.java +++ b/key.core.infflow/src/main/java/de/uka/ilkd/key/informationflow/rule/InfFlowBlockContractInternalRule.java @@ -25,7 +25,6 @@ import de.uka.ilkd.key.logic.JTerm; import de.uka.ilkd.key.logic.ProgramElementName; import de.uka.ilkd.key.logic.TermBuilder; -import de.uka.ilkd.key.logic.TermServices; import de.uka.ilkd.key.logic.label.ParameterlessTermLabel; import de.uka.ilkd.key.logic.op.JFunction; import de.uka.ilkd.key.logic.op.LocationVariable; @@ -43,6 +42,7 @@ import de.uka.ilkd.key.speclang.BlockContract; import de.uka.ilkd.key.util.MiscTools; +import org.key_project.logic.LogicServices; import org.key_project.logic.Name; import org.key_project.logic.op.Function; import org.key_project.prover.sequent.PosInOccurrence; @@ -101,7 +101,7 @@ private InfFlowBlockContractInternalRule() { @Override public BlockContractInternalBuiltInRuleApp createApp( - PosInOccurrence occurrence, TermServices services) { + PosInOccurrence occurrence, LogicServices services) { return new InfFlowBlockContractInternalBuiltInRuleApp(this, occurrence); } diff --git a/key.core.infflow/src/main/java/de/uka/ilkd/key/informationflow/rule/InfFlowWhileInvariantRule.java b/key.core.infflow/src/main/java/de/uka/ilkd/key/informationflow/rule/InfFlowWhileInvariantRule.java index cd4645f9955..20d85489797 100644 --- a/key.core.infflow/src/main/java/de/uka/ilkd/key/informationflow/rule/InfFlowWhileInvariantRule.java +++ b/key.core.infflow/src/main/java/de/uka/ilkd/key/informationflow/rule/InfFlowWhileInvariantRule.java @@ -32,6 +32,7 @@ import de.uka.ilkd.key.speclang.LoopSpecification; import de.uka.ilkd.key.util.MiscTools; +import org.key_project.logic.LogicServices; import org.key_project.logic.Name; import org.key_project.logic.Namespace; import org.key_project.logic.op.Function; @@ -58,8 +59,8 @@ public Name name() { @Override public InfFlowLoopInvariantBuiltInRuleApp createApp(PosInOccurrence pos, - TermServices services) { - return new InfFlowLoopInvariantBuiltInRuleApp(this, pos, services); + LogicServices services) { + return new InfFlowLoopInvariantBuiltInRuleApp(this, pos, (TermServices) services); } @Override diff --git a/key.core.symbolic_execution/src/main/java/de/uka/ilkd/key/symbolic_execution/rule/ModalitySideProofRule.java b/key.core.symbolic_execution/src/main/java/de/uka/ilkd/key/symbolic_execution/rule/ModalitySideProofRule.java index 17ad88fed2f..1fdb515dccf 100644 --- a/key.core.symbolic_execution/src/main/java/de/uka/ilkd/key/symbolic_execution/rule/ModalitySideProofRule.java +++ b/key.core.symbolic_execution/src/main/java/de/uka/ilkd/key/symbolic_execution/rule/ModalitySideProofRule.java @@ -10,7 +10,6 @@ import de.uka.ilkd.key.java.Services; import de.uka.ilkd.key.logic.JTerm; import de.uka.ilkd.key.logic.TermBuilder; -import de.uka.ilkd.key.logic.TermServices; import de.uka.ilkd.key.logic.op.*; import de.uka.ilkd.key.proof.Goal; import de.uka.ilkd.key.proof.mgt.ProofEnvironment; @@ -20,6 +19,7 @@ import de.uka.ilkd.key.symbolic_execution.util.SymbolicExecutionSideProofUtil; import de.uka.ilkd.key.symbolic_execution.util.SymbolicExecutionUtil; +import org.key_project.logic.LogicServices; import org.key_project.logic.Name; import org.key_project.logic.op.Function; import org.key_project.prover.rules.RuleAbortException; @@ -119,7 +119,7 @@ public boolean isApplicable(Goal goal, PosInOccurrence pio) { * {@inheritDoc} */ @Override - public IBuiltInRuleApp createApp(PosInOccurrence pos, TermServices services) { + public IBuiltInRuleApp createApp(PosInOccurrence pos, LogicServices services) { return new DefaultBuiltInRuleApp(this, pos); } diff --git a/key.core.symbolic_execution/src/main/java/de/uka/ilkd/key/symbolic_execution/rule/QuerySideProofRule.java b/key.core.symbolic_execution/src/main/java/de/uka/ilkd/key/symbolic_execution/rule/QuerySideProofRule.java index 614dcb995db..ebe67383c14 100644 --- a/key.core.symbolic_execution/src/main/java/de/uka/ilkd/key/symbolic_execution/rule/QuerySideProofRule.java +++ b/key.core.symbolic_execution/src/main/java/de/uka/ilkd/key/symbolic_execution/rule/QuerySideProofRule.java @@ -8,16 +8,15 @@ import de.uka.ilkd.key.java.Services; import de.uka.ilkd.key.logic.JTerm; import de.uka.ilkd.key.logic.TermBuilder; -import de.uka.ilkd.key.logic.TermServices; import de.uka.ilkd.key.logic.op.*; import de.uka.ilkd.key.proof.Goal; import de.uka.ilkd.key.proof.mgt.ProofEnvironment; import de.uka.ilkd.key.rule.BuiltInRule; import de.uka.ilkd.key.rule.DefaultBuiltInRuleApp; import de.uka.ilkd.key.rule.IBuiltInRuleApp; -import de.uka.ilkd.key.rule.QueryExpand; import de.uka.ilkd.key.symbolic_execution.util.SymbolicExecutionSideProofUtil; +import org.key_project.logic.LogicServices; import org.key_project.logic.Name; import org.key_project.logic.op.Function; import org.key_project.logic.sort.Sort; @@ -150,7 +149,7 @@ public boolean isApplicable(Goal goal, PosInOccurrence pio) { /** * Checks if the query term is supported. The functionality is identical to - * {@link QueryExpand#isApplicable(Goal, PosInOccurrence)}. + * {@link BuiltInRule#isApplicable(org.key_project.prover.proof.ProofGoal, PosInOccurrence)}. * * @param goal The {@link Goal}. * @param pmTerm The {@link JTerm} to with the query to check. @@ -182,7 +181,7 @@ private boolean isApplicableQuery(Goal goal, JTerm pmTerm, * {@inheritDoc} */ @Override - public IBuiltInRuleApp createApp(PosInOccurrence pos, TermServices services) { + public IBuiltInRuleApp createApp(PosInOccurrence pos, LogicServices services) { return new DefaultBuiltInRuleApp(this, pos); } diff --git a/key.core.symbolic_execution/src/main/java/de/uka/ilkd/key/symbolic_execution/strategy/SimplifyTermStrategy.java b/key.core.symbolic_execution/src/main/java/de/uka/ilkd/key/symbolic_execution/strategy/SimplifyTermStrategy.java index 5ad174975fd..a4b0b8f8454 100644 --- a/key.core.symbolic_execution/src/main/java/de/uka/ilkd/key/symbolic_execution/strategy/SimplifyTermStrategy.java +++ b/key.core.symbolic_execution/src/main/java/de/uka/ilkd/key/symbolic_execution/strategy/SimplifyTermStrategy.java @@ -26,13 +26,13 @@ import org.jspecify.annotations.NonNull; /** - * {@link Strategy} used to simplify {@link JTerm}s in side proofs. + * {@link JavaStrategy} used to simplify {@link JTerm}s in side proofs. * * @author Martin Hentschel */ public class SimplifyTermStrategy extends JavaCardDLStrategy { /** - * The {@link Name} of the side proof {@link Strategy}. + * The {@link Name} of the side proof {@link JavaStrategy}. */ public static final Name name = new Name("Simplify Term Strategy"); @@ -100,7 +100,8 @@ public static class Factory implements StrategyFactory { * {@inheritDoc} */ @Override - public Strategy create(Proof proof, StrategyProperties sp) { + public org.key_project.prover.strategy.Strategy create(Proof proof, + StrategyProperties sp) { return new SimplifyTermStrategy(proof, sp); } diff --git a/key.core.symbolic_execution/src/main/java/de/uka/ilkd/key/symbolic_execution/strategy/SymbolicExecutionStrategy.java b/key.core.symbolic_execution/src/main/java/de/uka/ilkd/key/symbolic_execution/strategy/SymbolicExecutionStrategy.java index db91ec77ac6..b297b3b05da 100644 --- a/key.core.symbolic_execution/src/main/java/de/uka/ilkd/key/symbolic_execution/strategy/SymbolicExecutionStrategy.java +++ b/key.core.symbolic_execution/src/main/java/de/uka/ilkd/key/symbolic_execution/strategy/SymbolicExecutionStrategy.java @@ -5,18 +5,16 @@ import java.util.ArrayList; -import de.uka.ilkd.key.logic.JTerm; import de.uka.ilkd.key.proof.Goal; import de.uka.ilkd.key.proof.Proof; import de.uka.ilkd.key.strategy.JavaCardDLStrategy; -import de.uka.ilkd.key.strategy.Strategy; +import de.uka.ilkd.key.strategy.JavaStrategy; import de.uka.ilkd.key.strategy.StrategyFactory; import de.uka.ilkd.key.strategy.StrategyProperties; import de.uka.ilkd.key.strategy.definition.IDefaultStrategyPropertiesFactory; import de.uka.ilkd.key.strategy.definition.OneOfStrategyPropertyDefinition; import de.uka.ilkd.key.strategy.definition.StrategyPropertyValueDefinition; import de.uka.ilkd.key.strategy.definition.StrategySettingsDefinition; -import de.uka.ilkd.key.strategy.feature.*; import de.uka.ilkd.key.strategy.feature.instantiator.OneOfCP; import de.uka.ilkd.key.strategy.termProjection.FocusProjection; import de.uka.ilkd.key.symbolic_execution.rule.ModalitySideProofRule; @@ -28,23 +26,26 @@ import org.key_project.prover.proof.rulefilter.SetRuleFilter; import org.key_project.prover.rules.RuleApp; import org.key_project.prover.sequent.PosInOccurrence; +import org.key_project.prover.strategy.Strategy; import org.key_project.prover.strategy.costbased.MutableState; import org.key_project.prover.strategy.costbased.RuleAppCost; import org.key_project.prover.strategy.costbased.TopRuleAppCost; import org.key_project.prover.strategy.costbased.feature.BinaryFeature; import org.key_project.prover.strategy.costbased.feature.ConditionalFeature; +import org.key_project.prover.strategy.costbased.feature.CountBranchFeature; import org.key_project.prover.strategy.costbased.feature.Feature; +import org.key_project.prover.strategy.costbased.feature.RuleSetDispatchFeature; import org.key_project.prover.strategy.costbased.feature.ScaleFeature; import org.key_project.prover.strategy.costbased.termProjection.TermBuffer; import org.jspecify.annotations.NonNull; /** - * {@link Strategy} to use for symbolic execution. + * {@link JavaStrategy} to use for symbolic execution. */ public class SymbolicExecutionStrategy extends JavaCardDLStrategy { /** - * The {@link Name} of the symbolic execution {@link Strategy}. + * The {@link Name} of the symbolic execution {@link JavaStrategy}. */ public static final Name name = new Name("Symbolic Execution Strategy"); @@ -85,7 +86,7 @@ private SymbolicExecutionStrategy(Proof proof, StrategyProperties sp) { .equals(sp.get(StrategyProperties.SYMBOLIC_EXECUTION_ALIAS_CHECK_OPTIONS_KEY))) { // Make sure that an immediately alias check is performed by doing cuts of objects to // find out if they can be the same or not - RuleSetDispatchFeature instRsd = getInstantiationDispatcher(); + RuleSetDispatchFeature instRsd = getDispatcher(StrategyAspect.Instantiation); enableInstantiate(); final TermBuffer buffer = new TermBuffer<>(); Feature originalCut = instRsd.get(getHeuristic("cut")); @@ -106,7 +107,7 @@ private SymbolicExecutionStrategy(Proof proof, StrategyProperties sp) { * {@inheritDoc} */ @Override - protected Feature setupApprovalF() { + protected @NonNull Feature setupApprovalF() { Feature result = super.setupApprovalF(); // Make sure that cuts are only applied if the cut term is not already part of the sequent. // This check is performed exactly before the rule is applied because the sequent might has @@ -122,17 +123,17 @@ protected Feature setupApprovalF() { * {@inheritDoc} */ @Override - protected Feature setupGlobalF(Feature dispatcher) { + protected @NonNull Feature setupGlobalF(@NonNull Feature dispatcher) { Feature globalF = super.setupGlobalF(dispatcher); // Make sure that modalities without symbolic execution label are executed first because // they might forbid rule application on modalities with symbolic execution label (see loop // body branches) globalF = add(globalF, ifZero(not(new BinaryFeature() { @Override - protected > boolean filter(RuleApp app, - PosInOccurrence pos, Goal goal, MutableState mState) { + protected > boolean filter(RuleApp app, + PosInOccurrence pos, GOAL goal, MutableState mState) { return pos != null - && SymbolicExecutionUtil.hasSymbolicExecutionLabel((JTerm) pos.subTerm()); + && SymbolicExecutionUtil.hasSymbolicExecutionLabel(pos.subTerm()); } }), longConst(-3000))); // Make sure that the modality which executes a loop body is preferred against the @@ -141,9 +142,9 @@ protected Feature setupGlobalF(Feature dispatcher) { add(globalF, ifZero(add(new Feature() { @Override - public > RuleAppCost computeCost( + public > RuleAppCost computeCost( RuleApp app, PosInOccurrence pos, - Goal goal, MutableState mState) { + GOAL goal, MutableState mState) { return pos != null ? cost(0) : TopRuleAppCost.INSTANCE; } }, @@ -302,7 +303,7 @@ public static class Factory implements StrategyFactory { * {@inheritDoc} */ @Override - public StrategySettingsDefinition getSettingsDefinition() { + public @NonNull StrategySettingsDefinition getSettingsDefinition() { // Properties OneOfStrategyPropertyDefinition methodTreatment = new OneOfStrategyPropertyDefinition( StrategyProperties.METHOD_OPTIONS_KEY, "Method Treatment", diff --git a/key.core.symbolic_execution/src/main/java/de/uka/ilkd/key/symbolic_execution/util/SymbolicExecutionUtil.java b/key.core.symbolic_execution/src/main/java/de/uka/ilkd/key/symbolic_execution/util/SymbolicExecutionUtil.java index a688d5aa657..348d3e667c5 100644 --- a/key.core.symbolic_execution/src/main/java/de/uka/ilkd/key/symbolic_execution/util/SymbolicExecutionUtil.java +++ b/key.core.symbolic_execution/src/main/java/de/uka/ilkd/key/symbolic_execution/util/SymbolicExecutionUtil.java @@ -46,8 +46,8 @@ import de.uka.ilkd.key.settings.StrategySettings; import de.uka.ilkd.key.speclang.Contract; import de.uka.ilkd.key.speclang.OperationContract; -import de.uka.ilkd.key.strategy.JavaCardDLStrategyFactory; -import de.uka.ilkd.key.strategy.Strategy; +import de.uka.ilkd.key.strategy.JavaStrategy; +import de.uka.ilkd.key.strategy.ModularJavaDLStrategyFactory; import de.uka.ilkd.key.strategy.StrategyProperties; import de.uka.ilkd.key.symbolic_execution.ExecutionVariableExtractor; import de.uka.ilkd.key.symbolic_execution.SymbolicExecutionTreeBuilder; @@ -2562,7 +2562,7 @@ private static JTerm computeTacletAppBranchCondition(Node parent, Node node, boo boolean improveReadability) throws ProofInputException { if (!(parent.getAppliedRuleApp() instanceof TacletApp app)) { throw new ProofInputException( - "Only TacletApp is allowed in branch computation but rule \"" + "Only ITacletApp is allowed in branch computation but rule \"" + parent.getAppliedRuleApp() + "\" was found."); } Services services = node.proof().getServices(); @@ -4312,7 +4312,7 @@ private static ImmutableArray extractValueFromUpdate( /** * Initializes the {@link Proof} of the given {@link SymbolicExecutionTreeBuilder} so that the - * correct {@link Strategy} is used. + * correct {@link JavaStrategy} is used. * * @param builder The {@link SymbolicExecutionTreeBuilder} to initialize. */ @@ -4325,7 +4325,7 @@ public static void initializeStrategy(SymbolicExecutionTreeBuilder builder) { new SymbolicExecutionStrategy.Factory().create(proof, strategyProperties)); } else { proof.setActiveStrategy( - new JavaCardDLStrategyFactory().create(proof, strategyProperties)); + new ModularJavaDLStrategyFactory().create(proof, strategyProperties)); } } diff --git a/key.core.testgen/src/main/java/de/uka/ilkd/key/testgen/macros/TestGenMacro.java b/key.core.testgen/src/main/java/de/uka/ilkd/key/testgen/macros/TestGenMacro.java index ec31a6f59cb..d531c029cff 100644 --- a/key.core.testgen/src/main/java/de/uka/ilkd/key/testgen/macros/TestGenMacro.java +++ b/key.core.testgen/src/main/java/de/uka/ilkd/key/testgen/macros/TestGenMacro.java @@ -11,7 +11,6 @@ import de.uka.ilkd.key.proof.Goal; import de.uka.ilkd.key.proof.Node; import de.uka.ilkd.key.proof.Proof; -import de.uka.ilkd.key.strategy.Strategy; import de.uka.ilkd.key.testgen.TestGenerationSettings; import org.key_project.logic.Name; @@ -19,6 +18,7 @@ import org.key_project.prover.rules.Rule; import org.key_project.prover.rules.RuleApp; import org.key_project.prover.sequent.PosInOccurrence; +import org.key_project.prover.strategy.Strategy; import org.key_project.prover.strategy.costbased.MutableState; import org.key_project.prover.strategy.costbased.NumberRuleAppCost; import org.key_project.prover.strategy.costbased.RuleAppCost; diff --git a/key.core.wd/src/main/java/de/uka/ilkd/key/wd/macro/WellDefinednessMacro.java b/key.core.wd/src/main/java/de/uka/ilkd/key/wd/macro/WellDefinednessMacro.java index 21bdf9cf3d8..e923507303c 100644 --- a/key.core.wd/src/main/java/de/uka/ilkd/key/wd/macro/WellDefinednessMacro.java +++ b/key.core.wd/src/main/java/de/uka/ilkd/key/wd/macro/WellDefinednessMacro.java @@ -9,8 +9,7 @@ import de.uka.ilkd.key.proof.Proof; import de.uka.ilkd.key.proof.init.ContractPO; import de.uka.ilkd.key.proof.init.FunctionalOperationContractPO; -import de.uka.ilkd.key.strategy.RuleAppCostCollector; -import de.uka.ilkd.key.strategy.Strategy; +import de.uka.ilkd.key.strategy.JavaStrategy; import de.uka.ilkd.key.wd.*; import de.uka.ilkd.key.wd.po.*; @@ -18,6 +17,8 @@ import org.key_project.prover.proof.ProofGoal; import org.key_project.prover.rules.RuleApp; import org.key_project.prover.sequent.PosInOccurrence; +import org.key_project.prover.strategy.RuleAppCostCollector; +import org.key_project.prover.strategy.Strategy; import org.key_project.prover.strategy.costbased.MutableState; import org.key_project.prover.strategy.costbased.NumberRuleAppCost; import org.key_project.prover.strategy.costbased.RuleAppCost; @@ -95,7 +96,7 @@ public boolean canApplyTo(Proof proof, ImmutableList goals, * This strategy accepts all rule apps for which the rule name is a Well-Definedness rule and * rejects everything else. */ - private static class WellDefinednessStrategy implements Strategy { + private static class WellDefinednessStrategy implements JavaStrategy { private static final Name NAME = new Name(WellDefinednessStrategy.class.getSimpleName()); diff --git a/key.core/src/main/java/de/uka/ilkd/key/control/instantiation_model/TacletFindModel.java b/key.core/src/main/java/de/uka/ilkd/key/control/instantiation_model/TacletFindModel.java index 0e4e53a806b..44e24fe93c7 100644 --- a/key.core/src/main/java/de/uka/ilkd/key/control/instantiation_model/TacletFindModel.java +++ b/key.core/src/main/java/de/uka/ilkd/key/control/instantiation_model/TacletFindModel.java @@ -70,7 +70,7 @@ public class TacletFindModel extends AbstractTableModel { /** * Create new data model for tree. * - * @param app the TacletApp where to get the necessary entries + * @param app the ITacletApp where to get the necessary entries * @param services services. * @param nss universal namespace of variables, minimum for input in a row. * @param scm the abbreviation map. diff --git a/key.core/src/main/java/de/uka/ilkd/key/control/instantiation_model/TacletInstantiationModel.java b/key.core/src/main/java/de/uka/ilkd/key/control/instantiation_model/TacletInstantiationModel.java index 429641df1a6..e7d67514292 100644 --- a/key.core/src/main/java/de/uka/ilkd/key/control/instantiation_model/TacletInstantiationModel.java +++ b/key.core/src/main/java/de/uka/ilkd/key/control/instantiation_model/TacletInstantiationModel.java @@ -216,7 +216,7 @@ public void setManualInput(int i, String s) { } /** - * replaces the TacletApp of this ApplyTacletDialogModel by an TacletApp where all name + * replaces the ITacletApp of this ApplyTacletDialogModel by an ITacletApp where all name * conflicts are resolved and thus the parser is enabled to accept variables from the context or * the prefix of the Taclet. * diff --git a/key.core/src/main/java/de/uka/ilkd/key/logic/VariableNamer.java b/key.core/src/main/java/de/uka/ilkd/key/logic/VariableNamer.java index f1c099e78e9..696ffd72ada 100644 --- a/key.core/src/main/java/de/uka/ilkd/key/logic/VariableNamer.java +++ b/key.core/src/main/java/de/uka/ilkd/key/logic/VariableNamer.java @@ -432,7 +432,7 @@ public ProgramElementName getTemporaryNameProposal(String basename) { @Override public String getProposal(TacletApp app, SchemaVariable var, Services services, Node undoAnchor, ImmutableList previousProposals) { - // determine posOfDeclaration from TacletApp + // determine posOfDeclaration from ITacletApp ContextStatementBlockInstantiation cie = app.instantiations().getContextInstantiation(); PosInProgram posOfDeclaration = (cie == null ? null : cie.prefix()); diff --git a/key.core/src/main/java/de/uka/ilkd/key/macros/AbstractBlastingMacro.java b/key.core/src/main/java/de/uka/ilkd/key/macros/AbstractBlastingMacro.java index ec0be803f4f..4ea22bf24c3 100644 --- a/key.core/src/main/java/de/uka/ilkd/key/macros/AbstractBlastingMacro.java +++ b/key.core/src/main/java/de/uka/ilkd/key/macros/AbstractBlastingMacro.java @@ -25,8 +25,7 @@ import de.uka.ilkd.key.rule.OneStepSimplifier; import de.uka.ilkd.key.speclang.ClassAxiom; import de.uka.ilkd.key.speclang.RepresentsAxiom; -import de.uka.ilkd.key.strategy.RuleAppCostCollector; -import de.uka.ilkd.key.strategy.Strategy; +import de.uka.ilkd.key.strategy.JavaStrategy; import org.key_project.logic.Name; import org.key_project.logic.op.Function; @@ -40,6 +39,8 @@ import org.key_project.prover.sequent.Semisequent; import org.key_project.prover.sequent.Sequent; import org.key_project.prover.sequent.SequentFormula; +import org.key_project.prover.strategy.RuleAppCostCollector; +import org.key_project.prover.strategy.Strategy; import org.key_project.prover.strategy.costbased.MutableState; import org.key_project.prover.strategy.costbased.NumberRuleAppCost; import org.key_project.prover.strategy.costbased.RuleAppCost; @@ -203,7 +204,7 @@ private static void addFormulas(List result, } } - private class SemanticsBlastingStrategy implements Strategy { + private class SemanticsBlastingStrategy implements JavaStrategy { @Override public @NonNull Name name() { diff --git a/key.core/src/main/java/de/uka/ilkd/key/macros/AbstractPropositionalExpansionMacro.java b/key.core/src/main/java/de/uka/ilkd/key/macros/AbstractPropositionalExpansionMacro.java index 3730ae239da..6232da484a5 100644 --- a/key.core/src/main/java/de/uka/ilkd/key/macros/AbstractPropositionalExpansionMacro.java +++ b/key.core/src/main/java/de/uka/ilkd/key/macros/AbstractPropositionalExpansionMacro.java @@ -61,7 +61,7 @@ public String getCategory() { protected abstract boolean allowOSS(); @Override - protected Strategy<@NonNull Goal> createStrategy(Proof proof, + protected org.key_project.prover.strategy.Strategy<@NonNull Goal> createStrategy(Proof proof, PosInOccurrence posInOcc) { return new PropExpansionStrategy(proof.getActiveStrategy(), getAdmittedRuleNames(), allowOSS()); @@ -85,15 +85,15 @@ protected boolean ruleApplicationInContextAllowed(RuleApp ruleApp, * This strategy accepts all rule apps for which the rule name is in the admitted set and * rejects everything else. */ - private static class PropExpansionStrategy implements Strategy { - + private static class PropExpansionStrategy implements JavaStrategy { private final Name NAME = new Name(PropExpansionStrategy.class.getSimpleName()); private final Set admittedRuleNames; - private final Strategy<@NonNull Goal> delegate; + private final org.key_project.prover.strategy.Strategy<@NonNull Goal> delegate; private final boolean allowOSS; - public PropExpansionStrategy(Strategy<@NonNull Goal> delegate, + public PropExpansionStrategy( + org.key_project.prover.strategy.Strategy<@NonNull Goal> delegate, Set admittedRuleNames, boolean allowOSS) { this.delegate = delegate; @@ -135,13 +135,12 @@ public boolean isApprovedApp(RuleApp app, PosInOccurrence pio, @Override public void instantiateApp(RuleApp app, PosInOccurrence pio, Goal goal, - RuleAppCostCollector collector) { + org.key_project.prover.strategy.RuleAppCostCollector collector) { } @Override public boolean isStopAtFirstNonCloseableGoal() { return false; } - } } diff --git a/key.core/src/main/java/de/uka/ilkd/key/macros/AutoMacro.java b/key.core/src/main/java/de/uka/ilkd/key/macros/AutoMacro.java index bad70679ffe..e8bbe7958b2 100644 --- a/key.core/src/main/java/de/uka/ilkd/key/macros/AutoMacro.java +++ b/key.core/src/main/java/de/uka/ilkd/key/macros/AutoMacro.java @@ -17,12 +17,12 @@ import de.uka.ilkd.key.proof.Goal; import de.uka.ilkd.key.proof.Proof; import de.uka.ilkd.key.rule.Taclet; -import de.uka.ilkd.key.strategy.Strategy; import org.key_project.logic.Name; import org.key_project.prover.rules.Rule; import org.key_project.prover.rules.RuleApp; import org.key_project.prover.sequent.PosInOccurrence; +import org.key_project.prover.strategy.Strategy; import org.jspecify.annotations.NonNull; diff --git a/key.core/src/main/java/de/uka/ilkd/key/macros/AutoPilotPrepareProofMacro.java b/key.core/src/main/java/de/uka/ilkd/key/macros/AutoPilotPrepareProofMacro.java index 81fac0efff8..29c3e231e60 100644 --- a/key.core/src/main/java/de/uka/ilkd/key/macros/AutoPilotPrepareProofMacro.java +++ b/key.core/src/main/java/de/uka/ilkd/key/macros/AutoPilotPrepareProofMacro.java @@ -71,10 +71,10 @@ public static boolean isAdmittedRule(Rule rule) { return false; } - private static class AutoPilotStrategy implements Strategy { + private static class AutoPilotStrategy implements JavaStrategy { private static final Name NAME = new Name("Autopilot filter strategy"); - private final Strategy<@NonNull Goal> delegate; + private final org.key_project.prover.strategy.Strategy<@NonNull Goal> delegate; /** the modality cache used by this strategy */ private final ModalityCache modalityCache = new ModalityCache(); @@ -139,7 +139,7 @@ public boolean isApprovedApp(RuleApp app, PosInOccurrence pio, Goal goal) { @Override public void instantiateApp(RuleApp app, PosInOccurrence pio, Goal goal, - RuleAppCostCollector collector) { + org.key_project.prover.strategy.RuleAppCostCollector collector) { delegate.instantiateApp(app, pio, goal, collector); } @@ -151,7 +151,7 @@ public boolean isStopAtFirstNonCloseableGoal() { } @Override - protected Strategy<@NonNull Goal> createStrategy(Proof proof, + protected org.key_project.prover.strategy.Strategy<@NonNull Goal> createStrategy(Proof proof, PosInOccurrence posInOcc) { return new AutoPilotStrategy(proof); } diff --git a/key.core/src/main/java/de/uka/ilkd/key/macros/FilterStrategy.java b/key.core/src/main/java/de/uka/ilkd/key/macros/FilterStrategy.java index c2f8d7a1794..c88c7beb2a6 100644 --- a/key.core/src/main/java/de/uka/ilkd/key/macros/FilterStrategy.java +++ b/key.core/src/main/java/de/uka/ilkd/key/macros/FilterStrategy.java @@ -4,19 +4,20 @@ package de.uka.ilkd.key.macros; import de.uka.ilkd.key.proof.Goal; -import de.uka.ilkd.key.strategy.RuleAppCostCollector; -import de.uka.ilkd.key.strategy.Strategy; +import de.uka.ilkd.key.strategy.JavaStrategy; import org.key_project.prover.proof.ProofGoal; import org.key_project.prover.rules.RuleApp; import org.key_project.prover.sequent.PosInOccurrence; +import org.key_project.prover.strategy.RuleAppCostCollector; +import org.key_project.prover.strategy.Strategy; import org.key_project.prover.strategy.costbased.MutableState; import org.key_project.prover.strategy.costbased.RuleAppCost; import org.key_project.prover.strategy.costbased.TopRuleAppCost; import org.jspecify.annotations.NonNull; -public abstract class FilterStrategy implements Strategy<@NonNull Goal> { +public abstract class FilterStrategy implements JavaStrategy { private final Strategy<@NonNull Goal> delegate; diff --git a/key.core/src/main/java/de/uka/ilkd/key/macros/FinishSymbolicExecutionMacro.java b/key.core/src/main/java/de/uka/ilkd/key/macros/FinishSymbolicExecutionMacro.java index c1ed41c7091..8d09c7a3196 100644 --- a/key.core/src/main/java/de/uka/ilkd/key/macros/FinishSymbolicExecutionMacro.java +++ b/key.core/src/main/java/de/uka/ilkd/key/macros/FinishSymbolicExecutionMacro.java @@ -6,13 +6,14 @@ import de.uka.ilkd.key.proof.Goal; import de.uka.ilkd.key.proof.Proof; import de.uka.ilkd.key.rule.Taclet; -import de.uka.ilkd.key.strategy.Strategy; +import de.uka.ilkd.key.strategy.JavaStrategy; import org.key_project.logic.Name; import org.key_project.prover.rules.Rule; import org.key_project.prover.rules.RuleApp; import org.key_project.prover.rules.RuleSet; import org.key_project.prover.sequent.PosInOccurrence; +import org.key_project.prover.strategy.Strategy; import org.jspecify.annotations.NonNull; @@ -20,7 +21,8 @@ * The macro FinishSymbolicExecutionMacro continues automatic rule application until there is no * more modality on the sequent. *

- * This is done by implementing a delegation {@link Strategy} which assigns to any rule application + * This is done by implementing a delegation {@link JavaStrategy} which assigns to any rule + * application * infinite costs if there is no modality on the sequent. * * @author mattias ulbrich diff --git a/key.core/src/main/java/de/uka/ilkd/key/macros/FinishSymbolicExecutionUntilMergePointMacro.java b/key.core/src/main/java/de/uka/ilkd/key/macros/FinishSymbolicExecutionUntilMergePointMacro.java index 3dd12582e8c..9b2b39a49f9 100644 --- a/key.core/src/main/java/de/uka/ilkd/key/macros/FinishSymbolicExecutionUntilMergePointMacro.java +++ b/key.core/src/main/java/de/uka/ilkd/key/macros/FinishSymbolicExecutionUntilMergePointMacro.java @@ -15,7 +15,7 @@ import de.uka.ilkd.key.proof.Node; import de.uka.ilkd.key.proof.Proof; import de.uka.ilkd.key.rule.merge.MergeRule; -import de.uka.ilkd.key.strategy.Strategy; +import de.uka.ilkd.key.strategy.JavaStrategy; import de.uka.ilkd.key.util.mergerule.MergeRuleUtils; import org.key_project.logic.Name; @@ -26,6 +26,7 @@ import org.key_project.prover.sequent.PosInOccurrence; import org.key_project.prover.sequent.Semisequent; import org.key_project.prover.sequent.SequentFormula; +import org.key_project.prover.strategy.Strategy; import org.key_project.util.collection.ImmutableArray; import org.key_project.util.collection.ImmutableList; @@ -37,7 +38,8 @@ * more modality on the sequent. *

* - * This is done by implementing a delegation {@link Strategy} which assigns to any rule application + * This is done by implementing a delegation {@link JavaStrategy} which assigns to any rule + * application * infinite costs if there is no modality on the sequent. * * @author Mattias Ulbrich diff --git a/key.core/src/main/java/de/uka/ilkd/key/macros/OneStepProofMacro.java b/key.core/src/main/java/de/uka/ilkd/key/macros/OneStepProofMacro.java index 989a4284d38..6f3230fdc49 100644 --- a/key.core/src/main/java/de/uka/ilkd/key/macros/OneStepProofMacro.java +++ b/key.core/src/main/java/de/uka/ilkd/key/macros/OneStepProofMacro.java @@ -5,13 +5,14 @@ import de.uka.ilkd.key.proof.Goal; import de.uka.ilkd.key.proof.Proof; -import de.uka.ilkd.key.strategy.RuleAppCostCollector; -import de.uka.ilkd.key.strategy.Strategy; +import de.uka.ilkd.key.strategy.JavaStrategy; import org.key_project.logic.Name; import org.key_project.prover.proof.ProofGoal; import org.key_project.prover.rules.RuleApp; import org.key_project.prover.sequent.PosInOccurrence; +import org.key_project.prover.strategy.RuleAppCostCollector; +import org.key_project.prover.strategy.Strategy; import org.key_project.prover.strategy.costbased.MutableState; import org.key_project.prover.strategy.costbased.RuleAppCost; @@ -57,7 +58,7 @@ public String getDescription() { * */ - private static class OneStepStrategy implements Strategy<@NonNull Goal> { + private static class OneStepStrategy implements JavaStrategy { private static final Name NAME = new Name(OneStepStrategy.class.getSimpleName()); private int counter; diff --git a/key.core/src/main/java/de/uka/ilkd/key/macros/StrategyProofMacro.java b/key.core/src/main/java/de/uka/ilkd/key/macros/StrategyProofMacro.java index 2975e0c6344..a19d58f74ad 100644 --- a/key.core/src/main/java/de/uka/ilkd/key/macros/StrategyProofMacro.java +++ b/key.core/src/main/java/de/uka/ilkd/key/macros/StrategyProofMacro.java @@ -12,13 +12,14 @@ import de.uka.ilkd.key.proof.Proof; import de.uka.ilkd.key.prover.impl.ApplyStrategy; import de.uka.ilkd.key.strategy.FocussedRuleApplicationManager; -import de.uka.ilkd.key.strategy.Strategy; +import de.uka.ilkd.key.strategy.JavaStrategy; import org.key_project.prover.engine.GoalChooser; import org.key_project.prover.engine.ProverCore; import org.key_project.prover.engine.ProverTaskListener; import org.key_project.prover.sequent.PosInOccurrence; import org.key_project.prover.strategy.RuleApplicationManager; +import org.key_project.prover.strategy.Strategy; import org.key_project.util.collection.ImmutableList; import org.jspecify.annotations.NonNull; @@ -31,11 +32,11 @@ * {@link #createStrategy(Proof, PosInOccurrence)}. * * This class is aware of Position in occurrences and can also be applied to inner nodes. Both - * {@link RuleApplicationManager} and {@link Strategy} are changed for the course of the + * {@link RuleApplicationManager} and {@link JavaStrategy} are changed for the course of the * macro but are restored afterwards using a {@link ProverTaskListener}. * * @see ProverTaskListener - * @see Strategy + * @see JavaStrategy */ public abstract class StrategyProofMacro extends AbstractProofMacro { diff --git a/key.core/src/main/java/de/uka/ilkd/key/macros/TranscendentalFloatSMTMacro.java b/key.core/src/main/java/de/uka/ilkd/key/macros/TranscendentalFloatSMTMacro.java index 95a4bee2b5b..debee133e9b 100644 --- a/key.core/src/main/java/de/uka/ilkd/key/macros/TranscendentalFloatSMTMacro.java +++ b/key.core/src/main/java/de/uka/ilkd/key/macros/TranscendentalFloatSMTMacro.java @@ -8,9 +8,9 @@ import de.uka.ilkd.key.proof.Goal; import de.uka.ilkd.key.proof.Proof; -import de.uka.ilkd.key.strategy.Strategy; import org.key_project.prover.sequent.PosInOccurrence; +import org.key_project.prover.strategy.Strategy; import org.jspecify.annotations.NonNull; diff --git a/key.core/src/main/java/de/uka/ilkd/key/nparser/KeyAst.java b/key.core/src/main/java/de/uka/ilkd/key/nparser/KeyAst.java index e3e50418712..b4c5510b9a0 100644 --- a/key.core/src/main/java/de/uka/ilkd/key/nparser/KeyAst.java +++ b/key.core/src/main/java/de/uka/ilkd/key/nparser/KeyAst.java @@ -5,7 +5,7 @@ import java.net.URI; import java.net.URISyntaxException; -import java.net.URL; +import java.nio.file.Path; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -129,7 +129,7 @@ public static class File extends KeyAst { /// Returns the includes (possible empty but not null) computed from the underlying parse /// tree. - public Includes getIncludes(URL base) { + public Includes getIncludes(Path base) { IncludeFinder finder = new IncludeFinder(base); accept(finder); return finder.getIncludes(); diff --git a/key.core/src/main/java/de/uka/ilkd/key/nparser/ParsingFacade.java b/key.core/src/main/java/de/uka/ilkd/key/nparser/ParsingFacade.java index 70881d2dfc6..b758e24d92e 100644 --- a/key.core/src/main/java/de/uka/ilkd/key/nparser/ParsingFacade.java +++ b/key.core/src/main/java/de/uka/ilkd/key/nparser/ParsingFacade.java @@ -6,6 +6,7 @@ import java.io.BufferedInputStream; import java.io.File; import java.io.IOException; +import java.net.URISyntaxException; import java.net.URL; import java.nio.channels.Channels; import java.nio.channels.ReadableByteChannel; @@ -70,7 +71,14 @@ public static List parseFiles(URL url) throws IOException { reached.add(url); KeyAst.File ctx = parseFile(url); ctxs.add(ctx); - Collection includes = ctx.getIncludes(url).getRuleSets(); + Path path = null; + try { + path = Path.of(url.toURI()); + } catch (URISyntaxException e) { + throw new IOException(e); + } + path = path.getParent(); + Collection includes = ctx.getIncludes(path).getRuleSets(); for (RuleSource u : includes) { if (!reached.contains(u.url())) { queue.push(u.url()); diff --git a/key.core/src/main/java/de/uka/ilkd/key/nparser/builder/IncludeFinder.java b/key.core/src/main/java/de/uka/ilkd/key/nparser/builder/IncludeFinder.java index 040a52fb953..e67fc462abc 100644 --- a/key.core/src/main/java/de/uka/ilkd/key/nparser/builder/IncludeFinder.java +++ b/key.core/src/main/java/de/uka/ilkd/key/nparser/builder/IncludeFinder.java @@ -5,7 +5,8 @@ import java.io.File; import java.net.MalformedURLException; -import java.net.URL; +import java.net.URI; +import java.nio.file.Path; import de.uka.ilkd.key.nparser.KeYParser; import de.uka.ilkd.key.proof.init.Includes; @@ -22,15 +23,12 @@ * @see #getIncludes() */ public class IncludeFinder extends AbstractBuilder { - private final URL base; + private final Path base; private final Includes includes = new Includes(); - private final String basePath; private boolean ldt = false; - public IncludeFinder(URL base) { + public IncludeFinder(Path base) { this.base = base; - String a = base.getPath(); - basePath = a.substring(0, a.lastIndexOf('/')); } @Override @@ -44,29 +42,30 @@ public Void visitOne_include_statement(KeYParser.One_include_statementContext ct public Void visitOne_include(KeYParser.One_includeContext ctx) { String value = StringUtil.trim(ctx.getText(), "\"'"); try { - addInclude(value, ctx.relfile != null); + addInclude(value); } catch (MalformedURLException e) { throw new BuildingException(ctx, e); } return null; } - private void addInclude(String filename, boolean relativePath) throws MalformedURLException { + private void addInclude(String filename) throws MalformedURLException { RuleSource source; if (!filename.endsWith(".key")) { filename += ".key"; } - if (relativePath) { - filename = filename.replace('/', File.separatorChar); // Not required for Windows, but - // whatsoever - filename = filename.replace('\\', File.separatorChar); // Special handling for Linux - URL path = new URL(base.getProtocol(), base.getHost(), base.getPort(), - basePath + "/" + filename); - source = RuleSourceFactory.initRuleFile(path); - } else { - source = RuleSourceFactory.fromDefaultLocation(filename); + filename = filename.replace('/', File.separatorChar); // Not required for Windows, but + // whatsoever + filename = filename.replace('\\', File.separatorChar); // Special handling for Linux + var path = base.resolve(filename).normalize(); + String pathString = path.toString().replace(File.separatorChar, '/'); // URIs on Windows + + if (!(pathString.startsWith("file:") || pathString.startsWith("jar:"))) { + pathString = "file:///" + pathString; } + var url = URI.create(pathString).toURL(); + source = RuleSourceFactory.initRuleFile(url); if (ldt) { includes.putLDT(filename, source); } else { diff --git a/key.core/src/main/java/de/uka/ilkd/key/proof/Goal.java b/key.core/src/main/java/de/uka/ilkd/key/proof/Goal.java index f9f410bd843..7481066feae 100644 --- a/key.core/src/main/java/de/uka/ilkd/key/proof/Goal.java +++ b/key.core/src/main/java/de/uka/ilkd/key/proof/Goal.java @@ -22,7 +22,6 @@ import de.uka.ilkd.key.rule.inst.SVInstantiations; import de.uka.ilkd.key.rule.merge.MergeRule; import de.uka.ilkd.key.strategy.QueueRuleApplicationManager; -import de.uka.ilkd.key.strategy.Strategy; import de.uka.ilkd.key.util.properties.MapProperties; import de.uka.ilkd.key.util.properties.Properties; import de.uka.ilkd.key.util.properties.Properties.Property; @@ -40,6 +39,7 @@ import org.key_project.prover.sequent.SequentChangeInfo; import org.key_project.prover.sequent.SequentFormula; import org.key_project.prover.strategy.RuleApplicationManager; +import org.key_project.prover.strategy.Strategy; import org.key_project.util.collection.ImmutableList; import org.key_project.util.collection.ImmutableSLList; @@ -442,7 +442,7 @@ public void removeFormula(PosInOccurrence p) { * puts the NoPosTacletApp to the set of TacletApps at the node of the goal and to the current * RuleAppIndex. * - * @param app the TacletApp + * @param app the ITacletApp */ public void addNoPosTacletApp(NoPosTacletApp app) { node().addNoPosTacletApp(app); @@ -450,11 +450,11 @@ public void addNoPosTacletApp(NoPosTacletApp app) { } /** - * creates a new TacletApp and puts it to the set of TacletApps at the node of the goal and to + * creates a new ITacletApp and puts it to the set of TacletApps at the node of the goal and to * the current RuleAppIndex. * - * @param rule the Taclet of the TacletApp to create - * @param insts the given instantiations of the TacletApp to be created + * @param rule the Taclet of the ITacletApp to create + * @param insts the given instantiations of the ITacletApp to be created */ public void addTaclet(Taclet rule, SVInstantiations insts, boolean isAxiom) { NoPosTacletApp tacletApp = @@ -650,6 +650,11 @@ public ImmutableList apply(final RuleApp ruleApp) { removeLastAppliedRuleApp(); node().setAppliedRuleApp(null); return null; + } catch (IndexOutOfBoundsException e) { + System.out.println(ruleApp.rule().displayName()); + removeLastAppliedRuleApp(); + node().setAppliedRuleApp(null); + return null; } finally { PERF_APP_EXECUTE.getAndAdd(System.nanoTime() - time); } diff --git a/key.core/src/main/java/de/uka/ilkd/key/proof/Proof.java b/key.core/src/main/java/de/uka/ilkd/key/proof/Proof.java index a6f5cab1498..2638d4b08e6 100644 --- a/key.core/src/main/java/de/uka/ilkd/key/proof/Proof.java +++ b/key.core/src/main/java/de/uka/ilkd/key/proof/Proof.java @@ -30,7 +30,6 @@ import de.uka.ilkd.key.settings.GeneralSettings; import de.uka.ilkd.key.settings.ProofIndependentSettings; import de.uka.ilkd.key.settings.ProofSettings; -import de.uka.ilkd.key.strategy.Strategy; import de.uka.ilkd.key.strategy.StrategyFactory; import de.uka.ilkd.key.strategy.StrategyProperties; @@ -39,6 +38,7 @@ import org.key_project.prover.proof.ProofObject; import org.key_project.prover.sequent.Sequent; import org.key_project.prover.sequent.SequentFormula; +import org.key_project.prover.strategy.Strategy; import org.key_project.util.collection.ImmutableList; import org.key_project.util.collection.ImmutableSLList; import org.key_project.util.lookup.Lookup; diff --git a/key.core/src/main/java/de/uka/ilkd/key/proof/TacletAppIndex.java b/key.core/src/main/java/de/uka/ilkd/key/proof/TacletAppIndex.java index 659999ce94c..0d8bacf4cd8 100644 --- a/key.core/src/main/java/de/uka/ilkd/key/proof/TacletAppIndex.java +++ b/key.core/src/main/java/de/uka/ilkd/key/proof/TacletAppIndex.java @@ -432,7 +432,7 @@ public String toString() { + tacletIndex; } - // helper because IList is no IList + // helper because IList is no IList private static ImmutableList prepend(ImmutableList l1, ImmutableList l2) { for (NoPosTacletApp aL2 : l2) { diff --git a/key.core/src/main/java/de/uka/ilkd/key/proof/delayedcut/DelayedCutProcessor.java b/key.core/src/main/java/de/uka/ilkd/key/proof/delayedcut/DelayedCutProcessor.java index 81d3d85e74a..a0c905aa5e4 100644 --- a/key.core/src/main/java/de/uka/ilkd/key/proof/delayedcut/DelayedCutProcessor.java +++ b/key.core/src/main/java/de/uka/ilkd/key/proof/delayedcut/DelayedCutProcessor.java @@ -367,7 +367,7 @@ private void check(Goal goal, final RuleApp app, throw new RuntimeException("Cannot apply taclet-app"); } return; - // ImmutableList list = + // ImmutableList list = // goal.ruleAppIndex().getTacletAppAt(new TacletFilter() { // // @Override diff --git a/key.core/src/main/java/de/uka/ilkd/key/proof/init/JavaProfile.java b/key.core/src/main/java/de/uka/ilkd/key/proof/init/JavaProfile.java index 196c2bea5be..267f4176035 100644 --- a/key.core/src/main/java/de/uka/ilkd/key/proof/init/JavaProfile.java +++ b/key.core/src/main/java/de/uka/ilkd/key/proof/init/JavaProfile.java @@ -20,7 +20,7 @@ import de.uka.ilkd.key.rule.label.TermLabelRefactoring; import de.uka.ilkd.key.rule.merge.MergeRule; import de.uka.ilkd.key.smt.newsmt2.DefinedSymbolsHandler; -import de.uka.ilkd.key.strategy.JavaCardDLStrategyFactory; +import de.uka.ilkd.key.strategy.ModularJavaDLStrategyFactory; import de.uka.ilkd.key.strategy.StrategyFactory; import org.key_project.prover.rules.RuleApp; @@ -71,7 +71,7 @@ public String description() { public static JavaProfile defaultInstance; public static JavaProfile defaultInstancePermissions; - public static final StrategyFactory DEFAULT = new JavaCardDLStrategyFactory(); + public static final StrategyFactory DEFAULT = new ModularJavaDLStrategyFactory(); private boolean permissions = false; diff --git a/key.core/src/main/java/de/uka/ilkd/key/proof/init/KeYUserProblemFile.java b/key.core/src/main/java/de/uka/ilkd/key/proof/init/KeYUserProblemFile.java index 7e9e1fe64b9..e132f4d52f2 100644 --- a/key.core/src/main/java/de/uka/ilkd/key/proof/init/KeYUserProblemFile.java +++ b/key.core/src/main/java/de/uka/ilkd/key/proof/init/KeYUserProblemFile.java @@ -140,7 +140,6 @@ public void readProblem() throws ProofInputException { } } - @Override public String chooseContract() { return getProblemFinder().getChooseContract(); diff --git a/key.core/src/main/java/de/uka/ilkd/key/proof/io/AbstractProblemLoader.java b/key.core/src/main/java/de/uka/ilkd/key/proof/io/AbstractProblemLoader.java index 167aff7270c..bf8591ffdd4 100644 --- a/key.core/src/main/java/de/uka/ilkd/key/proof/io/AbstractProblemLoader.java +++ b/key.core/src/main/java/de/uka/ilkd/key/proof/io/AbstractProblemLoader.java @@ -30,7 +30,7 @@ import de.uka.ilkd.key.settings.ProofIndependentSettings; import de.uka.ilkd.key.speclang.Contract; import de.uka.ilkd.key.speclang.SLEnvInput; -import de.uka.ilkd.key.strategy.Strategy; +import de.uka.ilkd.key.strategy.JavaStrategy; import de.uka.ilkd.key.strategy.StrategyProperties; import org.key_project.util.collection.Pair; @@ -724,7 +724,7 @@ private ReplayResult replayProof(Proof proof) { StrategyProperties newProps = proof.getSettings().getStrategySettings().getActiveStrategyProperties(); newProps.setProperty(StrategyProperties.OSS_OPTIONS_KEY, StrategyProperties.OSS_ON); - Strategy.updateStrategySettings(proof, newProps); + JavaStrategy.updateStrategySettings(proof, newProps); OneStepSimplifier.refreshOSS(proof); replayer = new IntermediateProofReplayer(this, proof, parserResult); @@ -758,7 +758,7 @@ private ReplayResult replayProof(Proof proof) { StrategyProperties newProps = proof.getSettings().getStrategySettings().getActiveStrategyProperties(); newProps.setProperty(StrategyProperties.OSS_OPTIONS_KEY, ossStatus); - Strategy.updateStrategySettings(proof, newProps); + JavaStrategy.updateStrategySettings(proof, newProps); OneStepSimplifier.refreshOSS(proof); result = new ReplayResult(status, errors, lastTouchedNode); diff --git a/key.core/src/main/java/de/uka/ilkd/key/proof/io/KeYFile.java b/key.core/src/main/java/de/uka/ilkd/key/proof/io/KeYFile.java index 95e0b13b51a..4b608fc1d31 100644 --- a/key.core/src/main/java/de/uka/ilkd/key/proof/io/KeYFile.java +++ b/key.core/src/main/java/de/uka/ilkd/key/proof/io/KeYFile.java @@ -219,9 +219,7 @@ public Includes readIncludes() throws ProofInputException { if (includes == null) { try { KeyAst.File ctx = getParseContext(); - // weigl: fix #3721, absolute path is required to solve relative filenames. - Path absPath = file.file().toAbsolutePath().getParent(); - includes = ctx.getIncludes(absPath.toUri().toURL()); + includes = ctx.getIncludes(file.file().getParent()); } catch (ParseCancellationException e) { throw new ParseCancellationException(e); } catch (Exception e) { diff --git a/key.core/src/main/java/de/uka/ilkd/key/proof/io/UrlRuleSource.java b/key.core/src/main/java/de/uka/ilkd/key/proof/io/UrlRuleSource.java index 5d3a19b03f6..f921f77d6e3 100644 --- a/key.core/src/main/java/de/uka/ilkd/key/proof/io/UrlRuleSource.java +++ b/key.core/src/main/java/de/uka/ilkd/key/proof/io/UrlRuleSource.java @@ -61,10 +61,11 @@ public Path file() { try { return Paths.get(uri); } catch (FileSystemNotFoundException e) { - URI rootFs = URI.create(StringUtil.takeUntil(uri.toString(), "!")); - String internal = StringUtil.takeAfter(uri.toString(), "!"); - FileSystem zipfs = FileSystems.newFileSystem(rootFs, new HashMap<>()); - return zipfs.getPath(internal); + URI rootFs = URI.create(StringUtil.takeUntil(uri.toString(), "\\!")); + String internal = StringUtil.takeAfter(uri.toString(), "\\!"); + try (FileSystem zipfs = FileSystems.newFileSystem(rootFs, new HashMap<>())) { + return zipfs.getPath(internal); + } } } catch (URISyntaxException | IOException e) { throw new RuntimeException(e); diff --git a/key.core/src/main/java/de/uka/ilkd/key/proof/replay/AbstractProofReplayer.java b/key.core/src/main/java/de/uka/ilkd/key/proof/replay/AbstractProofReplayer.java index b4071100ccf..172977e3129 100644 --- a/key.core/src/main/java/de/uka/ilkd/key/proof/replay/AbstractProofReplayer.java +++ b/key.core/src/main/java/de/uka/ilkd/key/proof/replay/AbstractProofReplayer.java @@ -217,7 +217,7 @@ private TacletApp constructTacletApp(Node originalStep, Goal currGoal) { originalTacletApp = tacletApp; } assert originalTacletApp != null - : "Tried to construct TacletApp for a rule that is not a taclet"; + : "Tried to construct ITacletApp for a rule that is not a taclet"; final String tacletName = originalTacletApp.rule().name().toString(); diff --git a/key.core/src/main/java/de/uka/ilkd/key/prover/impl/PerfScope.java b/key.core/src/main/java/de/uka/ilkd/key/prover/impl/PerfScope.java index 18cceba4682..9256e076389 100644 --- a/key.core/src/main/java/de/uka/ilkd/key/prover/impl/PerfScope.java +++ b/key.core/src/main/java/de/uka/ilkd/key/prover/impl/PerfScope.java @@ -45,9 +45,9 @@ public class PerfScope { new Pair<>("Semi Taclet app index update update", SemisequentTacletAppIndex.PERF_UPDATE), new Pair<>("Taclet app index create all", TacletAppIndex.PERF_CREATE_ALL), new Pair<>("Goal update listeners", Goal.PERF_UPDATE_LISTENERS), - new Pair<>("TacletApp execute", TacletApp.PERF_EXECUTE), - new Pair<>("TacletApp pre", TacletApp.PERF_PRE), - new Pair<>("TacletApp Goal setSequent", TacletApp.PERF_SET_SEQUENT), + new Pair<>("ITacletApp execute", TacletApp.PERF_EXECUTE), + new Pair<>("ITacletApp pre", TacletApp.PERF_PRE), + new Pair<>("ITacletApp Goal setSequent", TacletApp.PERF_SET_SEQUENT), new Pair<>("NoFindTacletExecutor apply", NoFindTacletExecutor.PERF_APPLY), new Pair<>("NoFindTacletExecutor setSequent", NoFindTacletExecutor.PERF_SET_SEQUENT), new Pair<>("NoFindTacletExecutor term labels", NoFindTacletExecutor.PERF_TERM_LABELS), diff --git a/key.core/src/main/java/de/uka/ilkd/key/rule/AbstractExternalSolverRuleApp.java b/key.core/src/main/java/de/uka/ilkd/key/rule/AbstractExternalSolverRuleApp.java index d6339059ebb..3875a11096d 100644 --- a/key.core/src/main/java/de/uka/ilkd/key/rule/AbstractExternalSolverRuleApp.java +++ b/key.core/src/main/java/de/uka/ilkd/key/rule/AbstractExternalSolverRuleApp.java @@ -3,6 +3,7 @@ * SPDX-License-Identifier: GPL-2.0-only */ package de.uka.ilkd.key.rule; + import org.key_project.prover.sequent.PosInOccurrence; import org.key_project.util.collection.ImmutableList; diff --git a/key.core/src/main/java/de/uka/ilkd/key/rule/AbstractLoopInvariantRule.java b/key.core/src/main/java/de/uka/ilkd/key/rule/AbstractLoopInvariantRule.java index d06a048f02f..548b482c363 100644 --- a/key.core/src/main/java/de/uka/ilkd/key/rule/AbstractLoopInvariantRule.java +++ b/key.core/src/main/java/de/uka/ilkd/key/rule/AbstractLoopInvariantRule.java @@ -23,6 +23,7 @@ import de.uka.ilkd.key.speclang.LoopSpecification; import de.uka.ilkd.key.util.MiscTools; +import org.key_project.logic.LogicServices; import org.key_project.logic.Name; import org.key_project.logic.Namespace; import org.key_project.logic.op.Function; @@ -157,8 +158,8 @@ public boolean isApplicableOnSubTerms() { } @Override - public IBuiltInRuleApp createApp(PosInOccurrence pos, TermServices services) { - return new LoopInvariantBuiltInRuleApp(this, pos, services); + public IBuiltInRuleApp createApp(PosInOccurrence pos, LogicServices services) { + return new LoopInvariantBuiltInRuleApp(this, pos, (TermServices) services); } @Override diff --git a/key.core/src/main/java/de/uka/ilkd/key/rule/BlockContractExternalRule.java b/key.core/src/main/java/de/uka/ilkd/key/rule/BlockContractExternalRule.java index 7e7bbd0f524..cf0b2d43de2 100644 --- a/key.core/src/main/java/de/uka/ilkd/key/rule/BlockContractExternalRule.java +++ b/key.core/src/main/java/de/uka/ilkd/key/rule/BlockContractExternalRule.java @@ -8,7 +8,6 @@ import de.uka.ilkd.key.java.Services; import de.uka.ilkd.key.logic.JTerm; -import de.uka.ilkd.key.logic.TermServices; import de.uka.ilkd.key.logic.label.TermLabelState; import de.uka.ilkd.key.logic.op.LocationVariable; import de.uka.ilkd.key.proof.Goal; @@ -24,6 +23,7 @@ import de.uka.ilkd.key.speclang.Contract; import de.uka.ilkd.key.util.MiscTools; +import org.key_project.logic.LogicServices; import org.key_project.logic.Name; import org.key_project.logic.op.Function; import org.key_project.prover.rules.RuleAbortException; @@ -181,7 +181,7 @@ protected void setLastInstantiation(Instantiation lastInstantiation) { } @Override - public IBuiltInRuleApp createApp(PosInOccurrence pos, TermServices services) { + public IBuiltInRuleApp createApp(PosInOccurrence pos, LogicServices services) { return new BlockContractExternalBuiltInRuleApp(this, pos); } diff --git a/key.core/src/main/java/de/uka/ilkd/key/rule/BlockContractInternalRule.java b/key.core/src/main/java/de/uka/ilkd/key/rule/BlockContractInternalRule.java index e041d235090..6e03088067f 100644 --- a/key.core/src/main/java/de/uka/ilkd/key/rule/BlockContractInternalRule.java +++ b/key.core/src/main/java/de/uka/ilkd/key/rule/BlockContractInternalRule.java @@ -8,7 +8,6 @@ import de.uka.ilkd.key.java.Services; import de.uka.ilkd.key.logic.JTerm; -import de.uka.ilkd.key.logic.TermServices; import de.uka.ilkd.key.logic.label.TermLabelState; import de.uka.ilkd.key.logic.op.LocationVariable; import de.uka.ilkd.key.logic.op.ProgramVariable; @@ -21,6 +20,7 @@ import de.uka.ilkd.key.speclang.BlockContract; import de.uka.ilkd.key.util.MiscTools; +import org.key_project.logic.LogicServices; import org.key_project.logic.Name; import org.key_project.logic.op.Function; import org.key_project.prover.rules.RuleAbortException; @@ -194,7 +194,7 @@ protected void setLastInstantiation(Instantiation lastInstantiation) { @Override public BlockContractInternalBuiltInRuleApp createApp( - final PosInOccurrence occurrence, TermServices services) { + final PosInOccurrence occurrence, LogicServices services) { return new BlockContractInternalBuiltInRuleApp<>(this, occurrence); } diff --git a/key.core/src/main/java/de/uka/ilkd/key/rule/BuiltInRule.java b/key.core/src/main/java/de/uka/ilkd/key/rule/BuiltInRule.java index cac17c592b7..c05482cda49 100644 --- a/key.core/src/main/java/de/uka/ilkd/key/rule/BuiltInRule.java +++ b/key.core/src/main/java/de/uka/ilkd/key/rule/BuiltInRule.java @@ -3,13 +3,11 @@ * SPDX-License-Identifier: GPL-2.0-only */ package de.uka.ilkd.key.rule; -import de.uka.ilkd.key.logic.TermServices; import de.uka.ilkd.key.proof.Goal; -import org.key_project.prover.rules.RuleApp; +import org.key_project.logic.LogicServices; import org.key_project.prover.rules.RuleExecutor; import org.key_project.prover.sequent.PosInOccurrence; -import org.key_project.util.collection.ImmutableList; import org.jspecify.annotations.NullMarked; import org.jspecify.annotations.Nullable; @@ -20,21 +18,9 @@ * has to ensure that the goal split is done only iff the application was successful. */ @NullMarked -public interface BuiltInRule extends Rule, RuleExecutor { +public interface BuiltInRule extends org.key_project.prover.rules.IBuiltInRule, Rule { - /** - * Returning true iff a rule is applicable at the given position. - * This does not necessarily mean that a rule application will change the goal - * (this decision is made due to performance reasons) - */ - boolean isApplicable(Goal goal, @Nullable PosInOccurrence pio); - - boolean isApplicableOnSubTerms(); - - IBuiltInRuleApp createApp(@Nullable PosInOccurrence pos, TermServices services); - - @Override - ImmutableList apply(Goal goal, RuleApp ruleApp); + IBuiltInRuleApp createApp(@Nullable PosInOccurrence pos, LogicServices services); @Override default RuleExecutor getExecutor() { diff --git a/key.core/src/main/java/de/uka/ilkd/key/rule/EqualityModuloProofIrrelevancy.java b/key.core/src/main/java/de/uka/ilkd/key/rule/EqualityModuloProofIrrelevancy.java index daaef6ec02c..55501f8b217 100644 --- a/key.core/src/main/java/de/uka/ilkd/key/rule/EqualityModuloProofIrrelevancy.java +++ b/key.core/src/main/java/de/uka/ilkd/key/rule/EqualityModuloProofIrrelevancy.java @@ -457,13 +457,13 @@ public static int hashCodeModProofIrrelevancy(Taclet taclet) { } - // TacletApp + // ITacletApp /** * test for equality modulo proof irrelevancy for the given arguments * - * @param _this the first TacletApp - * @param that the second TacletApp + * @param _this the first ITacletApp + * @param that the second ITacletApp * @return true if both arguments are equal modulo proof irrelevancy */ public static boolean equalsModProofIrrelevancy(TacletApp _this, TacletApp that) { diff --git a/key.core/src/main/java/de/uka/ilkd/key/rule/ExternalSolverRule.java b/key.core/src/main/java/de/uka/ilkd/key/rule/ExternalSolverRule.java index 9b7753aea5a..f108d937d54 100644 --- a/key.core/src/main/java/de/uka/ilkd/key/rule/ExternalSolverRule.java +++ b/key.core/src/main/java/de/uka/ilkd/key/rule/ExternalSolverRule.java @@ -3,9 +3,9 @@ * SPDX-License-Identifier: GPL-2.0-only */ package de.uka.ilkd.key.rule; -import de.uka.ilkd.key.logic.TermServices; import de.uka.ilkd.key.proof.Goal; +import org.key_project.logic.LogicServices; import org.key_project.prover.sequent.PosInOccurrence; import org.key_project.util.collection.ImmutableList; @@ -27,7 +27,7 @@ AbstractExternalSolverRuleApp createApp( String successfulSolverName, ImmutableList unsatCore); @Override - IBuiltInRuleApp createApp(PosInOccurrence pos, TermServices services); + IBuiltInRuleApp createApp(PosInOccurrence pos, LogicServices services); @Override diff --git a/key.core/src/main/java/de/uka/ilkd/key/rule/IBuiltInRuleApp.java b/key.core/src/main/java/de/uka/ilkd/key/rule/IBuiltInRuleApp.java index e1e9997ee47..3bad4336fd0 100644 --- a/key.core/src/main/java/de/uka/ilkd/key/rule/IBuiltInRuleApp.java +++ b/key.core/src/main/java/de/uka/ilkd/key/rule/IBuiltInRuleApp.java @@ -8,19 +8,13 @@ import de.uka.ilkd.key.logic.op.LocationVariable; import de.uka.ilkd.key.proof.Goal; -import org.key_project.prover.rules.RuleApp; import org.key_project.prover.sequent.PosInOccurrence; import org.key_project.util.collection.ImmutableList; import org.jspecify.annotations.NullMarked; @NullMarked -public interface IBuiltInRuleApp extends RuleApp { - - /** - * returns the built-in rule of this rule application - */ - BuiltInRule rule(); +public interface IBuiltInRuleApp extends org.key_project.prover.rules.IBuiltInRuleApp { /** * Tries to complete the rule application from the available information. Attention: Do neither @@ -34,18 +28,14 @@ public interface IBuiltInRuleApp extends RuleApp { IBuiltInRuleApp forceInstantiate(Goal goal); - List getHeapContext(); + IBuiltInRuleApp setAssumesInsts(ImmutableList ifInsts); + + IBuiltInRuleApp replacePos(PosInOccurrence newPos); /** - * returns true if tryToInstantiate is able to complete the app - * - * @return true if tryToInstantiate is able to complete the app + * returns the built-in rule of this rule application */ - boolean isSufficientlyComplete(); - - ImmutableList assumesInsts(); - - IBuiltInRuleApp setAssumesInsts(ImmutableList ifInsts); + BuiltInRule rule(); - IBuiltInRuleApp replacePos(PosInOccurrence newPos); + List getHeapContext(); } diff --git a/key.core/src/main/java/de/uka/ilkd/key/rule/JmlAssertRule.java b/key.core/src/main/java/de/uka/ilkd/key/rule/JmlAssertRule.java index 6c82cdcb85c..bbc7b04725b 100644 --- a/key.core/src/main/java/de/uka/ilkd/key/rule/JmlAssertRule.java +++ b/key.core/src/main/java/de/uka/ilkd/key/rule/JmlAssertRule.java @@ -18,6 +18,7 @@ import de.uka.ilkd.key.speclang.jml.pretranslation.TextualJMLAssertStatement.Kind; import de.uka.ilkd.key.util.MiscTools; +import org.key_project.logic.LogicServices; import org.key_project.logic.Name; import org.key_project.logic.op.Modality; import org.key_project.prover.rules.RuleAbortException; @@ -102,7 +103,7 @@ public boolean isApplicableOnSubTerms() { } @Override - public IBuiltInRuleApp createApp(PosInOccurrence occurrence, TermServices services) { + public IBuiltInRuleApp createApp(PosInOccurrence occurrence, LogicServices services) { return new JmlAssertBuiltInRuleApp(this, occurrence); } diff --git a/key.core/src/main/java/de/uka/ilkd/key/rule/LoopApplyHeadRule.java b/key.core/src/main/java/de/uka/ilkd/key/rule/LoopApplyHeadRule.java index 903524a8dba..cc3dd304141 100644 --- a/key.core/src/main/java/de/uka/ilkd/key/rule/LoopApplyHeadRule.java +++ b/key.core/src/main/java/de/uka/ilkd/key/rule/LoopApplyHeadRule.java @@ -9,13 +9,13 @@ import de.uka.ilkd.key.logic.JTerm; import de.uka.ilkd.key.logic.JavaBlock; import de.uka.ilkd.key.logic.TermBuilder; -import de.uka.ilkd.key.logic.TermServices; import de.uka.ilkd.key.logic.op.Transformer; import de.uka.ilkd.key.proof.Goal; import de.uka.ilkd.key.rule.metaconstruct.ForToWhileTransformation; import de.uka.ilkd.key.speclang.LoopContract; import de.uka.ilkd.key.speclang.LoopContractImpl; +import org.key_project.logic.LogicServices; import org.key_project.logic.Name; import org.key_project.logic.op.Modality; import org.key_project.prover.rules.RuleAbortException; @@ -123,7 +123,7 @@ public String toString() { } @Override - public IBuiltInRuleApp createApp(@Nullable PosInOccurrence pos, TermServices services) { + public IBuiltInRuleApp createApp(@Nullable PosInOccurrence pos, LogicServices services) { return new LoopApplyHeadBuiltInRuleApp(this, pos); } diff --git a/key.core/src/main/java/de/uka/ilkd/key/rule/LoopContractExternalRule.java b/key.core/src/main/java/de/uka/ilkd/key/rule/LoopContractExternalRule.java index f469f6aca9f..7c47bf44c38 100644 --- a/key.core/src/main/java/de/uka/ilkd/key/rule/LoopContractExternalRule.java +++ b/key.core/src/main/java/de/uka/ilkd/key/rule/LoopContractExternalRule.java @@ -8,7 +8,6 @@ import de.uka.ilkd.key.java.Services; import de.uka.ilkd.key.logic.JTerm; -import de.uka.ilkd.key.logic.TermServices; import de.uka.ilkd.key.logic.label.TermLabelState; import de.uka.ilkd.key.logic.op.LocationVariable; import de.uka.ilkd.key.logic.op.Transformer; @@ -25,6 +24,7 @@ import de.uka.ilkd.key.speclang.LoopContract; import de.uka.ilkd.key.util.MiscTools; +import org.key_project.logic.LogicServices; import org.key_project.logic.Name; import org.key_project.logic.op.Function; import org.key_project.prover.rules.RuleAbortException; @@ -182,7 +182,7 @@ protected void setLastInstantiation(Instantiation lastInstantiation) { @Override public LoopContractExternalBuiltInRuleApp createApp(PosInOccurrence pos, - TermServices services) { + LogicServices services) { return new LoopContractExternalBuiltInRuleApp<>(this, pos); } diff --git a/key.core/src/main/java/de/uka/ilkd/key/rule/LoopContractInternalRule.java b/key.core/src/main/java/de/uka/ilkd/key/rule/LoopContractInternalRule.java index 213804a89b3..0d8c36d7c3b 100644 --- a/key.core/src/main/java/de/uka/ilkd/key/rule/LoopContractInternalRule.java +++ b/key.core/src/main/java/de/uka/ilkd/key/rule/LoopContractInternalRule.java @@ -8,7 +8,6 @@ import de.uka.ilkd.key.java.Services; import de.uka.ilkd.key.logic.JTerm; -import de.uka.ilkd.key.logic.TermServices; import de.uka.ilkd.key.logic.label.TermLabelState; import de.uka.ilkd.key.logic.op.LocationVariable; import de.uka.ilkd.key.proof.Goal; @@ -20,6 +19,7 @@ import de.uka.ilkd.key.speclang.LoopContract; import de.uka.ilkd.key.util.MiscTools; +import org.key_project.logic.LogicServices; import org.key_project.logic.Name; import org.key_project.logic.op.Function; import org.key_project.prover.rules.RuleAbortException; @@ -254,7 +254,7 @@ protected void setLastInstantiation(Instantiation lastInstantiation) { @Override public LoopContractInternalBuiltInRuleApp createApp(final PosInOccurrence occurrence, - TermServices services) { + LogicServices services) { return new LoopContractInternalBuiltInRuleApp(this, occurrence); } diff --git a/key.core/src/main/java/de/uka/ilkd/key/rule/NoPosTacletApp.java b/key.core/src/main/java/de/uka/ilkd/key/rule/NoPosTacletApp.java index a9c311b91e4..3dccd54c40b 100644 --- a/key.core/src/main/java/de/uka/ilkd/key/rule/NoPosTacletApp.java +++ b/key.core/src/main/java/de/uka/ilkd/key/rule/NoPosTacletApp.java @@ -89,7 +89,7 @@ public static NoPosTacletApp createNoPosTacletApp(Taclet taclet, MatchResultInfo } /** - * Create TacletApp with immutable "instantiations", i.e. this instantiations must not be + * Create ITacletApp with immutable "instantiations", i.e. this instantiations must not be * modified later (e.g. by "addInstantiation"). However, this information is currently only used * to decide about introduction of metavariables. Immutable instantiations are important for the * "addrules" part of taclets. @@ -128,7 +128,7 @@ private NoPosTacletApp(org.key_project.prover.rules.Taclet taclet, } /** - * adds a new instantiation to this TacletApp + * adds a new instantiation to this ITacletApp * * @param sv the SchemaVariable to be instantiated * @param se the SyntaxElement (usually a {@link Term} or {@link ProgramElement}) @@ -137,7 +137,7 @@ private NoPosTacletApp(org.key_project.prover.rules.Taclet taclet, * saving a proof; this is usually needed for new names as their creation * is not always deterministic * @param services the Services for access to the logic signature and more - * @return the new TacletApp + * @return the new ITacletApp */ @Override public TacletApp addInstantiation(SchemaVariable sv, SyntaxElement se, boolean interesting, @@ -166,7 +166,7 @@ public TacletApp addInstantiation(SVInstantiations svi, Services services) { /** * creates a new Taclet application containing all the instantiations given by the - * SVInstantiations and forget the ones in this TacletApp + * SVInstantiations and forget the ones in this ITacletApp * * @param svi the SVInstantiations whose entries are the needed instantiations * @return the new Taclet application @@ -224,7 +224,7 @@ protected Set contextVars(SchemaVariable sv) { * } * * - * @return TacletApp with the resulting instantiations or null + * @return ITacletApp with the resulting instantiations or null */ public NoPosTacletApp matchFind(PosInOccurrence pos, LogicServices services) { return matchFind(null, pos, services); diff --git a/key.core/src/main/java/de/uka/ilkd/key/rule/ObserverToUpdateRule.java b/key.core/src/main/java/de/uka/ilkd/key/rule/ObserverToUpdateRule.java index 14c46fdac18..629c9499418 100644 --- a/key.core/src/main/java/de/uka/ilkd/key/rule/ObserverToUpdateRule.java +++ b/key.core/src/main/java/de/uka/ilkd/key/rule/ObserverToUpdateRule.java @@ -19,7 +19,6 @@ import de.uka.ilkd.key.logic.JTerm; import de.uka.ilkd.key.logic.JavaBlock; import de.uka.ilkd.key.logic.TermBuilder; -import de.uka.ilkd.key.logic.TermServices; import de.uka.ilkd.key.logic.label.TermLabelManager; import de.uka.ilkd.key.logic.label.TermLabelState; import de.uka.ilkd.key.logic.op.IObserverFunction; @@ -33,6 +32,7 @@ import de.uka.ilkd.key.rule.UseOperationContractRule.Instantiation; import de.uka.ilkd.key.util.Union; +import org.key_project.logic.LogicServices; import org.key_project.logic.Name; import org.key_project.prover.rules.RuleApp; import org.key_project.prover.sequent.PosInOccurrence; @@ -108,7 +108,7 @@ public IBuiltInRuleApp createApp(PosInOccurrence pos) { } @Override - public IBuiltInRuleApp createApp(PosInOccurrence pos, TermServices services) { + public IBuiltInRuleApp createApp(PosInOccurrence pos, LogicServices services) { return new DefaultBuiltInRuleApp(this, pos); } diff --git a/key.core/src/main/java/de/uka/ilkd/key/rule/OneStepSimplifier.java b/key.core/src/main/java/de/uka/ilkd/key/rule/OneStepSimplifier.java index 5f5d6cb4986..d56e145be2b 100644 --- a/key.core/src/main/java/de/uka/ilkd/key/rule/OneStepSimplifier.java +++ b/key.core/src/main/java/de/uka/ilkd/key/rule/OneStepSimplifier.java @@ -12,7 +12,6 @@ import de.uka.ilkd.key.java.Services; import de.uka.ilkd.key.logic.JTerm; -import de.uka.ilkd.key.logic.TermServices; import de.uka.ilkd.key.logic.label.TermLabel; import de.uka.ilkd.key.logic.label.TermLabelManager; import de.uka.ilkd.key.logic.label.TermLabelState; @@ -32,6 +31,7 @@ import de.uka.ilkd.key.strategy.StrategyProperties; import de.uka.ilkd.key.util.MiscTools; +import org.key_project.logic.LogicServices; import org.key_project.logic.Name; import org.key_project.logic.PosInTerm; import org.key_project.logic.Term; @@ -81,10 +81,11 @@ public static final class Protocol extends ArrayList { * "evaluate_instanceof"; in any case there was a measurable slowdown. -- DB 03/06/14 */ private static final ImmutableList ruleSets = ImmutableSLList.nil() - .append("concrete").append("update_elim").append("update_apply_on_update") + .append("concrete").append("concrete_java").append("update_elim") + .append("update_apply_on_update") .append("update_apply").append("update_join").append("elimQuantifier"); - private static final boolean[] bottomUp = { false, false, true, true, true, false }; + private static final boolean[] bottomUp = { false, false, false, true, true, true, false }; private final Map applicabilityCache = new LRUCache<>(APPLICABILITY_CACHE_SIZE); @@ -267,7 +268,7 @@ private SequentFormula simplifyPos(Goal goal, protocol.add(app); } return result; - // TODO Idea: return new Pair(null, null); + // TODO Idea: return new Pair(null, null); } return null; } @@ -688,7 +689,6 @@ public Set getCapturedTaclets() { return result; } - // ------------------------------------------------------------------------- // inner classes // ------------------------------------------------------------------------- @@ -724,7 +724,7 @@ public String toString() { } @Override - public OneStepSimplifierRuleApp createApp(PosInOccurrence pos, TermServices services) { + public OneStepSimplifierRuleApp createApp(PosInOccurrence pos, LogicServices services) { return new OneStepSimplifierRuleApp(this, pos); } diff --git a/key.core/src/main/java/de/uka/ilkd/key/rule/PosTacletApp.java b/key.core/src/main/java/de/uka/ilkd/key/rule/PosTacletApp.java index 87b63623f94..60d1a116c38 100644 --- a/key.core/src/main/java/de/uka/ilkd/key/rule/PosTacletApp.java +++ b/key.core/src/main/java/de/uka/ilkd/key/rule/PosTacletApp.java @@ -93,7 +93,7 @@ private PosTacletApp(FindTaclet taclet, SVInstantiations instantiations, * __OPTIMIZE__ If this method is needed more than once caching the result should be considered. * * @return the set of the logicvariables that are bound for the indicated application position - * of the TacletApp. + * of the ITacletApp. */ private static Set varsBoundAboveFindPos(Taclet taclet, PosInOccurrence pos) { @@ -148,11 +148,11 @@ private static SVInstantiations resolveCollisionWithContext(Taclet taclet, /** - * adds a new instantiation to this TacletApp + * adds a new instantiation to this ITacletApp * * @param sv the SchemaVariable to be instantiated * @param term the Term the SchemaVariable is instantiated with - * @return the new TacletApp + * @return the new ITacletApp */ @Override public TacletApp addInstantiation(SchemaVariable sv, SyntaxElement term, boolean interesting, @@ -170,7 +170,7 @@ public TacletApp addInstantiation(SchemaVariable sv, SyntaxElement term, boolean /** * creates a new Taclet application containing all the instantiations given by the - * SVInstantiations and the ones of this TacletApp + * SVInstantiations and the ones of this ITacletApp * * @param svi the SVInstantiations whose entries are the needed instantiations * @return the new Taclet application diff --git a/key.core/src/main/java/de/uka/ilkd/key/rule/QueryExpand.java b/key.core/src/main/java/de/uka/ilkd/key/rule/QueryExpand.java index f13302128c9..a0429d73537 100644 --- a/key.core/src/main/java/de/uka/ilkd/key/rule/QueryExpand.java +++ b/key.core/src/main/java/de/uka/ilkd/key/rule/QueryExpand.java @@ -21,6 +21,7 @@ import de.uka.ilkd.key.rule.tacletbuilder.RewriteTacletBuilder; import de.uka.ilkd.key.util.MiscTools; +import org.key_project.logic.LogicServices; import org.key_project.logic.Name; import org.key_project.logic.Namespace; import org.key_project.logic.op.Function; @@ -669,7 +670,7 @@ public Long getTimeOfQuery(JTerm t) { } @Override - public DefaultBuiltInRuleApp createApp(PosInOccurrence pos, TermServices services) { + public DefaultBuiltInRuleApp createApp(PosInOccurrence pos, LogicServices services) { return new DefaultBuiltInRuleApp(this, pos); } diff --git a/key.core/src/main/java/de/uka/ilkd/key/rule/SetStatementRule.java b/key.core/src/main/java/de/uka/ilkd/key/rule/SetStatementRule.java index 4dc0db593d0..407bca5aacb 100644 --- a/key.core/src/main/java/de/uka/ilkd/key/rule/SetStatementRule.java +++ b/key.core/src/main/java/de/uka/ilkd/key/rule/SetStatementRule.java @@ -15,6 +15,7 @@ import de.uka.ilkd.key.proof.Goal; import de.uka.ilkd.key.util.MiscTools; +import org.key_project.logic.LogicServices; import org.key_project.logic.Name; import org.key_project.logic.op.Modality; import org.key_project.prover.rules.RuleAbortException; @@ -70,7 +71,7 @@ public boolean isApplicableOnSubTerms() { } @Override - public IBuiltInRuleApp createApp(PosInOccurrence occurrence, TermServices services) { + public IBuiltInRuleApp createApp(PosInOccurrence occurrence, LogicServices services) { return new SetStatementBuiltInRuleApp(this, occurrence); } diff --git a/key.core/src/main/java/de/uka/ilkd/key/rule/Taclet.java b/key.core/src/main/java/de/uka/ilkd/key/rule/Taclet.java index 6c2660bd593..ee791db1b22 100644 --- a/key.core/src/main/java/de/uka/ilkd/key/rule/Taclet.java +++ b/key.core/src/main/java/de/uka/ilkd/key/rule/Taclet.java @@ -53,7 +53,7 @@ * The find part of a taclet is used to attached the rule to a term in the sequent of the current * goal. Therefore the term of the sequent has to match the schema as found in the taclet's find * part. The taclet is then attached to this term, more precise not the taclet itself, but an - * application object of this taclet (see {@link TacletApp TacletApp}. When + * application object of this taclet (see {@link TacletApp ITacletApp}. When * this attached taclet application object is applied, the new goals are constructed as described by * the goal descriptions. For example
*
@@ -75,7 +75,7 @@ * looking where it can be applied, these tasks have to be done in advance. For example by one of * the following classes {@link de.uka.ilkd.key.proof.RuleAppIndex RuleAppIndex} or * {@link de.uka.ilkd.key.proof.TacletAppIndex TacletAppIndex} or - * {@link TacletApp TacletApp} + * {@link TacletApp ITacletApp} *

*/ public abstract class Taclet extends org.key_project.prover.rules.Taclet implements Rule { diff --git a/key.core/src/main/java/de/uka/ilkd/key/rule/TacletApp.java b/key.core/src/main/java/de/uka/ilkd/key/rule/TacletApp.java index 2a4a5d389e9..cac58cd8f4a 100644 --- a/key.core/src/main/java/de/uka/ilkd/key/rule/TacletApp.java +++ b/key.core/src/main/java/de/uka/ilkd/key/rule/TacletApp.java @@ -29,7 +29,7 @@ import org.key_project.logic.op.QuantifiableVariable; import org.key_project.logic.op.sv.SchemaVariable; import org.key_project.logic.sort.Sort; -import org.key_project.prover.rules.RuleApp; +import org.key_project.prover.rules.ITacletApp; import org.key_project.prover.rules.instantiation.*; import org.key_project.prover.sequent.*; import org.key_project.util.collection.*; @@ -38,7 +38,7 @@ import org.jspecify.annotations.Nullable; /** - * A TacletApp object contains information required for a concrete application. These information + * A ITacletApp object contains information required for a concrete application. These information * may consist of *
    *
  • instantiations of the schemavariables
  • @@ -48,7 +48,7 @@ * the information is complete or at least sufficient (can be completed using meta variables) * complete, so that is can be applied. */ -public abstract class TacletApp implements RuleApp { +public abstract class TacletApp implements ITacletApp { public static final AtomicLong PERF_EXECUTE = new AtomicLong(); public static final AtomicLong PERF_SET_SEQUENT = new AtomicLong(); public static final AtomicLong PERF_PRE = new AtomicLong(); @@ -82,7 +82,7 @@ public abstract class TacletApp implements RuleApp { protected boolean updateContextFixed = false; /** - * constructs a TacletApp for the given taclet, with an empty instantiation map + * constructs a ITacletApp for the given taclet, with an empty instantiation map */ TacletApp(org.key_project.prover.rules.Taclet taclet) { this(taclet, de.uka.ilkd.key.rule.inst.SVInstantiations.EMPTY_SVINSTANTIATIONS, null); @@ -406,7 +406,7 @@ protected ImmutableSet calculateNonInstantiatedSV() { * @param services the services object * @param interesting whether instantiations for this schema variable should be kept in the list * of "interesting" instantiations - * @return the new TacletApp + * @return the new ITacletApp */ public TacletApp addCheckedInstantiation(SchemaVariable sv, JTerm term, Services services, boolean interesting) { @@ -440,11 +440,11 @@ public TacletApp addCheckedInstantiation(SchemaVariable sv, JTerm term, Services * * @return ImmutableSet with SchemaVariables that have not been instantiated yet */ + @Override public @NonNull ImmutableSet uninstantiatedVars() { return calculateNonInstantiatedSV(); } - /** * returns true if the given {@link SchemaVariable} must be explicitly instantiated it does not * check whether sv is already instantiated or not @@ -478,7 +478,7 @@ public final TacletApp tryToInstantiateAsMuchAsPossible(Services services) { } /** - * @return A TacletApp with this.sufficientlyComplete() or null + * @return A ITacletApp with this.sufficientlyComplete() or null */ public final @Nullable TacletApp tryToInstantiate(Services services) { TacletApp app = instantiationHelper(true, services); @@ -714,7 +714,7 @@ && uninstantiatedVars().isEmpty() } /** - * adds a new instantiation to this TacletApp. This method does not check (beside some very + * adds a new instantiation to this ITacletApp. This method does not check (beside some very * rudimentary tests) if the instantiation is possible. If you cannot guarantee that adding the * entry (sv, se) will result in a valid taclet instantiation, you have to use * {@link #addCheckedInstantiation(SchemaVariable, ProgramElement, Services, boolean)} instead @@ -931,18 +931,19 @@ private ImmutableList createSemisequentList( } /** - * returns a new PosTacletApp that is equal to this TacletApp except that the position is set to + * returns a new PosTacletApp that is equal to this ITacletApp except that the position is set + * to * the given PosInOccurrence. * *

    * CAUTION: If you call this method, consider to call * {@link NoPosTacletApp#matchFind(PosInOccurrence, LogicServices)} * first (if applicable) as - * otherwise the TacletApp may become invalid. (This happened sometimes during interactive + * otherwise the ITacletApp may become invalid. (This happened sometimes during interactive * proofs). * * @param pos the PosInOccurrence of the newl created PosTacletApp - * @return the new TacletApp + * @return the new ITacletApp */ public PosTacletApp setPosInOccurrence(PosInOccurrence pos, Services services) { @@ -956,12 +957,13 @@ public PosTacletApp setPosInOccurrence(PosInOccurrence pos, /** * @return true iff the if-instantiation list is not null or no if sequent is needed */ + @Override public boolean assumesInstantionsComplete() { return assumesFormulaInstantiations != null || taclet().assumesSequent().isEmpty(); } /** - * compares the given Object with this one and returns true iff both are from type TacletApp + * compares the given Object with this one and returns true iff both are from type ITacletApp * with equal taclets, instantiations and positions. */ @Override @@ -996,12 +998,13 @@ public String toString() { /** * checks if there are name conflicts (i.e. there are two matched bound SchemaVariable that are - * matched to variables with an equal name); if yes a new TacletApp is returned that equals this - * TacletApp except that the name conflict is resolved by replacing the instantiation of one of + * matched to variables with an equal name); if yes a new ITacletApp is returned that equals + * this + * ITacletApp except that the name conflict is resolved by replacing the instantiation of one of * the conflict-causing SchemaVariables by a bound SchemaVariable with a new name; if the check - * is negative, the same TacletApp is returned. + * is negative, the same ITacletApp is returned. * - * @return a conflict resolved TacletApp, remainder equal to this TacletApp + * @return a conflict resolved ITacletApp, remainder equal to this ITacletApp */ public TacletApp prepareUserInstantiation(Services services) { TacletApp result = this; @@ -1018,7 +1021,7 @@ public TacletApp prepareUserInstantiation(Services services) { /** * creates a new variable namespace by adding names of the instantiations of the schema - * variables in the context of the given schema variable and (if the TacletApp's prefix has the + * variables in the context of the given schema variable and (if the ITacletApp's prefix has the * context flag set) by adding names of the logic variables of the context. * * @param sv the schema variable to be considered diff --git a/key.core/src/main/java/de/uka/ilkd/key/rule/UseDependencyContractRule.java b/key.core/src/main/java/de/uka/ilkd/key/rule/UseDependencyContractRule.java index 8c30fb92ed2..fda2166fb49 100644 --- a/key.core/src/main/java/de/uka/ilkd/key/rule/UseDependencyContractRule.java +++ b/key.core/src/main/java/de/uka/ilkd/key/rule/UseDependencyContractRule.java @@ -24,6 +24,7 @@ import de.uka.ilkd.key.speclang.DependencyContract; import de.uka.ilkd.key.speclang.HeapContext; +import org.key_project.logic.LogicServices; import org.key_project.logic.Name; import org.key_project.logic.PosInTerm; import org.key_project.logic.Term; @@ -594,7 +595,7 @@ public UseDependencyContractApp createApp(PosInOccurrence pos) { } @Override - public UseDependencyContractApp createApp(PosInOccurrence pos, TermServices services) { + public UseDependencyContractApp createApp(PosInOccurrence pos, LogicServices services) { return new UseDependencyContractApp(this, pos); } diff --git a/key.core/src/main/java/de/uka/ilkd/key/rule/UseOperationContractRule.java b/key.core/src/main/java/de/uka/ilkd/key/rule/UseOperationContractRule.java index 5daaa777ad5..d1f82d8cecd 100644 --- a/key.core/src/main/java/de/uka/ilkd/key/rule/UseOperationContractRule.java +++ b/key.core/src/main/java/de/uka/ilkd/key/rule/UseOperationContractRule.java @@ -33,6 +33,7 @@ import de.uka.ilkd.key.speclang.FunctionalOperationContract; import de.uka.ilkd.key.speclang.HeapContext; +import org.key_project.logic.LogicServices; import org.key_project.logic.Name; import org.key_project.logic.op.Function; import org.key_project.prover.rules.RuleApp; @@ -544,7 +545,7 @@ public ContractRuleApp createApp(PosInOccurrence pos) { } @Override - public ContractRuleApp createApp(PosInOccurrence pos, TermServices services) { + public ContractRuleApp createApp(PosInOccurrence pos, LogicServices services) { return new ContractRuleApp(this, pos); } diff --git a/key.core/src/main/java/de/uka/ilkd/key/rule/WhileInvariantRule.java b/key.core/src/main/java/de/uka/ilkd/key/rule/WhileInvariantRule.java index bae9c49e129..f602a3913f8 100644 --- a/key.core/src/main/java/de/uka/ilkd/key/rule/WhileInvariantRule.java +++ b/key.core/src/main/java/de/uka/ilkd/key/rule/WhileInvariantRule.java @@ -29,6 +29,7 @@ import de.uka.ilkd.key.speclang.LoopSpecification; import de.uka.ilkd.key.util.MiscTools; +import org.key_project.logic.LogicServices; import org.key_project.logic.Name; import org.key_project.logic.op.Function; import org.key_project.logic.op.Modality; @@ -129,8 +130,8 @@ public String toString() { @Override - public LoopInvariantBuiltInRuleApp createApp(PosInOccurrence pos, TermServices services) { - return new LoopInvariantBuiltInRuleApp<>(this, pos, services); + public LoopInvariantBuiltInRuleApp createApp(PosInOccurrence pos, LogicServices services) { + return new LoopInvariantBuiltInRuleApp<>(this, pos, (TermServices) services); } /** diff --git a/key.core/src/main/java/de/uka/ilkd/key/rule/executor/javadl/AntecTacletExecutor.java b/key.core/src/main/java/de/uka/ilkd/key/rule/executor/javadl/AntecTacletExecutor.java index 4433601b9d8..3523e83e2f8 100644 --- a/key.core/src/main/java/de/uka/ilkd/key/rule/executor/javadl/AntecTacletExecutor.java +++ b/key.core/src/main/java/de/uka/ilkd/key/rule/executor/javadl/AntecTacletExecutor.java @@ -70,7 +70,7 @@ protected void applyReplacewith(TacletGoalTemplate gt, TermLabelState termLabelS * match took place * @param matchCond the {@link MatchResultInfo} with all required instantiations * @param goal the Goal where the taclet is applied to - * @param ruleApp the {@link RuleApp} (a TacletApp) describing the current ongoing taclet + * @param ruleApp the {@link RuleApp} (a ITacletApp) describing the current ongoing taclet * application * @param services the {@link Services} encapsulating all Java model information */ diff --git a/key.core/src/main/java/de/uka/ilkd/key/rule/executor/javadl/FindTacletExecutor.java b/key.core/src/main/java/de/uka/ilkd/key/rule/executor/javadl/FindTacletExecutor.java index 5f10ae4312e..85bab724f9f 100644 --- a/key.core/src/main/java/de/uka/ilkd/key/rule/executor/javadl/FindTacletExecutor.java +++ b/key.core/src/main/java/de/uka/ilkd/key/rule/executor/javadl/FindTacletExecutor.java @@ -168,7 +168,7 @@ public final ImmutableList apply(@NonNull Goal goal, @NonNull RuleApp rule * creates a new position information object, describing where to add the formulas or * {@code null} if it should just be added to the beginning * - * @param tacletApp a TacletApp with application information + * @param tacletApp a ITacletApp with application information * @param gt the TacletGoalTemplate to be applied * @param currentSequent the current sequent (the one of the new goal) * @return the PosInOccurrence object describing where to add the formula diff --git a/key.core/src/main/java/de/uka/ilkd/key/rule/executor/javadl/TacletExecutor.java b/key.core/src/main/java/de/uka/ilkd/key/rule/executor/javadl/TacletExecutor.java index c01f777c4db..5fb231f091b 100644 --- a/key.core/src/main/java/de/uka/ilkd/key/rule/executor/javadl/TacletExecutor.java +++ b/key.core/src/main/java/de/uka/ilkd/key/rule/executor/javadl/TacletExecutor.java @@ -178,7 +178,7 @@ protected void applyAddrule(ImmutableList AbstractExternalSolverRuleApp createApp @Override - public SMTRuleApp createApp(PosInOccurrence pos, TermServices services) { + public SMTRuleApp createApp(PosInOccurrence pos, LogicServices services) { return new SMTRuleApp(this, null, ""); } diff --git a/key.core/src/main/java/de/uka/ilkd/key/strategy/AbstractFeatureStrategy.java b/key.core/src/main/java/de/uka/ilkd/key/strategy/AbstractFeatureStrategy.java index 90e67da550e..64c77d25502 100644 --- a/key.core/src/main/java/de/uka/ilkd/key/strategy/AbstractFeatureStrategy.java +++ b/key.core/src/main/java/de/uka/ilkd/key/strategy/AbstractFeatureStrategy.java @@ -3,13 +3,14 @@ * SPDX-License-Identifier: GPL-2.0-only */ package de.uka.ilkd.key.strategy; +import de.uka.ilkd.key.java.Services; import de.uka.ilkd.key.logic.NamespaceSet; import de.uka.ilkd.key.proof.Goal; import de.uka.ilkd.key.proof.Proof; -import de.uka.ilkd.key.strategy.feature.RuleSetDispatchFeature; import de.uka.ilkd.key.strategy.feature.instantiator.ForEachCP; import de.uka.ilkd.key.strategy.feature.instantiator.OneOfCP; import de.uka.ilkd.key.strategy.feature.instantiator.SVInstantiationCP; +import de.uka.ilkd.key.strategy.termgenerator.SuperTermGenerator; import org.key_project.logic.Name; import org.key_project.logic.Namespace; @@ -23,9 +24,11 @@ import org.key_project.prover.strategy.costbased.TopRuleAppCost; import org.key_project.prover.strategy.costbased.feature.ConditionalFeature; import org.key_project.prover.strategy.costbased.feature.Feature; +import org.key_project.prover.strategy.costbased.feature.RuleSetDispatchFeature; import org.key_project.prover.strategy.costbased.feature.instantiator.BackTrackingManager; import org.key_project.prover.strategy.costbased.termProjection.ProjectionToTerm; import org.key_project.prover.strategy.costbased.termProjection.TermBuffer; +import org.key_project.prover.strategy.costbased.termfeature.TermFeature; import org.key_project.prover.strategy.costbased.termgenerator.TermGenerator; import org.key_project.util.collection.ImmutableList; import org.key_project.util.collection.ImmutableSLList; @@ -33,7 +36,7 @@ import org.jspecify.annotations.NonNull; public abstract class AbstractFeatureStrategy extends StaticFeatureCollection - implements Strategy { + implements JavaStrategy { private final Proof proof; @@ -114,7 +117,7 @@ protected void clearRuleSetBindings(RuleSetDispatchFeature d, String ruleSet) { @Override public void instantiateApp(RuleApp app, PosInOccurrence pio, Goal goal, - RuleAppCostCollector collector) { + org.key_project.prover.strategy.RuleAppCostCollector collector) { final MutableState mState = new MutableState(); final BackTrackingManager btManager = mState.getBacktrackingManager(); btManager.setup(app); @@ -131,8 +134,21 @@ public void instantiateApp(RuleApp app, PosInOccurrence pio, } while (btManager.backtrack()); } - protected abstract RuleAppCost instantiateApp(RuleApp app, PosInOccurrence pio, Goal goal, - MutableState mState); + /** + * returns the service instance for access to {@link de.uka.ilkd.key.ldt.LDT}s + * + * @return the services for access to the meta logic + */ + protected final Services getServices() { + return getProof().getServices(); + } + + protected final Feature isBelow(TermFeature t) { + final de.uka.ilkd.key.strategy.termProjection.TermBuffer superTerm = + new de.uka.ilkd.key.strategy.termProjection.TermBuffer(); + return not(sum(superTerm, SuperTermGenerator.upwards(any(), getServices()), + not(applyTF(superTerm, t)))); + } protected Feature forEach(TermBuffer x, TermGenerator gen, Feature body) { return ForEachCP.create(x, gen, body); @@ -147,22 +163,25 @@ protected Feature oneOf(Feature feature0, Feature feature1) { return oneOf(new Feature[] { feature0, feature1 }); } - // it is possible to turn off the method instantiate, - // which can be useful in order to use the same feature definitions both for - // cost computation and instantiation - - private boolean instantiateActive = false; + /// It is possible to turn off the method instantiate, + /// which can be useful in order to use the same feature definitions both for + /// cost computation and instantiation. + /// + /// Counts nesting depth of instantiation activation to avoid premature deactivation. + private short instantiateActive = 0; protected void enableInstantiate() { - instantiateActive = true; + instantiateActive++; + assert instantiateActive >= 0 : "overflow occurred"; } protected void disableInstantiate() { - instantiateActive = false; + instantiateActive--; + assert instantiateActive >= 0; } protected Feature instantiate(Name sv, ProjectionToTerm value) { - if (instantiateActive) { + if (instantiateActive != 0) { return SVInstantiationCP.create(sv, value); } else { return longConst(0); @@ -170,7 +189,7 @@ protected Feature instantiate(Name sv, ProjectionToTerm value) { } protected Feature instantiateTriggeredVariable(ProjectionToTerm value) { - if (instantiateActive) { + if (instantiateActive != 0) { return SVInstantiationCP.createTriggeredVarCP(value); } else { return longConst(0); diff --git a/key.core/src/main/java/de/uka/ilkd/key/strategy/FIFOStrategy.java b/key.core/src/main/java/de/uka/ilkd/key/strategy/FIFOStrategy.java index 9aaac0ef5a5..11e08eff6e0 100644 --- a/key.core/src/main/java/de/uka/ilkd/key/strategy/FIFOStrategy.java +++ b/key.core/src/main/java/de/uka/ilkd/key/strategy/FIFOStrategy.java @@ -21,7 +21,7 @@ * Trivial implementation of the Strategy interface that uses only the goal time to determine the * cost of a RuleApp. */ -public class FIFOStrategy implements Strategy { +public class FIFOStrategy implements JavaStrategy { private static final Name NAME = new Name("FIFO"); @@ -57,14 +57,15 @@ public boolean isApprovedApp(RuleApp app, PosInOccurrence pio, @Override public void instantiateApp(RuleApp app, PosInOccurrence pio, Goal goal, - RuleAppCostCollector collector) {} + org.key_project.prover.strategy.RuleAppCostCollector collector) {} @Override public Name name() { return NAME; } - public static final Strategy INSTANCE = new FIFOStrategy(); + public static final org.key_project.prover.strategy.Strategy INSTANCE = + new FIFOStrategy(); public static class Factory implements StrategyFactory { @Override @@ -73,7 +74,8 @@ public Name name() { } @Override - public Strategy create(Proof proof, StrategyProperties properties) { + public org.key_project.prover.strategy.Strategy create(Proof proof, + StrategyProperties properties) { return INSTANCE; } diff --git a/key.core/src/main/java/de/uka/ilkd/key/strategy/FOLStrategy.java b/key.core/src/main/java/de/uka/ilkd/key/strategy/FOLStrategy.java new file mode 100644 index 00000000000..be09c621037 --- /dev/null +++ b/key.core/src/main/java/de/uka/ilkd/key/strategy/FOLStrategy.java @@ -0,0 +1,628 @@ +/* This file is part of KeY - https://key-project.org + * KeY is licensed under the GNU General Public License Version 2 + * SPDX-License-Identifier: GPL-2.0-only */ +package de.uka.ilkd.key.strategy; + +import java.util.HashSet; +import java.util.Set; + +import de.uka.ilkd.key.logic.op.Equality; +import de.uka.ilkd.key.logic.op.Junctor; +import de.uka.ilkd.key.logic.op.Quantifier; +import de.uka.ilkd.key.proof.Goal; +import de.uka.ilkd.key.proof.Proof; +import de.uka.ilkd.key.rule.OneStepSimplifier; +import de.uka.ilkd.key.strategy.feature.*; +import de.uka.ilkd.key.strategy.quantifierHeuristics.*; +import de.uka.ilkd.key.strategy.termProjection.AssumptionProjection; +import de.uka.ilkd.key.strategy.termProjection.FocusFormulaProjection; +import de.uka.ilkd.key.strategy.termProjection.FocusProjection; +import de.uka.ilkd.key.strategy.termProjection.TermBuffer; +import de.uka.ilkd.key.strategy.termfeature.ContainsExecutableCodeTermFeature; +import de.uka.ilkd.key.strategy.termgenerator.AllowedCutPositionsGenerator; +import de.uka.ilkd.key.strategy.termgenerator.SuperTermGenerator; +import de.uka.ilkd.key.strategy.termgenerator.TriggeredInstantiations; +import de.uka.ilkd.key.util.MiscTools; + +import org.key_project.logic.Name; +import org.key_project.prover.proof.ProofGoal; +import org.key_project.prover.proof.rulefilter.SetRuleFilter; +import org.key_project.prover.rules.IBuiltInRule; +import org.key_project.prover.rules.RuleApp; +import org.key_project.prover.rules.RuleSet; +import org.key_project.prover.sequent.PosInOccurrence; +import org.key_project.prover.strategy.ComponentStrategy; +import org.key_project.prover.strategy.costbased.MutableState; +import org.key_project.prover.strategy.costbased.RuleAppCost; +import org.key_project.prover.strategy.costbased.TopRuleAppCost; +import org.key_project.prover.strategy.costbased.feature.*; +import org.key_project.prover.strategy.costbased.feature.instantiator.ChoicePoint; +import org.key_project.prover.strategy.costbased.termProjection.ProjectionToTerm; +import org.key_project.prover.strategy.costbased.termfeature.IsNonRigidTermFeature; +import org.key_project.prover.strategy.costbased.termfeature.OperatorClassTF; + +import org.jspecify.annotations.NonNull; + +/// Strategy for general FOL rules. This does not consider other +/// theories like integers or Java-specific functions. +/// +/// In particular, instantiation of quantifiers is not supported by this +/// strategy, as the current E-matching depends on the theory of integers. +/// For that reason, instantiation can be found [JFOLStrategy]. +public class FOLStrategy extends AbstractFeatureStrategy implements ComponentStrategy { + public static final Name NAME = new Name("FOL Strategy"); + + protected final StrategyProperties strategyProperties; + + private final RuleSetDispatchFeature costComputationDispatcher; + private final RuleSetDispatchFeature approvalDispatcher; + private final RuleSetDispatchFeature instantiationDispatcher; + private final Feature costComputationF; + private final Feature approvalF; + private final Feature instantiationF; + + protected final ArithTermFeatures tf; + protected final FormulaTermFeatures ff; + + public FOLStrategy(Proof proof, StrategyProperties strategyProperties) { + super(proof); + + this.strategyProperties = (StrategyProperties) strategyProperties.clone(); + + this.tf = new ArithTermFeatures(getServices().getTypeConverter().getIntegerLDT()); + this.ff = new FormulaTermFeatures(this.tf); + + costComputationDispatcher = setupCostComputationF(); + approvalDispatcher = setupApprovalDispatcher(); + instantiationDispatcher = setupInstantiationF(); + + costComputationF = setUpGlobalF(costComputationDispatcher); + instantiationF = setUpGlobalF(instantiationDispatcher); + approvalF = approvalDispatcher; + } + + private Feature setUpGlobalF(RuleSetDispatchFeature d) { + final Feature oneStepSimplificationF = + oneStepSimplificationFeature(longConst(-11000)); + return add(d, oneStepSimplificationF); + } + + private Feature oneStepSimplificationFeature(Feature cost) { + SetRuleFilter filter = new SetRuleFilter(); + filter.addRuleToSet(MiscTools.findOneStepSimplifier(getProof())); + return ConditionalFeature.createConditional(filter, cost); + } + + private RuleSetDispatchFeature setupCostComputationF() { + final RuleSetDispatchFeature d = new RuleSetDispatchFeature(); + + bindRuleSet(d, "closure", -15000); + bindRuleSet(d, "alpha", -7000); + bindRuleSet(d, "delta", -6000); + bindRuleSet(d, "simplify_boolean", -200); + + final Feature findDepthFeature = + FindDepthFeature.getInstance(); + + bindRuleSet(d, "concrete", + add(longConst(-11000), + ScaleFeature.createScaled(findDepthFeature, 10.0))); + bindRuleSet(d, "simplify", -4500); + bindRuleSet(d, "simplify_enlarging", -2000); + bindRuleSet(d, "simplify_ENLARGING", -1900); + + // always give infinite cost to obsolete rules + bindRuleSet(d, "obsolete", inftyConst()); + + bindRuleSet(d, "no_self_application", + ifZero(MatchedAssumesFeature.INSTANCE, NoSelfApplicationFeature.INSTANCE)); + + bindRuleSet(d, "find_term_not_in_assumes", ifZero(MatchedAssumesFeature.INSTANCE, + not(contains(AssumptionProjection.create(0), FocusProjection.INSTANCE)))); + + bindRuleSet(d, "update_elim", + add(longConst(-8000), ScaleFeature.createScaled(findDepthFeature, 10.0))); + bindRuleSet(d, "update_apply_on_update", + add(longConst(-7000), ScaleFeature.createScaled(findDepthFeature, 10.0))); + bindRuleSet(d, "update_join", -4600); + bindRuleSet(d, "update_apply", -4500); + + setupSplitting(d); + + bindRuleSet(d, "gamma", add(not(isInstantiated("t")), + ifZero(allowQuantifierSplitting(), longConst(0), longConst(50)))); + bindRuleSet(d, "gamma_destructive", inftyConst()); + + bindRuleSet(d, "triggered", add(not(isTriggerVariableInstantiated()), longConst(500))); + + bindRuleSet(d, "comprehension_split", + add(applyTF(FocusFormulaProjection.INSTANCE, ff.notContainsExecutable), + ifZero(allowQuantifierSplitting(), longConst(2500), longConst(5000)))); + + setupReplaceKnown(d); + + setupEquationReasoning(d); + + bindRuleSet(d, "order_terms", + add(termSmallerThan("commEqLeft", "commEqRight"), longConst(-5000))); + + bindRuleSet(d, "simplify_instanceof_static", + add(EqNonDuplicateAppFeature.INSTANCE, longConst(-500))); + + bindRuleSet(d, "evaluate_instanceof", longConst(-500)); + + bindRuleSet(d, "instanceof_to_exists", TopLevelFindFeature.ANTEC); + + bindRuleSet(d, "try_apply_subst", + add(EqNonDuplicateAppFeature.INSTANCE, longConst(-10000))); + + // delete cast + bindRuleSet(d, "cast_deletion", + ifZero(implicitCastNecessary(instOf("castedTerm")), longConst(-5000), inftyConst())); + + bindRuleSet(d, "type_hierarchy_def", -6500); + + bindRuleSet(d, "cut", not(isInstantiated("cutFormula"))); + + if (quantifierInstantiatedEnabled()) { + setupFormulaNormalisation(d); + } else { + bindRuleSet(d, "negationNormalForm", inftyConst()); + bindRuleSet(d, "moveQuantToLeft", inftyConst()); + bindRuleSet(d, "conjNormalForm", inftyConst()); + bindRuleSet(d, "apply_equations_andOr", inftyConst()); + bindRuleSet(d, "elimQuantifier", inftyConst()); + bindRuleSet(d, "distrQuantifier", inftyConst()); + bindRuleSet(d, "swapQuantifiers", inftyConst()); + bindRuleSet(d, "pullOutQuantifierAll", inftyConst()); + bindRuleSet(d, "pullOutQuantifierEx", inftyConst()); + } + + return d; + } + + private RuleSetDispatchFeature setupApprovalDispatcher() { + final RuleSetDispatchFeature d = new RuleSetDispatchFeature(); + + setupQuantifierInstantiationApproval(d); + setupSplittingApproval(d); + + // Without EqNonDuplicateAppFeature.INSTANCE + // rule 'applyEq' might be applied on the same term + // without changing the sequent for a really long time. This is tested by + // TestSymbolicExecutionTreeBuilder#testInstanceOfNotInEndlessLoop() + bindRuleSet(d, "apply_equations", EqNonDuplicateAppFeature.INSTANCE); + + return d; + } + + private RuleSetDispatchFeature setupInstantiationF() { + enableInstantiate(); + + final RuleSetDispatchFeature d = new RuleSetDispatchFeature(); + setupQuantifierInstantiation(d); + + disableInstantiate(); + return d; + } + + @Override + public RuleAppCost instantiateApp(RuleApp app, PosInOccurrence pio, Goal goal, + MutableState mState) { + return instantiationF.computeCost(app, pio, goal, mState); + } + + @Override + public Set getResponsibilities(StrategyAspect aspect) { + var set = new HashSet(); + set.addAll(getDispatcher(aspect).ruleSets()); + return set; + } + + @Override + public RuleSetDispatchFeature getDispatcher(StrategyAspect aspect) { + return switch (aspect) { + case StrategyAspect.Cost -> costComputationDispatcher; + case StrategyAspect.Instantiation -> instantiationDispatcher; + case StrategyAspect.Approval -> approvalDispatcher; + }; + } + + @Override + public boolean isResponsibleFor(RuleSet rs) { + return costComputationDispatcher.get(rs) != null || instantiationDispatcher.get(rs) != null + || approvalDispatcher.get(rs) != null; + } + + @Override + public boolean isStopAtFirstNonCloseableGoal() { + return false; + } + + @Override + public boolean isApprovedApp(RuleApp app, PosInOccurrence pio, Goal goal) { + return approvalF.computeCost(app, pio, goal, new MutableState()) != TopRuleAppCost.INSTANCE; + } + + @Override + public Name name() { + return NAME; + } + + /** + * Evaluate the cost of a RuleApp. + * + * @param app rule application + * @param pio corresponding {@link PosInOccurrence} + * @param goal corresponding goal + * @param mState the {@link MutableState} to query for information like current value of + * {@link TermBuffer}s or + * {@link ChoicePoint}s + * @return the cost of the rule application expressed as a RuleAppCost object. + * TopRuleAppCost.INSTANCE indicates that the rule shall not be applied at + * all (it is discarded by the strategy). + */ + @Override + public > RuleAppCost computeCost(@NonNull RuleApp app, + @NonNull PosInOccurrence pio, + @NonNull GOAL goal, + @NonNull MutableState mState) { + return costComputationF.computeCost(app, pio, goal, mState); + } + + // ////////////////////////////////////////////////////////////////////////// + // ////////////////////////////////////////////////////////////////////////// + // + // Normalisation of formulas; this is mostly a pre-processing step for + // handling quantified formulas + // + // ////////////////////////////////////////////////////////////////////////// + // ////////////////////////////////////////////////////////////////////////// + + protected void setupFormulaNormalisation(RuleSetDispatchFeature d) { + bindRuleSet(d, "negationNormalForm", add(BelowBinderFeature.getInstance(), + longConst(-500), + ScaleFeature.createScaled(FindDepthFeature.getInstance(), 10.0))); + + bindRuleSet(d, "moveQuantToLeft", + add(quantifiersMightSplit() ? longConst(0) + : applyTF(FocusFormulaProjection.INSTANCE, ff.quantifiedPureLitConjDisj), + longConst(-550))); + + bindRuleSet(d, "conjNormalForm", + ifZero( + add(or(FocusInAntecFeature.getInstance(), notBelowQuantifier()), + NotInScopeOfModalityFeature.INSTANCE), + add(longConst(-150), + ScaleFeature.createScaled(FindDepthFeature.getInstance(), 20)), + inftyConst())); + + bindRuleSet(d, "setEqualityBlastingRight", longConst(-100)); + + + + bindRuleSet(d, "elimQuantifier", -1000); + bindRuleSet(d, "elimQuantifierWithCast", 50); + + final TermBuffer left = new TermBuffer(); + final TermBuffer right = new TermBuffer(); + bindRuleSet(d, "apply_equations_andOr", + add(let(left, instOf("applyEqLeft"), + let(right, instOf("applyEqRight"), + TermSmallerThanFeature.create(right, left))), + longConst(-150))); + + bindRuleSet(d, "distrQuantifier", + add(or( + applyTF(FocusProjection.INSTANCE, + add(ff.quantifiedClauseSet, not(opSub(Quantifier.ALL, ff.orF)), + EliminableQuantifierTF.INSTANCE)), + SumFeature.createSum(onlyInScopeOfQuantifiers(), + SplittableQuantifiedFormulaFeature.INSTANCE, + ifZero(FocusInAntecFeature.getInstance(), + applyTF(FocusProjection.INSTANCE, sub(ff.andF)), + applyTF(FocusProjection.INSTANCE, sub(ff.orF))))), + longConst(-300))); + + bindRuleSet(d, "swapQuantifiers", + add(applyTF(FocusProjection.INSTANCE, add(ff.quantifiedClauseSet, + EliminableQuantifierTF.INSTANCE, sub(not(EliminableQuantifierTF.INSTANCE)))), + longConst(-300))); + + // category "conjunctive normal form" + + bindRuleSet(d, "cnf_orAssoc", + SumFeature.createSum(applyTF("assoc0", ff.clause), + applyTF("assoc1", ff.clause), applyTF("assoc2", ff.literal), longConst(-80))); + + bindRuleSet(d, "cnf_andAssoc", + SumFeature.createSum(applyTF("assoc0", ff.clauseSet), + applyTF("assoc1", ff.clauseSet), applyTF("assoc2", ff.clause), longConst(-10))); + + bindRuleSet(d, "cnf_dist", + SumFeature.createSum(applyTF("distRight0", ff.clauseSet), + applyTF("distRight1", ff.clauseSet), ifZero(applyTF("distLeft", ff.clause), + longConst(-15), applyTF("distLeft", ff.clauseSet)), + longConst(-35))); + + final TermBuffer superFor = new TermBuffer(); + final Feature onlyBelowQuanAndOr = + sum(superFor, SuperTermGenerator.upwards(any(), getServices()), + applyTF(superFor, or(ff.quantifiedFor, ff.andF, ff.orF))); + + final Feature belowUnskolemisableQuantifier = + ifZero(FocusInAntecFeature.getInstance(), + not(sum(superFor, SuperTermGenerator.upwards(any(), getServices()), + not(applyTF(superFor, op(Quantifier.ALL))))), + not(sum(superFor, SuperTermGenerator.upwards(any(), getServices()), + not(applyTF(superFor, op(Quantifier.EX)))))); + + bindRuleSet(d, "cnf_expandIfThenElse", add( + isBelow(OperatorClassTF.create(Quantifier.class)), + onlyBelowQuanAndOr, belowUnskolemisableQuantifier)); + + final Feature pullOutQuantifierAllowed = + add(isBelow(OperatorClassTF.create(Quantifier.class)), onlyBelowQuanAndOr, applyTF( + FocusProjection.create(0), sub(ff.quantifiedClauseSet, ff.quantifiedClauseSet))); + + bindRuleSet(d, "pullOutQuantifierUnifying", -20); + + bindRuleSet(d, "pullOutQuantifierAll", add(pullOutQuantifierAllowed, + ifZero(FocusInAntecFeature.getInstance(), longConst(-20), longConst(-40)))); + + bindRuleSet(d, "pullOutQuantifierEx", add(pullOutQuantifierAllowed, + ifZero(FocusInAntecFeature.getInstance(), longConst(-40), longConst(-20)))); + } + + // ////////////////////////////////////////////////////////////////////////// + // ////////////////////////////////////////////////////////////////////////// + // + // Heuristic instantiation of quantified formulas + // + // ////////////////////////////////////////////////////////////////////////// + // ////////////////////////////////////////////////////////////////////////// + + private void setupQuantifierInstantiation(RuleSetDispatchFeature d) { + if (quantifierInstantiatedEnabled()) { + final TermBuffer varInst = new TermBuffer(); + final Feature branchPrediction = InstantiationCostScalerFeature + .create(InstantiationCost.create(varInst), allowQuantifierSplitting()); + + bindRuleSet(d, "gamma", + SumFeature.createSum(FocusInAntecFeature.getInstance(), + applyTF(FocusProjection.create(0), + add(ff.quantifiedClauseSet, + instQuantifiersWithQueries() ? longTermConst(0) + : ff.notContainsExecutable)), + forEach(varInst, HeuristicInstantiation.INSTANCE, + add(instantiate("t", varInst), branchPrediction, longConst(10))))); + final TermBuffer splitInst = new TermBuffer(); + + bindRuleSet(d, "triggered", + SumFeature.createSum(forEach(splitInst, TriggeredInstantiations.create(true), + add(instantiateTriggeredVariable(splitInst), longConst(500))), + longConst(1500))); + + } else { + bindRuleSet(d, "gamma", inftyConst()); + bindRuleSet(d, "triggered", inftyConst()); + } + } + + private void setupQuantifierInstantiationApproval(RuleSetDispatchFeature d) { + if (quantifierInstantiatedEnabled()) { + final TermBuffer varInst = new TermBuffer(); + + bindRuleSet(d, "gamma", add(isInstantiated("t"), + not(sum(varInst, HeuristicInstantiation.INSTANCE, not(eq(instOf("t"), varInst)))), + InstantiationCostScalerFeature.create(InstantiationCost.create(instOf("t")), + longConst(0)))); + + final TermBuffer splitInst = new TermBuffer(); + bindRuleSet(d, "triggered", + add(isTriggerVariableInstantiated(), + not(sum(splitInst, TriggeredInstantiations.create(false), + not(eq(instOfTriggerVariable(), splitInst)))))); + } else { + bindRuleSet(d, "gamma", inftyConst()); + bindRuleSet(d, "triggered", inftyConst()); + } + } + + + protected final Feature onlyInScopeOfQuantifiers() { + final TermBuffer buf = new TermBuffer(); + return sum(buf, SuperTermGenerator.upwards(any(), getServices()), + applyTF(buf, ff.quantifiedFor)); + } + + protected Feature notBelowQuantifier() { + final TermBuffer superFor = new TermBuffer(); + return or(TopLevelFindFeature.ANTEC_OR_SUCC, + sum(superFor, SuperTermGenerator.upwards(any(), getServices()), + not(applyTF(superFor, OperatorClassTF.create(Quantifier.class))))); + } + + private void setupReplaceKnown(RuleSetDispatchFeature d) { + final Feature commonF = + add(ifZero(MatchedAssumesFeature.INSTANCE, DiffFindAndIfFeature.INSTANCE), + longConst(-5000), + add(DiffFindAndReplacewithFeature.INSTANCE, + ScaleFeature.createScaled(CountMaxDPathFeature.INSTANCE, 10.0))); + + bindRuleSet(d, "replace_known_left", commonF); + + bindRuleSet(d, "replace_known_right", + add(commonF, ifZero(directlyBelowSymbolAtIndex(Junctor.IMP, 1), longConst(100), + ifZero(directlyBelowSymbolAtIndex(Equality.EQV, -1), longConst(100))))); + } + + // ////////////////////////////////////////////////////////////////////////// + // ////////////////////////////////////////////////////////////////////////// + // + // Application of beta- and cut-rules to handle disjunctions + // + // ////////////////////////////////////////////////////////////////////////// + // ////////////////////////////////////////////////////////////////////////// + + protected void setupSplitting(RuleSetDispatchFeature d) { + final TermBuffer subFor = new TermBuffer(); + final Feature noCutsAllowed = + sum(subFor, AllowedCutPositionsGenerator.INSTANCE, not(applyTF(subFor, ff.cutAllowed))); + bindRuleSet(d, "beta", + SumFeature.createSum(noCutsAllowed, + ifZero(PurePosDPathFeature.INSTANCE, longConst(-200)), + ScaleFeature.createScaled(CountPosDPathFeature.INSTANCE, -3.0), + ScaleFeature.createScaled(CountMaxDPathFeature.INSTANCE, 10.0), longConst(20))); + TermBuffer superF = new TermBuffer(); + final ProjectionToTerm splitCondition = sub(FocusProjection.INSTANCE, 0); + bindRuleSet(d, "split_cond", add(// do not split over formulas containing auxiliary + // variables + applyTF(FocusProjection.INSTANCE, + rec(any(), not(selectSkolemConstantTermFeature()))), + // prefer splits when condition has quantifiers (less + // likely to be simplified away) + applyTF(splitCondition, + rec(ff.quantifiedFor, ifZero(ff.quantifiedFor, longTermConst(-10)))), + FindDepthFeature.getInstance(), // prefer top level splits + ScaleFeature.createAffine(countOccurrences(splitCondition), -10, 10), + sum(superF, SuperTermGenerator.upwards(any(), getServices()), + applyTF(superF, not(ff.elemUpdate))), + ifZero(applyTF(FocusProjection.INSTANCE, ContainsExecutableCodeTermFeature.PROGRAMS), + longConst(-100), longConst(25)))); + ProjectionToTerm cutFormula = instOf("cutFormula"); + Feature countOccurrencesInSeq = + ScaleFeature.createAffine(countOccurrences(cutFormula), -10, 10); + bindRuleSet(d, "cut_direct", + SumFeature + .createSum( + not(TopLevelFindFeature.ANTEC_OR_SUCC_WITH_UPDATE), + AllowedCutPositionFeature.INSTANCE, + ifZero(notBelowQuantifier(), + add( + applyTF(cutFormula, add(ff.cutAllowed, + // do not cut over formulas containing + // auxiliary variables + rec(any(), not(selectSkolemConstantTermFeature())))), + countOccurrencesInSeq, // standard costs + longConst(100)), + SumFeature // check for cuts below quantifiers + .createSum(applyTF(cutFormula, ff.cutAllowedBelowQuantifier), + applyTF(FocusFormulaProjection.INSTANCE, + ff.quantifiedClauseSet), + ifZero(allowQuantifierSplitting(), longConst(0), + longConst(100)))))); + } + + private void setupSplittingApproval(RuleSetDispatchFeature d) { + bindRuleSet(d, "beta", allowSplitting(FocusFormulaProjection.INSTANCE)); + + bindRuleSet(d, "split_cond", allowSplitting(FocusProjection.INSTANCE)); + + final TermBuffer subFor = new TermBuffer(); + final Feature compareCutAllowed = ifZero(applyTF(subFor, ff.cutAllowed), + leq(applyTF("cutFormula", ff.cutPriority), applyTF(subFor, ff.cutPriority))); + + final Feature noBetterCut = + sum(subFor, AllowedCutPositionsGenerator.INSTANCE, compareCutAllowed); + + bindRuleSet(d, "cut_direct", add(allowSplitting(FocusFormulaProjection.INSTANCE), + ifZero(notBelowQuantifier(), noBetterCut))); + } + + // ////////////////////////////////////////////////////////////////////////// + // ////////////////////////////////////////////////////////////////////////// + // + // Application of equations + // + // ////////////////////////////////////////////////////////////////////////// + // ////////////////////////////////////////////////////////////////////////// + + private void setupEquationReasoning(RuleSetDispatchFeature d) { + final TermBuffer equation = new TermBuffer(); + final TermBuffer left = new TermBuffer(); + final TermBuffer right = new TermBuffer(); + + // applying equations less deep/less leftish in terms/formulas is + // preferred + // this is important for reducing polynomials (start with the biggest + // summands) + bindRuleSet(d, "apply_equations", + SumFeature.createSum( + ifZero(MatchedAssumesFeature.INSTANCE, + add(CheckApplyEqFeature.INSTANCE, let(equation, AssumptionProjection.create(0), + add(not(applyTF(equation, ff.update)), + // there might be updates in + // front of the assumption + // formula; in this case we wait + // until the updates have + // been applied + let(left, sub(equation, 0), + let(right, sub(equation, 1), + TermSmallerThanFeature.create(right, left))))))), + longConst(-4000))); + + bindRuleSet(d, "insert_eq_nonrigid", + applyTF(FocusProjection.create(0), IsNonRigidTermFeature.INSTANCE)); + } + + // ////////////////////////////////////////////////////////////////////////// + // ////////////////////////////////////////////////////////////////////////// + // + // Queries for the active taclet options + // + // ////////////////////////////////////////////////////////////////////////// + // ////////////////////////////////////////////////////////////////////////// + + private boolean instQuantifiersWithQueries() { + return StrategyProperties.QUANTIFIERS_INSTANTIATE + .equals(strategyProperties.getProperty(StrategyProperties.QUANTIFIERS_OPTIONS_KEY)); + } + + private boolean quantifiersMightSplit() { + return StrategyProperties.QUANTIFIERS_INSTANTIATE + .equals(strategyProperties.getProperty(StrategyProperties.QUANTIFIERS_OPTIONS_KEY)) + || StrategyProperties.QUANTIFIERS_NON_SPLITTING_WITH_PROGS.equals( + strategyProperties.getProperty(StrategyProperties.QUANTIFIERS_OPTIONS_KEY)); + } + + private Feature allowQuantifierSplitting() { + if (StrategyProperties.QUANTIFIERS_INSTANTIATE.equals( + strategyProperties.getProperty(StrategyProperties.QUANTIFIERS_OPTIONS_KEY))) { + return longConst(0); + } + if (StrategyProperties.QUANTIFIERS_NON_SPLITTING_WITH_PROGS.equals( + strategyProperties.getProperty(StrategyProperties.QUANTIFIERS_OPTIONS_KEY))) { + return sequentContainsNoPrograms(); + } + return inftyConst(); + } + + private boolean quantifierInstantiatedEnabled() { + return !StrategyProperties.QUANTIFIERS_NONE + .equals(strategyProperties.getProperty(StrategyProperties.QUANTIFIERS_OPTIONS_KEY)); + } + + private Feature allowSplitting(ProjectionToTerm focus) { + if (normalSplitting()) { + return longConst(0); + } + if (StrategyProperties.SPLITTING_DELAYED + .equals(strategyProperties.getProperty(StrategyProperties.SPLITTING_OPTIONS_KEY))) { + return or(applyTF(focus, ContainsExecutableCodeTermFeature.PROGRAMS), + sequentContainsNoPrograms()); + } + // else: SPLITTING_OFF + return applyTF(focus, ContainsExecutableCodeTermFeature.PROGRAMS); + } + + private boolean normalSplitting() { + return StrategyProperties.SPLITTING_NORMAL + .equals(strategyProperties.getProperty(StrategyProperties.SPLITTING_OPTIONS_KEY)); + } + + @Override + public boolean isResponsibleFor(IBuiltInRule rule) { + return rule instanceof OneStepSimplifier; + } +} diff --git a/key.core/src/main/java/de/uka/ilkd/key/strategy/IntegerStrategy.java b/key.core/src/main/java/de/uka/ilkd/key/strategy/IntegerStrategy.java new file mode 100644 index 00000000000..fed278e1022 --- /dev/null +++ b/key.core/src/main/java/de/uka/ilkd/key/strategy/IntegerStrategy.java @@ -0,0 +1,1042 @@ +/* This file is part of KeY - https://key-project.org + * KeY is licensed under the GNU General Public License Version 2 + * SPDX-License-Identifier: GPL-2.0-only */ +package de.uka.ilkd.key.strategy; + +import java.util.HashSet; +import java.util.Set; + +import de.uka.ilkd.key.ldt.IntegerLDT; +import de.uka.ilkd.key.logic.JTerm; +import de.uka.ilkd.key.logic.op.Equality; +import de.uka.ilkd.key.logic.op.Junctor; +import de.uka.ilkd.key.proof.Goal; +import de.uka.ilkd.key.proof.Proof; +import de.uka.ilkd.key.strategy.feature.*; +import de.uka.ilkd.key.strategy.termProjection.*; +import de.uka.ilkd.key.strategy.termgenerator.MultiplesModEquationsGenerator; +import de.uka.ilkd.key.strategy.termgenerator.RootsGenerator; +import de.uka.ilkd.key.strategy.termgenerator.SuperTermGenerator; + +import org.key_project.logic.Name; +import org.key_project.logic.PosInTerm; +import org.key_project.logic.Term; +import org.key_project.prover.proof.ProofGoal; +import org.key_project.prover.rules.IBuiltInRule; +import org.key_project.prover.rules.RuleApp; +import org.key_project.prover.rules.RuleSet; +import org.key_project.prover.sequent.PosInOccurrence; +import org.key_project.prover.strategy.ComponentStrategy; +import org.key_project.prover.strategy.costbased.MutableState; +import org.key_project.prover.strategy.costbased.RuleAppCost; +import org.key_project.prover.strategy.costbased.TopRuleAppCost; +import org.key_project.prover.strategy.costbased.feature.Feature; +import org.key_project.prover.strategy.costbased.feature.FocusInAntecFeature; +import org.key_project.prover.strategy.costbased.feature.RuleSetDispatchFeature; +import org.key_project.prover.strategy.costbased.feature.ScaleFeature; +import org.key_project.prover.strategy.costbased.feature.SumFeature; +import org.key_project.prover.strategy.costbased.termfeature.TermFeature; +import org.key_project.prover.strategy.costbased.termgenerator.SequentFormulasGenerator; +import org.key_project.prover.strategy.costbased.termgenerator.SubtermGenerator; + +import org.jspecify.annotations.NonNull; + +/// This strategy implements reasoning for integer arithmetics. In particular, +/// it supports linear integer arithmetics via Gaussian elimination, +/// Fourier-Motzkin; and non-linear integer reasoning via cross-multiplication +/// and Gröbner basis. +/// +/// Do not create directly, instead use [IntegerStrategyFactory]. +public class IntegerStrategy extends AbstractFeatureStrategy implements ComponentStrategy { + + public static final Name NAME = new Name("Integer Strategy"); + + /// Magic constants + private static final int IN_EQ_SIMP_NON_LIN_COST = 1000; + private static final int POLY_DIVISION_COST = -2250; + + /// The features defining the three phases: cost computation, approval, + /// additionalInstanceCreationAndEvaluation + private final RuleSetDispatchFeature costComputationDispatcher; + private final RuleSetDispatchFeature approvalDispatcher; + private final RuleSetDispatchFeature instantiationDispatcher; + + /// Useful [TermFeature] collections + private final ArithTermFeatures tf; + private final FormulaTermFeatures ff; + + /// configuration options extracted from [StrategyProperties] + private final boolean nonLinearArithmeticEnabled; + private final boolean divAndModuloReasoningEnabled; + private final boolean stopAtFirstNonCloseableGoal; + + public IntegerStrategy(Proof proof, StrategyProperties strategyProperties) { + super(proof); + this.tf = new ArithTermFeatures(proof.getServices().getTypeConverter().getIntegerLDT()); + this.ff = new FormulaTermFeatures(this.tf); + + // determine configuration + nonLinearArithmeticEnabled = StrategyProperties.NON_LIN_ARITH_COMPLETION.equals( + strategyProperties.getProperty(StrategyProperties.NON_LIN_ARITH_OPTIONS_KEY)); + + divAndModuloReasoningEnabled = + nonLinearArithmeticEnabled || StrategyProperties.NON_LIN_ARITH_DEF_OPS.equals( + strategyProperties.getProperty(StrategyProperties.NON_LIN_ARITH_OPTIONS_KEY)); + + stopAtFirstNonCloseableGoal = + strategyProperties.getProperty(StrategyProperties.STOPMODE_OPTIONS_KEY) + .equals(StrategyProperties.STOPMODE_NONCLOSE); + + // setup cost computations + costComputationDispatcher = setupCostComputationF(); + approvalDispatcher = setupApprovalDispatcher(); + instantiationDispatcher = setupInstantiationF(); + + } + + @Override + public boolean isResponsibleFor(RuleSet rs) { + return costComputationDispatcher.get(rs) != null || instantiationDispatcher.get(rs) != null; + } + + private RuleSetDispatchFeature setupInstantiationF() { + enableInstantiate(); + + final RuleSetDispatchFeature d = new RuleSetDispatchFeature(); + setupArithPrimaryCategories(d); + setupDefOpsPrimaryCategories(d); + setupInstantiationWithoutRetry(d); + setupInEqSimpInstantiation(d); + + disableInstantiate(); + return d; + } + + private RuleSetDispatchFeature setupApprovalDispatcher() { + final RuleSetDispatchFeature d = new RuleSetDispatchFeature(); + final IntegerLDT numbers = getServices().getTypeConverter().getIntegerLDT(); + + if (arithNonLinInferences()) { + setupMultiplyInequations(d, inftyConst()); + } + // these taclets are not supposed to be applied with metavariable + // instantiations + // I'll keep it here for the moment as documentation, but comment it out + // as meta variables are no longer part of KeY 2.x + /* + * bindRuleSet ( d, "inEqSimp_pullOutGcd", isInstantiated ( "elimGcd" ) ); bindRuleSet ( d, + * "polySimp_pullOutGcd", isInstantiated ( "elimGcd" ) ); + * + * bindRuleSet ( d, "inEqSimp_nonNegSquares", isInstantiated ( "squareFac" ) ); bindRuleSet + * ( d, "inEqSimp_nonLin_divide", isInstantiated ( "divY" ) ); bindRuleSet ( d, + * "inEqSimp_nonLin_pos", isInstantiated ( "divY" ) ); bindRuleSet ( d, + * "inEqSimp_nonLin_neg", isInstantiated ( "divY" ) ); + * + * bindRuleSet ( d, "inEqSimp_signCases", isInstantiated ( "signCasesLeft" ) ); + */ + + setupNewSymApproval(d, numbers); + + + bindRuleSet(d, "defOps_div", NonDuplicateAppModPositionFeature.INSTANCE); + bindRuleSet(d, "defOps_jdiv", NonDuplicateAppModPositionFeature.INSTANCE); + + if (arithNonLinInferences()) { + setupInEqCaseDistinctionsApproval(d); + } + + return d; + } + + private RuleSetDispatchFeature setupCostComputationF() { + final RuleSetDispatchFeature d = new RuleSetDispatchFeature(); + final IntegerLDT numbers = getServices().getTypeConverter().getIntegerLDT(); + + bindRuleSet(d, "simplify_int", inftyConst()); + + setupArithPrimaryCategories(d); + setupPolySimp(d, numbers); + setupInEqSimp(d, numbers); + + setupDefOpsPrimaryCategories(d); + + bindRuleSet(d, "order_terms", + add(applyTF("commEqRight", tf.monomial), applyTF("commEqLeft", tf.polynomial), + monSmallerThan("commEqLeft", "commEqRight", numbers), longConst(-5000))); + + final TermBuffer equation = new TermBuffer(); + final TermBuffer left = new TermBuffer(); + final TermBuffer right = new TermBuffer(); + bindRuleSet(d, "apply_equations", + SumFeature.createSum( + add(applyTF(FocusProjection.create(0), tf.monomial), + ScaleFeature.createScaled(FindRightishFeature.create(numbers), 5.0)), + ifZero(MatchedAssumesFeature.INSTANCE, + add(CheckApplyEqFeature.INSTANCE, let(equation, AssumptionProjection.create(0), + add(not(applyTF(equation, ff.update)), + // there might be updates in + // front of the assumption + // formula; in this case we wait + // until the updates have + // been applied + let(left, sub(equation, 0), + let(right, sub(equation, 1), + add(applyTF(left, tf.nonNegOrNonCoeffMonomial), + applyTF(right, tf.polynomial), + MonomialsSmallerThanFeature.create(right, left, + numbers)))))))), + longConst(-4000))); + + final TermBuffer l = new TermBuffer(); + final TermBuffer r = new TermBuffer(); + bindRuleSet(d, "apply_equations_andOr", + add(let(l, instOf("applyEqLeft"), + let(r, instOf("applyEqRight"), + add(applyTF(l, tf.nonNegOrNonCoeffMonomial), applyTF(r, tf.polynomial), + MonomialsSmallerThanFeature.create(r, l, numbers)))), + longConst(-150))); + + // For taclets that need instantiation, but where the instantiation is + // deterministic and does not have to be repeated at a later point, we + // setup the same feature terms as in the instantiation method. The + // definitions in setupInstantiationWithoutRetry should + // give cost infinity to those incomplete rule applications that will + // never be instantiated (so that these applications can be removed from + // the queue and do not have to be considered again). + setupInstantiationWithoutRetry(d); + + return d; + } + + private boolean arithNonLinInferences() { + return nonLinearArithmeticEnabled; + } + + private boolean arithDefOps() { + return divAndModuloReasoningEnabled; + } + + @Override + public boolean isStopAtFirstNonCloseableGoal() { + return stopAtFirstNonCloseableGoal; + } + + + // ////////////////////////////////////////////////////////////////////////// + // ////////////////////////////////////////////////////////////////////////// + // + // Handling of arithmetic + // + // ////////////////////////////////////////////////////////////////////////// + // ////////////////////////////////////////////////////////////////////////// + + private void setupArithPrimaryCategories(RuleSetDispatchFeature d) { + // Gaussian elimination + Euclidian algorithm for linear equations; + // Buchberger's algorithmus for handling polynomial equations over + // the integers + + bindRuleSet(d, "polySimp_expand", -4500); + bindRuleSet(d, "polySimp_directEquations", -3000); + bindRuleSet(d, "polySimp_pullOutGcd", -2250); + bindRuleSet(d, "polySimp_leftNonUnit", -2000); + bindRuleSet(d, "polySimp_saturate", 0); + + // Omega test for handling linear arithmetic and inequalities over the + // integers; cross-multiplication + case distinctions for nonlinear + // inequalities + + bindRuleSet(d, "inEqSimp_expand", -4400); + bindRuleSet(d, "inEqSimp_directInEquations", -2900); + bindRuleSet(d, "inEqSimp_propagation", -2400); + bindRuleSet(d, "inEqSimp_pullOutGcd", -2150); + bindRuleSet(d, "inEqSimp_saturate", -1900); + bindRuleSet(d, "inEqSimp_forNormalisation", -1100); + bindRuleSet(d, "inEqSimp_special_nonLin", -1400); + + if (arithNonLinInferences()) { + bindRuleSet(d, "inEqSimp_nonLin", IN_EQ_SIMP_NON_LIN_COST); + } else { + bindRuleSet(d, "inEqSimp_nonLin", inftyConst()); + } + // polynomial division, simplification of fractions and mods + bindRuleSet(d, "polyDivision", POLY_DIVISION_COST); + + } + + private void setupPolySimp(RuleSetDispatchFeature d, IntegerLDT numbers) { + + // category "expansion" (normalising polynomial terms) + + bindRuleSet(d, "polySimp_elimSubNeg", longConst(-120)); + + bindRuleSet(d, "polySimp_homo", + add(applyTF("homoRight", add(not(tf.zeroLiteral), tf.polynomial)), + or(applyTF("homoLeft", or(tf.addF, tf.negMonomial)), + not(monSmallerThan("homoRight", "homoLeft", numbers))), + longConst(-120))); + + bindRuleSet(d, "polySimp_pullOutFactor", add(applyTFNonStrict("pullOutLeft", tf.literal), + applyTFNonStrict("pullOutRight", tf.literal), longConst(-120))); + + bindRuleSet(d, "polySimp_elimOneLeft", -120); + + bindRuleSet(d, "polySimp_elimOneRight", -120); + + bindRuleSet(d, "polySimp_mulOrder", add(applyTF("commRight", tf.monomial), or( + applyTF("commLeft", tf.addF), + add(applyTF("commLeft", tf.atom), atomSmallerThan("commLeft", "commRight", numbers))), + longConst(-100))); + + bindRuleSet(d, "polySimp_mulAssoc", + SumFeature.createSum(applyTF("mulAssocMono0", tf.monomial), + applyTF("mulAssocMono1", tf.monomial), applyTF("mulAssocAtom", tf.atom), + longConst(-80))); + + bindRuleSet(d, "polySimp_addOrder", + SumFeature.createSum(applyTF("commLeft", tf.monomial), + applyTF("commRight", tf.polynomial), + monSmallerThan("commRight", "commLeft", numbers), longConst(-60))); + + bindRuleSet(d, "polySimp_addAssoc", + SumFeature.createSum(applyTF("addAssocPoly0", tf.polynomial), + applyTF("addAssocPoly1", tf.polynomial), applyTF("addAssocMono", tf.monomial), + longConst(-10))); + + bindRuleSet(d, "polySimp_dist", + SumFeature.createSum(applyTF("distSummand0", tf.polynomial), + applyTF("distSummand1", tf.polynomial), + ifZero(applyTF("distCoeff", tf.monomial), longConst(-15), + applyTF("distCoeff", tf.polynomial)), + applyTF("distSummand0", tf.polynomial), + + applyTF("distSummand1", tf.polynomial), longConst(-35))); + + // category "direct equations" + + bindRuleSet(d, "polySimp_balance", + SumFeature + .createSum(applyTF("sepResidue", tf.polynomial), + ifZero(isInstantiated("sepPosMono"), + add(applyTF("sepPosMono", tf.nonNegMonomial), + monSmallerThan("sepResidue", "sepPosMono", numbers))), + ifZero(isInstantiated("sepNegMono"), + add(applyTF("sepNegMono", tf.negMonomial), + monSmallerThan("sepResidue", "sepNegMono", numbers))), + longConst(-30))); + + bindRuleSet(d, "polySimp_normalise", add(applyTF("invertRight", tf.zeroLiteral), + applyTF("invertLeft", tf.negMonomial), longConst(-30))); + + // application of equations: some specialised rules that handle + // monomials and their coefficients properly + + final TermBuffer eqLeft = new TermBuffer(); + final TermBuffer focus = new TermBuffer(); + + final TermFeature atLeastTwoLCEquation = + opSub(Equality.EQUALS, opSub(tf.mul, tf.atom, tf.atLeastTwoLiteral), tf.intF); + + final Feature validEqApplication = add(not(eq(eqLeft, focus)), + // otherwise, the normal equation rules can and should + // be used + ifZero(applyTF(AssumptionProjection.create(0), atLeastTwoLCEquation), + add(FocusInAntecFeature.getInstance(), + applyTF(FocusFormulaProjection.INSTANCE, atLeastTwoLCEquation))), + ReducibleMonomialsFeature.createReducible(focus, eqLeft)); + + final Feature eqMonomialFeature = add(not(directlyBelowSymbolAtIndex(tf.mul, -1)), + ifZero(MatchedAssumesFeature.INSTANCE, let(focus, FocusProjection.create(0), + let(eqLeft, sub(AssumptionProjection.create(0), 0), validEqApplication)))); + + bindRuleSet(d, "polySimp_applyEq", add(eqMonomialFeature, longConst(1))); + + bindRuleSet(d, "polySimp_applyEqRigid", add(eqMonomialFeature, longConst(2))); + + // + bindRuleSet(d, "defOps_expandModulo", + add(NonDuplicateAppModPositionFeature.INSTANCE, longConst(-600))); + + // category "saturate" + + bindRuleSet(d, "polySimp_critPair", + ifZero(MatchedAssumesFeature.INSTANCE, + add(monSmallerThan("cpLeft1", "cpLeft2", numbers), + not(TrivialMonomialLCRFeature.create(instOf("cpLeft1"), instOf("cpLeft2")))))); + } + + private void setupDivModDivision(RuleSetDispatchFeature d) { + + final TermBuffer denomLC = new TermBuffer(); + final TermBuffer numTerm = new TermBuffer(); + final TermBuffer divCoeff = new TermBuffer(); + + // exact polynomial division + + final Feature checkNumTerm = ifZero( + add(not(applyTF(numTerm, tf.addF)), + ReducibleMonomialsFeature.createReducible(numTerm, denomLC)), + add(instantiate("polyDivCoeff", ReduceMonomialsProjection.create(numTerm, denomLC)), + inftyConst())); + + final Feature isReduciblePoly = + sum(numTerm, SubtermGenerator.rightTraverse(instOf("divNum"), tf.addF), checkNumTerm); + + // polynomial division modulo equations of the antecedent + + final Feature checkCoeffE = ifZero(contains(divCoeff, FocusProjection.create(0)), + // do not apply if the result contains the original term + longConst(0), add(instantiate("polyDivCoeff", divCoeff), inftyConst())); + + final Feature isReduciblePolyE = + sum(numTerm, SubtermGenerator.rightTraverse(instOf("divNum"), tf.addF), + ifZero(applyTF(numTerm, tf.addF), longConst(0), sum(divCoeff, + MultiplesModEquationsGenerator.create(numTerm, denomLC), checkCoeffE))); + + bindRuleSet(d, "defOps_divModPullOut", + SumFeature.createSum( + not(add(applyTF("divNum", tf.literal), applyTF("divDenom", tf.literal))), + applyTF("divNum", tf.polynomial), applyTF("divDenom", tf.polynomial), + ifZero(applyTF("divDenom", tf.addF), + let(denomLC, sub(instOf("divDenom"), 1), not(isReduciblePoly)), + let(denomLC, instOf("divDenom"), ifZero(isReduciblePoly, + // no possible division has been found so far + add(NotInScopeOfModalityFeature.INSTANCE, ifZero(isReduciblePolyE, + // try again later + longConst(-POLY_DIVISION_COST)))))), + longConst(100))); + + } + + + // For taclets that need instantiation, but where the instantiation is + // deterministic and does not have to be repeated at a later point, we + // setup the same feature terms as in the instantiation method. The + // definitions in setupInstantiationWithoutRetry should + // give cost infinity to those incomplete rule applications that will + // never be instantiated (so that these applications can be removed from + // the queue and do not have to be considered again). + private void setupPolySimpInstantiationWithoutRetry(RuleSetDispatchFeature d) { + final IntegerLDT numbers = getServices().getTypeConverter().getIntegerLDT(); + + // category "direct equations" + + setupPullOutGcd(d, "polySimp_pullOutGcd", false); + + // category "polynomial division" + + setupDivModDivision(d); + + // category "handling of equations with non-unit-coefficients on + // left-hand side" + + bindRuleSet(d, "polySimp_newSym", + ifZero(not(isInstantiated("newSymDef")), SumFeature.createSum( + applyTF("newSymLeft", tf.atom), applyTF("newSymLeftCoeff", tf.atLeastTwoLiteral), + applyTF("newSymRight", tf.polynomial), instantiate("newSymDef", + MonomialColumnOp.create(instOf("newSymLeftCoeff"), instOf("newSymRight")))))); + + final TermBuffer divisor = new TermBuffer(); + final TermBuffer dividend = new TermBuffer(); + + bindRuleSet(d, "polySimp_applyEqPseudo", + add(applyTF("aePseudoTargetLeft", tf.monomial), + applyTF("aePseudoTargetRight", tf.polynomial), + ifZero(MatchedAssumesFeature.INSTANCE, + SumFeature.createSum(DiffFindAndIfFeature.INSTANCE, + applyTF("aePseudoLeft", add(tf.nonCoeffMonomial, not(tf.atom))), + applyTF("aePseudoLeftCoeff", tf.atLeastTwoLiteral), + applyTF("aePseudoRight", tf.polynomial), + MonomialsSmallerThanFeature.create(instOf("aePseudoRight"), + instOf("aePseudoLeft"), numbers), + let(divisor, instOf("aePseudoLeft"), + let(dividend, instOf("aePseudoTargetLeft"), + add(ReducibleMonomialsFeature.createReducible(dividend, divisor), + instantiate("aePseudoTargetFactor", + ReduceMonomialsProjection.create(dividend, divisor))))))))); + } + + private void setupNewSymApproval(RuleSetDispatchFeature d, IntegerLDT numbers) { + final TermBuffer antecFor = new TermBuffer(); + final Feature columnOpEq = applyTF(antecFor, + opSub(tf.eq, opSub(tf.mul, tf.atom, tf.atLeastTwoLiteral), tf.polynomial)); + final Feature biggerLeftSide = + MonomialsSmallerThanFeature.create(instOf("newSymLeft"), + subAt(antecFor, PosInTerm.getTopLevel().down(0).down(0)), numbers); + bindRuleSet(d, "polySimp_newSym", add(isInstantiated("newSymDef"), sum(antecFor, + SequentFormulasGenerator.antecedent(), not(add(columnOpEq, biggerLeftSide))))); + } + + private void setupPullOutGcd(RuleSetDispatchFeature d, String ruleSet, boolean roundingUp) { + final TermBuffer gcd = new TermBuffer(); + + final Feature instantiateDivs; + if (roundingUp) { + instantiateDivs = add( + instantiate("elimGcdLeftDiv", + DividePolynomialsProjection.createRoundingUp(gcd, instOf("elimGcdLeft"))), + instantiate("elimGcdRightDiv", + DividePolynomialsProjection.createRoundingUp(gcd, instOf("elimGcdRight")))); + } else { + instantiateDivs = add( + instantiate("elimGcdLeftDiv", + DividePolynomialsProjection.createRoundingDown(gcd, instOf("elimGcdLeft"))), + instantiate("elimGcdRightDiv", + DividePolynomialsProjection.createRoundingDown(gcd, instOf("elimGcdRight")))); + } + bindRuleSet(d, ruleSet, + add(applyTF("elimGcdLeft", tf.nonNegMonomial), applyTF("elimGcdRight", tf.polynomial), + let(gcd, CoeffGcdProjection.create(instOf("elimGcdLeft"), instOf("elimGcdRight")), + add(applyTF(gcd, tf.atLeastTwoLiteral), instantiate("elimGcd", gcd), + instantiateDivs)))); + } + + private void setupInEqSimp(RuleSetDispatchFeature d, IntegerLDT numbers) { + + // category "expansion" (normalising inequations) + + bindRuleSet(d, "inEqSimp_moveLeft", -90); + + bindRuleSet(d, "inEqSimp_makeNonStrict", -80); + + bindRuleSet(d, "inEqSimp_commute", + SumFeature.createSum(applyTF("commRight", tf.monomial), + applyTF("commLeft", tf.polynomial), + monSmallerThan("commLeft", "commRight", numbers), longConst(-40))); + + // this is copied from "polySimp_homo" + bindRuleSet(d, "inEqSimp_homo", + add(applyTF("homoRight", add(not(tf.zeroLiteral), tf.polynomial)), + or(applyTF("homoLeft", or(tf.addF, tf.negMonomial)), + not(monSmallerThan("homoRight", "homoLeft", numbers))))); + + // category "direct inequations" + + // this is copied from "polySimp_balance" + bindRuleSet(d, "inEqSimp_balance", + add(applyTF("sepResidue", tf.polynomial), + ifZero(isInstantiated("sepPosMono"), + add(applyTF("sepPosMono", tf.nonNegMonomial), + monSmallerThan("sepResidue", "sepPosMono", numbers))), + ifZero(isInstantiated("sepNegMono"), add(applyTF("sepNegMono", tf.negMonomial), + monSmallerThan("sepResidue", "sepNegMono", numbers))))); + + // this is copied from "polySimp_normalise" + bindRuleSet(d, "inEqSimp_normalise", + add(applyTF("invertRight", tf.zeroLiteral), applyTF("invertLeft", tf.negMonomial))); + + // category "saturate" + + bindRuleSet(d, "inEqSimp_antiSymm", longConst(-20)); + + bindRuleSet(d, "inEqSimp_exactShadow", + SumFeature.createSum(applyTF("esLeft", tf.nonCoeffMonomial), + applyTFNonStrict("esCoeff2", tf.nonNegLiteral), applyTF("esRight2", tf.polynomial), + ifZero(MatchedAssumesFeature.INSTANCE, + SumFeature.createSum(applyTFNonStrict("esCoeff1", tf.nonNegLiteral), + applyTF("esRight1", tf.polynomial), + not(PolynomialValuesCmpFeature.leq(instOf("esRight2"), instOf("esRight1"), + instOfNonStrict("esCoeff1"), instOfNonStrict("esCoeff2"))))))); + + // category "propagation" + + bindRuleSet(d, "inEqSimp_contradInEqs", + add(applyTF("contradLeft", tf.monomial), + ifZero(MatchedAssumesFeature.INSTANCE, + SumFeature.createSum(DiffFindAndIfFeature.INSTANCE, + applyTF("contradRightSmaller", tf.polynomial), + applyTF("contradRightBigger", tf.polynomial), + applyTFNonStrict("contradCoeffSmaller", tf.posLiteral), + applyTFNonStrict("contradCoeffBigger", tf.posLiteral), + PolynomialValuesCmpFeature.lt(instOf("contradRightSmaller"), + instOf("contradRightBigger"), instOfNonStrict("contradCoeffBigger"), + instOfNonStrict("contradCoeffSmaller")))))); + + bindRuleSet(d, "inEqSimp_contradEqs", + add(applyTF("contradLeft", tf.monomial), + ifZero(MatchedAssumesFeature.INSTANCE, + SumFeature.createSum(applyTF("contradRightSmaller", tf.polynomial), + applyTF("contradRightBigger", tf.polynomial), PolynomialValuesCmpFeature + .lt(instOf("contradRightSmaller"), instOf("contradRightBigger")))), + longConst(-60))); + + bindRuleSet(d, "inEqSimp_strengthen", longConst(-30)); + + bindRuleSet(d, "inEqSimp_subsumption", + add(applyTF("subsumLeft", tf.monomial), + ifZero(MatchedAssumesFeature.INSTANCE, + SumFeature.createSum(DiffFindAndIfFeature.INSTANCE, + applyTF("subsumRightSmaller", tf.polynomial), + applyTF("subsumRightBigger", tf.polynomial), + applyTFNonStrict("subsumCoeffSmaller", tf.posLiteral), + applyTFNonStrict("subsumCoeffBigger", tf.posLiteral), + PolynomialValuesCmpFeature.leq(instOf("subsumRightSmaller"), + instOf("subsumRightBigger"), instOfNonStrict("subsumCoeffBigger"), + instOfNonStrict("subsumCoeffSmaller")))))); + + // category "handling of non-linear inequations" + + if (arithNonLinInferences()) { + setupMultiplyInequations(d, longConst(100)); + + bindRuleSet(d, "inEqSimp_split_eq", add(TopLevelFindFeature.SUCC, longConst(-100))); + + bindRuleSet(d, "inEqSimp_signCases", not(isInstantiated("signCasesLeft"))); + } + + // category "normalisation of formulas" + // (e.g., quantified formulas, where the normal sequent calculus + // does not do any normalisation) + + bindRuleSet(d, "inEqSimp_and_contradInEqs", + SumFeature.createSum(applyTF("contradLeft", tf.monomial), + applyTF("contradRightSmaller", tf.polynomial), + applyTF("contradRightBigger", tf.polynomial), PolynomialValuesCmpFeature + .lt(instOf("contradRightSmaller"), instOf("contradRightBigger")))); + + bindRuleSet(d, "inEqSimp_andOr_subsumption", + SumFeature.createSum(applyTF("subsumLeft", tf.monomial), + applyTF("subsumRightSmaller", tf.polynomial), + applyTF("subsumRightBigger", tf.polynomial), PolynomialValuesCmpFeature + .leq(instOf("subsumRightSmaller"), instOf("subsumRightBigger")))); + + bindRuleSet(d, "inEqSimp_and_subsumptionEq", + SumFeature.createSum(applyTF("subsumLeft", tf.monomial), + applyTF("subsumRightSmaller", tf.polynomial), + applyTF("subsumRightBigger", tf.polynomial), PolynomialValuesCmpFeature + .lt(instOf("subsumRightSmaller"), instOf("subsumRightBigger")))); + + final Term tOne = getServices().getTermBuilder().zTerm("1"); + final TermBuffer one = new TermBuffer() { + @Override + public void setContent(Term term, MutableState mState) {} + + @Override + public @NonNull Term getContent(MutableState mState) { + return tOne; + } + + @Override + public @NonNull Term toTerm(RuleApp app, PosInOccurrence pos, + Goal goal, MutableState mState) { + return tOne; + } + }; + + final JTerm tTwo = getServices().getTermBuilder().zTerm("2"); + final TermBuffer two = new TermBuffer() { + @Override + public void setContent(Term term, MutableState mState) {} + + @Override + public @NonNull Term getContent(MutableState mState) { + return tTwo; + } + + @Override + public @NonNull Term toTerm(RuleApp app, PosInOccurrence pos, + Goal goal, MutableState mState) { + return tTwo; + } + }; + + bindRuleSet(d, "inEqSimp_or_tautInEqs", + SumFeature.createSum(applyTF("tautLeft", tf.monomial), + applyTF("tautRightSmaller", tf.polynomial), + applyTF("tautRightBigger", tf.polynomial), + PolynomialValuesCmpFeature.leq(instOf("tautRightSmaller"), + opTerm(numbers.getAdd(), one, instOf("tautRightBigger"))))); + + bindRuleSet(d, "inEqSimp_or_weaken", + SumFeature.createSum(applyTF("weakenLeft", tf.monomial), + applyTF("weakenRightSmaller", tf.polynomial), + applyTF("weakenRightBigger", tf.polynomial), + PolynomialValuesCmpFeature.eq( + opTerm(numbers.getAdd(), one, instOf("weakenRightSmaller")), + instOf("weakenRightBigger")))); + + bindRuleSet(d, "inEqSimp_or_antiSymm", + SumFeature.createSum(applyTF("antiSymmLeft", tf.monomial), + applyTF("antiSymmRightSmaller", tf.polynomial), + applyTF("antiSymmRightBigger", tf.polynomial), + PolynomialValuesCmpFeature.eq( + opTerm(numbers.getAdd(), two, instOf("antiSymmRightSmaller")), + instOf("antiSymmRightBigger")))); + + } + + private void setupMultiplyInequations(RuleSetDispatchFeature d, Feature notAllowedF) { + final TermBuffer intRel = new TermBuffer(); + + /* + * final Feature partiallyBounded = not ( sum ( intRel, SequentFormulasGenerator.sequent (), + * not ( add ( applyTF ( intRel, tf.intRelation ), InEquationMultFeature .partiallyBounded ( + * instOf ( "multLeft" ), instOf ( "multFacLeft" ), sub ( intRel, 0 ) ) ) ) ) ); + */ + + final Feature totallyBounded = not(sum(intRel, SequentFormulasGenerator.sequent(), + not(add(applyTF(intRel, tf.intRelation), InEquationMultFeature + .totallyBounded(instOf("multLeft"), instOf("multFacLeft"), sub(intRel, 0)))))); + + final Feature exactlyBounded = not(sum(intRel, SequentFormulasGenerator.sequent(), + not(add(applyTF(intRel, tf.intRelation), InEquationMultFeature + .exactlyBounded(instOf("multLeft"), instOf("multFacLeft"), sub(intRel, 0)))))); + + // this is a bit hackish + // + // really, one would need a possibility to express that the cost + // computation for the rule application should be post-poned (and + // repeated at a later point) if the product of the left sides does not + // have any similarity with existing left sides + // (AllowInEquationMultiplication returns false). We + // simulate this by returning non-infinite costs here, but by declining + // the rule application in isApprovedApp). This is not + // perfect, because it is not possible to distinguish between the + // re-cost-computation delay and the normal costs for a rule application + bindRuleSet(d, "inEqSimp_nonLin_multiply", add( + applyTF("multLeft", tf.nonNegMonomial), + applyTF("multRight", tf.polynomial), + ifZero(MatchedAssumesFeature.INSTANCE, + SumFeature.createSum( + applyTF("multFacLeft", tf.nonNegMonomial), + ifZero(applyTF("multRight", tf.literal), longConst(-100)), + ifZero(applyTF("multFacRight", tf.literal), longConst(-100), + applyTF("multFacRight", tf.polynomial)), + /* + * ifZero ( applyTF ( "multRight", tf.literal ), longConst ( -100 ), applyTF ( + * "multRight", tf.polynomial ) ), ifZero ( applyTF ( "multFacRight", tf.literal + * ), longConst ( -100 ), applyTF ( "multFacRight", tf.polynomial ) ), + */ + not(TermSmallerThanFeature.create(FocusProjection.create(0), + AssumptionProjection.create(0))), + ifZero(exactlyBounded, longConst(0), + ifZero(totallyBounded, longConst(100), notAllowedF)) + /* + * ifZero ( partiallyBounded, longConst ( 400 ), notAllowedF ) ) ), + */ + /* + * applyTF ( "multLeft", rec ( tf.mulF, longTermConst ( 20 ) ) ), applyTF ( + * "multFacLeft", rec ( tf.mulF, longTermConst ( 20 ) ) ), applyTF ( "multRight", + * rec ( tf.addF, longTermConst ( 4 ) ) ), applyTF ( "multFacRight", rec ( tf.addF, + * longTermConst ( 4 ) ) ), + */ + ), notAllowedF))); + } + + private void setupInEqSimpInstantiation(RuleSetDispatchFeature d) { + // category "handling of non-linear inequations" + + setupSquaresAreNonNegative(d); + + if (arithNonLinInferences()) { + setupInEqCaseDistinctions(d); + } + } + + // For taclets that need instantiation, but where the instantiation is + // deterministic and does not have to be repeated at a later point, we + // setup the same feature terms as in the instantiation method. The + // definitions in setupInstantiationWithoutRetry should + // give cost infinity to those incomplete rule applications that will + // never be instantiated (so that these applications can be removed from + // the queue and do not have to be considered again). + private void setupInEqSimpInstantiationWithoutRetry(RuleSetDispatchFeature d) { + // category "direct inequations" + + setupPullOutGcd(d, "inEqSimp_pullOutGcd_leq", false); + setupPullOutGcd(d, "inEqSimp_pullOutGcd_geq", true); + + // more efficient (but not confluent) versions for the antecedent + bindRuleSet(d, "inEqSimp_pullOutGcd_antec", -10); + + // category "handling of non-linear inequations" + + final TermBuffer divisor = new TermBuffer(); + final TermBuffer dividend = new TermBuffer(); + + bindRuleSet(d, "inEqSimp_nonLin_divide", SumFeature.createSum( + applyTF("divProd", tf.nonCoeffMonomial), + applyTFNonStrict("divProdBoundNonPos", tf.nonPosLiteral), + applyTFNonStrict("divProdBoundNonNeg", tf.nonNegLiteral), + ifZero(MatchedAssumesFeature.INSTANCE, + let(divisor, instOf("divX"), let(dividend, instOf("divProd"), + SumFeature.createSum(applyTF(divisor, tf.nonCoeffMonomial), + not(eq(dividend, divisor)), applyTFNonStrict("divXBoundPos", tf.posLiteral), + applyTFNonStrict("divXBoundNeg", tf.negLiteral), + ReducibleMonomialsFeature.createReducible(dividend, divisor), instantiate( + "divY", ReduceMonomialsProjection.create(dividend, divisor)))))))); + + setupNonLinTermIsPosNeg(d, "inEqSimp_nonLin_pos", true); + setupNonLinTermIsPosNeg(d, "inEqSimp_nonLin_neg", false); + } + + private void setupNonLinTermIsPosNeg(RuleSetDispatchFeature d, String ruleSet, boolean pos) { + final TermBuffer divisor = new TermBuffer(); + final TermBuffer dividend = new TermBuffer(); + final TermBuffer quotient = new TermBuffer(); + final TermBuffer antecFor = new TermBuffer(); + + bindRuleSet(d, ruleSet, + SumFeature + .createSum(applyTF("divProd", tf.nonCoeffMonomial), + applyTFNonStrict("divProdBoundPos", tf.posLiteral), + applyTFNonStrict("divProdBoundNeg", tf.negLiteral), + ifZero(MatchedAssumesFeature.INSTANCE, + let(divisor, instOf("divX"), let(dividend, instOf("divProd"), + SumFeature.createSum(applyTF(divisor, tf.nonCoeffMonomial), + not(applyTF(dividend, eq(divisor))), + applyTFNonStrict("divXBoundNonPos", tf.nonPosLiteral), + applyTFNonStrict("divXBoundNonNeg", tf.nonNegLiteral), + ReducibleMonomialsFeature.createReducible(dividend, divisor), + let(quotient, + ReduceMonomialsProjection.create(dividend, divisor), add( + sum(antecFor, SequentFormulasGenerator.antecedent(), + not(applyTF(antecFor, + pos ? opSub(tf.geq, eq(quotient), tf.posLiteral) + : opSub(tf.leq, eq(quotient), + tf.negLiteral)))), + instantiate("divY", quotient))))))))); + } + + private void setupSquaresAreNonNegative(RuleSetDispatchFeature d) { + final TermBuffer intRel = new TermBuffer(); + final TermBuffer product = new TermBuffer(); + final TermBuffer factor = new TermBuffer(); + + final Feature productContainsSquare = + applyTF(sub(product, 0), or(eq(factor), opSub(tf.mul, any(), eq(factor)))); + final Feature productIsProduct = applyTF(product, opSub(tf.mul, any(), not(tf.mulF))); + + bindRuleSet(d, "inEqSimp_nonNegSquares", + forEach(intRel, SequentFormulasGenerator.sequent(), + ifZero(applyTF(intRel, tf.intRelation), + forEach(product, SubtermGenerator.leftTraverse(sub(intRel, 0), tf.mulF), + ifZero(productIsProduct, let(factor, sub(product, 1), + ifZero(productContainsSquare, instantiate("squareFac", factor)))))))); + } + + private void setupInEqCaseDistinctions(RuleSetDispatchFeature d) { + final TermBuffer intRel = new TermBuffer(); + final TermBuffer atom = new TermBuffer(); + final TermBuffer rootInf = new TermBuffer(); + + final Feature posNegSplitting = forEach(intRel, SequentFormulasGenerator.antecedent(), + add(applyTF(intRel, tf.intRelation), + forEach(atom, SubtermGenerator.leftTraverse(sub(intRel, 0), tf.mulF), + SumFeature.createSum(applyTF(atom, add(tf.atom, not(tf.literal))), + allowPosNegCaseDistinction(atom), instantiate("signCasesLeft", atom), + longConst(IN_EQ_SIMP_NON_LIN_COST + 200) + // , + // applyTF ( atom, rec ( any (), + // longTermConst ( 5 ) ) ) + )))); + + bindRuleSet(d, "inEqSimp_signCases", posNegSplitting); + + final Feature strengthening = forEach(intRel, SequentFormulasGenerator.antecedent(), + SumFeature.createSum( + applyTF(intRel, add(or(tf.geqF, tf.leqF), sub(tf.atom, tf.literal))), + instantiate("cutFormula", opTerm(tf.eq, sub(intRel, 0), sub(intRel, 1))), + longConst(IN_EQ_SIMP_NON_LIN_COST + 300) + // , + // applyTF ( sub ( intRel, 0 ), + // rec ( any (), longTermConst ( 5 ) ) ) + )); + + final Feature rootInferences = forEach(intRel, SequentFormulasGenerator.antecedent(), + add(isRootInferenceProducer(intRel), + forEach(rootInf, RootsGenerator.create(intRel, getServices()), + add(instantiate("cutFormula", rootInf), + ifZero(applyTF(rootInf, op(Junctor.OR)), longConst(50)), + ifZero(applyTF(rootInf, op(Junctor.AND)), longConst(20)))), + longConst(IN_EQ_SIMP_NON_LIN_COST))); + + // noinspection unchecked + bindRuleSet(d, "cut", oneOf(new Feature[] { strengthening, rootInferences })); + } + + private Feature isRootInferenceProducer(TermBuffer intRel) { + return applyTF(intRel, add(tf.intRelation, sub(tf.nonCoeffMonomial, tf.literal))); + } + + private Feature allowPosNegCaseDistinction(TermBuffer atom) { + final TermBuffer antecFor = new TermBuffer(); + final TermFeature eqAtom = eq(atom); + + return add(not(succIntEquationExists()), + sum(antecFor, SequentFormulasGenerator.antecedent(), + not(applyTF(antecFor, or(opSub(tf.eq, eqAtom, any()), + opSub(tf.leq, eqAtom, tf.negLiteral), opSub(tf.geq, eqAtom, tf.posLiteral)))))); + } + + private Feature allowInEqStrengthening(TermBuffer atom, TermBuffer literal) { + final TermBuffer antecFor = new TermBuffer(); + + return add(not(succIntEquationExists()), + not(sum(antecFor, SequentFormulasGenerator.antecedent(), + not(applyTF(antecFor, add(or(tf.leqF, tf.geqF), sub(eq(atom), eq(literal)))))))); + } + + private Feature succIntEquationExists() { + final TermBuffer succFor = new TermBuffer(); + + return not(sum(succFor, SequentFormulasGenerator.succedent(), + not(applyTF(succFor, tf.intEquation)))); + } + + private void setupInEqCaseDistinctionsApproval(RuleSetDispatchFeature d) { + final TermBuffer atom = new TermBuffer(); + final TermBuffer literal = new TermBuffer(); + final TermBuffer intRel = new TermBuffer(); + final TermBuffer rootInf = new TermBuffer(); + + bindRuleSet(d, "inEqSimp_signCases", add(isInstantiated("signCasesLeft"), + let(atom, instOf("signCasesLeft"), allowPosNegCaseDistinction(atom)))); + + // this is somewhat ugly. we should introduce some concept of "tagging" + // rule application so that they can be recognised again later + bindRuleSet(d, "cut", + add(isInstantiated("cutFormula"), or( + not(sum(intRel, SequentFormulasGenerator.antecedent(), + ifZero(isRootInferenceProducer(intRel), + sum(rootInf, RootsGenerator.create(intRel, getServices()), + not(eq(instOf("cutFormula"), rootInf)))))), + ifZero(applyTF("cutFormula", opSub(tf.eq, tf.atom, tf.literal)), + let(atom, sub(instOf("cutFormula"), 0), let(literal, + sub(instOf("cutFormula"), 1), allowInEqStrengthening(atom, literal))))))); + } + + // ////////////////////////////////////////////////////////////////////////// + // ////////////////////////////////////////////////////////////////////////// + // + // Axiomatisation and algorithms for further arithmetic operations: + // division, modulus, modular Java operations + // + // ////////////////////////////////////////////////////////////////////////// + // ////////////////////////////////////////////////////////////////////////// + + private void setupDefOpsPrimaryCategories(RuleSetDispatchFeature d) { + + if (arithDefOps()) { + // the axiom defining division only has to be inserted once, because + // it adds equations to the antecedent + bindRuleSet(d, "defOps_div", + SumFeature.createSum(NonDuplicateAppModPositionFeature.INSTANCE, + applyTF("divNum", tf.polynomial), applyTF("divDenom", tf.polynomial), + applyTF("divNum", tf.notContainsDivMod), + applyTF("divDenom", tf.notContainsDivMod), + ifZero(isBelow(ff.modalOperator), longConst(200)))); + + bindRuleSet(d, "defOps_jdiv", + SumFeature.createSum(NonDuplicateAppModPositionFeature.INSTANCE, + applyTF("divNum", tf.polynomial), applyTF("divDenom", tf.polynomial), + applyTF("divNum", tf.notContainsDivMod), + applyTF("divDenom", tf.notContainsDivMod), + ifZero(isBelow(ff.modalOperator), longConst(200)))); + + bindRuleSet(d, "defOps_jdiv_inline", add(applyTF("divNum", tf.literal), + applyTF("divDenom", tf.polynomial), longConst(-5000))); + + setupDefOpsExpandMod(d); + + bindRuleSet(d, "defOps_expandRanges", -8000); + bindRuleSet(d, "defOps_expandJNumericOp", -500); + bindRuleSet(d, "defOps_modHomoEq", -5000); + } else { + bindRuleSet(d, "defOps_div", inftyConst()); + bindRuleSet(d, "defOps_jdiv", inftyConst()); + + bindRuleSet(d, "defOps_jdiv_inline", add(applyTF("divNum", tf.literal), + applyTF("divDenom", tf.literal), longConst(-4000))); + + bindRuleSet(d, "defOps_mod", add(applyTF("divNum", tf.literal), + applyTF("divDenom", tf.literal), longConst(-4000))); + + bindRuleSet(d, "defOps_expandRanges", inftyConst()); + bindRuleSet(d, "defOps_expandJNumericOp", inftyConst()); + bindRuleSet(d, "defOps_modHomoEq", inftyConst()); + } + + } + + private void setupDefOpsExpandMod(RuleSetDispatchFeature d) { + final TermBuffer superTerm = new TermBuffer(); + + final Feature subsumedModulus = + add(applyTF(superTerm, sub(opSub(tf.mod, any(), tf.literal), tf.zeroLiteral)), + PolynomialValuesCmpFeature.divides(instOf("divDenom"), sub(sub(superTerm, 0), 1))); + + final Feature exSubsumedModulus = add(applyTF("divDenom", tf.literal), + not(sum(superTerm, + SuperTermGenerator.upwardsWithIndex(sub(or(tf.addF, tf.mulF), any()), + getServices()), + not(subsumedModulus)))); + + bindRuleSet(d, "defOps_mod", + ifZero(add(applyTF("divNum", tf.literal), applyTF("divDenom", tf.literal)), + longConst(-4000), + SumFeature.createSum(applyTF("divNum", tf.polynomial), + applyTF("divDenom", tf.polynomial), + ifZero(isBelow(ff.modalOperator), exSubsumedModulus, + or(add(applyTF("divNum", tf.notContainsDivMod), + applyTF("divDenom", tf.notContainsDivMod)), exSubsumedModulus)), + longConst(-3500)))); + } + + /** + * For taclets that need instantiation, but where the instantiation is deterministic and does + * not have to be repeated at a later point, we setup the same feature terms both in the cost + * computation method and in the instantiation method. The definitions in + * setupInstantiationWithoutRetry should give cost infinity to those incomplete + * rule applications that will never be instantiated (so that these applications can be removed + * from the queue and do not have to be considered again). + */ + private void setupInstantiationWithoutRetry(RuleSetDispatchFeature d) { + setupPolySimpInstantiationWithoutRetry(d); + setupInEqSimpInstantiationWithoutRetry(d); + } + + @Override + public boolean isApprovedApp(RuleApp app, PosInOccurrence pio, Goal goal) { + return !(approvalDispatcher.computeCost(app, pio, goal, + new MutableState()) == TopRuleAppCost.INSTANCE); + + } + + @Override + public RuleAppCost instantiateApp(RuleApp app, PosInOccurrence pio, Goal goal, + MutableState mState) { + return instantiationDispatcher.computeCost(app, pio, goal, mState); + } + + @Override + public Name name() { + return NAME; + } + + @Override + public > RuleAppCost computeCost(RuleApp app, + PosInOccurrence pos, Goal goal, MutableState mState) { + return this.costComputationDispatcher.computeCost(app, pos, goal, mState); + } + + @Override + public Set getResponsibilities(StrategyAspect aspect) { + var set = new HashSet(); + set.addAll(getDispatcher(aspect).ruleSets()); + return set; + } + + @Override + public RuleSetDispatchFeature getDispatcher(StrategyAspect aspect) { + return switch (aspect) { + case StrategyAspect.Cost -> costComputationDispatcher; + case StrategyAspect.Instantiation -> instantiationDispatcher; + case StrategyAspect.Approval -> approvalDispatcher; + }; + } + + @Override + public boolean isResponsibleFor(IBuiltInRule rule) { + return false; + } +} diff --git a/key.core/src/main/java/de/uka/ilkd/key/strategy/IntegerStrategyFactory.java b/key.core/src/main/java/de/uka/ilkd/key/strategy/IntegerStrategyFactory.java new file mode 100644 index 00000000000..c64563a9c90 --- /dev/null +++ b/key.core/src/main/java/de/uka/ilkd/key/strategy/IntegerStrategyFactory.java @@ -0,0 +1,63 @@ +/* This file is part of KeY - https://key-project.org + * KeY is licensed under the GNU General Public License Version 2 + * SPDX-License-Identifier: GPL-2.0-only */ +package de.uka.ilkd.key.strategy; + +import de.uka.ilkd.key.proof.Proof; +import de.uka.ilkd.key.strategy.definition.OneOfStrategyPropertyDefinition; +import de.uka.ilkd.key.strategy.definition.StrategyPropertyValueDefinition; +import de.uka.ilkd.key.strategy.definition.StrategySettingsDefinition; + +import org.key_project.logic.Name; + +/// Factory for [IntegerStrategy]. Additionally, handles all strategy settings +/// relevant to integers. +public class IntegerStrategyFactory implements StrategyFactory { + public static final String TOOL_TIP_ARITHMETIC_BASE = "" + "Basic arithmetic support:" + + "

      " + "
    • Simplification of polynomial expressions
    • " + + "
    • Computation of Gröbner Bases for polynomials in the antecedent
    • " + + "
    • (Partial) Omega procedure for handling linear inequations
    • " + "
    " + + ""; + public static final String TOOL_TIP_ARITHMETIC_DEF_OPS = + "" + "Automatically expand defined symbols like:" + "
      " + + "
    • /, %, jdiv, jmod, ...
    • " + + "
    • int_RANGE, short_MIN, ...
    • " + + "
    • inInt, inByte, ...
    • " + + "
    • addJint, mulJshort, ...
    • " + "
    " + ""; + public static final String TOOL_TIP_ARITHMETIC_MODEL_SEARCH = "" + + "Support for non-linear inequations and model search.
    " + "In addition, this performs:" + + "
      " + "
    • Multiplication of inequations with each other
    • " + + "
    • Systematic case distinctions (cuts)
    • " + "
    " + + "This method is guaranteed to find counterexamples for
    " + + "invalid goals that only contain polynomial (in)equations.
    " + + "Such counterexamples turn up as trivially unprovable goals.
    " + + "It is also able to prove many more valid goals involving
    " + + "(in)equations, but will in general not terminate on such goals." + ""; + + private static OneOfStrategyPropertyDefinition getArithmeticTreatment() { + return new OneOfStrategyPropertyDefinition(StrategyProperties.NON_LIN_ARITH_OPTIONS_KEY, + "Arithmetic treatment", + new StrategyPropertyValueDefinition(StrategyProperties.NON_LIN_ARITH_NONE, "Basic", + TOOL_TIP_ARITHMETIC_BASE), + new StrategyPropertyValueDefinition(StrategyProperties.NON_LIN_ARITH_DEF_OPS, "DefOps", + TOOL_TIP_ARITHMETIC_DEF_OPS), + new StrategyPropertyValueDefinition(StrategyProperties.NON_LIN_ARITH_COMPLETION, + "Model Search", TOOL_TIP_ARITHMETIC_MODEL_SEARCH)); + } + + @Override + public IntegerStrategy create(Proof proof, StrategyProperties strategyProperties) { + return new IntegerStrategy(proof, strategyProperties); + } + + @Override + public StrategySettingsDefinition getSettingsDefinition() { + final OneOfStrategyPropertyDefinition arithmeticTreatment = getArithmeticTreatment(); + return new StrategySettingsDefinition("Integer Options", arithmeticTreatment); + } + + @Override + public Name name() { + return IntegerStrategy.NAME; + } +} diff --git a/key.core/src/main/java/de/uka/ilkd/key/strategy/IntroducedSymbolBy.java b/key.core/src/main/java/de/uka/ilkd/key/strategy/IntroducedSymbolBy.java index 479da221106..d49ba7076ca 100644 --- a/key.core/src/main/java/de/uka/ilkd/key/strategy/IntroducedSymbolBy.java +++ b/key.core/src/main/java/de/uka/ilkd/key/strategy/IntroducedSymbolBy.java @@ -17,6 +17,8 @@ import org.key_project.prover.strategy.costbased.feature.Feature; import org.key_project.prover.strategy.costbased.termProjection.ProjectionToTerm; +import org.checkerframework.checker.nullness.qual.MonotonicNonNull; + public class IntroducedSymbolBy extends BinaryTacletAppFeature { private final Name ruleSetName; private final Name schemaVar; @@ -37,7 +39,8 @@ protected IntroducedSymbolBy(ProjectionToTerm termWithTopLevelOpToCheck, N } @Override - protected boolean filter(TacletApp app, PosInOccurrence pos, Goal goal, MutableState mState) { + protected boolean filter(@MonotonicNonNull TacletApp app, PosInOccurrence pos, Goal goal, + MutableState mState) { final Node root = goal.proof().root(); Node n = goal.node(); diff --git a/key.core/src/main/java/de/uka/ilkd/key/strategy/JFOLStrategy.java b/key.core/src/main/java/de/uka/ilkd/key/strategy/JFOLStrategy.java new file mode 100644 index 00000000000..490fba79421 --- /dev/null +++ b/key.core/src/main/java/de/uka/ilkd/key/strategy/JFOLStrategy.java @@ -0,0 +1,82 @@ +/* This file is part of KeY - https://key-project.org + * KeY is licensed under the GNU General Public License Version 2 + * SPDX-License-Identifier: GPL-2.0-only */ +package de.uka.ilkd.key.strategy; + +import de.uka.ilkd.key.ldt.IntegerLDT; +import de.uka.ilkd.key.proof.Goal; +import de.uka.ilkd.key.proof.Proof; +import de.uka.ilkd.key.strategy.quantifierHeuristics.ClausesSmallerThanFeature; +import de.uka.ilkd.key.strategy.termProjection.FocusProjection; + +import org.key_project.logic.Name; +import org.key_project.prover.strategy.costbased.feature.Feature; +import org.key_project.prover.strategy.costbased.feature.RuleSetDispatchFeature; +import org.key_project.prover.strategy.costbased.feature.SumFeature; +import org.key_project.prover.strategy.costbased.termProjection.ProjectionToTerm; + +/// This strategy extends the classical [FOLStrategy] with heuristics +/// for quantifier instantiation based on E-matching, which involves +/// normalization of quantified formulas, as well as term features depending on +/// integer theory. +/// +/// Do not create directly; use [JFOLStrategyFactory] instead. +public class JFOLStrategy extends FOLStrategy { + public static final Name NAME = new Name("JFOL Strategy"); + + public JFOLStrategy(Proof proof, StrategyProperties strategyProperties) { + super(proof, strategyProperties); + } + + @Override + protected void setupFormulaNormalisation(RuleSetDispatchFeature d) { + super.setupFormulaNormalisation(d); + var numbers = getServices().getTypeConverter().getIntegerLDT(); + bindRuleSet(d, "cnf_orComm", + SumFeature.createSum(applyTF("commRight", ff.clause), + applyTFNonStrict("commResidue", ff.clauseSet), + or(applyTF("commLeft", ff.andF), + add(applyTF("commLeft", ff.literal), + literalsSmallerThan("commRight", "commLeft", numbers))), + longConst(-100))); + bindRuleSet(d, "cnf_andComm", + SumFeature.createSum(applyTF("commLeft", ff.clause), + applyTF("commRight", ff.clauseSet), applyTFNonStrict("commResidue", ff.clauseSet), + // at least one of the subformulas has to be a literal; + // otherwise, sorting is not likely to have any big effect + ifZero( + add(applyTF("commLeft", not(ff.literal)), + applyTF("commRight", rec(ff.andF, not(ff.literal)))), + longConst(100), longConst(-60)), + clausesSmallerThan("commRight", "commLeft", numbers))); + } + + @Override + protected void setupSplitting(RuleSetDispatchFeature d) { + super.setupSplitting(d); + var heapLDT = getServices().getTypeConverter().getHeapLDT(); + var vf = new ValueTermFeature(op(heapLDT.getNull())); + ProjectionToTerm cutFormula = instOf("cutFormula"); + bindRuleSet(d, "cut_direct", + SumFeature + .createSum( + ifZero(notBelowQuantifier(), + add( + // prefer cuts over "something = null" + ifZero(applyTF(FocusProjection.INSTANCE, + opSub(tf.eq, any(), vf.nullTerm)), + longConst(-5), longConst(0)), + // punish cuts over formulas containing anon heap functions + ifZero(applyTF(cutFormula, rec(any(), not(anonHeapTermFeature()))), + longConst(0), longConst(1000)))))); + } + + private Feature clausesSmallerThan(String smaller, String bigger, IntegerLDT numbers) { + return ClausesSmallerThanFeature.create(instOf(smaller), instOf(bigger), numbers); + } + + @Override + public Name name() { + return NAME; + } +} diff --git a/key.core/src/main/java/de/uka/ilkd/key/strategy/JFOLStrategyFactory.java b/key.core/src/main/java/de/uka/ilkd/key/strategy/JFOLStrategyFactory.java new file mode 100644 index 00000000000..0a30ea974b7 --- /dev/null +++ b/key.core/src/main/java/de/uka/ilkd/key/strategy/JFOLStrategyFactory.java @@ -0,0 +1,68 @@ +/* This file is part of KeY - https://key-project.org + * KeY is licensed under the GNU General Public License Version 2 + * SPDX-License-Identifier: GPL-2.0-only */ +package de.uka.ilkd.key.strategy; + +import de.uka.ilkd.key.proof.Goal; +import de.uka.ilkd.key.proof.Proof; +import de.uka.ilkd.key.strategy.definition.OneOfStrategyPropertyDefinition; +import de.uka.ilkd.key.strategy.definition.StrategyPropertyValueDefinition; +import de.uka.ilkd.key.strategy.definition.StrategySettingsDefinition; + +import org.key_project.logic.Name; + +import org.jspecify.annotations.NonNull; + +/// Factory for [JFOLStrategy]. Additionally, handles all strategy settings +/// relevant to it. +public class JFOLStrategyFactory implements StrategyFactory { + public static final String TOOL_TIP_QUANTIFIER_NONE = + "" + "Do not instantiate quantified formulas automatically" + ""; + public static final String TOOL_TIP_QUANTIFIER_NO_SPLITS = "" + + "Instantiate quantified formulas automatically
    " + + "with terms that occur in a sequent, but only if
    " + + "this does not cause proof splitting. Further, quantified
    " + + "formulas that contain queries are not instantiated
    " + "automatically." + ""; + public static final String TOOL_TIP_QUANTIFIER_NO_SPLITS_WITH_PROGS = + "" + "Instantiate quantified formulas automatically
    " + + "with terms that occur in a sequent, but if the
    " + + "sequent contains programs then only perform
    " + + "instantiations that do not cause proof splitting.
    " + + "Further, quantified formulas that contain queries
    " + + "are not instantiated automatically." + ""; + public static final String TOOL_TIP_QUANTIFIER_FREE = + "" + "Instantiate quantified formulas automatically
    " + + "with terms that occur in a sequent, also if this
    " + + "might cause proof splitting." + ""; + + @Override + public org.key_project.prover.strategy.Strategy<@NonNull Goal> create(Proof proof, + StrategyProperties strategyProperties) { + return new JFOLStrategy(proof, strategyProperties); + } + + private static OneOfStrategyPropertyDefinition getQuantifierTreatment() { + return new OneOfStrategyPropertyDefinition(StrategyProperties.QUANTIFIERS_OPTIONS_KEY, + "Quantifier treatment", 2, + new StrategyPropertyValueDefinition(StrategyProperties.QUANTIFIERS_NONE, "None", + TOOL_TIP_QUANTIFIER_NONE, 2, 4), + new StrategyPropertyValueDefinition(StrategyProperties.QUANTIFIERS_NON_SPLITTING, + "No Splits", TOOL_TIP_QUANTIFIER_NO_SPLITS, 6, 2), + new StrategyPropertyValueDefinition( + StrategyProperties.QUANTIFIERS_NON_SPLITTING_WITH_PROGS, "No Splits with Progs", + TOOL_TIP_QUANTIFIER_NO_SPLITS_WITH_PROGS, 2, 4), + new StrategyPropertyValueDefinition(StrategyProperties.QUANTIFIERS_INSTANTIATE, "Free", + TOOL_TIP_QUANTIFIER_FREE, 6, 2)); + } + + @Override + public StrategySettingsDefinition getSettingsDefinition() { + final OneOfStrategyPropertyDefinition quantifierTreatment = getQuantifierTreatment(); + return new StrategySettingsDefinition("FOL Options", quantifierTreatment); + } + + @Override + public Name name() { + return FOLStrategy.NAME; + } +} diff --git a/key.core/src/main/java/de/uka/ilkd/key/strategy/JavaCardDLStrategy.java b/key.core/src/main/java/de/uka/ilkd/key/strategy/JavaCardDLStrategy.java index 5b18237454f..de8ed39d82a 100644 --- a/key.core/src/main/java/de/uka/ilkd/key/strategy/JavaCardDLStrategy.java +++ b/key.core/src/main/java/de/uka/ilkd/key/strategy/JavaCardDLStrategy.java @@ -3,75 +3,49 @@ * SPDX-License-Identifier: GPL-2.0-only */ package de.uka.ilkd.key.strategy; +import java.util.HashSet; +import java.util.Set; import java.util.concurrent.atomic.AtomicLong; -import de.uka.ilkd.key.java.Services; -import de.uka.ilkd.key.ldt.BooleanLDT; -import de.uka.ilkd.key.ldt.CharListLDT; import de.uka.ilkd.key.ldt.HeapLDT; -import de.uka.ilkd.key.ldt.IntegerLDT; import de.uka.ilkd.key.ldt.LocSetLDT; -import de.uka.ilkd.key.ldt.SeqLDT; -import de.uka.ilkd.key.logic.JTerm; -import de.uka.ilkd.key.logic.op.Equality; -import de.uka.ilkd.key.logic.op.Junctor; -import de.uka.ilkd.key.logic.op.Quantifier; -import de.uka.ilkd.key.logic.op.SortDependingFunction; import de.uka.ilkd.key.proof.Goal; import de.uka.ilkd.key.proof.Proof; +import de.uka.ilkd.key.rule.QueryExpand; import de.uka.ilkd.key.rule.UseDependencyContractRule; import de.uka.ilkd.key.strategy.feature.*; -import de.uka.ilkd.key.strategy.feature.findprefix.FindPrefixRestrictionFeature; -import de.uka.ilkd.key.strategy.quantifierHeuristics.ClausesSmallerThanFeature; -import de.uka.ilkd.key.strategy.quantifierHeuristics.EliminableQuantifierTF; -import de.uka.ilkd.key.strategy.quantifierHeuristics.HeuristicInstantiation; -import de.uka.ilkd.key.strategy.quantifierHeuristics.InstantiationCost; -import de.uka.ilkd.key.strategy.quantifierHeuristics.InstantiationCostScalerFeature; -import de.uka.ilkd.key.strategy.quantifierHeuristics.SplittableQuantifiedFormulaFeature; import de.uka.ilkd.key.strategy.termProjection.*; import de.uka.ilkd.key.strategy.termfeature.*; -import de.uka.ilkd.key.strategy.termgenerator.AllowedCutPositionsGenerator; import de.uka.ilkd.key.strategy.termgenerator.HeapGenerator; -import de.uka.ilkd.key.strategy.termgenerator.MultiplesModEquationsGenerator; -import de.uka.ilkd.key.strategy.termgenerator.RootsGenerator; -import de.uka.ilkd.key.strategy.termgenerator.SuperTermGenerator; -import de.uka.ilkd.key.strategy.termgenerator.TriggeredInstantiations; -import de.uka.ilkd.key.util.MiscTools; import org.key_project.logic.Name; -import org.key_project.logic.PosInTerm; -import org.key_project.logic.Term; import org.key_project.prover.proof.ProofGoal; import org.key_project.prover.proof.rulefilter.SetRuleFilter; +import org.key_project.prover.rules.IBuiltInRule; import org.key_project.prover.rules.RuleApp; +import org.key_project.prover.rules.RuleSet; import org.key_project.prover.sequent.PosInOccurrence; +import org.key_project.prover.strategy.ComponentStrategy; import org.key_project.prover.strategy.costbased.MutableState; import org.key_project.prover.strategy.costbased.RuleAppCost; import org.key_project.prover.strategy.costbased.TopRuleAppCost; import org.key_project.prover.strategy.costbased.feature.*; import org.key_project.prover.strategy.costbased.feature.instantiator.ChoicePoint; -import org.key_project.prover.strategy.costbased.termProjection.ProjectionToTerm; -import org.key_project.prover.strategy.costbased.termfeature.IsNonRigidTermFeature; -import org.key_project.prover.strategy.costbased.termfeature.OperatorClassTF; -import org.key_project.prover.strategy.costbased.termfeature.TermFeature; -import org.key_project.prover.strategy.costbased.termgenerator.SequentFormulasGenerator; -import org.key_project.prover.strategy.costbased.termgenerator.SubtermGenerator; import org.jspecify.annotations.NonNull; -/** - * Strategy tailored to be used as long as a java program can be found in the sequent. - */ -public class JavaCardDLStrategy extends AbstractFeatureStrategy { +/// This strategy is the catch-all for Java related features that are either +/// cross-cutting or one of the features that do not fit well into any other +/// strategy. +/// +/// Do not create directly, instead use [JavaCardDLStrategyFactory]. +public class JavaCardDLStrategy extends AbstractFeatureStrategy implements ComponentStrategy { public static final AtomicLong PERF_COMPUTE = new AtomicLong(); public static final AtomicLong PERF_APPROVE = new AtomicLong(); public static final AtomicLong PERF_INSTANTIATE = new AtomicLong(); public static final String JAVA_CARD_DL_STRATEGY = "JavaCardDLStrategy"; - private static final int IN_EQ_SIMP_NON_LIN_COST = 1000; - private static final int POLY_DIVISION_COST = -2250; - protected final StrategyProperties strategyProperties; private final RuleSetDispatchFeature costComputationDispatcher; @@ -85,11 +59,9 @@ public class JavaCardDLStrategy extends AbstractFeatureStrategy { private final ArithTermFeatures tf; private final FormulaTermFeatures ff; - private final ValueTermFeature vf; protected JavaCardDLStrategy(Proof proof, StrategyProperties strategyProperties) { - super(proof); heapLDT = getServices().getTypeConverter().getHeapLDT(); @@ -97,7 +69,6 @@ protected JavaCardDLStrategy(Proof proof, StrategyProperties strategyProperties) this.tf = new ArithTermFeatures(getServices().getTypeConverter().getIntegerLDT()); this.ff = new FormulaTermFeatures(this.tf); - this.vf = new ValueTermFeature(op(heapLDT.getNull())); costComputationDispatcher = setupCostComputationF(); approvalDispatcher = setupApprovalDispatcher(); @@ -106,34 +77,36 @@ protected JavaCardDLStrategy(Proof proof, StrategyProperties strategyProperties) costComputationF = setupGlobalF(costComputationDispatcher); instantiationF = setupGlobalF(instantiationDispatcher); approvalF = add(setupApprovalF(), approvalDispatcher); - } + protected final RuleSetDispatchFeature getCostComputationDispatcher() { return costComputationDispatcher; } - protected final RuleSetDispatchFeature getInstantiationDispatcher() { - return instantiationDispatcher; + @Override + public Set getResponsibilities(StrategyAspect aspect) { + var set = new HashSet(); + set.addAll(getDispatcher(aspect).ruleSets()); + return set; } - protected Feature setupGlobalF(Feature dispatcher) { - final Feature ifMatchedF = ifZero(MatchedAssumesFeature.INSTANCE, longConst(+1)); - - final Feature methodSpecF; - final String methProp = - strategyProperties.getProperty(StrategyProperties.METHOD_OPTIONS_KEY); - switch (methProp) { - case StrategyProperties.METHOD_CONTRACT -> - methodSpecF = methodSpecFeature(longConst(-20)); - case StrategyProperties.METHOD_EXPAND, StrategyProperties.METHOD_NONE -> methodSpecF = - methodSpecFeature(inftyConst()); - default -> { - methodSpecF = null; - assert false; - } - } + @Override + public RuleSetDispatchFeature getDispatcher(StrategyAspect aspect) { + return switch (aspect) { + case StrategyAspect.Cost -> costComputationDispatcher; + case StrategyAspect.Instantiation -> instantiationDispatcher; + case StrategyAspect.Approval -> approvalDispatcher; + }; + } + + @Override + public boolean isResponsibleFor(RuleSet rs) { + return costComputationDispatcher.get(rs) != null || instantiationDispatcher.get(rs) != null + || approvalDispatcher.get(rs) != null; + } + protected Feature setupGlobalF(@NonNull Feature dispatcher) { final String queryProp = strategyProperties.getProperty(StrategyProperties.QUERY_OPTIONS_KEY); final Feature queryF; @@ -161,72 +134,13 @@ protected Feature setupGlobalF(Feature dispatcher) { depSpecF = ConditionalFeature.createConditional(depFilter, inftyConst()); } - // NOTE (DS, 2019-04-10): The new loop-scope based rules are realized - // as taclets. The strategy settings for those are handled further - // down in this class. - Feature loopInvF; - final String loopProp = strategyProperties.getProperty(StrategyProperties.LOOP_OPTIONS_KEY); - if (loopProp.equals(StrategyProperties.LOOP_INVARIANT)) { - loopInvF = loopInvFeature(longConst(0)); - /* - * NOTE (DS, 2019-04-10): Deactivated the built-in loop scope rule since we now have the - * loop scope taclets which are based on the same theory, but offer several advantages. - */ - // } else if (loopProp.equals(StrategyProperties.LOOP_SCOPE_INVARIANT)) { - // loopInvF = loopInvFeature(inftyConst(), longConst(0)); - } else { - loopInvF = loopInvFeature(inftyConst()); - } - - final Feature blockFeature; - final Feature loopBlockFeature; - final Feature loopBlockApplyHeadFeature; - final String blockProperty = - strategyProperties.getProperty(StrategyProperties.BLOCK_OPTIONS_KEY); - if (blockProperty.equals(StrategyProperties.BLOCK_CONTRACT_INTERNAL)) { - blockFeature = blockContractInternalFeature(longConst(Long.MIN_VALUE)); - loopBlockFeature = loopContractInternalFeature(longConst(Long.MIN_VALUE)); - loopBlockApplyHeadFeature = loopContractApplyHead(longConst(Long.MIN_VALUE)); - } else if (blockProperty.equals(StrategyProperties.BLOCK_CONTRACT_EXTERNAL)) { - blockFeature = blockContractExternalFeature(longConst(Long.MIN_VALUE)); - loopBlockFeature = - SumFeature.createSum(loopContractExternalFeature(longConst(Long.MIN_VALUE)), - loopContractInternalFeature(longConst(42))); - loopBlockApplyHeadFeature = loopContractApplyHead(longConst(Long.MIN_VALUE)); - } else { - blockFeature = blockContractInternalFeature(inftyConst()); - loopBlockFeature = loopContractExternalFeature(inftyConst()); - loopBlockApplyHeadFeature = loopContractApplyHead(inftyConst()); - } - - final Feature oneStepSimplificationF = - oneStepSimplificationFeature(longConst(-11000)); - - final Feature mergeRuleF; - final String mpsProperty = - strategyProperties.getProperty(StrategyProperties.MPS_OPTIONS_KEY); - if (mpsProperty.equals(StrategyProperties.MPS_MERGE)) { - mergeRuleF = mergeRuleFeature(longConst(-4000)); - } else { - mergeRuleF = mergeRuleFeature(inftyConst()); - } - // final Feature smtF = smtFeature(inftyConst()); - return SumFeature.createSum(AutomatedRuleFeature.getInstance(), - NonDuplicateAppFeature.INSTANCE, + return SumFeature.createSum( // splitF, // strengthenConstraints, - AgeFeature.INSTANCE, oneStepSimplificationF, mergeRuleF, // smtF, - methodSpecF, queryF, depSpecF, loopInvF, blockFeature, loopBlockFeature, - loopBlockApplyHeadFeature, ifMatchedF, dispatcher); - } - - private Feature oneStepSimplificationFeature(Feature cost) { - SetRuleFilter filter = new SetRuleFilter(); - filter.addRuleToSet(MiscTools.findOneStepSimplifier(getProof())); - return ConditionalFeature.createConditional(filter, cost); + queryF, depSpecF, dispatcher); } // ////////////////////////////////////////////////////////////////////////// @@ -239,92 +153,34 @@ private Feature oneStepSimplificationFeature(Feature cost) { // ////////////////////////////////////////////////////////////////////////// private RuleSetDispatchFeature setupCostComputationF() { - final IntegerLDT numbers = getServices().getTypeConverter().getIntegerLDT(); - final LocSetLDT locSetLDT = getServices().getTypeConverter().getLocSetLDT(); - final RuleSetDispatchFeature d = new RuleSetDispatchFeature(); bindRuleSet(d, "semantics_blasting", inftyConst()); bindRuleSet(d, "simplify_heap_high_costs", inftyConst()); - bindRuleSet(d, "closure", -15000); - bindRuleSet(d, "alpha", -7000); - bindRuleSet(d, "delta", -6000); - bindRuleSet(d, "simplify_boolean", -200); - - final Feature findDepthFeature = - FindDepthFeature.getInstance(); - - bindRuleSet(d, "concrete", - add(longConst(-11000), - ScaleFeature.createScaled(findDepthFeature, 10.0))); - bindRuleSet(d, "simplify", -4500); - bindRuleSet(d, "simplify_enlarging", -2000); - bindRuleSet(d, "simplify_ENLARGING", -1900); - bindRuleSet(d, "simplify_expression", -100); - bindRuleSet(d, "executeIntegerAssignment", -100); - bindRuleSet(d, "executeDoubleAssignment", -100); - bindRuleSet(d, "simplify_int", inftyConst()); - bindRuleSet(d, "javaIntegerSemantics", ifZero(sequentContainsNoPrograms(), longConst(-5000), ifZero( leq(CountBranchFeature.INSTANCE, longConst(1)), longConst(-5000), inftyConst()))); - // always give infinite cost to obsolete rules - bindRuleSet(d, "obsolete", inftyConst()); - - // taclets for special invariant handling - bindRuleSet(d, "loopInvariant", -20000); - setupSelectSimplification(d); - bindRuleSet(d, "no_self_application", - ifZero(MatchedAssumesFeature.INSTANCE, NoSelfApplicationFeature.INSTANCE)); - - bindRuleSet(d, "find_term_not_in_assumes", ifZero(MatchedAssumesFeature.INSTANCE, - not(contains(AssumptionProjection.create(0), FocusProjection.INSTANCE)))); - - bindRuleSet(d, "update_elim", - add(longConst(-8000), ScaleFeature.createScaled(findDepthFeature, 10.0))); - bindRuleSet(d, "update_apply_on_update", - add(longConst(-7000), ScaleFeature.createScaled(findDepthFeature, 10.0))); - bindRuleSet(d, "update_join", -4600); - bindRuleSet(d, "update_apply", -4500); - - setUpStringNormalisation(d); - - setupSplitting(d); - bindRuleSet(d, "test_gen", inftyConst()); bindRuleSet(d, "test_gen_empty_modality_hide", inftyConst()); bindRuleSet(d, "test_gen_quan", inftyConst()); bindRuleSet(d, "test_gen_quan_num", inftyConst()); - bindRuleSet(d, "gamma", add(not(isInstantiated("t")), - ifZero(allowQuantifierSplitting(), longConst(0), longConst(50)))); - bindRuleSet(d, "gamma_destructive", inftyConst()); - - bindRuleSet(d, "triggered", add(not(isTriggerVariableInstantiated()), longConst(500))); - - bindRuleSet(d, "comprehension_split", - add(applyTF(FocusFormulaProjection.INSTANCE, ff.notContainsExecutable), - ifZero(allowQuantifierSplitting(), longConst(2500), longConst(5000)))); - - setupReplaceKnown(d); - - bindRuleSet(d, "confluence_restricted", - ifZero(MatchedAssumesFeature.INSTANCE, DiffFindAndIfFeature.INSTANCE)); - - setupApplyEq(d, numbers); - - bindRuleSet(d, "insert_eq_nonrigid", - applyTF(FocusProjection.create(0), IsNonRigidTermFeature.INSTANCE)); - - bindRuleSet(d, "order_terms", - add(ifZero(applyTF("commEqLeft", tf.intF), - add(applyTF("commEqRight", tf.monomial), applyTF("commEqLeft", tf.polynomial), - monSmallerThan("commEqLeft", "commEqRight", numbers)), - termSmallerThan("commEqLeft", "commEqRight")), longConst(-5000))); + // This is moved here instead of FOLStrategy, because it deals only w/ loc sets + if (!StrategyProperties.QUANTIFIERS_NONE + .equals( + strategyProperties.getProperty(StrategyProperties.QUANTIFIERS_OPTIONS_KEY))) { + final LocSetLDT locSetLDT = getServices().getTypeConverter().getLocSetLDT(); + bindRuleSet(d, "cnf_setComm", + add(SetsSmallerThanFeature.create(instOf("commRight"), instOf("commLeft"), + locSetLDT), + NotInScopeOfModalityFeature.INSTANCE, longConst(-800))); + } else { + bindRuleSet(d, "cnf_setComm", inftyConst()); + } bindRuleSet(d, "simplify_literals", // ifZero ( ConstraintStrengthenFeatureUC.create(proof), @@ -333,9 +189,7 @@ private RuleSetDispatchFeature setupCostComputationF() { bindRuleSet(d, "nonDuplicateAppCheckEq", EqNonDuplicateAppFeature.INSTANCE); - bindRuleSet(d, "simplify_instanceof_static", - add(EqNonDuplicateAppFeature.INSTANCE, longConst(-500))); - + // TODO: rename rule set? bindRuleSet(d, "comprehensions", add(NonDuplicateAppModPositionFeature.INSTANCE, longConst(-50))); @@ -345,79 +199,11 @@ private RuleSetDispatchFeature setupCostComputationF() { bindRuleSet(d, "comprehensions_low_costs", add(NonDuplicateAppModPositionFeature.INSTANCE, longConst(-5000))); - bindRuleSet(d, "evaluate_instanceof", longConst(-500)); - - bindRuleSet(d, "instanceof_to_exists", TopLevelFindFeature.ANTEC); - - bindRuleSet(d, "try_apply_subst", - add(EqNonDuplicateAppFeature.INSTANCE, longConst(-10000))); - - final TermBuffer superFor = new TermBuffer(); - bindRuleSet(d, "split_if", - add(sum(superFor, SuperTermGenerator.upwards(any(), getServices()), - applyTF(superFor, not(ff.program))), longConst(50))); - - final String[] exceptionsWithPenalty = { "java.lang.NullPointerException", - "java.lang.ArrayIndexOutOfBoundsException", "java.lang.ArrayStoreException", - "java.lang.ClassCastException" }; - - bindRuleSet(d, "simplify_prog", - ifZero(ThrownExceptionFeature.create(exceptionsWithPenalty, getServices()), - longConst(500), - ifZero(isBelow(add(ff.forF, not(ff.atom))), longConst(200), longConst(-100)))); - - bindRuleSet(d, "simplify_prog_subset", longConst(-4000)); - bindRuleSet(d, "modal_tautology", longConst(-10000)); - // features influenced by the strategy options - - boolean useLoopExpand = strategyProperties.getProperty(StrategyProperties.LOOP_OPTIONS_KEY) - .equals(StrategyProperties.LOOP_EXPAND); - boolean useLoopInvTaclets = - strategyProperties.getProperty(StrategyProperties.LOOP_OPTIONS_KEY) - .equals(StrategyProperties.LOOP_SCOPE_INV_TACLET); - boolean useLoopScopeExpand = - strategyProperties.getProperty(StrategyProperties.LOOP_OPTIONS_KEY) - .equals(StrategyProperties.LOOP_SCOPE_EXPAND); /* * boolean useBlockExpand = strategyProperties.getProperty( * StrategyProperties.BLOCK_OPTIONS_KEY). equals(StrategyProperties.BLOCK_EXPAND); */ - boolean programsToRight = true; // XXX - - final String methProp = - strategyProperties.getProperty(StrategyProperties.METHOD_OPTIONS_KEY); - - switch (methProp) { - case StrategyProperties.METHOD_CONTRACT -> - /* - * If method treatment by contracts is chosen, this does not mean that method - * expansion - * is disabled. The original cost was 200 and is now increased to 2000 in order to - * repress method expansion stronger when method treatment by contracts is chosen. - */ - bindRuleSet(d, "method_expand", longConst(2000)); - case StrategyProperties.METHOD_EXPAND -> - bindRuleSet(d, "method_expand", longConst(100)); - case StrategyProperties.METHOD_NONE -> bindRuleSet(d, "method_expand", inftyConst()); - default -> throw new RuntimeException("Unexpected strategy property " + methProp); - } - - final String mpsProp = strategyProperties.getProperty(StrategyProperties.MPS_OPTIONS_KEY); - - switch (mpsProp) { - case StrategyProperties.MPS_MERGE -> - /* - * For this case, we use a special feature, since deleting merge points should only - * be - * done after a merge rule application. - */ - bindRuleSet(d, "merge_point", DeleteMergePointRuleFeature.INSTANCE); - case StrategyProperties.MPS_SKIP -> bindRuleSet(d, "merge_point", longConst(-5000)); - case StrategyProperties.MPS_NONE -> bindRuleSet(d, "merge_point", inftyConst()); - default -> throw new RuntimeException("Unexpected strategy property " + methProp); - } - final String queryAxProp = strategyProperties.getProperty(StrategyProperties.QUERYAXIOM_OPTIONS_KEY); @@ -434,20 +220,10 @@ private RuleSetDispatchFeature setupCostComputationF() { bindRuleSet(d, "classAxiom", inftyConst()); } - bindRuleSet(d, "loop_expand", useLoopExpand ? longConst(0) : inftyConst()); - bindRuleSet(d, "loop_scope_inv_taclet", useLoopInvTaclets ? longConst(0) : inftyConst()); - bindRuleSet(d, "loop_scope_expand", useLoopScopeExpand ? longConst(1000) : inftyConst()); - /* * bindRuleSet ( d, "block_expand", useBlockExpand ? longConst ( 0 ) : inftyConst () ); */ - // delete cast - bindRuleSet(d, "cast_deletion", - ifZero(implicitCastNecessary(instOf("castedTerm")), longConst(-5000), inftyConst())); - - bindRuleSet(d, "type_hierarchy_def", -6500); - // partial inv axiom bindRuleSet(d, "partialInvAxiom", add(NonDuplicateAppModPositionFeature.INSTANCE, longConst(10000))); @@ -460,52 +236,10 @@ private RuleSetDispatchFeature setupCostComputationF() { bindRuleSet(d, "limitObserver", add(NonDuplicateAppModPositionFeature.INSTANCE, longConst(-200))); - if (programsToRight) { - bindRuleSet(d, "boxDiamondConv", - SumFeature.createSum( - new FindPrefixRestrictionFeature( - FindPrefixRestrictionFeature.PositionModifier.ALLOW_UPDATE_AS_PARENT, - FindPrefixRestrictionFeature.PrefixChecker.ANTEC_POLARITY), - longConst(-1000))); - } else { - bindRuleSet(d, "boxDiamondConv", inftyConst()); - } - - bindRuleSet(d, "cut", not(isInstantiated("cutFormula"))); - setupUserTaclets(d); - setupArithPrimaryCategories(d); - setupPolySimp(d, numbers); - setupInEqSimp(d, numbers); - - setupDefOpsPrimaryCategories(d); - setupSystemInvariantSimp(d); - if (quantifierInstantiatedEnabled()) { - setupFormulaNormalisation(d, numbers, locSetLDT); - } else { - bindRuleSet(d, "negationNormalForm", inftyConst()); - bindRuleSet(d, "moveQuantToLeft", inftyConst()); - bindRuleSet(d, "conjNormalForm", inftyConst()); - bindRuleSet(d, "apply_equations_andOr", inftyConst()); - bindRuleSet(d, "elimQuantifier", inftyConst()); - bindRuleSet(d, "distrQuantifier", inftyConst()); - bindRuleSet(d, "swapQuantifiers", inftyConst()); - bindRuleSet(d, "pullOutQuantifierAll", inftyConst()); - bindRuleSet(d, "pullOutQuantifierEx", inftyConst()); - } - - // For taclets that need instantiation, but where the instantiation is - // deterministic and does not have to be repeated at a later point, we - // setup the same feature terms as in the instantiation method. The - // definitions in setupInstantiationWithoutRetry should - // give cost infinity to those incomplete rule applications that will - // never be instantiated (so that these applications can be removed from - // the queue and do not have to be considered again). - setupInstantiationWithoutRetry(d); - // chrisg: The following rule, if active, must be applied delta rules. if (autoInductionEnabled()) { bindRuleSet(d, "auto_induction", -6500); // chrisg @@ -583,108 +317,6 @@ private void setupSelectSimplification(final RuleSetDispatchFeature d) { add(isSelectSkolemConstantTerm("auxiliarySK"), longConst(-500))); } - private void setUpStringNormalisation(RuleSetDispatchFeature d) { - - // translates an integer into its string representation - bindRuleSet(d, "integerToString", -10000); - - // do not convert char to int when inside a string function - // feature used to recognize if one is inside a string literal - final SeqLDT seqLDT = getServices().getTypeConverter().getSeqLDT(); - final CharListLDT charListLDT = getServices().getTypeConverter().getCharListLDT(); - final BooleanLDT booleanLDT = getServices().getTypeConverter().getBooleanLDT(); - - - final TermFeature keepChar = - or(op(seqLDT.getSeqSingleton()), or(op(charListLDT.getClIndexOfChar()), - or(op(charListLDT.getClReplace()), op(charListLDT.getClLastIndexOfChar())))); - - bindRuleSet(d, "charLiteral_to_intLiteral", - ifZero(isBelow(keepChar), inftyConst(), longConst(-100))); - - // establish normalform - - // tf below only for test - final TermFeature anyLiteral = or(tf.charLiteral, - or(tf.literal, op(booleanLDT.getFalseConst()), op(booleanLDT.getTrueConst()))); - - final TermFeature seqLiteral = rec(anyLiteral, or(op(seqLDT.getSeqConcat()), - or(op(seqLDT.getSeqSingleton()), or(anyLiteral, inftyTermConst())))); - - Feature belowModOpPenality = ifZero(isBelow(ff.modalOperator), longConst(500)); - - bindRuleSet(d, "defOpsSeqEquality", - add(NonDuplicateAppModPositionFeature.INSTANCE, - ifZero(add(applyTF("left", seqLiteral), applyTF("right", seqLiteral)), - longConst(1000), inftyConst()), - belowModOpPenality)); - - bindRuleSet(d, "defOpsConcat", - add(NonDuplicateAppModPositionFeature.INSTANCE, - ifZero( - or(applyTF("leftStr", not(seqLiteral)), applyTF("rightStr", not(seqLiteral))), - longConst(1000) - // concat is often introduced for construction purposes, - // we do not want to use its definition right at the - // beginning - ), belowModOpPenality)); - - bindRuleSet(d, "stringsSimplify", longConst(-5000)); - - final TermFeature charOrIntLiteral = or(tf.charLiteral, tf.literal, - or(add(OperatorClassTF.create(SortDependingFunction.class), // XXX: - // was CastFunctionSymbol.class - sub(tf.literal)), inftyTermConst())); - - bindRuleSet(d, "defOpsReplaceInline", - ifZero(add(applyTF("str", seqLiteral), applyTF("searchChar", charOrIntLiteral), - applyTF("replChar", charOrIntLiteral)), longConst(-2500), inftyConst())); - - bindRuleSet(d, "defOpsReplace", add(NonDuplicateAppModPositionFeature.INSTANCE, - ifZero(or(applyTF("str", not(seqLiteral)), applyTF("searchChar", not(charOrIntLiteral)), - applyTF("replChar", not(charOrIntLiteral))), longConst(500), inftyConst()), - belowModOpPenality)); - - bindRuleSet(d, "stringsReduceSubstring", - add(NonDuplicateAppModPositionFeature.INSTANCE, longConst(100))); - - bindRuleSet(d, "defOpsStartsEndsWith", longConst(250)); - - bindRuleSet(d, "stringsConcatNotBothLiterals", - ifZero(MatchedAssumesFeature.INSTANCE, ifZero( - add(applyTF(instOf("leftStr"), seqLiteral), - applyTF(instOf("rightStr"), seqLiteral)), - inftyConst()), inftyConst())); - - bindRuleSet(d, "stringsReduceConcat", longConst(100)); - - bindRuleSet(d, "stringsReduceOrMoveOutsideConcat", - ifZero(NonDuplicateAppModPositionFeature.INSTANCE, longConst(800), inftyConst())); - - bindRuleSet(d, "stringsMoveReplaceInside", - ifZero(NonDuplicateAppModPositionFeature.INSTANCE, longConst(400), inftyConst())); - - - bindRuleSet(d, "stringsExpandDefNormalOp", longConst(500)); - - bindRuleSet(d, "stringsContainsDefInline", SumFeature - .createSum(EqNonDuplicateAppFeature.INSTANCE, longConst(1000))); - } - - private void setupReplaceKnown(RuleSetDispatchFeature d) { - final Feature commonF = - add(ifZero(MatchedAssumesFeature.INSTANCE, DiffFindAndIfFeature.INSTANCE), - longConst(-5000), - add(DiffFindAndReplacewithFeature.INSTANCE, - ScaleFeature.createScaled(CountMaxDPathFeature.INSTANCE, 10.0))); - - bindRuleSet(d, "replace_known_left", commonF); - - bindRuleSet(d, "replace_known_right", - add(commonF, ifZero(directlyBelowSymbolAtIndex(Junctor.IMP, 1), longConst(100), - ifZero(directlyBelowSymbolAtIndex(Equality.EQV, -1), longConst(100))))); - } - private void setupUserTaclets(RuleSetDispatchFeature d) { for (int i = 1; i <= StrategyProperties.USER_TACLETS_NUM; ++i) { final String userTacletsProbs = @@ -713,47 +345,6 @@ private void setupSystemInvariantSimp(RuleSetDispatchFeature d) { // ////////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////////// - private boolean arithNonLinInferences() { - return StrategyProperties.NON_LIN_ARITH_COMPLETION.equals( - strategyProperties.getProperty(StrategyProperties.NON_LIN_ARITH_OPTIONS_KEY)); - } - - protected boolean arithDefOps() { - return StrategyProperties.NON_LIN_ARITH_DEF_OPS.equals( - strategyProperties.getProperty(StrategyProperties.NON_LIN_ARITH_OPTIONS_KEY)) - || StrategyProperties.NON_LIN_ARITH_COMPLETION.equals( - strategyProperties.getProperty(StrategyProperties.NON_LIN_ARITH_OPTIONS_KEY)); - } - - private boolean instQuantifiersWithQueries() { - return StrategyProperties.QUANTIFIERS_INSTANTIATE - .equals(strategyProperties.getProperty(StrategyProperties.QUANTIFIERS_OPTIONS_KEY)); - } - - private boolean quantifiersMightSplit() { - return StrategyProperties.QUANTIFIERS_INSTANTIATE - .equals(strategyProperties.getProperty(StrategyProperties.QUANTIFIERS_OPTIONS_KEY)) - || StrategyProperties.QUANTIFIERS_NON_SPLITTING_WITH_PROGS.equals( - strategyProperties.getProperty(StrategyProperties.QUANTIFIERS_OPTIONS_KEY)); - } - - private Feature allowQuantifierSplitting() { - if (StrategyProperties.QUANTIFIERS_INSTANTIATE.equals( - strategyProperties.getProperty(StrategyProperties.QUANTIFIERS_OPTIONS_KEY))) { - return longConst(0); - } - if (StrategyProperties.QUANTIFIERS_NON_SPLITTING_WITH_PROGS.equals( - strategyProperties.getProperty(StrategyProperties.QUANTIFIERS_OPTIONS_KEY))) { - return sequentContainsNoPrograms(); - } - return inftyConst(); - } - - private boolean quantifierInstantiatedEnabled() { - return !StrategyProperties.QUANTIFIERS_NONE - .equals(strategyProperties.getProperty(StrategyProperties.QUANTIFIERS_OPTIONS_KEY)); - } - private boolean classAxiomDelayedApplication() { String classAxiomSetting = strategyProperties.getProperty(StrategyProperties.CLASS_AXIOM_OPTIONS_KEY); @@ -783,1110 +374,6 @@ private boolean autoInductionLemmaEnabled() { // chrisg */ } - private Feature allowSplitting(ProjectionToTerm focus) { - if (normalSplitting()) { - return longConst(0); - } - if (StrategyProperties.SPLITTING_DELAYED - .equals(strategyProperties.getProperty(StrategyProperties.SPLITTING_OPTIONS_KEY))) { - return or(applyTF(focus, ContainsExecutableCodeTermFeature.PROGRAMS), - sequentContainsNoPrograms()); - } - // else: SPLITTING_OFF - return applyTF(focus, ContainsExecutableCodeTermFeature.PROGRAMS); - } - - private boolean normalSplitting() { - return StrategyProperties.SPLITTING_NORMAL - .equals(strategyProperties.getProperty(StrategyProperties.SPLITTING_OPTIONS_KEY)); - } - - // ////////////////////////////////////////////////////////////////////////// - // ////////////////////////////////////////////////////////////////////////// - // - // Application of beta- and cut-rules to handle disjunctions - // - // ////////////////////////////////////////////////////////////////////////// - // ////////////////////////////////////////////////////////////////////////// - - private void setupSplitting(RuleSetDispatchFeature d) { - final TermBuffer subFor = new TermBuffer(); - final Feature noCutsAllowed = - sum(subFor, AllowedCutPositionsGenerator.INSTANCE, not(applyTF(subFor, ff.cutAllowed))); - bindRuleSet(d, "beta", - SumFeature.createSum(noCutsAllowed, - ifZero(PurePosDPathFeature.INSTANCE, longConst(-200)), - ScaleFeature.createScaled(CountPosDPathFeature.INSTANCE, -3.0), - ScaleFeature.createScaled(CountMaxDPathFeature.INSTANCE, 10.0), longConst(20))); - TermBuffer superF = new TermBuffer(); - final ProjectionToTerm splitCondition = sub(FocusProjection.INSTANCE, 0); - bindRuleSet(d, "split_cond", add(// do not split over formulas containing auxiliary - // variables - applyTF(FocusProjection.INSTANCE, - rec(any(), not(selectSkolemConstantTermFeature()))), - // prefer splits when condition has quantifiers (less - // likely to be simplified away) - applyTF(splitCondition, - rec(ff.quantifiedFor, ifZero(ff.quantifiedFor, longTermConst(-10)))), - FindDepthFeature.getInstance(), // prefer top level splits - ScaleFeature.createAffine(countOccurrences(splitCondition), -10, 10), - sum(superF, SuperTermGenerator.upwards(any(), getServices()), - applyTF(superF, not(ff.elemUpdate))), - ifZero(applyTF(FocusProjection.INSTANCE, ContainsExecutableCodeTermFeature.PROGRAMS), - longConst(-100), longConst(25)))); - ProjectionToTerm cutFormula = instOf("cutFormula"); - Feature countOccurrencesInSeq = - ScaleFeature.createAffine(countOccurrences(cutFormula), -10, 10); - bindRuleSet(d, "cut_direct", - SumFeature - .createSum( - not(TopLevelFindFeature.ANTEC_OR_SUCC_WITH_UPDATE), - AllowedCutPositionFeature.INSTANCE, - ifZero(notBelowQuantifier(), - add( - applyTF(cutFormula, add(ff.cutAllowed, - // do not cut over formulas containing - // auxiliary variables - rec(any(), not(selectSkolemConstantTermFeature())))), - // prefer cuts over "something = null" - ifZero(applyTF(FocusProjection.INSTANCE, - opSub(tf.eq, any(), vf.nullTerm)), - longConst(-5), longConst(0)), - // punish cuts over formulas containing anon heap functions - ifZero(applyTF(cutFormula, rec(any(), not(anonHeapTermFeature()))), - longConst(0), longConst(1000)), - countOccurrencesInSeq, // standard costs - longConst(100)), - SumFeature // check for cuts below quantifiers - .createSum(applyTF(cutFormula, ff.cutAllowedBelowQuantifier), - applyTF(FocusFormulaProjection.INSTANCE, - ff.quantifiedClauseSet), - ifZero(allowQuantifierSplitting(), longConst(0), - longConst(100)))))); - } - - private void setupSplittingApproval(RuleSetDispatchFeature d) { - bindRuleSet(d, "beta", allowSplitting(FocusFormulaProjection.INSTANCE)); - - bindRuleSet(d, "split_cond", allowSplitting(FocusProjection.INSTANCE)); - - final TermBuffer subFor = new TermBuffer(); - final Feature compareCutAllowed = ifZero(applyTF(subFor, ff.cutAllowed), - leq(applyTF("cutFormula", ff.cutPriority), applyTF(subFor, ff.cutPriority))); - - final Feature noBetterCut = - sum(subFor, AllowedCutPositionsGenerator.INSTANCE, compareCutAllowed); - - bindRuleSet(d, "cut_direct", add(allowSplitting(FocusFormulaProjection.INSTANCE), - ifZero(notBelowQuantifier(), noBetterCut))); - } - - // ////////////////////////////////////////////////////////////////////////// - // ////////////////////////////////////////////////////////////////////////// - // - // Application of equations - // - // ////////////////////////////////////////////////////////////////////////// - // ////////////////////////////////////////////////////////////////////////// - - private void setupApplyEq(RuleSetDispatchFeature d, IntegerLDT numbers) { - final TermBuffer equation = new TermBuffer(); - final TermBuffer left = new TermBuffer(); - final TermBuffer right = new TermBuffer(); - - // applying equations less deep/less leftish in terms/formulas is - // preferred - // this is important for reducing polynomials (start with the biggest - // summands) - bindRuleSet(d, "apply_equations", - SumFeature.createSum(ifZero(applyTF(FocusProjection.create(0), tf.intF), - add(applyTF(FocusProjection.create(0), tf.monomial), - ScaleFeature.createScaled(FindRightishFeature.create(numbers), 5.0))), - ifZero(MatchedAssumesFeature.INSTANCE, - add(CheckApplyEqFeature.INSTANCE, let(equation, AssumptionProjection.create(0), - add(not(applyTF(equation, ff.update)), - // there might be updates in - // front of the assumption - // formula; in this case we wait - // until the updates have - // been applied - let(left, sub(equation, 0), - let(right, sub(equation, 1), ifZero(applyTF(left, tf.intF), - add(applyTF(left, tf.nonNegOrNonCoeffMonomial), - applyTF(right, tf.polynomial), - MonomialsSmallerThanFeature.create(right, left, numbers)), - TermSmallerThanFeature.create(right, left)))))))), - longConst(-4000))); - } - - // ////////////////////////////////////////////////////////////////////////// - // ////////////////////////////////////////////////////////////////////////// - // - // Normalisation of formulas; this is mostly a pre-processing step for - // handling quantified formulas - // - // ////////////////////////////////////////////////////////////////////////// - // ////////////////////////////////////////////////////////////////////////// - - private void setupFormulaNormalisation(RuleSetDispatchFeature d, IntegerLDT numbers, - LocSetLDT locSetLDT) { - - bindRuleSet(d, "negationNormalForm", add(BelowBinderFeature.getInstance(), - longConst(-500), - ScaleFeature.createScaled(FindDepthFeature.getInstance(), 10.0))); - - bindRuleSet(d, "moveQuantToLeft", - add(quantifiersMightSplit() ? longConst(0) - : applyTF(FocusFormulaProjection.INSTANCE, ff.quantifiedPureLitConjDisj), - longConst(-550))); - - bindRuleSet(d, "conjNormalForm", - ifZero( - add(or(FocusInAntecFeature.getInstance(), notBelowQuantifier()), - NotInScopeOfModalityFeature.INSTANCE), - add(longConst(-150), - ScaleFeature.createScaled(FindDepthFeature.getInstance(), 20)), - inftyConst())); - - bindRuleSet(d, "setEqualityBlastingRight", longConst(-100)); - - bindRuleSet(d, "cnf_setComm", - add(SetsSmallerThanFeature.create(instOf("commRight"), instOf("commLeft"), locSetLDT), - NotInScopeOfModalityFeature.INSTANCE, longConst(-800))); - - bindRuleSet(d, "elimQuantifier", -1000); - bindRuleSet(d, "elimQuantifierWithCast", 50); - - final TermBuffer left = new TermBuffer(); - final TermBuffer right = new TermBuffer(); - bindRuleSet(d, "apply_equations_andOr", - add(let(left, instOf("applyEqLeft"), - let(right, instOf("applyEqRight"), ifZero(applyTF(left, tf.intF), - add(applyTF(left, tf.nonNegOrNonCoeffMonomial), applyTF(right, tf.polynomial), - MonomialsSmallerThanFeature.create(right, left, numbers)), - TermSmallerThanFeature.create(right, left)))), - longConst(-150))); - - bindRuleSet(d, "distrQuantifier", - add(or( - applyTF(FocusProjection.INSTANCE, - add(ff.quantifiedClauseSet, not(opSub(Quantifier.ALL, ff.orF)), - EliminableQuantifierTF.INSTANCE)), - SumFeature.createSum(onlyInScopeOfQuantifiers(), - SplittableQuantifiedFormulaFeature.INSTANCE, - ifZero(FocusInAntecFeature.getInstance(), - applyTF(FocusProjection.INSTANCE, sub(ff.andF)), - applyTF(FocusProjection.INSTANCE, sub(ff.orF))))), - longConst(-300))); - - bindRuleSet(d, "swapQuantifiers", - add(applyTF(FocusProjection.INSTANCE, add(ff.quantifiedClauseSet, - EliminableQuantifierTF.INSTANCE, sub(not(EliminableQuantifierTF.INSTANCE)))), - longConst(-300))); - - // category "conjunctive normal form" - - bindRuleSet(d, "cnf_orComm", - SumFeature.createSum(applyTF("commRight", ff.clause), - applyTFNonStrict("commResidue", ff.clauseSet), - or(applyTF("commLeft", ff.andF), - add(applyTF("commLeft", ff.literal), - literalsSmallerThan("commRight", "commLeft", numbers))), - longConst(-100))); - - bindRuleSet(d, "cnf_orAssoc", - SumFeature.createSum(applyTF("assoc0", ff.clause), - applyTF("assoc1", ff.clause), applyTF("assoc2", ff.literal), longConst(-80))); - - bindRuleSet(d, "cnf_andComm", - SumFeature.createSum(applyTF("commLeft", ff.clause), - applyTF("commRight", ff.clauseSet), applyTFNonStrict("commResidue", ff.clauseSet), - // at least one of the subformulas has to be a literal; - // otherwise, sorting is not likely to have any big effect - ifZero( - add(applyTF("commLeft", not(ff.literal)), - applyTF("commRight", rec(ff.andF, not(ff.literal)))), - longConst(100), longConst(-60)), - clausesSmallerThan("commRight", "commLeft", numbers))); - - bindRuleSet(d, "cnf_andAssoc", - SumFeature.createSum(applyTF("assoc0", ff.clauseSet), - applyTF("assoc1", ff.clauseSet), applyTF("assoc2", ff.clause), longConst(-10))); - - bindRuleSet(d, "cnf_dist", - SumFeature.createSum(applyTF("distRight0", ff.clauseSet), - applyTF("distRight1", ff.clauseSet), ifZero(applyTF("distLeft", ff.clause), - longConst(-15), applyTF("distLeft", ff.clauseSet)), - longConst(-35))); - - final TermBuffer superFor = new TermBuffer(); - final Feature onlyBelowQuanAndOr = - sum(superFor, SuperTermGenerator.upwards(any(), getServices()), - applyTF(superFor, or(ff.quantifiedFor, ff.andF, ff.orF))); - - final Feature belowUnskolemisableQuantifier = - ifZero(FocusInAntecFeature.getInstance(), - not(sum(superFor, SuperTermGenerator.upwards(any(), getServices()), - not(applyTF(superFor, op(Quantifier.ALL))))), - not(sum(superFor, SuperTermGenerator.upwards(any(), getServices()), - not(applyTF(superFor, op(Quantifier.EX)))))); - - bindRuleSet(d, "cnf_expandIfThenElse", add( - isBelow(OperatorClassTF.create(Quantifier.class)), - onlyBelowQuanAndOr, belowUnskolemisableQuantifier)); - - final Feature pullOutQuantifierAllowed = - add(isBelow(OperatorClassTF.create(Quantifier.class)), onlyBelowQuanAndOr, applyTF( - FocusProjection.create(0), sub(ff.quantifiedClauseSet, ff.quantifiedClauseSet))); - - bindRuleSet(d, "pullOutQuantifierUnifying", -20); - - bindRuleSet(d, "pullOutQuantifierAll", add(pullOutQuantifierAllowed, - ifZero(FocusInAntecFeature.getInstance(), longConst(-20), longConst(-40)))); - - bindRuleSet(d, "pullOutQuantifierEx", add(pullOutQuantifierAllowed, - ifZero(FocusInAntecFeature.getInstance(), longConst(-40), longConst(-20)))); - } - - private Feature clausesSmallerThan(String smaller, String bigger, IntegerLDT numbers) { - return ClausesSmallerThanFeature.create(instOf(smaller), instOf(bigger), numbers); - } - - // ////////////////////////////////////////////////////////////////////////// - // ////////////////////////////////////////////////////////////////////////// - // - // Heuristic instantiation of quantified formulas - // - // ////////////////////////////////////////////////////////////////////////// - // ////////////////////////////////////////////////////////////////////////// - - private void setupQuantifierInstantiation(RuleSetDispatchFeature d) { - if (quantifierInstantiatedEnabled()) { - final TermBuffer varInst = new TermBuffer(); - final Feature branchPrediction = InstantiationCostScalerFeature - .create(InstantiationCost.create(varInst), allowQuantifierSplitting()); - - bindRuleSet(d, "gamma", - SumFeature.createSum(FocusInAntecFeature.getInstance(), - applyTF(FocusProjection.create(0), - add(ff.quantifiedClauseSet, - instQuantifiersWithQueries() ? longTermConst(0) - : ff.notContainsExecutable)), - forEach(varInst, HeuristicInstantiation.INSTANCE, - add(instantiate("t", varInst), branchPrediction, longConst(10))))); - final TermBuffer splitInst = new TermBuffer(); - - bindRuleSet(d, "triggered", - SumFeature.createSum(forEach(splitInst, TriggeredInstantiations.create(true), - add(instantiateTriggeredVariable(splitInst), longConst(500))), - longConst(1500))); - - } else { - bindRuleSet(d, "gamma", inftyConst()); - bindRuleSet(d, "triggered", inftyConst()); - } - } - - private void setupQuantifierInstantiationApproval(RuleSetDispatchFeature d) { - if (quantifierInstantiatedEnabled()) { - final TermBuffer varInst = new TermBuffer(); - - bindRuleSet(d, "gamma", add(isInstantiated("t"), - not(sum(varInst, HeuristicInstantiation.INSTANCE, not(eq(instOf("t"), varInst)))), - InstantiationCostScalerFeature.create(InstantiationCost.create(instOf("t")), - longConst(0)))); - - final TermBuffer splitInst = new TermBuffer(); - bindRuleSet(d, "triggered", - add(isTriggerVariableInstantiated(), - not(sum(splitInst, TriggeredInstantiations.create(false), - not(eq(instOfTriggerVariable(), splitInst)))))); - } else { - bindRuleSet(d, "gamma", inftyConst()); - bindRuleSet(d, "triggered", inftyConst()); - } - } - - // ////////////////////////////////////////////////////////////////////////// - // ////////////////////////////////////////////////////////////////////////// - // - // Handling of arithmetic - // - // ////////////////////////////////////////////////////////////////////////// - // ////////////////////////////////////////////////////////////////////////// - - private void setupArithPrimaryCategories(RuleSetDispatchFeature d) { - // Gaussian elimination + Euclidian algorithm for linear equations; - // Buchberger's algorithmus for handling polynomial equations over - // the integers - - bindRuleSet(d, "polySimp_expand", -4500); - bindRuleSet(d, "polySimp_directEquations", -3000); - bindRuleSet(d, "polySimp_pullOutGcd", -2250); - bindRuleSet(d, "polySimp_leftNonUnit", -2000); - bindRuleSet(d, "polySimp_saturate", 0); - - // Omega test for handling linear arithmetic and inequalities over the - // integers; cross-multiplication + case distinctions for nonlinear - // inequalities - - bindRuleSet(d, "inEqSimp_expand", -4400); - bindRuleSet(d, "inEqSimp_directInEquations", -2900); - bindRuleSet(d, "inEqSimp_propagation", -2400); - bindRuleSet(d, "inEqSimp_pullOutGcd", -2150); - bindRuleSet(d, "inEqSimp_saturate", -1900); - bindRuleSet(d, "inEqSimp_forNormalisation", -1100); - bindRuleSet(d, "inEqSimp_special_nonLin", -1400); - - if (arithNonLinInferences()) { - bindRuleSet(d, "inEqSimp_nonLin", IN_EQ_SIMP_NON_LIN_COST); - } else { - bindRuleSet(d, "inEqSimp_nonLin", inftyConst()); - } - // polynomial division, simplification of fractions and mods - bindRuleSet(d, "polyDivision", POLY_DIVISION_COST); - - } - - private void setupPolySimp(RuleSetDispatchFeature d, IntegerLDT numbers) { - - // category "expansion" (normalising polynomial terms) - - bindRuleSet(d, "polySimp_elimSubNeg", longConst(-120)); - - bindRuleSet(d, "polySimp_homo", - add(applyTF("homoRight", add(not(tf.zeroLiteral), tf.polynomial)), - or(applyTF("homoLeft", or(tf.addF, tf.negMonomial)), - not(monSmallerThan("homoRight", "homoLeft", numbers))), - longConst(-120))); - - bindRuleSet(d, "polySimp_pullOutFactor", add(applyTFNonStrict("pullOutLeft", tf.literal), - applyTFNonStrict("pullOutRight", tf.literal), longConst(-120))); - - bindRuleSet(d, "polySimp_elimOneLeft", -120); - - bindRuleSet(d, "polySimp_elimOneRight", -120); - - bindRuleSet(d, "polySimp_mulOrder", add(applyTF("commRight", tf.monomial), or( - applyTF("commLeft", tf.addF), - add(applyTF("commLeft", tf.atom), atomSmallerThan("commLeft", "commRight", numbers))), - longConst(-100))); - - bindRuleSet(d, "polySimp_mulAssoc", - SumFeature.createSum(applyTF("mulAssocMono0", tf.monomial), - applyTF("mulAssocMono1", tf.monomial), applyTF("mulAssocAtom", tf.atom), - longConst(-80))); - - bindRuleSet(d, "polySimp_addOrder", - SumFeature.createSum(applyTF("commLeft", tf.monomial), - applyTF("commRight", tf.polynomial), - monSmallerThan("commRight", "commLeft", numbers), longConst(-60))); - - bindRuleSet(d, "polySimp_addAssoc", - SumFeature.createSum(applyTF("addAssocPoly0", tf.polynomial), - applyTF("addAssocPoly1", tf.polynomial), applyTF("addAssocMono", tf.monomial), - longConst(-10))); - - bindRuleSet(d, "polySimp_dist", - SumFeature.createSum(applyTF("distSummand0", tf.polynomial), - applyTF("distSummand1", tf.polynomial), - ifZero(applyTF("distCoeff", tf.monomial), longConst(-15), - applyTF("distCoeff", tf.polynomial)), - applyTF("distSummand0", tf.polynomial), - - applyTF("distSummand1", tf.polynomial), longConst(-35))); - - // category "direct equations" - - bindRuleSet(d, "polySimp_balance", - SumFeature - .createSum(applyTF("sepResidue", tf.polynomial), - ifZero(isInstantiated("sepPosMono"), - add(applyTF("sepPosMono", tf.nonNegMonomial), - monSmallerThan("sepResidue", "sepPosMono", numbers))), - ifZero(isInstantiated("sepNegMono"), - add(applyTF("sepNegMono", tf.negMonomial), - monSmallerThan("sepResidue", "sepNegMono", numbers))), - longConst(-30))); - - bindRuleSet(d, "polySimp_normalise", add(applyTF("invertRight", tf.zeroLiteral), - applyTF("invertLeft", tf.negMonomial), longConst(-30))); - - // application of equations: some specialised rules that handle - // monomials and their coefficients properly - - final TermBuffer eqLeft = new TermBuffer(); - final TermBuffer focus = new TermBuffer(); - - final TermFeature atLeastTwoLCEquation = - opSub(Equality.EQUALS, opSub(tf.mul, tf.atom, tf.atLeastTwoLiteral), tf.intF); - - final Feature validEqApplication = add(not(eq(eqLeft, focus)), - // otherwise, the normal equation rules can and should - // be used - ifZero(applyTF(AssumptionProjection.create(0), atLeastTwoLCEquation), - add(FocusInAntecFeature.getInstance(), - applyTF(FocusFormulaProjection.INSTANCE, atLeastTwoLCEquation))), - ReducibleMonomialsFeature.createReducible(focus, eqLeft)); - - final Feature eqMonomialFeature = add(not(directlyBelowSymbolAtIndex(tf.mul, -1)), - ifZero(MatchedAssumesFeature.INSTANCE, let(focus, FocusProjection.create(0), - let(eqLeft, sub(AssumptionProjection.create(0), 0), validEqApplication)))); - - bindRuleSet(d, "polySimp_applyEq", add(eqMonomialFeature, longConst(1))); - - bindRuleSet(d, "polySimp_applyEqRigid", add(eqMonomialFeature, longConst(2))); - - // - bindRuleSet(d, "defOps_expandModulo", - add(NonDuplicateAppModPositionFeature.INSTANCE, longConst(-600))); - - // category "saturate" - - bindRuleSet(d, "polySimp_critPair", - ifZero(MatchedAssumesFeature.INSTANCE, - add(monSmallerThan("cpLeft1", "cpLeft2", numbers), - not(TrivialMonomialLCRFeature.create(instOf("cpLeft1"), instOf("cpLeft2")))))); - } - - // For taclets that need instantiation, but where the instantiation is - // deterministic and does not have to be repeated at a later point, we - // setup the same feature terms as in the instantiation method. The - // definitions in setupInstantiationWithoutRetry should - // give cost infinity to those incomplete rule applications that will - // never be instantiated (so that these applications can be removed from - // the queue and do not have to be considered again). - private void setupPolySimpInstantiationWithoutRetry(RuleSetDispatchFeature d) { - final IntegerLDT numbers = getServices().getTypeConverter().getIntegerLDT(); - - // category "direct equations" - - setupPullOutGcd(d, "polySimp_pullOutGcd", false); - - // category "polynomial division" - - setupDivModDivision(d); - - // category "handling of equations with non-unit-coefficients on - // left-hand side" - - bindRuleSet(d, "polySimp_newSym", - ifZero(not(isInstantiated("newSymDef")), SumFeature.createSum( - applyTF("newSymLeft", tf.atom), applyTF("newSymLeftCoeff", tf.atLeastTwoLiteral), - applyTF("newSymRight", tf.polynomial), instantiate("newSymDef", - MonomialColumnOp.create(instOf("newSymLeftCoeff"), instOf("newSymRight")))))); - - final TermBuffer divisor = new TermBuffer(); - final TermBuffer dividend = new TermBuffer(); - - bindRuleSet(d, "polySimp_applyEqPseudo", - add(applyTF("aePseudoTargetLeft", tf.monomial), - applyTF("aePseudoTargetRight", tf.polynomial), - ifZero(MatchedAssumesFeature.INSTANCE, - SumFeature.createSum(DiffFindAndIfFeature.INSTANCE, - applyTF("aePseudoLeft", add(tf.nonCoeffMonomial, not(tf.atom))), - applyTF("aePseudoLeftCoeff", tf.atLeastTwoLiteral), - applyTF("aePseudoRight", tf.polynomial), - MonomialsSmallerThanFeature.create(instOf("aePseudoRight"), - instOf("aePseudoLeft"), numbers), - let(divisor, instOf("aePseudoLeft"), - let(dividend, instOf("aePseudoTargetLeft"), - add(ReducibleMonomialsFeature.createReducible(dividend, divisor), - instantiate("aePseudoTargetFactor", - ReduceMonomialsProjection.create(dividend, divisor))))))))); - } - - private void setupNewSymApproval(RuleSetDispatchFeature d, IntegerLDT numbers) { - final TermBuffer antecFor = new TermBuffer(); - final Feature columnOpEq = applyTF(antecFor, - opSub(tf.eq, opSub(tf.mul, tf.atom, tf.atLeastTwoLiteral), tf.polynomial)); - final Feature biggerLeftSide = - MonomialsSmallerThanFeature.create(instOf("newSymLeft"), - subAt(antecFor, PosInTerm.getTopLevel().down(0).down(0)), numbers); - bindRuleSet(d, "polySimp_newSym", add(isInstantiated("newSymDef"), sum(antecFor, - SequentFormulasGenerator.antecedent(), not(add(columnOpEq, biggerLeftSide))))); - } - - private void setupPullOutGcd(RuleSetDispatchFeature d, String ruleSet, boolean roundingUp) { - final TermBuffer gcd = new TermBuffer(); - - final Feature instantiateDivs; - if (roundingUp) { - instantiateDivs = add( - instantiate("elimGcdLeftDiv", - DividePolynomialsProjection.createRoundingUp(gcd, instOf("elimGcdLeft"))), - instantiate("elimGcdRightDiv", - DividePolynomialsProjection.createRoundingUp(gcd, instOf("elimGcdRight")))); - } else { - instantiateDivs = add( - instantiate("elimGcdLeftDiv", - DividePolynomialsProjection.createRoundingDown(gcd, instOf("elimGcdLeft"))), - instantiate("elimGcdRightDiv", - DividePolynomialsProjection.createRoundingDown(gcd, instOf("elimGcdRight")))); - } - bindRuleSet(d, ruleSet, - add(applyTF("elimGcdLeft", tf.nonNegMonomial), applyTF("elimGcdRight", tf.polynomial), - let(gcd, CoeffGcdProjection.create(instOf("elimGcdLeft"), instOf("elimGcdRight")), - add(applyTF(gcd, tf.atLeastTwoLiteral), instantiate("elimGcd", gcd), - instantiateDivs)))); - } - - private void setupInEqSimp(RuleSetDispatchFeature d, IntegerLDT numbers) { - - // category "expansion" (normalising inequations) - - bindRuleSet(d, "inEqSimp_moveLeft", -90); - - bindRuleSet(d, "inEqSimp_makeNonStrict", -80); - - bindRuleSet(d, "inEqSimp_commute", - SumFeature.createSum(applyTF("commRight", tf.monomial), - applyTF("commLeft", tf.polynomial), - monSmallerThan("commLeft", "commRight", numbers), longConst(-40))); - - // this is copied from "polySimp_homo" - bindRuleSet(d, "inEqSimp_homo", - add(applyTF("homoRight", add(not(tf.zeroLiteral), tf.polynomial)), - or(applyTF("homoLeft", or(tf.addF, tf.negMonomial)), - not(monSmallerThan("homoRight", "homoLeft", numbers))))); - - // category "direct inequations" - - // this is copied from "polySimp_balance" - bindRuleSet(d, "inEqSimp_balance", - add(applyTF("sepResidue", tf.polynomial), - ifZero(isInstantiated("sepPosMono"), - add(applyTF("sepPosMono", tf.nonNegMonomial), - monSmallerThan("sepResidue", "sepPosMono", numbers))), - ifZero(isInstantiated("sepNegMono"), add(applyTF("sepNegMono", tf.negMonomial), - monSmallerThan("sepResidue", "sepNegMono", numbers))))); - - // this is copied from "polySimp_normalise" - bindRuleSet(d, "inEqSimp_normalise", - add(applyTF("invertRight", tf.zeroLiteral), applyTF("invertLeft", tf.negMonomial))); - - // category "saturate" - - bindRuleSet(d, "inEqSimp_antiSymm", longConst(-20)); - - bindRuleSet(d, "inEqSimp_exactShadow", - SumFeature.createSum(applyTF("esLeft", tf.nonCoeffMonomial), - applyTFNonStrict("esCoeff2", tf.nonNegLiteral), applyTF("esRight2", tf.polynomial), - ifZero(MatchedAssumesFeature.INSTANCE, - SumFeature.createSum(applyTFNonStrict("esCoeff1", tf.nonNegLiteral), - applyTF("esRight1", tf.polynomial), - not(PolynomialValuesCmpFeature.leq(instOf("esRight2"), instOf("esRight1"), - instOfNonStrict("esCoeff1"), instOfNonStrict("esCoeff2"))))))); - - // category "propagation" - - bindRuleSet(d, "inEqSimp_contradInEqs", - add(applyTF("contradLeft", tf.monomial), - ifZero(MatchedAssumesFeature.INSTANCE, - SumFeature.createSum(DiffFindAndIfFeature.INSTANCE, - applyTF("contradRightSmaller", tf.polynomial), - applyTF("contradRightBigger", tf.polynomial), - applyTFNonStrict("contradCoeffSmaller", tf.posLiteral), - applyTFNonStrict("contradCoeffBigger", tf.posLiteral), - PolynomialValuesCmpFeature.lt(instOf("contradRightSmaller"), - instOf("contradRightBigger"), instOfNonStrict("contradCoeffBigger"), - instOfNonStrict("contradCoeffSmaller")))))); - - bindRuleSet(d, "inEqSimp_contradEqs", - add(applyTF("contradLeft", tf.monomial), - ifZero(MatchedAssumesFeature.INSTANCE, - SumFeature.createSum(applyTF("contradRightSmaller", tf.polynomial), - applyTF("contradRightBigger", tf.polynomial), PolynomialValuesCmpFeature - .lt(instOf("contradRightSmaller"), instOf("contradRightBigger")))), - longConst(-60))); - - bindRuleSet(d, "inEqSimp_strengthen", longConst(-30)); - - bindRuleSet(d, "inEqSimp_subsumption", - add(applyTF("subsumLeft", tf.monomial), - ifZero(MatchedAssumesFeature.INSTANCE, - SumFeature.createSum(DiffFindAndIfFeature.INSTANCE, - applyTF("subsumRightSmaller", tf.polynomial), - applyTF("subsumRightBigger", tf.polynomial), - applyTFNonStrict("subsumCoeffSmaller", tf.posLiteral), - applyTFNonStrict("subsumCoeffBigger", tf.posLiteral), - PolynomialValuesCmpFeature.leq(instOf("subsumRightSmaller"), - instOf("subsumRightBigger"), instOfNonStrict("subsumCoeffBigger"), - instOfNonStrict("subsumCoeffSmaller")))))); - - // category "handling of non-linear inequations" - - if (arithNonLinInferences()) { - setupMultiplyInequations(d, longConst(100)); - - bindRuleSet(d, "inEqSimp_split_eq", add(TopLevelFindFeature.SUCC, longConst(-100))); - - bindRuleSet(d, "inEqSimp_signCases", not(isInstantiated("signCasesLeft"))); - } - - // category "normalisation of formulas" - // (e.g., quantified formulas, where the normal sequent calculus - // does not do any normalisation) - - bindRuleSet(d, "inEqSimp_and_contradInEqs", - SumFeature.createSum(applyTF("contradLeft", tf.monomial), - applyTF("contradRightSmaller", tf.polynomial), - applyTF("contradRightBigger", tf.polynomial), PolynomialValuesCmpFeature - .lt(instOf("contradRightSmaller"), instOf("contradRightBigger")))); - - bindRuleSet(d, "inEqSimp_andOr_subsumption", - SumFeature.createSum(applyTF("subsumLeft", tf.monomial), - applyTF("subsumRightSmaller", tf.polynomial), - applyTF("subsumRightBigger", tf.polynomial), PolynomialValuesCmpFeature - .leq(instOf("subsumRightSmaller"), instOf("subsumRightBigger")))); - - bindRuleSet(d, "inEqSimp_and_subsumptionEq", - SumFeature.createSum(applyTF("subsumLeft", tf.monomial), - applyTF("subsumRightSmaller", tf.polynomial), - applyTF("subsumRightBigger", tf.polynomial), PolynomialValuesCmpFeature - .lt(instOf("subsumRightSmaller"), instOf("subsumRightBigger")))); - - final Term tOne = getServices().getTermBuilder().zTerm("1"); - final TermBuffer one = new TermBuffer() { - @Override - public void setContent(Term term, MutableState mState) {} - - @Override - public @NonNull Term getContent(MutableState mState) { - return tOne; - } - - @Override - public @NonNull Term toTerm(RuleApp app, PosInOccurrence pos, - Goal goal, MutableState mState) { - return tOne; - } - }; - - final JTerm tTwo = getServices().getTermBuilder().zTerm("2"); - final TermBuffer two = new TermBuffer() { - @Override - public void setContent(Term term, MutableState mState) {} - - @Override - public @NonNull Term getContent(MutableState mState) { - return tTwo; - } - - @Override - public @NonNull Term toTerm(RuleApp app, PosInOccurrence pos, - Goal goal, MutableState mState) { - return tTwo; - } - }; - - bindRuleSet(d, "inEqSimp_or_tautInEqs", - SumFeature.createSum(applyTF("tautLeft", tf.monomial), - applyTF("tautRightSmaller", tf.polynomial), - applyTF("tautRightBigger", tf.polynomial), - PolynomialValuesCmpFeature.leq(instOf("tautRightSmaller"), - opTerm(numbers.getAdd(), one, instOf("tautRightBigger"))))); - - bindRuleSet(d, "inEqSimp_or_weaken", - SumFeature.createSum(applyTF("weakenLeft", tf.monomial), - applyTF("weakenRightSmaller", tf.polynomial), - applyTF("weakenRightBigger", tf.polynomial), - PolynomialValuesCmpFeature.eq( - opTerm(numbers.getAdd(), one, instOf("weakenRightSmaller")), - instOf("weakenRightBigger")))); - - bindRuleSet(d, "inEqSimp_or_antiSymm", - SumFeature.createSum(applyTF("antiSymmLeft", tf.monomial), - applyTF("antiSymmRightSmaller", tf.polynomial), - applyTF("antiSymmRightBigger", tf.polynomial), - PolynomialValuesCmpFeature.eq( - opTerm(numbers.getAdd(), two, instOf("antiSymmRightSmaller")), - instOf("antiSymmRightBigger")))); - - } - - private void setupMultiplyInequations(RuleSetDispatchFeature d, Feature notAllowedF) { - final TermBuffer intRel = new TermBuffer(); - - /* - * final Feature partiallyBounded = not ( sum ( intRel, SequentFormulasGenerator.sequent (), - * not ( add ( applyTF ( intRel, tf.intRelation ), InEquationMultFeature .partiallyBounded ( - * instOf ( "multLeft" ), instOf ( "multFacLeft" ), sub ( intRel, 0 ) ) ) ) ) ); - */ - - final Feature totallyBounded = not(sum(intRel, SequentFormulasGenerator.sequent(), - not(add(applyTF(intRel, tf.intRelation), InEquationMultFeature - .totallyBounded(instOf("multLeft"), instOf("multFacLeft"), sub(intRel, 0)))))); - - final Feature exactlyBounded = not(sum(intRel, SequentFormulasGenerator.sequent(), - not(add(applyTF(intRel, tf.intRelation), InEquationMultFeature - .exactlyBounded(instOf("multLeft"), instOf("multFacLeft"), sub(intRel, 0)))))); - - // this is a bit hackish - // - // really, one would need a possibility to express that the cost - // computation for the rule application should be post-poned (and - // repeated at a later point) if the product of the left sides does not - // have any similarity with existing left sides - // (AllowInEquationMultiplication returns false). We - // simulate this by returning non-infinite costs here, but by declining - // the rule application in isApprovedApp). This is not - // perfect, because it is not possible to distinguish between the - // re-cost-computation delay and the normal costs for a rule application - bindRuleSet(d, "inEqSimp_nonLin_multiply", add(applyTF("multLeft", tf.nonNegMonomial), - applyTF("multRight", tf.polynomial), - ifZero(MatchedAssumesFeature.INSTANCE, - SumFeature.createSum(applyTF("multFacLeft", tf.nonNegMonomial), - ifZero(applyTF("multRight", tf.literal), longConst(-100)), - ifZero(applyTF("multFacRight", tf.literal), longConst(-100), - applyTF("multFacRight", tf.polynomial)), - /* - * ifZero ( applyTF ( "multRight", tf.literal ), longConst ( -100 ), applyTF ( - * "multRight", tf.polynomial ) ), ifZero ( applyTF ( "multFacRight", tf.literal - * ), longConst ( -100 ), applyTF ( "multFacRight", tf.polynomial ) ), - */ - not(TermSmallerThanFeature.create(FocusProjection.create(0), - AssumptionProjection.create(0))), - ifZero(exactlyBounded, longConst(0), - ifZero(totallyBounded, longConst(100), notAllowedF)) - /* - * ifZero ( partiallyBounded, longConst ( 400 ), notAllowedF ) ) ), - */ - /* - * applyTF ( "multLeft", rec ( tf.mulF, longTermConst ( 20 ) ) ), applyTF ( - * "multFacLeft", rec ( tf.mulF, longTermConst ( 20 ) ) ), applyTF ( "multRight", - * rec ( tf.addF, longTermConst ( 4 ) ) ), applyTF ( "multFacRight", rec ( tf.addF, - * longTermConst ( 4 ) ) ), - */ - ), notAllowedF))); - } - - private void setupInEqSimpInstantiation(RuleSetDispatchFeature d) { - // category "handling of non-linear inequations" - - setupSquaresAreNonNegative(d); - - if (arithNonLinInferences()) { - setupInEqCaseDistinctions(d); - } - } - - // For taclets that need instantiation, but where the instantiation is - // deterministic and does not have to be repeated at a later point, we - // setup the same feature terms as in the instantiation method. The - // definitions in setupInstantiationWithoutRetry should - // give cost infinity to those incomplete rule applications that will - // never be instantiated (so that these applications can be removed from - // the queue and do not have to be considered again). - private void setupInEqSimpInstantiationWithoutRetry(RuleSetDispatchFeature d) { - // category "direct inequations" - - setupPullOutGcd(d, "inEqSimp_pullOutGcd_leq", false); - setupPullOutGcd(d, "inEqSimp_pullOutGcd_geq", true); - - // more efficient (but not confluent) versions for the antecedent - bindRuleSet(d, "inEqSimp_pullOutGcd_antec", -10); - - // category "handling of non-linear inequations" - - final TermBuffer divisor = new TermBuffer(); - final TermBuffer dividend = new TermBuffer(); - - bindRuleSet(d, "inEqSimp_nonLin_divide", SumFeature.createSum( - applyTF("divProd", tf.nonCoeffMonomial), - applyTFNonStrict("divProdBoundNonPos", tf.nonPosLiteral), - applyTFNonStrict("divProdBoundNonNeg", tf.nonNegLiteral), - ifZero(MatchedAssumesFeature.INSTANCE, - let(divisor, instOf("divX"), let(dividend, instOf("divProd"), - SumFeature.createSum(applyTF(divisor, tf.nonCoeffMonomial), - not(eq(dividend, divisor)), applyTFNonStrict("divXBoundPos", tf.posLiteral), - applyTFNonStrict("divXBoundNeg", tf.negLiteral), - ReducibleMonomialsFeature.createReducible(dividend, divisor), instantiate( - "divY", ReduceMonomialsProjection.create(dividend, divisor)))))))); - - setupNonLinTermIsPosNeg(d, "inEqSimp_nonLin_pos", true); - setupNonLinTermIsPosNeg(d, "inEqSimp_nonLin_neg", false); - } - - private void setupNonLinTermIsPosNeg(RuleSetDispatchFeature d, String ruleSet, boolean pos) { - final TermBuffer divisor = new TermBuffer(); - final TermBuffer dividend = new TermBuffer(); - final TermBuffer quotient = new TermBuffer(); - final TermBuffer antecFor = new TermBuffer(); - - bindRuleSet(d, ruleSet, - SumFeature - .createSum(applyTF("divProd", tf.nonCoeffMonomial), - applyTFNonStrict("divProdBoundPos", tf.posLiteral), - applyTFNonStrict("divProdBoundNeg", tf.negLiteral), - ifZero(MatchedAssumesFeature.INSTANCE, - let(divisor, instOf("divX"), let(dividend, instOf("divProd"), - SumFeature.createSum(applyTF(divisor, tf.nonCoeffMonomial), - not(applyTF(dividend, eq(divisor))), - applyTFNonStrict("divXBoundNonPos", tf.nonPosLiteral), - applyTFNonStrict("divXBoundNonNeg", tf.nonNegLiteral), - ReducibleMonomialsFeature.createReducible(dividend, divisor), - let(quotient, - ReduceMonomialsProjection.create(dividend, divisor), add( - sum(antecFor, SequentFormulasGenerator.antecedent(), - not(applyTF(antecFor, - pos ? opSub(tf.geq, eq(quotient), tf.posLiteral) - : opSub(tf.leq, eq(quotient), - tf.negLiteral)))), - instantiate("divY", quotient))))))))); - } - - private void setupSquaresAreNonNegative(RuleSetDispatchFeature d) { - final TermBuffer intRel = new TermBuffer(); - final TermBuffer product = new TermBuffer(); - final TermBuffer factor = new TermBuffer(); - - final Feature productContainsSquare = - applyTF(sub(product, 0), or(eq(factor), opSub(tf.mul, any(), eq(factor)))); - final Feature productIsProduct = applyTF(product, opSub(tf.mul, any(), not(tf.mulF))); - - bindRuleSet(d, "inEqSimp_nonNegSquares", - forEach(intRel, SequentFormulasGenerator.sequent(), - ifZero(applyTF(intRel, tf.intRelation), - forEach(product, SubtermGenerator.leftTraverse(sub(intRel, 0), tf.mulF), - ifZero(productIsProduct, let(factor, sub(product, 1), - ifZero(productContainsSquare, instantiate("squareFac", factor)))))))); - } - - private void setupInEqCaseDistinctions(RuleSetDispatchFeature d) { - final TermBuffer intRel = new TermBuffer(); - final TermBuffer atom = new TermBuffer(); - final TermBuffer rootInf = new TermBuffer(); - - final Feature posNegSplitting = forEach(intRel, SequentFormulasGenerator.antecedent(), - add(applyTF(intRel, tf.intRelation), - forEach(atom, SubtermGenerator.leftTraverse(sub(intRel, 0), tf.mulF), - SumFeature.createSum(applyTF(atom, add(tf.atom, not(tf.literal))), - allowPosNegCaseDistinction(atom), instantiate("signCasesLeft", atom), - longConst(IN_EQ_SIMP_NON_LIN_COST + 200) - // , - // applyTF ( atom, rec ( any (), - // longTermConst ( 5 ) ) ) - )))); - - bindRuleSet(d, "inEqSimp_signCases", posNegSplitting); - - final Feature strengthening = forEach(intRel, SequentFormulasGenerator.antecedent(), - SumFeature.createSum( - applyTF(intRel, add(or(tf.geqF, tf.leqF), sub(tf.atom, tf.literal))), - instantiate("cutFormula", opTerm(tf.eq, sub(intRel, 0), sub(intRel, 1))), - longConst(IN_EQ_SIMP_NON_LIN_COST + 300) - // , - // applyTF ( sub ( intRel, 0 ), - // rec ( any (), longTermConst ( 5 ) ) ) - )); - - final Feature rootInferences = forEach(intRel, SequentFormulasGenerator.antecedent(), - add(isRootInferenceProducer(intRel), - forEach(rootInf, RootsGenerator.create(intRel, getServices()), - add(instantiate("cutFormula", rootInf), - ifZero(applyTF(rootInf, op(Junctor.OR)), longConst(50)), - ifZero(applyTF(rootInf, op(Junctor.AND)), longConst(20)))), - longConst(IN_EQ_SIMP_NON_LIN_COST))); - - // noinspection unchecked - bindRuleSet(d, "cut", oneOf(new Feature[] { strengthening, rootInferences })); - } - - private Feature isRootInferenceProducer(TermBuffer intRel) { - return applyTF(intRel, add(tf.intRelation, sub(tf.nonCoeffMonomial, tf.literal))); - } - - private Feature allowPosNegCaseDistinction(TermBuffer atom) { - final TermBuffer antecFor = new TermBuffer(); - final TermFeature eqAtom = eq(atom); - - return add(not(succIntEquationExists()), - sum(antecFor, SequentFormulasGenerator.antecedent(), - not(applyTF(antecFor, or(opSub(tf.eq, eqAtom, any()), - opSub(tf.leq, eqAtom, tf.negLiteral), opSub(tf.geq, eqAtom, tf.posLiteral)))))); - } - - private Feature allowInEqStrengthening(TermBuffer atom, TermBuffer literal) { - final TermBuffer antecFor = new TermBuffer(); - - return add(not(succIntEquationExists()), - not(sum(antecFor, SequentFormulasGenerator.antecedent(), - not(applyTF(antecFor, add(or(tf.leqF, tf.geqF), sub(eq(atom), eq(literal)))))))); - } - - private Feature succIntEquationExists() { - final TermBuffer succFor = new TermBuffer(); - - return not(sum(succFor, SequentFormulasGenerator.succedent(), - not(applyTF(succFor, tf.intEquation)))); - } - - protected final Services getServices() { - return getProof().getServices(); - } - - private void setupInEqCaseDistinctionsApproval(RuleSetDispatchFeature d) { - final TermBuffer atom = new TermBuffer(); - final TermBuffer literal = new TermBuffer(); - final TermBuffer intRel = new TermBuffer(); - final TermBuffer rootInf = new TermBuffer(); - - bindRuleSet(d, "inEqSimp_signCases", add(isInstantiated("signCasesLeft"), - let(atom, instOf("signCasesLeft"), allowPosNegCaseDistinction(atom)))); - - // this is somewhat ugly. we should introduce some concept of "tagging" - // rule application so that they can be recognised again later - bindRuleSet(d, "cut", - add(isInstantiated("cutFormula"), or( - not(sum(intRel, SequentFormulasGenerator.antecedent(), - ifZero(isRootInferenceProducer(intRel), - sum(rootInf, RootsGenerator.create(intRel, getServices()), - not(eq(instOf("cutFormula"), rootInf)))))), - ifZero(applyTF("cutFormula", opSub(tf.eq, tf.atom, tf.literal)), - let(atom, sub(instOf("cutFormula"), 0), let(literal, - sub(instOf("cutFormula"), 1), allowInEqStrengthening(atom, literal))))))); - } - - // ////////////////////////////////////////////////////////////////////////// - // ////////////////////////////////////////////////////////////////////////// - // - // Axiomatisation and algorithms for further arithmetic operations: - // division, modulus, modular Java operations - // - // ////////////////////////////////////////////////////////////////////////// - // ////////////////////////////////////////////////////////////////////////// - - private void setupDefOpsPrimaryCategories(RuleSetDispatchFeature d) { - - if (arithDefOps()) { - // the axiom defining division only has to be inserted once, because - // it adds equations to the antecedent - bindRuleSet(d, "defOps_div", - SumFeature.createSum(NonDuplicateAppModPositionFeature.INSTANCE, - applyTF("divNum", tf.polynomial), applyTF("divDenom", tf.polynomial), - applyTF("divNum", tf.notContainsDivMod), - applyTF("divDenom", tf.notContainsDivMod), - ifZero(isBelow(ff.modalOperator), longConst(200)))); - - bindRuleSet(d, "defOps_jdiv", - SumFeature.createSum(NonDuplicateAppModPositionFeature.INSTANCE, - applyTF("divNum", tf.polynomial), applyTF("divDenom", tf.polynomial), - applyTF("divNum", tf.notContainsDivMod), - applyTF("divDenom", tf.notContainsDivMod), - ifZero(isBelow(ff.modalOperator), longConst(200)))); - - bindRuleSet(d, "defOps_jdiv_inline", add(applyTF("divNum", tf.literal), - applyTF("divDenom", tf.polynomial), longConst(-5000))); - - setupDefOpsExpandMod(d); - - bindRuleSet(d, "defOps_expandRanges", -8000); - bindRuleSet(d, "defOps_expandJNumericOp", -500); - bindRuleSet(d, "defOps_modHomoEq", -5000); - } else { - bindRuleSet(d, "defOps_div", inftyConst()); - bindRuleSet(d, "defOps_jdiv", inftyConst()); - - bindRuleSet(d, "defOps_jdiv_inline", add(applyTF("divNum", tf.literal), - applyTF("divDenom", tf.literal), longConst(-4000))); - - bindRuleSet(d, "defOps_mod", add(applyTF("divNum", tf.literal), - applyTF("divDenom", tf.literal), longConst(-4000))); - - bindRuleSet(d, "defOps_expandRanges", inftyConst()); - bindRuleSet(d, "defOps_expandJNumericOp", inftyConst()); - bindRuleSet(d, "defOps_modHomoEq", inftyConst()); - } - - } - - private void setupDefOpsExpandMod(RuleSetDispatchFeature d) { - final TermBuffer superTerm = new TermBuffer(); - - final Feature subsumedModulus = - add(applyTF(superTerm, sub(opSub(tf.mod, any(), tf.literal), tf.zeroLiteral)), - PolynomialValuesCmpFeature.divides(instOf("divDenom"), sub(sub(superTerm, 0), 1))); - - final Feature exSubsumedModulus = add(applyTF("divDenom", tf.literal), - not(sum(superTerm, - SuperTermGenerator.upwardsWithIndex(sub(or(tf.addF, tf.mulF), any()), - getServices()), - not(subsumedModulus)))); - - bindRuleSet(d, "defOps_mod", - ifZero(add(applyTF("divNum", tf.literal), applyTF("divDenom", tf.literal)), - longConst(-4000), - SumFeature.createSum(applyTF("divNum", tf.polynomial), - applyTF("divDenom", tf.polynomial), - ifZero(isBelow(ff.modalOperator), exSubsumedModulus, - or(add(applyTF("divNum", tf.notContainsDivMod), - applyTF("divDenom", tf.notContainsDivMod)), exSubsumedModulus)), - longConst(-3500)))); - } - - protected final Feature isBelow(TermFeature t) { - final TermBuffer superTerm = new TermBuffer(); - return not(sum(superTerm, SuperTermGenerator.upwards(any(), getServices()), - not(applyTF(superTerm, t)))); - } - - protected final Feature onlyInScopeOfQuantifiers() { - final TermBuffer buf = new TermBuffer(); - return sum(buf, SuperTermGenerator.upwards(any(), getServices()), - applyTF(buf, ff.quantifiedFor)); - } - - protected Feature notBelowQuantifier() { - final TermBuffer superFor = new TermBuffer(); - return or(TopLevelFindFeature.ANTEC_OR_SUCC, - sum(superFor, SuperTermGenerator.upwards(any(), getServices()), - not(applyTF(superFor, OperatorClassTF.create(Quantifier.class))))); - } - - private void setupDivModDivision(RuleSetDispatchFeature d) { - - final TermBuffer denomLC = new TermBuffer(); - final TermBuffer numTerm = new TermBuffer(); - final TermBuffer divCoeff = new TermBuffer(); - - // exact polynomial division - - final Feature checkNumTerm = ifZero( - add(not(applyTF(numTerm, tf.addF)), - ReducibleMonomialsFeature.createReducible(numTerm, denomLC)), - add(instantiate("polyDivCoeff", ReduceMonomialsProjection.create(numTerm, denomLC)), - inftyConst())); - - final Feature isReduciblePoly = - sum(numTerm, SubtermGenerator.rightTraverse(instOf("divNum"), tf.addF), checkNumTerm); - - // polynomial division modulo equations of the antecedent - - final Feature checkCoeffE = ifZero(contains(divCoeff, FocusProjection.create(0)), - // do not apply if the result contains the original term - longConst(0), add(instantiate("polyDivCoeff", divCoeff), inftyConst())); - - final Feature isReduciblePolyE = - sum(numTerm, SubtermGenerator.rightTraverse(instOf("divNum"), tf.addF), - ifZero(applyTF(numTerm, tf.addF), longConst(0), sum(divCoeff, - MultiplesModEquationsGenerator.create(numTerm, denomLC), checkCoeffE))); - - bindRuleSet(d, "defOps_divModPullOut", - SumFeature.createSum( - not(add(applyTF("divNum", tf.literal), applyTF("divDenom", tf.literal))), - applyTF("divNum", tf.polynomial), applyTF("divDenom", tf.polynomial), - ifZero(applyTF("divDenom", tf.addF), - let(denomLC, sub(instOf("divDenom"), 1), not(isReduciblePoly)), - let(denomLC, instOf("divDenom"), ifZero(isReduciblePoly, - // no possible division has been found so far - add(NotInScopeOfModalityFeature.INSTANCE, ifZero(isReduciblePolyE, - // try again later - longConst(-POLY_DIVISION_COST)))))), - longConst(100))); - - } - // ////////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////////// // @@ -1907,49 +394,17 @@ protected Feature setupApprovalF() { depSpecF = ConditionalFeature.createConditional(depFilter, inftyConst()); } - return add(NonDuplicateAppFeature.INSTANCE, depSpecF); + return depSpecF; // add(NonDuplicateAppFeature.INSTANCE, depSpecF); } private RuleSetDispatchFeature setupApprovalDispatcher() { final RuleSetDispatchFeature d = new RuleSetDispatchFeature(); - final IntegerLDT numbers = getServices().getTypeConverter().getIntegerLDT(); - - if (arithNonLinInferences()) { - setupMultiplyInequations(d, inftyConst()); - } - - // these taclets are not supposed to be applied with metavariable - // instantiations - // I'll keep it here for the moment as documentation, but comment it out - // as meta variables are no longer part of KeY 2.x - /* - * bindRuleSet ( d, "inEqSimp_pullOutGcd", isInstantiated ( "elimGcd" ) ); bindRuleSet ( d, - * "polySimp_pullOutGcd", isInstantiated ( "elimGcd" ) ); - * - * bindRuleSet ( d, "inEqSimp_nonNegSquares", isInstantiated ( "squareFac" ) ); bindRuleSet - * ( d, "inEqSimp_nonLin_divide", isInstantiated ( "divY" ) ); bindRuleSet ( d, - * "inEqSimp_nonLin_pos", isInstantiated ( "divY" ) ); bindRuleSet ( d, - * "inEqSimp_nonLin_neg", isInstantiated ( "divY" ) ); - * - * bindRuleSet ( d, "inEqSimp_signCases", isInstantiated ( "signCasesLeft" ) ); - */ - - setupNewSymApproval(d, numbers); - - bindRuleSet(d, "defOps_div", NonDuplicateAppModPositionFeature.INSTANCE); - bindRuleSet(d, "defOps_jdiv", NonDuplicateAppModPositionFeature.INSTANCE); - - if (arithNonLinInferences()) { - setupInEqCaseDistinctionsApproval(d); - } bindRuleSet(d, "inReachableStateImplication", NonDuplicateAppModPositionFeature.INSTANCE); bindRuleSet(d, "limitObserver", NonDuplicateAppModPositionFeature.INSTANCE); bindRuleSet(d, "partialInvAxiom", NonDuplicateAppModPositionFeature.INSTANCE); setupClassAxiomApproval(d); - setupQuantifierInstantiationApproval(d); - setupSplittingApproval(d); bindRuleSet(d, "apply_select_eq", add(isInstantiated("s"), isInstantiated("t1"), @@ -1962,12 +417,6 @@ private RuleSetDispatchFeature setupApprovalDispatcher() { add(SimplifiedSelectTermFeature.create(heapLDT), not(ff.ifThenElse)))), not(ContainsTermFeature.create(instOf("s"), instOf("t1"))))); - // Without EqNonDuplicateAppFeature.INSTANCE - // rule 'applyEq' might be applied on the same term - // without changing the sequent for a really long time. This is tested by - // TestSymbolicExecutionTreeBuilder#testInstanceOfNotInEndlessLoop() - bindRuleSet(d, "apply_equations", EqNonDuplicateAppFeature.INSTANCE); - return d; } @@ -1995,13 +444,13 @@ private void setupClassAxiomApproval(final RuleSetDispatchFeature d) { /* * can be applied if sv_heap is instantiated or not present */ - not(needsInstantiation), approveInst, NonDuplicateAppFeature.INSTANCE)); + not(needsInstantiation), approveInst));// , NonDuplicateAppFeature.INSTANCE)); } else { bindRuleSet(d, "classAxiom", add( /* * can be applied if sv_heap is instantiated or not present */ - not(needsInstantiation), approveInst, NonDuplicateAppFeature.INSTANCE)); + not(needsInstantiation), approveInst));// , NonDuplicateAppFeature.INSTANCE)); } } else { bindRuleSet(d, "classAxiom", inftyConst()); @@ -2021,16 +470,6 @@ private RuleSetDispatchFeature setupInstantiationF() { enableInstantiate(); final RuleSetDispatchFeature d = new RuleSetDispatchFeature(); - - setupQuantifierInstantiation(d); - - setupArithPrimaryCategories(d); - setupDefOpsPrimaryCategories(d); - - setupInstantiationWithoutRetry(d); - - setupInEqSimpInstantiation(d); - setClassAxiomInstantiation(d); disableInstantiate(); @@ -2053,18 +492,6 @@ private void setClassAxiomInstantiation(final RuleSetDispatchFeature d) { bindRuleSet(d, "classAxiom", heapInstantiator); } - /** - * For taclets that need instantiation, but where the instantiation is deterministic and does - * not have to be repeated at a later point, we setup the same feature terms both in the cost - * computation method and in the instantiation method. The definitions in - * setupInstantiationWithoutRetry should give cost infinity to those incomplete - * rule applications that will never be instantiated (so that these applications can be removed - * from the queue and do not have to be considered again). - */ - private void setupInstantiationWithoutRetry(RuleSetDispatchFeature d) { - setupPolySimpInstantiationWithoutRetry(d); - setupInEqSimpInstantiationWithoutRetry(d); - } @Override public @NonNull Name name() { @@ -2085,10 +512,10 @@ private void setupInstantiationWithoutRetry(RuleSetDispatchFeature d) { * all (it is discarded by the strategy). */ @Override - public > RuleAppCost computeCost(RuleApp app, - PosInOccurrence pio, - Goal goal, - MutableState mState) { + public > RuleAppCost computeCost(@NonNull RuleApp app, + @NonNull PosInOccurrence pio, + @NonNull GOAL goal, + @NonNull MutableState mState) { var time = System.nanoTime(); try { return costComputationF.computeCost(app, pio, goal, mState); @@ -2119,7 +546,7 @@ public final boolean isApprovedApp(RuleApp app, } @Override - protected RuleAppCost instantiateApp(RuleApp app, + public RuleAppCost instantiateApp(RuleApp app, PosInOccurrence pio, Goal goal, MutableState mState) { var time = System.nanoTime(); @@ -2143,4 +570,9 @@ public boolean isStopAtFirstNonCloseableGoal() { return strategyProperties.getProperty(StrategyProperties.STOPMODE_OPTIONS_KEY) .equals(StrategyProperties.STOPMODE_NONCLOSE); } + + @Override + public boolean isResponsibleFor(IBuiltInRule rule) { + return rule instanceof QueryExpand || rule instanceof UseDependencyContractRule; + } } diff --git a/key.core/src/main/java/de/uka/ilkd/key/strategy/JavaCardDLStrategyFactory.java b/key.core/src/main/java/de/uka/ilkd/key/strategy/JavaCardDLStrategyFactory.java index a828f7ef9a0..873eb4757b5 100644 --- a/key.core/src/main/java/de/uka/ilkd/key/strategy/JavaCardDLStrategyFactory.java +++ b/key.core/src/main/java/de/uka/ilkd/key/strategy/JavaCardDLStrategyFactory.java @@ -3,10 +3,7 @@ * SPDX-License-Identifier: GPL-2.0-only */ package de.uka.ilkd.key.strategy; -import java.util.LinkedList; -import java.util.List; -import de.uka.ilkd.key.proof.Goal; import de.uka.ilkd.key.proof.Proof; import de.uka.ilkd.key.strategy.definition.AbstractStrategyPropertyDefinition; import de.uka.ilkd.key.strategy.definition.OneOfStrategyPropertyDefinition; @@ -16,12 +13,9 @@ import org.key_project.logic.Name; -import org.jspecify.annotations.NonNull; - -/** - * - * @author Kai Wallisch - */ +/// Factory for [JavaCardDLStrategy]. Additionally, handles all strategy settings +/// relevant to it. +/// @author Kai Wallisch public class JavaCardDLStrategyFactory implements StrategyFactory { /** @@ -29,13 +23,6 @@ public class JavaCardDLStrategyFactory implements StrategyFactory { */ public static final Name NAME = new Name(JavaCardDLStrategy.JAVA_CARD_DL_STRATEGY); - public static final String TOOL_TIP_STOP_AT_DEFAULT = - "Stop when (i) the maximum number of rule
    " - + "applications is reached or (ii) no more rules are
    " - + "applicable on the proof tree."; - public static final String TOOL_TIP_STOP_AT_UNCLOSABLE = - "Stop as soon as the first not automatically
    " - + "closable goal is encountered."; public static final String TOOL_TIP_OSS_ON = "" + "Turns on One Step Simplification. This will result in
    " + "(sometimes significantly) shorter proofs which,
    " @@ -67,71 +54,6 @@ public class JavaCardDLStrategyFactory implements StrategyFactory { + "proofs even for simple problems. This option can,
    " + "nevertheless, be meaningful to keep the complexity
    " + "of proofs small and support interactive proving." + ""; - public static final String TOOL_TIP_LOOP_INVARIANT = - "" + "Use loop invariants for loops.
    " + "Three properties have to be shown:
    " - + "
    • Validity of invariant of a loop is preserved by the
      " - + "loop guard and loop body (initially valid).
    • " - + "
    • If the invariant was valid at the start of the loop, it holds
      " - + "after arbitrarily many loop iterations (body preserves invariant).
    • " - + "
    • Invariant holds after the loop terminates (use case).
    • " + "
    "; - public static final String TOOL_TIP_LOOP_SCOPE_INVARIANT = "" - + "Use loop (scope) invariants for loops.
    " + "Three properties have to be shown:
    " - + "
    • Validity of invariant of a loop is preserved by the
      " - + "loop guard and loop body (initially valid).
    • " - + "
    • If the invariant was valid at the start of the loop, it holds
      " - + "after arbitrarily many loop iterations (body preserves invariant).
    • " - + "
    • Invariant holds after the loop terminates (use case).
    • " + "
    " - + "

    In the loop scope invariant rule, the last two are combined " - + "into a single goal.
    " - + "This rule is easier to comprehend than the traditional rule in " + "the presence of
    " - + "potentially exceptional program behavior.

    " + ""; - public static final String TOOL_TIP_LOOP_SCOPE_INVARIANT_TACLET = - "" + "Use the loop scope-based invariant taclet, i.e. not the built-in rules.
    " - + "Three properties have to be shown:
    " - + "
    • Validity of invariant of a loop is preserved by the
      " - + "loop guard and loop body (initially valid).
    • " - + "
    • If the invariant was valid at the start of the loop, it holds
      " - + "after arbitrarily many loop iterations (body preserves invariant).
    • " - + "
    • Invariant holds after the loop terminates (use case).
    • " + "
    " - + "

    The last two are combined into a single goal or split into two
    " - + "goals based on the 'javaLoopTreatment' strategy option.

    " + ""; - public static final String TOOL_TIP_LOOP_SCOPE_EXPAND = - "" + "Unroll loop body, but with the loop scope technology.
    " - + "This requires less program transformation for irregular
    " - + "termination behavior." + ""; - public static final String TOOL_TIP_LOOP_EXPAND = "" + "Unroll loop body." + ""; - public static final String TOOL_TIP_LOOP_NONE = "" + "Leave loops untouched." + ""; - public static final String TOOL_TIP_BLOCK_CONTRACT_INTERNAL = "" - + "Java blocks are replaced by their contracts.
    " + "Three properties are shown:" - + "
    • Validity of block contract in the method context
    • " - + "
    • Precondition of contract holds
    • " - + "
    • Postcondition holds after block terminates
    • " + "
    " + ""; - public static final String TOOL_TIP_BLOCK_CONTRACT_EXTERNAL = - "" + "Java blocks are replaced by their contracts.
    " + "Two properties are shown:" - + "
    • Precondition of contract holds
    • " - + "
    • Postcondition holds after block terminates
    • " + "
    "; - public static final String TOOL_TIP_BLOCK_EXPAND = - "" + "Do not use block contracts for Java blocks. Expand Java blocks." + ""; - public static final String TOOL_TIP_METHOD_CONTRACT = - "Replace method calls by contracts. In some cases
    " - + "a method call may also be replaced by its method body.
    " - + "If query treatment is activated, this behavior applies
    " - + "to queries as well."; - public static final String TOOL_TIP_METHOD_EXPAND = - "Replace method calls by their bodies, i.e. by their
    " - + "implementation. Method contracts are strictly deactivated."; - public static final String TOOL_TIP_METHOD_NONE = - "" + "Stop when encountering a method" + ""; - public static final String TOOL_TIP_MPS_MERGE = - "Use merge point statements for merging. That is,
    " - + "whenever all branches with a given merge point statement
    " - + "have reached it, the strategies will eventually merge
    " - + "the branches together using the merge point specification."; - public static final String TOOL_TIP_MPS_SKIP = - "Simply removes (skips) the merge point statment;
    " - + "no state merging is applied."; - public static final String TOOL_TIP_MPS_NONE = - "" + "Stop when encountering a merge point statement" + ""; public static final String TOOL_TIP_CLASSAXIOM_FREE = "Expand class axioms (such as invariants) freely."; public static final String TOOL_TIP_CLASSAXIOM_DELAYED = @@ -189,44 +111,6 @@ public class JavaCardDLStrategyFactory implements StrategyFactory { public static final String TOOL_TIP_EXPAND_LOCAL_QUERIES_OFF = "" + "Expansion of local queries is turned off.
    " + "This setting is independent of the query treatment setting." + ""; - public static final String TOOL_TIP_ARITHMETIC_BASE = "" + "Basic arithmetic support:" - + "
      " + "
    • Simplification of polynomial expressions
    • " - + "
    • Computation of Gröbner Bases for polynomials in the antecedent
    • " - + "
    • (Partial) Omega procedure for handling linear inequations
    • " + "
    " - + ""; - public static final String TOOL_TIP_ARITHMETIC_DEF_OPS = - "" + "Automatically expand defined symbols like:" + "
      " - + "
    • /, %, jdiv, jmod, ...
    • " - + "
    • int_RANGE, short_MIN, ...
    • " - + "
    • inInt, inByte, ...
    • " - + "
    • addJint, mulJshort, ...
    • " + "
    " + ""; - public static final String TOOL_TIP_ARITHMETIC_MODEL_SEARCH = "" - + "Support for non-linear inequations and model search.
    " + "In addition, this performs:" - + "
      " + "
    • Multiplication of inequations with each other
    • " - + "
    • Systematic case distinctions (cuts)
    • " + "
    " - + "This method is guaranteed to find counterexamples for
    " - + "invalid goals that only contain polynomial (in)equations.
    " - + "Such counterexamples turn up as trivially unprovable goals.
    " - + "It is also able to prove many more valid goals involving
    " - + "(in)equations, but will in general not terminate on such goals." + ""; - public static final String TOOL_TIP_QUANTIFIER_NONE = - "" + "Do not instantiate quantified formulas automatically" + ""; - public static final String TOOL_TIP_QUANTIFIER_NO_SPLITS = "" - + "Instantiate quantified formulas automatically
    " - + "with terms that occur in a sequent, but only if
    " - + "this does not cause proof splitting. Further, quantified
    " - + "formulas that contain queries are not instantiated
    " + "automatically." + ""; - public static final String TOOL_TIP_QUANTIFIER_NO_SPLITS_WITH_PROGS = - "" + "Instantiate quantified formulas automatically
    " - + "with terms that occur in a sequent, but if the
    " - + "sequent contains programs then only perform
    " - + "instantiations that do not cause proof splitting.
    " - + "Further, quantified formulas that contain queries
    " - + "are not instantiated automatically." + ""; - public static final String TOOL_TIP_QUANTIFIER_FREE = - "" + "Instantiate quantified formulas automatically
    " - + "with terms that occur in a sequent, also if this
    " - + "might cause proof splitting." + ""; public static final String TOOL_TIP_AUTO_INDUCTION_ON = "" + "Create an inductive proof for formulas of the form:
    " + " ==> \\forall int i; 0<=i->phi
    " @@ -257,29 +141,6 @@ public class JavaCardDLStrategyFactory implements StrategyFactory { public JavaCardDLStrategyFactory() { } - public static final String toolTipUserOff(int i) { - return "Taclets of the rule set \"userTaclets" + i + "\" are not applied automatically"; - } - - public static final String toolTipUserLow(int i) { - return "Taclets of the rule set \"userTaclets" + i - + "\" are applied automatically with low priority"; - } - - public static final String toolTipUserHigh(int i) { - return "Taclets of the rule set \"userTaclets" + i - + "\" are applied automatically with high priority"; - } - - private static OneOfStrategyPropertyDefinition getStopAt() { - return new OneOfStrategyPropertyDefinition(StrategyProperties.STOPMODE_OPTIONS_KEY, - "Stop at", - new StrategyPropertyValueDefinition(StrategyProperties.STOPMODE_DEFAULT, "Default", - TOOL_TIP_STOP_AT_DEFAULT), - new StrategyPropertyValueDefinition(StrategyProperties.STOPMODE_NONCLOSE, "Unclosable", - TOOL_TIP_STOP_AT_UNCLOSABLE)); - } - private static OneOfStrategyPropertyDefinition getOssUsage() { return new OneOfStrategyPropertyDefinition(StrategyProperties.OSS_OPTIONS_KEY, "One Step Simplification", @@ -300,61 +161,6 @@ private static OneOfStrategyPropertyDefinition getProofSplitting() { TOOL_TIP_PROOF_SPLITTING_OFF)); } - private static OneOfStrategyPropertyDefinition getLoopTreatment() { - return new OneOfStrategyPropertyDefinition(StrategyProperties.LOOP_OPTIONS_KEY, - "Loop treatment", 2, - /* - * NOTE (DS, 2019-04-10): Deactivated the built-in loop scope rule since we now have the - * loop scope taclets which are based on the same theory, but offer several advantages. - */ - // new StrategyPropertyValueDefinition( - // StrategyProperties.LOOP_SCOPE_INVARIANT, - // "Loop Scope Invariant", TOOL_TIP_LOOP_SCOPE_INVARIANT), - new StrategyPropertyValueDefinition(StrategyProperties.LOOP_SCOPE_INV_TACLET, - "Invariant (Loop Scope)", TOOL_TIP_LOOP_SCOPE_INVARIANT_TACLET), - new StrategyPropertyValueDefinition(StrategyProperties.LOOP_SCOPE_EXPAND, - "Expand (Loop Scope)", TOOL_TIP_LOOP_SCOPE_EXPAND), - new StrategyPropertyValueDefinition(StrategyProperties.LOOP_INVARIANT, - "Invariant (Transformation)", TOOL_TIP_LOOP_INVARIANT), - new StrategyPropertyValueDefinition(StrategyProperties.LOOP_EXPAND, - "Expand (Transformation)", TOOL_TIP_LOOP_EXPAND), - new StrategyPropertyValueDefinition(StrategyProperties.LOOP_NONE, "None", - TOOL_TIP_LOOP_NONE)); - } - - private static OneOfStrategyPropertyDefinition getBlockTreatment() { - return new OneOfStrategyPropertyDefinition(StrategyProperties.BLOCK_OPTIONS_KEY, - "Block treatment", 1, - new StrategyPropertyValueDefinition(StrategyProperties.BLOCK_CONTRACT_INTERNAL, - "Internal Contract", TOOL_TIP_BLOCK_CONTRACT_INTERNAL), - new StrategyPropertyValueDefinition(StrategyProperties.BLOCK_CONTRACT_EXTERNAL, - "External Contract", TOOL_TIP_BLOCK_CONTRACT_EXTERNAL), - new StrategyPropertyValueDefinition(StrategyProperties.BLOCK_EXPAND, "Expand", - TOOL_TIP_BLOCK_EXPAND)); - } - - private static OneOfStrategyPropertyDefinition getMethodTreatment() { - return new OneOfStrategyPropertyDefinition(StrategyProperties.METHOD_OPTIONS_KEY, - "Method treatment", - new StrategyPropertyValueDefinition(StrategyProperties.METHOD_CONTRACT, "Contract", - TOOL_TIP_METHOD_CONTRACT), - new StrategyPropertyValueDefinition(StrategyProperties.METHOD_EXPAND, "Expand", - TOOL_TIP_METHOD_EXPAND), - new StrategyPropertyValueDefinition(StrategyProperties.METHOD_NONE, "None", - TOOL_TIP_METHOD_NONE)); - } - - private static OneOfStrategyPropertyDefinition getMergePointStatementTreatment() { - return new OneOfStrategyPropertyDefinition(StrategyProperties.MPS_OPTIONS_KEY, - "Merge point statements", - new StrategyPropertyValueDefinition(StrategyProperties.MPS_MERGE, "Merge", - TOOL_TIP_MPS_MERGE), - new StrategyPropertyValueDefinition(StrategyProperties.MPS_SKIP, "Skip", - TOOL_TIP_MPS_SKIP), - new StrategyPropertyValueDefinition(StrategyProperties.MPS_NONE, "None", - TOOL_TIP_MPS_NONE)); - } - private static OneOfStrategyPropertyDefinition getDependencyContracts() { return new OneOfStrategyPropertyDefinition(StrategyProperties.DEP_OPTIONS_KEY, "Dependency contracts", @@ -382,31 +188,6 @@ private static OneOfStrategyPropertyDefinition getQueryTreatment() { TOOL_TIP_QUERY_OFF)); } - private static OneOfStrategyPropertyDefinition getArithmeticTreatment() { - return new OneOfStrategyPropertyDefinition(StrategyProperties.NON_LIN_ARITH_OPTIONS_KEY, - "Arithmetic treatment", - new StrategyPropertyValueDefinition(StrategyProperties.NON_LIN_ARITH_NONE, "Basic", - TOOL_TIP_ARITHMETIC_BASE), - new StrategyPropertyValueDefinition(StrategyProperties.NON_LIN_ARITH_DEF_OPS, "DefOps", - TOOL_TIP_ARITHMETIC_DEF_OPS), - new StrategyPropertyValueDefinition(StrategyProperties.NON_LIN_ARITH_COMPLETION, - "Model Search", TOOL_TIP_ARITHMETIC_MODEL_SEARCH)); - } - - private static OneOfStrategyPropertyDefinition getQuantifierTreatment() { - return new OneOfStrategyPropertyDefinition(StrategyProperties.QUANTIFIERS_OPTIONS_KEY, - "Quantifier treatment", 2, - new StrategyPropertyValueDefinition(StrategyProperties.QUANTIFIERS_NONE, "None", - TOOL_TIP_QUANTIFIER_NONE, 2, 4), - new StrategyPropertyValueDefinition(StrategyProperties.QUANTIFIERS_NON_SPLITTING, - "No Splits", TOOL_TIP_QUANTIFIER_NO_SPLITS, 6, 2), - new StrategyPropertyValueDefinition( - StrategyProperties.QUANTIFIERS_NON_SPLITTING_WITH_PROGS, "No Splits with Progs", - TOOL_TIP_QUANTIFIER_NO_SPLITS_WITH_PROGS, 2, 4), - new StrategyPropertyValueDefinition(StrategyProperties.QUANTIFIERS_INSTANTIATE, "Free", - TOOL_TIP_QUANTIFIER_FREE, 6, 2)); - } - private static OneOfStrategyPropertyDefinition getClassAxiom() { return new OneOfStrategyPropertyDefinition(StrategyProperties.CLASS_AXIOM_OPTIONS_KEY, "Class axiom rule", @@ -429,32 +210,8 @@ private static OneOfStrategyPropertyDefinition getAutoInduction() { TOOL_TIP_AUTO_INDUCTION_OFF)); } - private static OneOfStrategyPropertyDefinition getUserOptions() { - // User properties - List props = new LinkedList<>(); - for (int i = 1; i <= StrategyProperties.USER_TACLETS_NUM; ++i) { - OneOfStrategyPropertyDefinition user = new OneOfStrategyPropertyDefinition( - StrategyProperties.userTacletsOptionsKey(i), i + ": ", - new StrategyPropertyValueDefinition(StrategyProperties.USER_TACLETS_OFF, "Off", - toolTipUserOff(i), 3, 1), - new StrategyPropertyValueDefinition(StrategyProperties.USER_TACLETS_LOW, - "Low prior.", toolTipUserLow(i), 4, 2), - new StrategyPropertyValueDefinition(StrategyProperties.USER_TACLETS_HIGH, - "High prior.", toolTipUserHigh(i), 6, 2)); - props.add(user); - } - - return new OneOfStrategyPropertyDefinition(null, "User-specific taclet sets", - "" + "These options define whether user- and problem-specific taclet sets
    " - + "are applied automatically by the strategy. Problem-specific taclets
    " - + "can be defined in the \\rules-section of a .key-problem file. For
    " - + "automatic application, the taclets have to contain a clause
    " - + "\\heuristics(userTaclets1), \\heuristics(userTaclets2), etc." + "", - -1, props.toArray(new AbstractStrategyPropertyDefinition[0])); - } - @Override - public Strategy<@NonNull Goal> create(Proof proof, StrategyProperties strategyProperties) { + public JavaCardDLStrategy create(Proof proof, StrategyProperties strategyProperties) { return new JavaCardDLStrategy(proof, strategyProperties); } @@ -466,25 +223,14 @@ public Name name() { @Override public StrategySettingsDefinition getSettingsDefinition() { // Properties - final OneOfStrategyPropertyDefinition stopAt = getStopAt(); final OneOfStrategyPropertyDefinition ossUsage = getOssUsage(); final OneOfStrategyPropertyDefinition proofSplitting = getProofSplitting(); - final OneOfStrategyPropertyDefinition loopTreatment = getLoopTreatment(); - final OneOfStrategyPropertyDefinition blockTreatment = getBlockTreatment(); - final OneOfStrategyPropertyDefinition methodTreatment = getMethodTreatment(); - final OneOfStrategyPropertyDefinition mergePointStatementTreatment = - getMergePointStatementTreatment(); final OneOfStrategyPropertyDefinition dependencyContracts = getDependencyContracts(); final OneOfStrategyPropertyDefinition queryTreatment = getQueryTreatment(); - final OneOfStrategyPropertyDefinition arithmeticTreatment = getArithmeticTreatment(); - final OneOfStrategyPropertyDefinition quantifierTreatment = getQuantifierTreatment(); final OneOfStrategyPropertyDefinition classAxiom = getClassAxiom(); final OneOfStrategyPropertyDefinition autoInduction = getAutoInduction(); - final OneOfStrategyPropertyDefinition userOptions = getUserOptions(); // Model - return new StrategySettingsDefinition("Java DL Options", stopAt, ossUsage, proofSplitting, - loopTreatment, blockTreatment, methodTreatment, mergePointStatementTreatment, - dependencyContracts, queryTreatment, arithmeticTreatment, quantifierTreatment, - classAxiom, autoInduction, userOptions); + return new StrategySettingsDefinition("Java DL Options", ossUsage, proofSplitting, + dependencyContracts, queryTreatment, classAxiom, autoInduction); } } diff --git a/key.core/src/main/java/de/uka/ilkd/key/strategy/JavaStrategy.java b/key.core/src/main/java/de/uka/ilkd/key/strategy/JavaStrategy.java new file mode 100644 index 00000000000..6d03b495d79 --- /dev/null +++ b/key.core/src/main/java/de/uka/ilkd/key/strategy/JavaStrategy.java @@ -0,0 +1,66 @@ +/* This file is part of KeY - https://key-project.org + * KeY is licensed under the GNU General Public License Version 2 + * SPDX-License-Identifier: GPL-2.0-only */ +package de.uka.ilkd.key.strategy; + +import de.uka.ilkd.key.proof.Goal; +import de.uka.ilkd.key.proof.Proof; +import de.uka.ilkd.key.settings.ProofSettings; + +import org.key_project.prover.rules.RuleApp; +import org.key_project.prover.rules.RuleSet; +import org.key_project.prover.sequent.PosInOccurrence; +import org.key_project.prover.strategy.Strategy; +import org.key_project.prover.strategy.costbased.MutableState; +import org.key_project.prover.strategy.costbased.RuleAppCost; + + +/** + * Generic interface for evaluating the cost of a RuleApp with regard to a specific strategy + */ +public interface JavaStrategy extends Strategy { + /** + * Evaluate the cost of a RuleApp. Starts a new independent computation. + * + * @param app the RuleApp + * @param pos position where app is to be applied + * @param goal the goal on which app is to be applied + * @return the cost of the rule application expressed as a + * RuleAppCost object. TopRuleAppCost.INSTANCE + * indicates that the rule shall not be applied at all (it is discarded by + * the strategy). + */ + @Override + default RuleAppCost computeCost(RuleApp app, PosInOccurrence pos, Goal goal) { + return computeCost(app, pos, goal, new MutableState()); + } + + /** + * Updates the {@link JavaStrategy} for the given {@link Proof} by setting the + * {@link JavaStrategy}'s + * {@link StrategyProperties} to the given ones. + * + * @param proof The {@link Proof} the strategy of which should be updated. + * @param p The new {@link StrategyProperties} + */ + static void updateStrategySettings(Proof proof, StrategyProperties p) { + final org.key_project.prover.strategy.Strategy strategy = + proof.getActiveStrategy(); + ProofSettings.DEFAULT_SETTINGS.getStrategySettings().setStrategy(strategy.name()); + ProofSettings.DEFAULT_SETTINGS.getStrategySettings().setActiveStrategyProperties(p); + + proof.getSettings().getStrategySettings().setStrategy(strategy.name()); + proof.getSettings().getStrategySettings().setActiveStrategyProperties(p); + + proof.setActiveStrategy(strategy); + } + + @Override + default boolean isResponsibleFor(RuleSet rs) { return false; } + + @Override + default RuleAppCost instantiateApp(RuleApp app, PosInOccurrence pio, + Goal goal, MutableState mState) { + return null; + } +} diff --git a/key.core/src/main/java/de/uka/ilkd/key/strategy/ModularJavaDLStrategy.java b/key.core/src/main/java/de/uka/ilkd/key/strategy/ModularJavaDLStrategy.java new file mode 100644 index 00000000000..e05aac3840c --- /dev/null +++ b/key.core/src/main/java/de/uka/ilkd/key/strategy/ModularJavaDLStrategy.java @@ -0,0 +1,257 @@ +/* This file is part of KeY - https://key-project.org + * KeY is licensed under the GNU General Public License Version 2 + * SPDX-License-Identifier: GPL-2.0-only */ +package de.uka.ilkd.key.strategy; + +import java.util.*; +import java.util.function.BiFunction; +import java.util.function.Function; + +import de.uka.ilkd.key.proof.Goal; +import de.uka.ilkd.key.proof.Proof; +import de.uka.ilkd.key.strategy.feature.AgeFeature; +import de.uka.ilkd.key.strategy.feature.MatchedAssumesFeature; +import de.uka.ilkd.key.strategy.feature.NonDuplicateAppFeature; +import de.uka.ilkd.key.strategy.termProjection.FocusProjection; + +import org.key_project.logic.Name; +import org.key_project.prover.proof.ProofGoal; +import org.key_project.prover.rules.Rule; +import org.key_project.prover.rules.RuleApp; +import org.key_project.prover.rules.RuleSet; +import org.key_project.prover.sequent.PosInOccurrence; +import org.key_project.prover.strategy.ComponentStrategy; +import org.key_project.prover.strategy.ComponentStrategy.StrategyAspect; +import org.key_project.prover.strategy.costbased.MutableState; +import org.key_project.prover.strategy.costbased.NumberRuleAppCost; +import org.key_project.prover.strategy.costbased.RuleAppCost; +import org.key_project.prover.strategy.costbased.TopRuleAppCost; +import org.key_project.prover.strategy.costbased.feature.AutomatedRuleFeature; +import org.key_project.prover.strategy.costbased.feature.Feature; +import org.key_project.prover.strategy.costbased.feature.RuleSetDispatchFeature; + +import org.jspecify.annotations.NonNull; + +/// Combines a list of component strategies [ComponentStrategy] into a unified strategy. Theory +/// combination +/// is based on the costs computed by each component strategy. Age of the rule +/// application is used to ensure that any applicable rule will eventually be +/// applied. +/// +/// Conflicts (i.e., when more than one component strategy provides a cost +/// computation for one rule set) have to be resolved explicitly by declaring +/// a conflict resolution [#resolveConflict(RuleSetDispatchFeature, RuleSet, List)]. +/// +/// Do not create directly. Use [ModularJavaDLStrategyFactory] instead. +public class ModularJavaDLStrategy extends AbstractFeatureStrategy { + public static final Name NAME = new Name("Modular JavaDL Strategy"); + + /// List of component strategies. Order is not strictly important. + private final List> strategies = new ArrayList<>(); + private final StrategyProperties strategyProperties; + + private final Feature reduceInstTillMaxF; + private final ArithTermFeatures tf; + private final Feature totalCost; + + private final ResponsibleStrategyCache responsibleStrategyCache; + + public ModularJavaDLStrategy(Proof proof, List> componentStrategies, + StrategyProperties properties) { + super(proof); + strategies.addAll(componentStrategies); + this.strategyProperties = (StrategyProperties) properties.clone(); + this.tf = new ArithTermFeatures(getServices().getTypeConverter().getIntegerLDT()); + + responsibleStrategyCache = new ResponsibleStrategyCache(strategies); + + // if more than one strategy is responsible for a _ruleset_ we need to determine how to + // resolve the + // competing computations + RuleSetDispatchFeature conflictCostDispatcher = resolveConflicts(); + + final Feature ifMatchedF = ifZero(MatchedAssumesFeature.INSTANCE, longConst(+1)); + Feature reduceCostTillMaxF = new ReduceTillMaxFeature(Feature::computeCost, + (rule) -> responsibleStrategyCache.getResponsibleStrategies(rule, strategies, + StrategyAspect.Cost)); + + reduceInstTillMaxF = new ReduceTillMaxFeature(ComponentStrategy::instantiateApp, + (rule) -> responsibleStrategyCache.getResponsibleStrategies(rule, strategies, + StrategyAspect.Instantiation)); + + // the feature for the cost computation + totalCost = + add(AutomatedRuleFeature.getInstance(), ifMatchedF, NonDuplicateAppFeature.INSTANCE, + reduceCostTillMaxF, conflictCostDispatcher, AgeFeature.INSTANCE); + } + + private record StratAndDispatcher(ComponentStrategy strategy, + RuleSetDispatchFeature dispatcher) { + } + + /** + * checks for conflicts and resolves known ones (in case an unknown conflict is encountered the + * method fails with a runtime exception + * + * @return the feature implementing the conflict resolution + */ + private RuleSetDispatchFeature resolveConflicts() { + var dis = new RuleSetDispatchFeature(); + var dispatchers = + strategies.stream() + .map(s -> new StratAndDispatcher(s, s.getDispatcher(StrategyAspect.Cost))) + .toList(); + var map = new HashMap>(); + for (var d : dispatchers) { + var s = d.strategy; + for (var rs : d.dispatcher.ruleSets()) { + var lst = map.computeIfAbsent(rs, r -> new ArrayList<>()); + lst.add(s.name()); + } + } + for (var e : map.entrySet()) { + if (e.getValue().size() > 1) { + resolveConflict(dis, e.getKey()); + } + } + return dis; + } + + /** + * resolves known conflicts + * + * @param d the RuleSetDispatchFeature to which the conflict resolution will be bound + * @param rs the RuleSet for which a conflict resolution is required + * @throws IllegalArgumentException if the conflict cannot be resolved + */ + private void resolveConflict(RuleSetDispatchFeature d, RuleSet rs) { + var folStrat = responsibleStrategyCache.getStrategyByName(JFOLStrategy.NAME); + var intStrat = responsibleStrategyCache.getStrategyByName(IntegerStrategy.NAME); + switch (rs.name().toString()) { + case "order_terms" -> { + bindRuleSet(d, "order_terms", + ifZero(applyTF("commEqLeft", tf.intF), + intStrat.getDispatcher(StrategyAspect.Cost).remove(rs), + folStrat.getDispatcher(StrategyAspect.Cost).remove(rs))); + } + case "apply_equations" -> { + bindRuleSet(d, "apply_equations", + ifZero(applyTF(FocusProjection.create(0), tf.intF), + intStrat.getDispatcher(StrategyAspect.Cost).remove(rs), + folStrat.getDispatcher(StrategyAspect.Cost).remove(rs))); + } + case "apply_equations_andOr" -> { + if (quantifierInstantiatedEnabled()) { + bindRuleSet(d, "apply_equations_andOr", + ifZero(applyTF(FocusProjection.create(0), tf.intF), + intStrat.getDispatcher(StrategyAspect.Cost).remove(rs), + folStrat.getDispatcher(StrategyAspect.Cost).remove(rs))); + } else { + bindRuleSet(d, "apply_equations_andOr", inftyConst()); + } + } + default -> throw new IllegalArgumentException("No resolution defined for " + rs); + } + } + + @Override + public RuleAppCost instantiateApp(RuleApp app, PosInOccurrence pio, Goal goal, + MutableState mState) { + enableInstantiate(); + final Feature ifMatchedF = ifZero(MatchedAssumesFeature.INSTANCE, longConst(+1)); + final Feature conflictCostDispatcher = resolveConflicts(); + final Feature totalCost = + add(AutomatedRuleFeature.getInstance(), ifMatchedF, NonDuplicateAppFeature.INSTANCE, + conflictCostDispatcher, reduceInstTillMaxF, AgeFeature.INSTANCE); + disableInstantiate(); + return totalCost.computeCost(app, pio, goal, mState); + } + + @Override + public boolean isStopAtFirstNonCloseableGoal() { + return strategyProperties.getProperty(StrategyProperties.STOPMODE_OPTIONS_KEY) + .equals(StrategyProperties.STOPMODE_NONCLOSE); + } + + @Override + public boolean isApprovedApp(RuleApp app, PosInOccurrence pio, Goal goal) { + boolean isApproved = + NonDuplicateAppFeature.INSTANCE.computeCost(app, pio, goal, + new MutableState()) != TopRuleAppCost.INSTANCE; + if (!isApproved) { + return false; + } + return reduceTillMax(isApproved, false, Boolean::logicalAnd, + s -> s.isApprovedApp(app, pio, goal), + responsibleStrategyCache.getResponsibleStrategies(app.rule(), + strategies, StrategyAspect.Approval)); + } + + @Override + public Name name() { + return NAME; + } + + /// A reducer method that accumulates something computed by strategies, e.g., cost or approval + /// (boolean) + /// and stops once the maximum is reached (top cost or `false`). + /// @param the result type to be accumulated + /// @param init initial value + /// @param max the maximal value; once reached, nothing further is computed + /// @param accumulator accumulator function + /// @param mapper maps a strategy to the required value (cost/approval); e.g., + /// [ComponentStrategy#computeCost(RuleApp, PosInOccurrence, ProofGoal)] + /// @param strats the relevant [ComponentStrategy]s for this computation + private R reduceTillMax(R init, R max, BiFunction accumulator, + Function mapper, LinkedHashSet> strats) { + for (ComponentStrategy strategy : strats) { + init = accumulator.apply(init, mapper.apply(strategy)); + if (init == max) { + break; + } + } + return init; + } + + @Override + public > RuleAppCost computeCost(RuleApp app, + PosInOccurrence pos, GOAL goal, MutableState mState) { + return totalCost.computeCost(app, pos, goal, mState); + } + + @FunctionalInterface + private interface StrategyCostFunction { + RuleAppCost compute(ComponentStrategy strategy, RuleApp app, + PosInOccurrence pos, Goal goal, MutableState mState); + } + + /// A [Feature] that computes a [RuleAppCost] as defined in + /// [ModularJavaDLStrategy#reduceInstTillMaxF]. + private class ReduceTillMaxFeature implements Feature { + /// A function to get the relevant [RuleAppCost] (i.e., [Feature#computeCost(RuleApp, + /// PosInOccurrence, ProofGoal, MutableState)] or + /// [ComponentStrategy#instantiateApp(RuleApp, PosInOccurrence, Goal, MutableState)]). + private final StrategyCostFunction mapper; + /// A function to get the relevant strategies for a [Rule] + private final Function>> ruleToStrategy; + + ReduceTillMaxFeature(StrategyCostFunction mapper, + Function>> ruleToStrategy) { + this.mapper = mapper; + this.ruleToStrategy = ruleToStrategy; + } + + @Override + public > RuleAppCost computeCost(RuleApp app, + PosInOccurrence pos, GOAL goal, MutableState mState) { + return reduceTillMax(NumberRuleAppCost.getZeroCost(), TopRuleAppCost.INSTANCE, + RuleAppCost::add, s -> mapper.compute(s, app, pos, (Goal) goal, mState), + ruleToStrategy.apply(app.rule())); + } + } + + private boolean quantifierInstantiatedEnabled() { + return !StrategyProperties.QUANTIFIERS_NONE + .equals(strategyProperties.getProperty(StrategyProperties.QUANTIFIERS_OPTIONS_KEY)); + } +} diff --git a/key.core/src/main/java/de/uka/ilkd/key/strategy/ModularJavaDLStrategyFactory.java b/key.core/src/main/java/de/uka/ilkd/key/strategy/ModularJavaDLStrategyFactory.java new file mode 100644 index 00000000000..f54d4f1f28e --- /dev/null +++ b/key.core/src/main/java/de/uka/ilkd/key/strategy/ModularJavaDLStrategyFactory.java @@ -0,0 +1,157 @@ +/* This file is part of KeY - https://key-project.org + * KeY is licensed under the GNU General Public License Version 2 + * SPDX-License-Identifier: GPL-2.0-only */ +package de.uka.ilkd.key.strategy; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.LinkedList; +import java.util.List; +import java.util.stream.Collectors; + +import de.uka.ilkd.key.proof.Goal; +import de.uka.ilkd.key.proof.Proof; +import de.uka.ilkd.key.strategy.definition.AbstractStrategyPropertyDefinition; +import de.uka.ilkd.key.strategy.definition.OneOfStrategyPropertyDefinition; +import de.uka.ilkd.key.strategy.definition.StrategyPropertyValueDefinition; +import de.uka.ilkd.key.strategy.definition.StrategySettingsDefinition; + +import org.key_project.logic.Name; +import org.key_project.prover.strategy.ComponentStrategy; + +import org.jspecify.annotations.NonNull; + +/// Creates a [ModularJavaDLStrategy] and handles strategy settings relevant to it. +public class ModularJavaDLStrategyFactory implements StrategyFactory { + private final List componentFactories = + Arrays.asList(new JFOLStrategyFactory(), + new IntegerStrategyFactory(), new SymExStrategyFactory(), new StringStrategyFactory(), + new JavaCardDLStrategyFactory()); + + /** + * The unique {@link Name} of this {@link StrategyFactory}. + */ + public static final Name NAME = ModularJavaDLStrategy.NAME; + + public static final String TOOL_TIP_STOP_AT_DEFAULT = + "Stop when (i) the maximum number of rule
    " + + "applications is reached or (ii) no more rules are
    " + + "applicable on the proof tree."; + public static final String TOOL_TIP_STOP_AT_UNCLOSABLE = + "Stop as soon as the first not automatically
    " + + "closable goal is encountered."; + public static final String TOOL_TIP_ARITHMETIC_BASE = "" + "Basic arithmetic support:" + + "
      " + "
    • Simplification of polynomial expressions
    • " + + "
    • Computation of Gröbner Bases for polynomials in the antecedent
    • " + + "
    • (Partial) Omega procedure for handling linear inequations
    • " + "
    " + + ""; + public static final String TOOL_TIP_ARITHMETIC_DEF_OPS = + "" + "Automatically expand defined symbols like:" + "
      " + + "
    • /, %, jdiv, jmod, ...
    • " + + "
    • int_RANGE, short_MIN, ...
    • " + + "
    • inInt, inByte, ...
    • " + + "
    • addJint, mulJshort, ...
    • " + "
    " + ""; + public static final String TOOL_TIP_ARITHMETIC_MODEL_SEARCH = "" + + "Support for non-linear inequations and model search.
    " + "In addition, this performs:" + + "
      " + "
    • Multiplication of inequations with each other
    • " + + "
    • Systematic case distinctions (cuts)
    • " + "
    " + + "This method is guaranteed to find counterexamples for
    " + + "invalid goals that only contain polynomial (in)equations.
    " + + "Such counterexamples turn up as trivially unprovable goals.
    " + + "It is also able to prove many more valid goals involving
    " + + "(in)equations, but will in general not terminate on such goals." + ""; + + public ModularJavaDLStrategyFactory() { + } + + public static final String toolTipUserOff(int i) { + return "Taclets of the rule set \"userTaclets" + i + "\" are not applied automatically"; + } + + public static final String toolTipUserLow(int i) { + return "Taclets of the rule set \"userTaclets" + i + + "\" are applied automatically with low priority"; + } + + public static final String toolTipUserHigh(int i) { + return "Taclets of the rule set \"userTaclets" + i + + "\" are applied automatically with high priority"; + } + + private static OneOfStrategyPropertyDefinition getStopAt() { + return new OneOfStrategyPropertyDefinition(StrategyProperties.STOPMODE_OPTIONS_KEY, + "Stop at", + new StrategyPropertyValueDefinition(StrategyProperties.STOPMODE_DEFAULT, "Default", + TOOL_TIP_STOP_AT_DEFAULT), + new StrategyPropertyValueDefinition(StrategyProperties.STOPMODE_NONCLOSE, "Unclosable", + TOOL_TIP_STOP_AT_UNCLOSABLE)); + } + + private static OneOfStrategyPropertyDefinition getArithmeticTreatment() { + return new OneOfStrategyPropertyDefinition(StrategyProperties.NON_LIN_ARITH_OPTIONS_KEY, + "Arithmetic treatment", + new StrategyPropertyValueDefinition(StrategyProperties.NON_LIN_ARITH_NONE, "Basic", + TOOL_TIP_ARITHMETIC_BASE), + new StrategyPropertyValueDefinition(StrategyProperties.NON_LIN_ARITH_DEF_OPS, "DefOps", + TOOL_TIP_ARITHMETIC_DEF_OPS), + new StrategyPropertyValueDefinition(StrategyProperties.NON_LIN_ARITH_COMPLETION, + "Model Search", TOOL_TIP_ARITHMETIC_MODEL_SEARCH)); + } + + private static OneOfStrategyPropertyDefinition getUserOptions() { + // User properties + List props = new LinkedList<>(); + for (int i = 1; i <= StrategyProperties.USER_TACLETS_NUM; ++i) { + OneOfStrategyPropertyDefinition user = new OneOfStrategyPropertyDefinition( + StrategyProperties.userTacletsOptionsKey(i), i + ": ", + new StrategyPropertyValueDefinition(StrategyProperties.USER_TACLETS_OFF, "Off", + toolTipUserOff(i), 3, 1), + new StrategyPropertyValueDefinition(StrategyProperties.USER_TACLETS_LOW, + "Low prior.", toolTipUserLow(i), 4, 2), + new StrategyPropertyValueDefinition(StrategyProperties.USER_TACLETS_HIGH, + "High prior.", toolTipUserHigh(i), 6, 2)); + props.add(user); + } + + return new OneOfStrategyPropertyDefinition(null, "User-specific taclet sets", + "" + "These options define whether user- and problem-specific taclet sets
    " + + "are applied automatically by the strategy. Problem-specific taclets
    " + + "can be defined in the \\rules-section of a .key-problem file. For
    " + + "automatic application, the taclets have to contain a clause
    " + + "\\heuristics(userTaclets1), \\heuristics(userTaclets2), etc." + "", + -1, props.toArray(new AbstractStrategyPropertyDefinition[0])); + } + + @Override + public org.key_project.prover.strategy.Strategy<@NonNull Goal> create(Proof proof, + StrategyProperties strategyProperties) { + List> componentStrategies = componentFactories.stream() + .map(f -> (ComponentStrategy) f.create(proof, strategyProperties)) + .collect(Collectors.toList()); + return new ModularJavaDLStrategy(proof, componentStrategies, strategyProperties); + } + + @Override + public Name name() { + return NAME; + } + + @Override + public StrategySettingsDefinition getSettingsDefinition() { + // Properties + final OneOfStrategyPropertyDefinition stopAt = getStopAt(); + final OneOfStrategyPropertyDefinition userOptions = getUserOptions(); + + List componentSettings = componentFactories.stream() + .flatMap(f -> f.getSettingsDefinition().getProperties().stream()) + .collect(Collectors.toCollection(ArrayList::new)); + componentSettings.addFirst(stopAt); + componentSettings.add(userOptions); + + AbstractStrategyPropertyDefinition[] properties = + componentSettings.toArray(new AbstractStrategyPropertyDefinition[0]); + + // Model + return new StrategySettingsDefinition("JavaDL Options", properties); + } +} diff --git a/key.core/src/main/java/de/uka/ilkd/key/strategy/QueueRuleApplicationManager.java b/key.core/src/main/java/de/uka/ilkd/key/strategy/QueueRuleApplicationManager.java index ff7fbb523af..a18e74d9dfe 100644 --- a/key.core/src/main/java/de/uka/ilkd/key/strategy/QueueRuleApplicationManager.java +++ b/key.core/src/main/java/de/uka/ilkd/key/strategy/QueueRuleApplicationManager.java @@ -32,7 +32,7 @@ * {@link #next()}. This operation will remove the element from the queue. The priority of a given * {@link RuleApp} corresponds to its {@link RuleAppCost}. A {@link RuleApp} can be equipped with a * {@link RuleAppCost} by converting it into a {@link RuleAppContainer}. The cost of a - * {@link RuleApp} is computed according to a given {@link Strategy} (see + * {@link RuleApp} is computed according to a given {@link JavaStrategy} (see * {@link Feature#computeCost(RuleApp, PosInOccurrence, ProofGoal, MutableState)}). */ @NullMarked diff --git a/key.core/src/main/java/de/uka/ilkd/key/strategy/ResponsibleStrategyCache.java b/key.core/src/main/java/de/uka/ilkd/key/strategy/ResponsibleStrategyCache.java new file mode 100644 index 00000000000..d0037c8c6cd --- /dev/null +++ b/key.core/src/main/java/de/uka/ilkd/key/strategy/ResponsibleStrategyCache.java @@ -0,0 +1,114 @@ +/* This file is part of KeY - https://key-project.org + * KeY is licensed under the GNU General Public License Version 2 + * SPDX-License-Identifier: GPL-2.0-only */ +package de.uka.ilkd.key.strategy; + +import java.util.*; + +import de.uka.ilkd.key.proof.Goal; +import de.uka.ilkd.key.rule.BuiltInRule; + +import org.key_project.logic.Name; +import org.key_project.prover.rules.Rule; +import org.key_project.prover.rules.RuleSet; +import org.key_project.prover.strategy.ComponentStrategy; +import org.key_project.prover.strategy.ComponentStrategy.StrategyAspect; + +/// A cache for the strategies responsible for a given [Rule] and [RuleSet]. +public class ResponsibleStrategyCache { + // map rulesets to the strategies that participate in their cost computations, instantiation or + // approval decisions + private final Map>> costResponsibilityMap = + new LinkedHashMap>>(); + private final Map>> instantiationResponsibilityMap = + new LinkedHashMap>>(); + private final Map>> approvalResponsibilityMap = + new LinkedHashMap>>(); + // map rules to the strategies that participate in their cost computations, instantiation or + // approval decisions + private final Map>> costRuleToStrategyMap = + new LinkedHashMap>>(); + private final Map>> instantiationRuleToStrategyMap = + new LinkedHashMap>>(); + private final Map>> approvalRuleToStrategyMap = + new LinkedHashMap>>(); + private final Map> nameToStrategyMap = + new HashMap>(); + + public ResponsibleStrategyCache(List> strategies) { + initialize(StrategyAspect.Cost, strategies); + initialize(StrategyAspect.Instantiation, strategies); + initialize(StrategyAspect.Approval, strategies); + } + + /** + * Caches the information which strategies are responsible for which ruleset + * + * @param aspect the StrategyAspect for which the cache is created + * @param strategies list of all component strategies + */ + private void initialize(StrategyAspect aspect, List> strategies) { + var map = getResponsibilityMap(aspect); + for (ComponentStrategy strategy : strategies) { + nameToStrategyMap.put(strategy.name(), strategy); + var res = strategy.getResponsibilities(aspect); + for (var rs : res) { + map.computeIfAbsent(rs, k -> new ArrayList<>()).add(strategy); + } + } + } + + /// Returns the map for the given aspect + private Map>> getRuleToStrategyMap( + StrategyAspect aspect) { + return switch (aspect) { + case Cost -> costRuleToStrategyMap; + case Instantiation -> instantiationRuleToStrategyMap; + case Approval -> approvalRuleToStrategyMap; + }; + } + + /// Returns the map for the given aspect + private Map>> getResponsibilityMap( + StrategyAspect aspect) { + return switch (aspect) { + case Cost -> costResponsibilityMap; + case Instantiation -> instantiationResponsibilityMap; + case Approval -> approvalResponsibilityMap; + }; + } + + /// Returns the strategies responsible for the given [Rule] under the given [StrategyAspect]. + public LinkedHashSet> getResponsibleStrategies(Rule rule, + List> strategies, StrategyAspect aspect) { + var ruleToStrategyMap = getRuleToStrategyMap(aspect); + LinkedHashSet> strats = ruleToStrategyMap.get(rule); + if (strats == null) { + strats = new LinkedHashSet<>(); + if (rule instanceof BuiltInRule bir) { + for (var cs : strategies) { + if (cs.isResponsibleFor(bir)) { + strats.add(cs); + } + } + } else { + var ruleSets = rule.ruleSets(); + Map>> responsibilityMap = + getResponsibilityMap(aspect); + while (ruleSets.hasNext()) { + var rs = ruleSets.next(); + List> s = responsibilityMap.get(rs); + if (s != null) + strats.addAll(s); + } + } + ruleToStrategyMap.put(rule, strats); + } + return strats; + } + + /// Returns the strategy with the given [Name] + public ComponentStrategy getStrategyByName(Name name) { + return nameToStrategyMap.get(name); + } +} diff --git a/key.core/src/main/java/de/uka/ilkd/key/strategy/SimpleFilteredStrategy.java b/key.core/src/main/java/de/uka/ilkd/key/strategy/SimpleFilteredStrategy.java index 7c20b783df1..97c8c31249b 100644 --- a/key.core/src/main/java/de/uka/ilkd/key/strategy/SimpleFilteredStrategy.java +++ b/key.core/src/main/java/de/uka/ilkd/key/strategy/SimpleFilteredStrategy.java @@ -24,7 +24,7 @@ * Trivial implementation of the Strategy interface that uses only the goal time to determine the * cost of a RuleApp. A TacletFilter is used to filter out RuleApps. */ -public class SimpleFilteredStrategy implements Strategy { +public class SimpleFilteredStrategy implements JavaStrategy { private static final Name NAME = new Name("Simple ruleset"); @@ -90,7 +90,7 @@ public boolean isApprovedApp(RuleApp app, PosInOccurrence pio, @Override public void instantiateApp(RuleApp app, PosInOccurrence pio, Goal goal, - RuleAppCostCollector collector) {} + org.key_project.prover.strategy.RuleAppCostCollector collector) {} @Override public boolean isStopAtFirstNonCloseableGoal() { diff --git a/key.core/src/main/java/de/uka/ilkd/key/strategy/StaticFeatureCollection.java b/key.core/src/main/java/de/uka/ilkd/key/strategy/StaticFeatureCollection.java index 93e0a540e5d..2581326631f 100644 --- a/key.core/src/main/java/de/uka/ilkd/key/strategy/StaticFeatureCollection.java +++ b/key.core/src/main/java/de/uka/ilkd/key/strategy/StaticFeatureCollection.java @@ -493,4 +493,12 @@ protected static TermFeature constantTermFeature() { return TermPredicateTermFeature .create(term -> term.op() instanceof Function && term.arity() == 0); } + + protected static Feature print(Feature f) { + return new PrintFeature(f); + } + + protected static Feature print(String msg, Feature f) { + return new PrintFeature(msg, f); + } } diff --git a/key.core/src/main/java/de/uka/ilkd/key/strategy/StrategyFactory.java b/key.core/src/main/java/de/uka/ilkd/key/strategy/StrategyFactory.java index fa6196d726a..1b9ce3a3514 100644 --- a/key.core/src/main/java/de/uka/ilkd/key/strategy/StrategyFactory.java +++ b/key.core/src/main/java/de/uka/ilkd/key/strategy/StrategyFactory.java @@ -24,11 +24,13 @@ public interface StrategyFactory extends Named { * @param strategyProperties the StrategyProperties to customize the strategy * @return the newly created strategy */ - Strategy<@NonNull Goal> create(Proof proof, StrategyProperties strategyProperties); + org.key_project.prover.strategy.Strategy<@NonNull Goal> create(Proof proof, + StrategyProperties strategyProperties); /** * Returns the {@link StrategySettingsDefinition} which describes how an user interface has to - * look like to edit {@link StrategySettings} supported by created {@link Strategy} instances. + * look like to edit {@link StrategySettings} supported by created {@link JavaStrategy} + * instances. * * @return The {@link StrategySettingsDefinition} which describes the user interface. */ diff --git a/key.core/src/main/java/de/uka/ilkd/key/strategy/StringStrategy.java b/key.core/src/main/java/de/uka/ilkd/key/strategy/StringStrategy.java new file mode 100644 index 00000000000..904f503d7c8 --- /dev/null +++ b/key.core/src/main/java/de/uka/ilkd/key/strategy/StringStrategy.java @@ -0,0 +1,213 @@ +/* This file is part of KeY - https://key-project.org + * KeY is licensed under the GNU General Public License Version 2 + * SPDX-License-Identifier: GPL-2.0-only */ +package de.uka.ilkd.key.strategy; + +import java.util.HashSet; +import java.util.Set; + +import de.uka.ilkd.key.ldt.BooleanLDT; +import de.uka.ilkd.key.ldt.CharListLDT; +import de.uka.ilkd.key.ldt.SeqLDT; +import de.uka.ilkd.key.logic.op.SortDependingFunction; +import de.uka.ilkd.key.proof.Goal; +import de.uka.ilkd.key.proof.Proof; +import de.uka.ilkd.key.strategy.feature.*; + +import org.key_project.logic.Name; +import org.key_project.prover.proof.ProofGoal; +import org.key_project.prover.rules.IBuiltInRule; +import org.key_project.prover.rules.RuleApp; +import org.key_project.prover.rules.RuleSet; +import org.key_project.prover.sequent.PosInOccurrence; +import org.key_project.prover.strategy.ComponentStrategy; +import org.key_project.prover.strategy.costbased.MutableState; +import org.key_project.prover.strategy.costbased.RuleAppCost; +import org.key_project.prover.strategy.costbased.feature.Feature; +import org.key_project.prover.strategy.costbased.feature.RuleSetDispatchFeature; +import org.key_project.prover.strategy.costbased.feature.SumFeature; +import org.key_project.prover.strategy.costbased.termfeature.OperatorClassTF; +import org.key_project.prover.strategy.costbased.termfeature.TermFeature; + +import org.jspecify.annotations.NonNull; + +/// Strategy for string related rules. +/// +/// Do not create directly; use [StringStrategyFactory] instead. +public class StringStrategy extends AbstractFeatureStrategy implements ComponentStrategy { + public static final Name NAME = new Name("String Strategy"); + + /// The features defining the three phases: cost computation, approval, + /// additionalInstanceCreationAndEvaluation + private final RuleSetDispatchFeature costComputationDispatcher; + + /// Useful [TermFeature] collections + private final ArithTermFeatures tf; + private final FormulaTermFeatures ff; + + private final boolean stopAtFirstNonCloseableGoal; + + public StringStrategy(Proof proof, StrategyProperties strategyProperties) { + super(proof); + this.tf = new ArithTermFeatures(proof.getServices().getTypeConverter().getIntegerLDT()); + this.ff = new FormulaTermFeatures(this.tf); + + costComputationDispatcher = setupCostComputationF(); + + stopAtFirstNonCloseableGoal = + strategyProperties.getProperty(StrategyProperties.STOPMODE_OPTIONS_KEY) + .equals(StrategyProperties.STOPMODE_NONCLOSE); + } + + @Override + public boolean isResponsibleFor(RuleSet rs) { + return costComputationDispatcher.get(rs) != null; + } + + private RuleSetDispatchFeature setupCostComputationF() { + final RuleSetDispatchFeature d = new RuleSetDispatchFeature(); + setUpStringNormalisation(d); + return d; + } + + private void setUpStringNormalisation(RuleSetDispatchFeature d) { + // translates an integer into its string representation + bindRuleSet(d, "integerToString", -10000); + + // do not convert char to int when inside a string function + // feature used to recognize if one is inside a string literal + final SeqLDT seqLDT = getServices().getTypeConverter().getSeqLDT(); + final CharListLDT charListLDT = getServices().getTypeConverter().getCharListLDT(); + final BooleanLDT booleanLDT = getServices().getTypeConverter().getBooleanLDT(); + + + final TermFeature keepChar = + or(op(seqLDT.getSeqSingleton()), or(op(charListLDT.getClIndexOfChar()), + or(op(charListLDT.getClReplace()), op(charListLDT.getClLastIndexOfChar())))); + + bindRuleSet(d, "charLiteral_to_intLiteral", + ifZero(isBelow(keepChar), inftyConst(), longConst(-100))); + + // establish normalform + + // tf below only for test + final TermFeature anyLiteral = or(tf.charLiteral, + or(tf.literal, op(booleanLDT.getFalseConst()), op(booleanLDT.getTrueConst()))); + + final TermFeature seqLiteral = rec(anyLiteral, or(op(seqLDT.getSeqConcat()), + or(op(seqLDT.getSeqSingleton()), or(anyLiteral, inftyTermConst())))); + + Feature belowModOpPenality = ifZero(isBelow(ff.modalOperator), longConst(500)); + + bindRuleSet(d, "defOpsSeqEquality", + add(NonDuplicateAppModPositionFeature.INSTANCE, + ifZero(add(applyTF("left", seqLiteral), applyTF("right", seqLiteral)), + longConst(1000), inftyConst()), + belowModOpPenality)); + + bindRuleSet(d, "defOpsConcat", + add(NonDuplicateAppModPositionFeature.INSTANCE, + ifZero( + or(applyTF("leftStr", not(seqLiteral)), applyTF("rightStr", not(seqLiteral))), + longConst(1000) + // concat is often introduced for construction purposes, + // we do not want to use its definition right at the + // beginning + ), belowModOpPenality)); + + bindRuleSet(d, "stringsSimplify", longConst(-5000)); + + final TermFeature charOrIntLiteral = or(tf.charLiteral, tf.literal, + or(add(OperatorClassTF.create(SortDependingFunction.class), // XXX: + // was CastFunctionSymbol.class + sub(tf.literal)), inftyTermConst())); + + bindRuleSet(d, "defOpsReplaceInline", + ifZero(add(applyTF("str", seqLiteral), applyTF("searchChar", charOrIntLiteral), + applyTF("replChar", charOrIntLiteral)), longConst(-2500), inftyConst())); + + bindRuleSet(d, "defOpsReplace", add(NonDuplicateAppModPositionFeature.INSTANCE, + ifZero(or(applyTF("str", not(seqLiteral)), applyTF("searchChar", not(charOrIntLiteral)), + applyTF("replChar", not(charOrIntLiteral))), longConst(500), inftyConst()), + belowModOpPenality)); + + bindRuleSet(d, "stringsReduceSubstring", + add(NonDuplicateAppModPositionFeature.INSTANCE, longConst(100))); + + bindRuleSet(d, "defOpsStartsEndsWith", longConst(250)); + + bindRuleSet(d, "stringsConcatNotBothLiterals", + ifZero(MatchedAssumesFeature.INSTANCE, ifZero( + add(applyTF(instOf("leftStr"), seqLiteral), + applyTF(instOf("rightStr"), seqLiteral)), + inftyConst()), inftyConst())); + + bindRuleSet(d, "stringsReduceConcat", longConst(100)); + + bindRuleSet(d, "stringsReduceOrMoveOutsideConcat", + ifZero(NonDuplicateAppModPositionFeature.INSTANCE, longConst(800), inftyConst())); + + bindRuleSet(d, "stringsMoveReplaceInside", + ifZero(NonDuplicateAppModPositionFeature.INSTANCE, longConst(400), inftyConst())); + + + bindRuleSet(d, "stringsExpandDefNormalOp", longConst(500)); + + bindRuleSet(d, "stringsContainsDefInline", SumFeature + .createSum(EqNonDuplicateAppFeature.INSTANCE, longConst(1000))); + } + + @Override + public boolean isStopAtFirstNonCloseableGoal() { + return stopAtFirstNonCloseableGoal; + } + + @Override + public boolean isApprovedApp(RuleApp app, PosInOccurrence pio, Goal goal) { + return true; + /* + * NonDuplicateAppFeature.INSTANCE.computeCost(app, pio, goal, + * new MutableState()) != TopRuleAppCost.INSTANCE; + */ + } + + @Override + public RuleAppCost instantiateApp(RuleApp app, PosInOccurrence pio, Goal goal, + MutableState mState) { + return longConst(0).computeCost(app, pio, goal, mState); + } + + @Override + public Name name() { + return NAME; + } + + @Override + public > RuleAppCost computeCost(RuleApp app, + PosInOccurrence pos, Goal goal, MutableState mState) { + return this.costComputationDispatcher.computeCost(app, pos, goal, mState); + } + + @Override + public Set getResponsibilities(StrategyAspect aspect) { + var set = new HashSet(); + RuleSetDispatchFeature dispatcher = getDispatcher(aspect); + if (dispatcher != null) { + set.addAll(dispatcher.ruleSets()); + } + return set; + } + + @Override + public RuleSetDispatchFeature getDispatcher(StrategyAspect aspect) { + return switch (aspect) { + case StrategyAspect.Cost -> costComputationDispatcher; + default -> null; + }; + } + + @Override + public boolean isResponsibleFor(IBuiltInRule rule) { + return false; + } +} diff --git a/key.core/src/main/java/de/uka/ilkd/key/strategy/StringStrategyFactory.java b/key.core/src/main/java/de/uka/ilkd/key/strategy/StringStrategyFactory.java new file mode 100644 index 00000000000..9d1a4b68139 --- /dev/null +++ b/key.core/src/main/java/de/uka/ilkd/key/strategy/StringStrategyFactory.java @@ -0,0 +1,27 @@ +/* This file is part of KeY - https://key-project.org + * KeY is licensed under the GNU General Public License Version 2 + * SPDX-License-Identifier: GPL-2.0-only */ +package de.uka.ilkd.key.strategy; + +import de.uka.ilkd.key.proof.Proof; +import de.uka.ilkd.key.strategy.definition.StrategySettingsDefinition; + +import org.key_project.logic.Name; + +/// Creates [StringStrategy]. +public class StringStrategyFactory implements StrategyFactory { + @Override + public StringStrategy create(Proof proof, StrategyProperties strategyProperties) { + return new StringStrategy(proof, strategyProperties); + } + + @Override + public StrategySettingsDefinition getSettingsDefinition() { + return new StrategySettingsDefinition("String Options"); + } + + @Override + public Name name() { + return StringStrategy.NAME; + } +} diff --git a/key.core/src/main/java/de/uka/ilkd/key/strategy/SymExStrategy.java b/key.core/src/main/java/de/uka/ilkd/key/strategy/SymExStrategy.java new file mode 100644 index 00000000000..e2edca94b5b --- /dev/null +++ b/key.core/src/main/java/de/uka/ilkd/key/strategy/SymExStrategy.java @@ -0,0 +1,282 @@ +/* This file is part of KeY - https://key-project.org + * KeY is licensed under the GNU General Public License Version 2 + * SPDX-License-Identifier: GPL-2.0-only */ +package de.uka.ilkd.key.strategy; + +import java.util.HashSet; +import java.util.Set; + +import de.uka.ilkd.key.proof.Goal; +import de.uka.ilkd.key.proof.Proof; +import de.uka.ilkd.key.rule.*; +import de.uka.ilkd.key.rule.merge.MergeRule; +import de.uka.ilkd.key.strategy.feature.*; +import de.uka.ilkd.key.strategy.feature.findprefix.FindPrefixRestrictionFeature; +import de.uka.ilkd.key.strategy.termProjection.TermBuffer; +import de.uka.ilkd.key.strategy.termgenerator.SuperTermGenerator; + +import org.key_project.logic.Name; +import org.key_project.prover.proof.ProofGoal; +import org.key_project.prover.rules.IBuiltInRule; +import org.key_project.prover.rules.RuleApp; +import org.key_project.prover.rules.RuleSet; +import org.key_project.prover.sequent.PosInOccurrence; +import org.key_project.prover.strategy.ComponentStrategy; +import org.key_project.prover.strategy.costbased.MutableState; +import org.key_project.prover.strategy.costbased.RuleAppCost; +import org.key_project.prover.strategy.costbased.feature.Feature; +import org.key_project.prover.strategy.costbased.feature.FindDepthFeature; +import org.key_project.prover.strategy.costbased.feature.RuleSetDispatchFeature; +import org.key_project.prover.strategy.costbased.feature.ScaleFeature; +import org.key_project.prover.strategy.costbased.feature.SumFeature; + +import org.jspecify.annotations.NonNull; + +/// Strategy for symbolic execution rules. +/// +/// Do not create directly. Use [SymExStrategyFactory] instead. +public class SymExStrategy extends AbstractFeatureStrategy implements ComponentStrategy { + public static final Name NAME = new Name("SymExStrategy"); + + private final FormulaTermFeatures ff; + + private final StrategyProperties strategyProperties; + + private final RuleSetDispatchFeature costComputationDispatcher; + private final Feature costComputationF; + private final RuleSetDispatchFeature instantiationDispatcher; + private final Feature instantiationF; + + public SymExStrategy(Proof proof, StrategyProperties strategyProperties) { + super(proof); + + this.strategyProperties = strategyProperties; + var tf = new ArithTermFeatures(getServices().getTypeConverter().getIntegerLDT()); + ff = new FormulaTermFeatures(tf); + + costComputationDispatcher = setupCostComputationF(); + instantiationDispatcher = new RuleSetDispatchFeature(); + + costComputationF = setupGlobalF(costComputationDispatcher); + instantiationF = setupGlobalF(instantiationDispatcher); + } + + @Override + public boolean isResponsibleFor(RuleSet rs) { + return costComputationDispatcher.get(rs) != null || instantiationDispatcher.get(rs) != null; + } + + @Override + public Set getResponsibilities(StrategyAspect aspect) { + var set = new HashSet(); + RuleSetDispatchFeature dispatcher = getDispatcher(aspect); + if (dispatcher != null) { + set.addAll(dispatcher.ruleSets()); + } + return set; + } + + @Override + public RuleSetDispatchFeature getDispatcher(StrategyAspect aspect) { + return switch (aspect) { + case StrategyAspect.Cost -> costComputationDispatcher; + case StrategyAspect.Instantiation -> instantiationDispatcher; + default -> null; + }; + } + + + private Feature setupGlobalF(Feature dispatcher) { + final Feature methodSpecF; + final String methProp = + strategyProperties.getProperty(StrategyProperties.METHOD_OPTIONS_KEY); + switch (methProp) { + case StrategyProperties.METHOD_CONTRACT -> + methodSpecF = methodSpecFeature(longConst(-20)); + case StrategyProperties.METHOD_EXPAND, StrategyProperties.METHOD_NONE -> methodSpecF = + methodSpecFeature(inftyConst()); + default -> { + methodSpecF = null; + assert false; + } + } + + Feature loopInvF; + final String loopProp = strategyProperties.getProperty(StrategyProperties.LOOP_OPTIONS_KEY); + if (loopProp.equals(StrategyProperties.LOOP_INVARIANT)) { + loopInvF = loopInvFeature(longConst(0)); + } else { + loopInvF = loopInvFeature(inftyConst()); + } + + final Feature blockFeature; + final Feature loopBlockFeature; + final Feature loopBlockApplyHeadFeature; + final String blockProperty = + strategyProperties.getProperty(StrategyProperties.BLOCK_OPTIONS_KEY); + if (blockProperty.equals(StrategyProperties.BLOCK_CONTRACT_INTERNAL)) { + blockFeature = blockContractInternalFeature(longConst(Long.MIN_VALUE)); + loopBlockFeature = loopContractInternalFeature(longConst(Long.MIN_VALUE)); + loopBlockApplyHeadFeature = loopContractApplyHead(longConst(Long.MIN_VALUE)); + } else if (blockProperty.equals(StrategyProperties.BLOCK_CONTRACT_EXTERNAL)) { + blockFeature = blockContractExternalFeature(longConst(Long.MIN_VALUE)); + loopBlockFeature = + SumFeature.createSum(loopContractExternalFeature(longConst(Long.MIN_VALUE)), + loopContractInternalFeature(longConst(42))); + loopBlockApplyHeadFeature = loopContractApplyHead(longConst(Long.MIN_VALUE)); + } else { + blockFeature = blockContractInternalFeature(inftyConst()); + loopBlockFeature = loopContractExternalFeature(inftyConst()); + loopBlockApplyHeadFeature = loopContractApplyHead(inftyConst()); + } + + final Feature mergeRuleF; + final String mpsProperty = + strategyProperties.getProperty(StrategyProperties.MPS_OPTIONS_KEY); + if (mpsProperty.equals(StrategyProperties.MPS_MERGE)) { + mergeRuleF = mergeRuleFeature(longConst(-4000)); + } else { + mergeRuleF = mergeRuleFeature(inftyConst()); + } + return SumFeature.createSum(mergeRuleF, methodSpecF, loopInvF, blockFeature, + loopBlockFeature, loopBlockApplyHeadFeature, dispatcher); + } + + private RuleSetDispatchFeature setupCostComputationF() { + final RuleSetDispatchFeature d = new RuleSetDispatchFeature(); + boolean programsToRight = true; // XXX + + final String[] exceptionsWithPenalty = { "java.lang.NullPointerException", + "java.lang.ArrayIndexOutOfBoundsException", "java.lang.ArrayStoreException", + "java.lang.ClassCastException" }; + + bindRuleSet(d, "simplify_prog", + ifZero(ThrownExceptionFeature.create(exceptionsWithPenalty, getServices()), + longConst(500), + ifZero(isBelow(add(ff.forF, not(ff.atom))), longConst(200), longConst(-100)))); + + bindRuleSet(d, "simplify_prog_subset", longConst(-4000)); + + bindRuleSet(d, "simplify_expression", -100); + + bindRuleSet(d, "simplify_java", -4500); + + bindRuleSet(d, "executeIntegerAssignment", -100); + bindRuleSet(d, "executeDoubleAssignment", -100); + + final Feature findDepthFeature = + FindDepthFeature.getInstance(); + bindRuleSet(d, "concrete_java", + add(longConst(-11000), + ScaleFeature.createScaled(findDepthFeature, 10.0))); + + // taclets for special invariant handling + bindRuleSet(d, "loopInvariant", -20000); + + boolean useLoopExpand = strategyProperties.getProperty(StrategyProperties.LOOP_OPTIONS_KEY) + .equals(StrategyProperties.LOOP_EXPAND); + boolean useLoopInvTaclets = + strategyProperties.getProperty(StrategyProperties.LOOP_OPTIONS_KEY) + .equals(StrategyProperties.LOOP_SCOPE_INV_TACLET); + boolean useLoopScopeExpand = + strategyProperties.getProperty(StrategyProperties.LOOP_OPTIONS_KEY) + .equals(StrategyProperties.LOOP_SCOPE_EXPAND); + + bindRuleSet(d, "loop_expand", useLoopExpand ? longConst(0) : inftyConst()); + bindRuleSet(d, "loop_scope_inv_taclet", useLoopInvTaclets ? longConst(0) : inftyConst()); + bindRuleSet(d, "loop_scope_expand", useLoopScopeExpand ? longConst(1000) : inftyConst()); + + + final String methProp = + strategyProperties.getProperty(StrategyProperties.METHOD_OPTIONS_KEY); + switch (methProp) { + case StrategyProperties.METHOD_CONTRACT -> + /* + * If method treatment by contracts is chosen, this does not mean that method + * expansion + * is disabled. The original cost was 200 and is now increased to 2000 in order to + * repress method expansion stronger when method treatment by contracts is chosen. + */ + bindRuleSet(d, "method_expand", longConst(2000)); + case StrategyProperties.METHOD_EXPAND -> + bindRuleSet(d, "method_expand", longConst(100)); + case StrategyProperties.METHOD_NONE -> bindRuleSet(d, "method_expand", inftyConst()); + default -> throw new RuntimeException("Unexpected strategy property " + methProp); + } + + final String mpsProp = strategyProperties.getProperty(StrategyProperties.MPS_OPTIONS_KEY); + switch (mpsProp) { + case StrategyProperties.MPS_MERGE -> + /* + * For this case, we use a special feature, since deleting merge points should only + * be + * done after a merge rule application. + */ + bindRuleSet(d, "merge_point", DeleteMergePointRuleFeature.INSTANCE); + case StrategyProperties.MPS_SKIP -> bindRuleSet(d, "merge_point", longConst(-5000)); + case StrategyProperties.MPS_NONE -> bindRuleSet(d, "merge_point", inftyConst()); + default -> throw new RuntimeException("Unexpected strategy property " + mpsProp); + } + + bindRuleSet(d, "modal_tautology", longConst(-10000)); + + if (programsToRight) { + bindRuleSet(d, "boxDiamondConv", + SumFeature.createSum( + new FindPrefixRestrictionFeature( + FindPrefixRestrictionFeature.PositionModifier.ALLOW_UPDATE_AS_PARENT, + FindPrefixRestrictionFeature.PrefixChecker.ANTEC_POLARITY), + longConst(-1000))); + } else { + bindRuleSet(d, "boxDiamondConv", inftyConst()); + } + + bindRuleSet(d, "confluence_restricted", + ifZero(MatchedAssumesFeature.INSTANCE, DiffFindAndIfFeature.INSTANCE)); + + final TermBuffer superFor = new TermBuffer(); + bindRuleSet(d, "split_if", + add(sum(superFor, SuperTermGenerator.upwards(any(), getServices()), + applyTF(superFor, not(ff.program))), longConst(50))); + + return d; + } + + @Override + public RuleAppCost instantiateApp(RuleApp app, PosInOccurrence pio, Goal goal, + MutableState mState) { + return instantiationF.computeCost(app, pio, goal, mState); + } + + @Override + public boolean isStopAtFirstNonCloseableGoal() { + return false; + } + + @Override + public boolean isApprovedApp(RuleApp app, PosInOccurrence pio, Goal goal) { + return true; + } + + @Override + public Name name() { + return NAME; + } + + @Override + public > RuleAppCost computeCost(RuleApp app, + PosInOccurrence pos, GOAL goal, MutableState mState) { + return costComputationF.computeCost(app, pos, goal, mState); + } + + @Override + public boolean isResponsibleFor(IBuiltInRule rule) { + return rule instanceof WhileInvariantRule || rule instanceof LoopScopeInvariantRule + || rule instanceof BlockContractInternalRule + || rule instanceof BlockContractExternalRule + || rule instanceof LoopContractInternalRule + || rule instanceof LoopContractExternalRule + || rule instanceof LoopApplyHeadRule || rule instanceof UseOperationContractRule + || rule instanceof MergeRule; + } +} diff --git a/key.core/src/main/java/de/uka/ilkd/key/strategy/SymExStrategyFactory.java b/key.core/src/main/java/de/uka/ilkd/key/strategy/SymExStrategyFactory.java new file mode 100644 index 00000000000..7e7ab19dab7 --- /dev/null +++ b/key.core/src/main/java/de/uka/ilkd/key/strategy/SymExStrategyFactory.java @@ -0,0 +1,138 @@ +/* This file is part of KeY - https://key-project.org + * KeY is licensed under the GNU General Public License Version 2 + * SPDX-License-Identifier: GPL-2.0-only */ +package de.uka.ilkd.key.strategy; + +import de.uka.ilkd.key.proof.Proof; +import de.uka.ilkd.key.strategy.definition.OneOfStrategyPropertyDefinition; +import de.uka.ilkd.key.strategy.definition.StrategyPropertyValueDefinition; +import de.uka.ilkd.key.strategy.definition.StrategySettingsDefinition; + +import org.key_project.logic.Name; + +/// Creates [SymExStrategy]. Handles strategy settings for symbolic execution. +public class SymExStrategyFactory implements StrategyFactory { + public static final String TOOL_TIP_LOOP_INVARIANT = + "" + "Use loop invariants for loops.
    " + "Three properties have to be shown:
    " + + "
    • Validity of invariant of a loop is preserved by the
      " + + "loop guard and loop body (initially valid).
    • " + + "
    • If the invariant was valid at the start of the loop, it holds
      " + + "after arbitrarily many loop iterations (body preserves invariant).
    • " + + "
    • Invariant holds after the loop terminates (use case).
    • " + "
    "; + public static final String TOOL_TIP_LOOP_SCOPE_INVARIANT_TACLET = + "" + "Use the loop scope-based invariant taclet, i.e. not the built-in rules.
    " + + "Three properties have to be shown:
    " + + "
    • Validity of invariant of a loop is preserved by the
      " + + "loop guard and loop body (initially valid).
    • " + + "
    • If the invariant was valid at the start of the loop, it holds
      " + + "after arbitrarily many loop iterations (body preserves invariant).
    • " + + "
    • Invariant holds after the loop terminates (use case).
    • " + "
    " + + "

    The last two are combined into a single goal or split into two
    " + + "goals based on the 'javaLoopTreatment' strategy option.

    " + ""; + public static final String TOOL_TIP_LOOP_SCOPE_EXPAND = + "" + "Unroll loop body, but with the loop scope technology.
    " + + "This requires less program transformation for irregular
    " + + "termination behavior." + ""; + public static final String TOOL_TIP_LOOP_EXPAND = "" + "Unroll loop body." + ""; + public static final String TOOL_TIP_LOOP_NONE = "" + "Leave loops untouched." + ""; + public static final String TOOL_TIP_BLOCK_CONTRACT_INTERNAL = "" + + "Java blocks are replaced by their contracts.
    " + "Three properties are shown:" + + "
    • Validity of block contract in the method context
    • " + + "
    • Precondition of contract holds
    • " + + "
    • Postcondition holds after block terminates
    • " + "
    " + ""; + public static final String TOOL_TIP_BLOCK_CONTRACT_EXTERNAL = + "" + "Java blocks are replaced by their contracts.
    " + "Two properties are shown:" + + "
    • Precondition of contract holds
    • " + + "
    • Postcondition holds after block terminates
    • " + "
    "; + public static final String TOOL_TIP_BLOCK_EXPAND = + "" + "Do not use block contracts for Java blocks. Expand Java blocks." + ""; + public static final String TOOL_TIP_METHOD_CONTRACT = + "Replace method calls by contracts. In some cases
    " + + "a method call may also be replaced by its method body.
    " + + "If query treatment is activated, this behavior applies
    " + + "to queries as well."; + public static final String TOOL_TIP_METHOD_EXPAND = + "Replace method calls by their bodies, i.e. by their
    " + + "implementation. Method contracts are strictly deactivated."; + public static final String TOOL_TIP_METHOD_NONE = + "" + "Stop when encountering a method" + ""; + public static final String TOOL_TIP_MPS_MERGE = + "Use merge point statements for merging. That is,
    " + + "whenever all branches with a given merge point statement
    " + + "have reached it, the strategies will eventually merge
    " + + "the branches together using the merge point specification."; + public static final String TOOL_TIP_MPS_SKIP = + "Simply removes (skips) the merge point statment;
    " + + "no state merging is applied."; + public static final String TOOL_TIP_MPS_NONE = + "" + "Stop when encountering a merge point statement" + ""; + + @Override + public SymExStrategy create(Proof proof, StrategyProperties strategyProperties) { + return new SymExStrategy(proof, strategyProperties); + } + + private static OneOfStrategyPropertyDefinition getLoopTreatment() { + return new OneOfStrategyPropertyDefinition(StrategyProperties.LOOP_OPTIONS_KEY, + "Loop treatment", 2, + new StrategyPropertyValueDefinition(StrategyProperties.LOOP_SCOPE_INV_TACLET, + "Invariant (Loop Scope)", TOOL_TIP_LOOP_SCOPE_INVARIANT_TACLET), + new StrategyPropertyValueDefinition(StrategyProperties.LOOP_SCOPE_EXPAND, + "Expand (Loop Scope)", TOOL_TIP_LOOP_SCOPE_EXPAND), + new StrategyPropertyValueDefinition(StrategyProperties.LOOP_INVARIANT, + "Invariant (Transformation)", TOOL_TIP_LOOP_INVARIANT), + new StrategyPropertyValueDefinition(StrategyProperties.LOOP_EXPAND, + "Expand (Transformation)", TOOL_TIP_LOOP_EXPAND), + new StrategyPropertyValueDefinition(StrategyProperties.LOOP_NONE, "None", + TOOL_TIP_LOOP_NONE)); + } + + private static OneOfStrategyPropertyDefinition getBlockTreatment() { + return new OneOfStrategyPropertyDefinition(StrategyProperties.BLOCK_OPTIONS_KEY, + "Block treatment", 1, + new StrategyPropertyValueDefinition(StrategyProperties.BLOCK_CONTRACT_INTERNAL, + "Internal Contract", TOOL_TIP_BLOCK_CONTRACT_INTERNAL), + new StrategyPropertyValueDefinition(StrategyProperties.BLOCK_CONTRACT_EXTERNAL, + "External Contract", TOOL_TIP_BLOCK_CONTRACT_EXTERNAL), + new StrategyPropertyValueDefinition(StrategyProperties.BLOCK_EXPAND, "Expand", + TOOL_TIP_BLOCK_EXPAND)); + } + + private static OneOfStrategyPropertyDefinition getMethodTreatment() { + return new OneOfStrategyPropertyDefinition(StrategyProperties.METHOD_OPTIONS_KEY, + "Method treatment", + new StrategyPropertyValueDefinition(StrategyProperties.METHOD_CONTRACT, "Contract", + TOOL_TIP_METHOD_CONTRACT), + new StrategyPropertyValueDefinition(StrategyProperties.METHOD_EXPAND, "Expand", + TOOL_TIP_METHOD_EXPAND), + new StrategyPropertyValueDefinition(StrategyProperties.METHOD_NONE, "None", + TOOL_TIP_METHOD_NONE)); + } + + private static OneOfStrategyPropertyDefinition getMergePointStatementTreatment() { + return new OneOfStrategyPropertyDefinition(StrategyProperties.MPS_OPTIONS_KEY, + "Merge point statements", + new StrategyPropertyValueDefinition(StrategyProperties.MPS_MERGE, "Merge", + TOOL_TIP_MPS_MERGE), + new StrategyPropertyValueDefinition(StrategyProperties.MPS_SKIP, "Skip", + TOOL_TIP_MPS_SKIP), + new StrategyPropertyValueDefinition(StrategyProperties.MPS_NONE, "None", + TOOL_TIP_MPS_NONE)); + } + + @Override + public StrategySettingsDefinition getSettingsDefinition() { + final OneOfStrategyPropertyDefinition loopTreatment = getLoopTreatment(); + final OneOfStrategyPropertyDefinition blockTreatment = getBlockTreatment(); + final OneOfStrategyPropertyDefinition methodTreatment = getMethodTreatment(); + final OneOfStrategyPropertyDefinition mergePointStatementTreatment = + getMergePointStatementTreatment(); + return new StrategySettingsDefinition("Symbolic Execution Options", + loopTreatment, blockTreatment, methodTreatment, mergePointStatementTreatment); + } + + @Override + public Name name() { + return SymExStrategy.NAME; + } +} diff --git a/key.core/src/main/java/de/uka/ilkd/key/strategy/TacletAppContainer.java b/key.core/src/main/java/de/uka/ilkd/key/strategy/TacletAppContainer.java index 22282daa683..865b50bc510 100644 --- a/key.core/src/main/java/de/uka/ilkd/key/strategy/TacletAppContainer.java +++ b/key.core/src/main/java/de/uka/ilkd/key/strategy/TacletAppContainer.java @@ -132,7 +132,7 @@ private ImmutableList instantiateApp(NoPosTacletApp app, @SuppressWarnings("unchecked") final ImmutableList[] resA = new ImmutableList[] { targetList }; - final RuleAppCostCollector collector = (newApp, cost) -> { + final org.key_project.prover.strategy.RuleAppCostCollector collector = (newApp, cost) -> { if (cost instanceof TopRuleAppCost) { return; } @@ -214,7 +214,7 @@ protected static ImmutableList createInitialAppContainers( * Create containers for FindTaclets or NoFindTaclets. * * @param p_app if p_pio is null, p_app has to be a - * TacletApp for a NoFindTaclet, otherwise for a + * ITacletApp for a NoFindTaclet, otherwise for a * FindTaclet. * @return list of containers for currently applicable TacletApps, the cost may be an instance * of TopRuleAppCost. diff --git a/key.core/src/main/java/de/uka/ilkd/key/strategy/definition/AbstractStrategyPropertyDefinition.java b/key.core/src/main/java/de/uka/ilkd/key/strategy/definition/AbstractStrategyPropertyDefinition.java index 080b987c5eb..f96a252ecce 100644 --- a/key.core/src/main/java/de/uka/ilkd/key/strategy/definition/AbstractStrategyPropertyDefinition.java +++ b/key.core/src/main/java/de/uka/ilkd/key/strategy/definition/AbstractStrategyPropertyDefinition.java @@ -62,9 +62,9 @@ public String getApiKey() { } /** - * Returns the human readable name of the property. + * Returns the human-readable name of the property. * - * @return The human readable name of the property. + * @return The human-readable name of the property. */ public String getName() { return name; diff --git a/key.core/src/main/java/de/uka/ilkd/key/strategy/definition/IDefaultStrategyPropertiesFactory.java b/key.core/src/main/java/de/uka/ilkd/key/strategy/definition/IDefaultStrategyPropertiesFactory.java index c8a7e9899b6..bdceed2be33 100644 --- a/key.core/src/main/java/de/uka/ilkd/key/strategy/definition/IDefaultStrategyPropertiesFactory.java +++ b/key.core/src/main/java/de/uka/ilkd/key/strategy/definition/IDefaultStrategyPropertiesFactory.java @@ -3,12 +3,12 @@ * SPDX-License-Identifier: GPL-2.0-only */ package de.uka.ilkd.key.strategy.definition; -import de.uka.ilkd.key.strategy.Strategy; +import de.uka.ilkd.key.strategy.JavaStrategy; import de.uka.ilkd.key.strategy.StrategyProperties; /** * Instances of this factory are used to create default {@link StrategyProperties} used by a - * {@link Strategy} defined via its {@link StrategySettingsDefinition}. + * {@link JavaStrategy} defined via its {@link StrategySettingsDefinition}. * * @author Martin Hentschel */ diff --git a/key.core/src/main/java/de/uka/ilkd/key/strategy/definition/StrategySettingsDefinition.java b/key.core/src/main/java/de/uka/ilkd/key/strategy/definition/StrategySettingsDefinition.java index af4ca3ab930..ac1f0e150c1 100644 --- a/key.core/src/main/java/de/uka/ilkd/key/strategy/definition/StrategySettingsDefinition.java +++ b/key.core/src/main/java/de/uka/ilkd/key/strategy/definition/StrategySettingsDefinition.java @@ -6,7 +6,7 @@ import java.util.ArrayList; import de.uka.ilkd.key.settings.StrategySettings; -import de.uka.ilkd.key.strategy.Strategy; +import de.uka.ilkd.key.strategy.JavaStrategy; import de.uka.ilkd.key.strategy.StrategyFactory; import de.uka.ilkd.key.strategy.StrategyProperties; @@ -23,7 +23,7 @@ *

    * Each {@link StrategyFactory} should provide an instance of this class to define the user * interface which the user can use to edit supported {@link StrategySettings} in created - * {@link Strategy} instances. If a {@link StrategyFactory} provides no + * {@link JavaStrategy} instances. If a {@link StrategyFactory} provides no * {@link StrategySettingsDefinition} an empty user interface or even bedder an error message should * be shown to the user. *

    diff --git a/key.core/src/main/java/de/uka/ilkd/key/strategy/feature/BinaryTacletAppFeature.java b/key.core/src/main/java/de/uka/ilkd/key/strategy/feature/BinaryTacletAppFeature.java index 1aa0f1108db..fe37b23ce61 100644 --- a/key.core/src/main/java/de/uka/ilkd/key/strategy/feature/BinaryTacletAppFeature.java +++ b/key.core/src/main/java/de/uka/ilkd/key/strategy/feature/BinaryTacletAppFeature.java @@ -47,11 +47,11 @@ protected BinaryTacletAppFeature(boolean p_nonTacletValue) { * Compute whether the result of the feature is zero (true) or infinity * (false) * - * @param app the TacletApp + * @param app the ITacletApp * @param pos position where app is to be applied * @param goal the goal on which app is to be applied * @param mState the MutableState used to store modifiable information - * @return true iff the the result of the feature is supposed to be zero. + * @return true iff the result of the feature is supposed to be zero. */ protected abstract boolean filter(TacletApp app, PosInOccurrence pos, Goal goal, MutableState mState); diff --git a/key.core/src/main/java/de/uka/ilkd/key/strategy/feature/CheckApplyEqFeature.java b/key.core/src/main/java/de/uka/ilkd/key/strategy/feature/CheckApplyEqFeature.java index 6cf5302230b..9af69d855c2 100644 --- a/key.core/src/main/java/de/uka/ilkd/key/strategy/feature/CheckApplyEqFeature.java +++ b/key.core/src/main/java/de/uka/ilkd/key/strategy/feature/CheckApplyEqFeature.java @@ -15,6 +15,8 @@ import org.key_project.prover.strategy.costbased.MutableState; import org.key_project.prover.strategy.costbased.feature.Feature; +import org.checkerframework.checker.nullness.qual.MonotonicNonNull; + /** * This feature checks that an equation is not applied to itself. This means that the focus of the * rule application must not be one side of an equation that is the instantiation of the first @@ -27,7 +29,8 @@ public class CheckApplyEqFeature extends BinaryTacletAppFeature { private CheckApplyEqFeature() {} @Override - protected boolean filter(TacletApp p_app, PosInOccurrence pos, Goal goal, MutableState mState) { + protected boolean filter(@MonotonicNonNull TacletApp p_app, PosInOccurrence pos, Goal goal, + MutableState mState) { assert pos != null : "Need to know the position of " + "the application of the taclet"; AssumesFormulaInstantiation ifInst = p_app.assumesFormulaInstantiations().head(); diff --git a/key.core/src/main/java/de/uka/ilkd/key/strategy/feature/DiffFindAndIfFeature.java b/key.core/src/main/java/de/uka/ilkd/key/strategy/feature/DiffFindAndIfFeature.java index 2a212b123a0..a31c09aaf46 100644 --- a/key.core/src/main/java/de/uka/ilkd/key/strategy/feature/DiffFindAndIfFeature.java +++ b/key.core/src/main/java/de/uka/ilkd/key/strategy/feature/DiffFindAndIfFeature.java @@ -14,6 +14,8 @@ import org.key_project.prover.strategy.costbased.feature.Feature; import org.key_project.util.collection.ImmutableList; +import org.checkerframework.checker.nullness.qual.MonotonicNonNull; + /** * Binary feature that returns zero iff the \assumes- and find-formula of a Taclet are * matched to different members of the sequent. If a taclet has more than one formula in its @@ -27,7 +29,8 @@ public class DiffFindAndIfFeature extends BinaryTacletAppFeature { private DiffFindAndIfFeature() {} @Override - protected boolean filter(TacletApp app, PosInOccurrence pos, Goal goal, MutableState mState) { + protected boolean filter(@MonotonicNonNull TacletApp app, PosInOccurrence pos, Goal goal, + MutableState mState) { assert pos != null : "Feature is only applicable to rules with find"; ImmutableList list = app.assumesFormulaInstantiations(); diff --git a/key.core/src/main/java/de/uka/ilkd/key/strategy/feature/DiffFindAndReplacewithFeature.java b/key.core/src/main/java/de/uka/ilkd/key/strategy/feature/DiffFindAndReplacewithFeature.java index 3a26d98cce0..ec521057ee0 100644 --- a/key.core/src/main/java/de/uka/ilkd/key/strategy/feature/DiffFindAndReplacewithFeature.java +++ b/key.core/src/main/java/de/uka/ilkd/key/strategy/feature/DiffFindAndReplacewithFeature.java @@ -14,6 +14,8 @@ import org.key_project.prover.strategy.costbased.MutableState; import org.key_project.prover.strategy.costbased.feature.Feature; +import org.checkerframework.checker.nullness.qual.MonotonicNonNull; + import static de.uka.ilkd.key.logic.equality.IrrelevantTermLabelsProperty.IRRELEVANT_TERM_LABELS_PROPERTY; /** @@ -28,15 +30,18 @@ public class DiffFindAndReplacewithFeature extends BinaryTacletAppFeature { private DiffFindAndReplacewithFeature() {} @Override - protected boolean filter(TacletApp app, PosInOccurrence pos, Goal goal, MutableState mState) { + protected boolean filter(@MonotonicNonNull TacletApp app, PosInOccurrence pos, Goal goal, + MutableState mState) { assert pos != null && app.rule() instanceof RewriteTaclet : "Feature is only applicable to rewrite taclets"; - for (TacletGoalTemplate template : app.rule().goalTemplates()) { - final JTerm replaceWith = ((RewriteTacletGoalTemplate) template).replaceWith(); - if (replaceWith.equalsModProperty(pos.subTerm(), - IRRELEVANT_TERM_LABELS_PROPERTY)) { - return false; + for (TacletGoalTemplate template : app.taclet().goalTemplates()) { + if (template instanceof RewriteTacletGoalTemplate rwTGT) { + final JTerm replaceWith = rwTGT.replaceWith(); + if (replaceWith.equalsModProperty(pos.subTerm(), + IRRELEVANT_TERM_LABELS_PROPERTY)) { + return false; + } } } return true; diff --git a/key.core/src/main/java/de/uka/ilkd/key/strategy/feature/EqNonDuplicateAppFeature.java b/key.core/src/main/java/de/uka/ilkd/key/strategy/feature/EqNonDuplicateAppFeature.java index 11226b0a9be..306c97387c6 100644 --- a/key.core/src/main/java/de/uka/ilkd/key/strategy/feature/EqNonDuplicateAppFeature.java +++ b/key.core/src/main/java/de/uka/ilkd/key/strategy/feature/EqNonDuplicateAppFeature.java @@ -10,6 +10,8 @@ import org.key_project.prover.strategy.costbased.MutableState; import org.key_project.prover.strategy.costbased.feature.Feature; +import org.checkerframework.checker.nullness.qual.MonotonicNonNull; + /** * Binary feature that returns zero iff a certain Taclet app has not already been performed. @@ -24,7 +26,7 @@ public class EqNonDuplicateAppFeature extends AbstractNonDuplicateAppFeature { private EqNonDuplicateAppFeature() {} @Override - public boolean filter(TacletApp app, PosInOccurrence pos, + public boolean filter(@MonotonicNonNull TacletApp app, PosInOccurrence pos, Goal goal, MutableState mState) { assert pos != null : "Feature is only applicable to rules with find"; diff --git a/key.core/src/main/java/de/uka/ilkd/key/strategy/feature/MatchedAssumesFeature.java b/key.core/src/main/java/de/uka/ilkd/key/strategy/feature/MatchedAssumesFeature.java index d712c639ec5..7548c1b8304 100644 --- a/key.core/src/main/java/de/uka/ilkd/key/strategy/feature/MatchedAssumesFeature.java +++ b/key.core/src/main/java/de/uka/ilkd/key/strategy/feature/MatchedAssumesFeature.java @@ -10,6 +10,8 @@ import org.key_project.prover.strategy.costbased.MutableState; import org.key_project.prover.strategy.costbased.feature.Feature; +import org.checkerframework.checker.nullness.qual.MonotonicNonNull; + /** * Binary features that returns zero iff the if-formulas of a Taclet are instantiated or the Taclet * does not have any if-formulas. @@ -21,7 +23,8 @@ public final class MatchedAssumesFeature extends BinaryTacletAppFeature { private MatchedAssumesFeature() {} @Override - protected boolean filter(TacletApp app, PosInOccurrence pos, Goal goal, MutableState mState) { + protected boolean filter(@MonotonicNonNull TacletApp app, PosInOccurrence pos, Goal goal, + MutableState mState) { return app.assumesInstantionsComplete(); } diff --git a/key.core/src/main/java/de/uka/ilkd/key/strategy/feature/NoSelfApplicationFeature.java b/key.core/src/main/java/de/uka/ilkd/key/strategy/feature/NoSelfApplicationFeature.java index 4b9d1c21a48..45d24b20189 100644 --- a/key.core/src/main/java/de/uka/ilkd/key/strategy/feature/NoSelfApplicationFeature.java +++ b/key.core/src/main/java/de/uka/ilkd/key/strategy/feature/NoSelfApplicationFeature.java @@ -12,6 +12,8 @@ import org.key_project.prover.strategy.costbased.feature.Feature; import org.key_project.util.collection.ImmutableList; +import org.checkerframework.checker.nullness.qual.MonotonicNonNull; + /** * This feature checks that the position of application is not contained in the if-formulas. If the * rule application is admissible, zero is returned. @@ -23,7 +25,8 @@ public class NoSelfApplicationFeature extends BinaryTacletAppFeature { private NoSelfApplicationFeature() {} @Override - protected boolean filter(TacletApp p_app, PosInOccurrence pos, Goal goal, MutableState mState) { + protected boolean filter(@MonotonicNonNull TacletApp p_app, PosInOccurrence pos, Goal goal, + MutableState mState) { assert pos != null : "NoSelfApplicationFeature: Need to know the position of the application of the taclet"; diff --git a/key.core/src/main/java/de/uka/ilkd/key/strategy/feature/NonDuplicateAppFeature.java b/key.core/src/main/java/de/uka/ilkd/key/strategy/feature/NonDuplicateAppFeature.java index a3fee055c1c..e7591cfd7ce 100644 --- a/key.core/src/main/java/de/uka/ilkd/key/strategy/feature/NonDuplicateAppFeature.java +++ b/key.core/src/main/java/de/uka/ilkd/key/strategy/feature/NonDuplicateAppFeature.java @@ -10,6 +10,8 @@ import org.key_project.prover.strategy.costbased.MutableState; import org.key_project.prover.strategy.costbased.feature.Feature; +import org.checkerframework.checker.nullness.qual.MonotonicNonNull; + /** * Binary feature that returns zero iff a certain Taclet app has not already been performed @@ -19,7 +21,7 @@ public class NonDuplicateAppFeature extends AbstractNonDuplicateAppFeature { public static final Feature INSTANCE = new NonDuplicateAppFeature(); @Override - public boolean filter(TacletApp app, PosInOccurrence pos, + public boolean filter(@MonotonicNonNull TacletApp app, PosInOccurrence pos, Goal goal, MutableState mState) { if (!app.assumesInstantionsComplete()) { return true; @@ -30,8 +32,7 @@ public boolean filter(TacletApp app, PosInOccurrence pos, @Override protected boolean comparePio(TacletApp newApp, TacletApp oldApp, - PosInOccurrence newPio, - PosInOccurrence oldPio) { + PosInOccurrence newPio, PosInOccurrence oldPio) { return oldPio.equals(newPio); } } diff --git a/key.core/src/main/java/de/uka/ilkd/key/strategy/feature/PolynomialValuesCmpFeature.java b/key.core/src/main/java/de/uka/ilkd/key/strategy/feature/PolynomialValuesCmpFeature.java index 02fbda9781b..ffbcce586b3 100644 --- a/key.core/src/main/java/de/uka/ilkd/key/strategy/feature/PolynomialValuesCmpFeature.java +++ b/key.core/src/main/java/de/uka/ilkd/key/strategy/feature/PolynomialValuesCmpFeature.java @@ -103,8 +103,9 @@ protected boolean compare(Polynomial leftPoly, Polynomial rightPoly) { @Override protected boolean filter(TacletApp app, PosInOccurrence pos, Goal goal, MutableState mState) { - return compare(getPolynomial(left, leftCoeff, app, pos, goal, mState), - getPolynomial(right, rightCoeff, app, pos, goal, mState)); + final TacletApp tacletApp = (TacletApp) app; + return compare(getPolynomial(left, leftCoeff, tacletApp, pos, goal, mState), + getPolynomial(right, rightCoeff, tacletApp, pos, goal, mState)); } protected abstract boolean compare(Polynomial leftPoly, Polynomial rightPoly); diff --git a/key.core/src/main/java/de/uka/ilkd/key/strategy/feature/PrintFeature.java b/key.core/src/main/java/de/uka/ilkd/key/strategy/feature/PrintFeature.java index 936b503ba11..72480202f93 100644 --- a/key.core/src/main/java/de/uka/ilkd/key/strategy/feature/PrintFeature.java +++ b/key.core/src/main/java/de/uka/ilkd/key/strategy/feature/PrintFeature.java @@ -38,6 +38,9 @@ public PrintFeature(Feature f) { PosInOccurrence pos, Goal goal, MutableState mState) { RuleAppCost cost = f.computeCost(app, pos, goal, mState); + System.out.println( + prefix + ":" + cost.toString() + ":" + (pos != null ? pos.subTerm() + ":" : "") + ":" + + app.rule().name()); LOGGER.debug("{}:{}:{}{}", prefix, cost.toString(), pos != null ? pos.subTerm() + ":" : "", app.rule().name()); return cost; diff --git a/key.core/src/main/java/de/uka/ilkd/key/strategy/feature/TriggerVarInstantiatedFeature.java b/key.core/src/main/java/de/uka/ilkd/key/strategy/feature/TriggerVarInstantiatedFeature.java index 7f0eb989ef4..be363d63fb2 100644 --- a/key.core/src/main/java/de/uka/ilkd/key/strategy/feature/TriggerVarInstantiatedFeature.java +++ b/key.core/src/main/java/de/uka/ilkd/key/strategy/feature/TriggerVarInstantiatedFeature.java @@ -11,6 +11,8 @@ import org.key_project.prover.strategy.costbased.MutableState; import org.key_project.prover.strategy.costbased.feature.Feature; +import org.checkerframework.checker.nullness.qual.MonotonicNonNull; + public class TriggerVarInstantiatedFeature extends BinaryTacletAppFeature { public static final Feature INSTANCE = new TriggerVarInstantiatedFeature(); @@ -19,7 +21,8 @@ private TriggerVarInstantiatedFeature() { } @Override - protected boolean filter(TacletApp app, PosInOccurrence pos, Goal goal, MutableState mState) { + protected boolean filter(@MonotonicNonNull TacletApp app, PosInOccurrence pos, Goal goal, + MutableState mState) { assert app.taclet().hasTrigger(); SVInstantiationProjection instProj = SVInstantiationProjection diff --git a/key.core/src/main/java/de/uka/ilkd/key/strategy/quantifierHeuristics/Substitution.java b/key.core/src/main/java/de/uka/ilkd/key/strategy/quantifierHeuristics/Substitution.java index 457218bd684..cafa348a2cc 100644 --- a/key.core/src/main/java/de/uka/ilkd/key/strategy/quantifierHeuristics/Substitution.java +++ b/key.core/src/main/java/de/uka/ilkd/key/strategy/quantifierHeuristics/Substitution.java @@ -88,8 +88,7 @@ public Term apply(Term t, Services services) { private Term applySubst(QuantifiableVariable var, Term instance, Term t, TermBuilder tb) { final ClashFreeSubst subst = - new ClashFreeSubst(var, - (JTerm) instance, tb); + new ClashFreeSubst(var, (JTerm) instance, tb); return subst.apply((JTerm) t); } diff --git a/key.core/src/main/java/de/uka/ilkd/key/util/HelperClassForTests.java b/key.core/src/main/java/de/uka/ilkd/key/util/HelperClassForTests.java index 260b9674042..2c026da04b2 100644 --- a/key.core/src/main/java/de/uka/ilkd/key/util/HelperClassForTests.java +++ b/key.core/src/main/java/de/uka/ilkd/key/util/HelperClassForTests.java @@ -25,7 +25,7 @@ import de.uka.ilkd.key.settings.ChoiceSettings; import de.uka.ilkd.key.settings.ProofSettings; import de.uka.ilkd.key.speclang.Contract; -import de.uka.ilkd.key.strategy.Strategy; +import de.uka.ilkd.key.strategy.JavaStrategy; import de.uka.ilkd.key.strategy.StrategyProperties; import org.key_project.util.collection.ImmutableList; @@ -138,7 +138,7 @@ public static void setOneStepSimplificationEnabled(Proof proof, boolean enabled) proof.getSettings().getStrategySettings().getActiveStrategyProperties(); newProps.setProperty(StrategyProperties.OSS_OPTIONS_KEY, newVal); - Strategy.updateStrategySettings(proof, newProps); + JavaStrategy.updateStrategySettings(proof, newProps); OneStepSimplifier.refreshOSS(proof); } } diff --git a/key.core/src/main/java/de/uka/ilkd/key/util/ProofStarter.java b/key.core/src/main/java/de/uka/ilkd/key/util/ProofStarter.java index aa5bcaa2884..70f09ddf693 100644 --- a/key.core/src/main/java/de/uka/ilkd/key/util/ProofStarter.java +++ b/key.core/src/main/java/de/uka/ilkd/key/util/ProofStarter.java @@ -18,7 +18,6 @@ import de.uka.ilkd.key.proof.mgt.ProofEnvironment; import de.uka.ilkd.key.prover.impl.ApplyStrategy; import de.uka.ilkd.key.rule.OneStepSimplifier; -import de.uka.ilkd.key.strategy.Strategy; import de.uka.ilkd.key.strategy.StrategyFactory; import de.uka.ilkd.key.strategy.StrategyProperties; @@ -27,6 +26,7 @@ import org.key_project.prover.engine.ProverTaskListener; import org.key_project.prover.sequent.Sequent; import org.key_project.prover.sequent.SequentFormula; +import org.key_project.prover.strategy.Strategy; import org.key_project.util.collection.ImmutableList; import org.key_project.util.collection.ImmutableSLList; diff --git a/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/firstOrderRules.key b/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/classicalLogic/firstOrderRules.key similarity index 100% rename from key.core/src/main/resources/de/uka/ilkd/key/proof/rules/firstOrderRules.key rename to key.core/src/main/resources/de/uka/ilkd/key/proof/rules/classicalLogic/firstOrderRules.key diff --git a/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/formulaNormalisationRules.key b/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/classicalLogic/formulaNormalisationRules.key similarity index 100% rename from key.core/src/main/resources/de/uka/ilkd/key/proof/rules/formulaNormalisationRules.key rename to key.core/src/main/resources/de/uka/ilkd/key/proof/rules/classicalLogic/formulaNormalisationRules.key diff --git a/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/propRule.key b/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/classicalLogic/propRule.key similarity index 100% rename from key.core/src/main/resources/de/uka/ilkd/key/proof/rules/propRule.key rename to key.core/src/main/resources/de/uka/ilkd/key/proof/rules/classicalLogic/propRule.key diff --git a/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/floatAssignment2UpdateRules.key b/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/float/floatAssignment2UpdateRules.key similarity index 100% rename from key.core/src/main/resources/de/uka/ilkd/key/proof/rules/floatAssignment2UpdateRules.key rename to key.core/src/main/resources/de/uka/ilkd/key/proof/rules/float/floatAssignment2UpdateRules.key diff --git a/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/floatHeader.key b/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/float/floatHeader.key similarity index 100% rename from key.core/src/main/resources/de/uka/ilkd/key/proof/rules/floatHeader.key rename to key.core/src/main/resources/de/uka/ilkd/key/proof/rules/float/floatHeader.key diff --git a/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/floatRules.key b/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/float/floatRules.key similarity index 100% rename from key.core/src/main/resources/de/uka/ilkd/key/proof/rules/floatRules.key rename to key.core/src/main/resources/de/uka/ilkd/key/proof/rules/float/floatRules.key diff --git a/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/floatRulesAssumeStrictfp.key b/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/float/floatRulesAssumeStrictfp.key similarity index 100% rename from key.core/src/main/resources/de/uka/ilkd/key/proof/rules/floatRulesAssumeStrictfp.key rename to key.core/src/main/resources/de/uka/ilkd/key/proof/rules/float/floatRulesAssumeStrictfp.key diff --git a/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/floatRulesCommon.key b/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/float/floatRulesCommon.key similarity index 100% rename from key.core/src/main/resources/de/uka/ilkd/key/proof/rules/floatRulesCommon.key rename to key.core/src/main/resources/de/uka/ilkd/key/proof/rules/float/floatRulesCommon.key diff --git a/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/floatRulesVerifyNormal.key b/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/float/floatRulesVerifyNormal.key similarity index 100% rename from key.core/src/main/resources/de/uka/ilkd/key/proof/rules/floatRulesVerifyNormal.key rename to key.core/src/main/resources/de/uka/ilkd/key/proof/rules/float/floatRulesVerifyNormal.key diff --git a/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/bigint.key b/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/integer/bigint.key similarity index 100% rename from key.core/src/main/resources/de/uka/ilkd/key/proof/rules/bigint.key rename to key.core/src/main/resources/de/uka/ilkd/key/proof/rules/integer/bigint.key diff --git a/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/binaryAxioms.key b/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/integer/binaryAxioms.key similarity index 100% rename from key.core/src/main/resources/de/uka/ilkd/key/proof/rules/binaryAxioms.key rename to key.core/src/main/resources/de/uka/ilkd/key/proof/rules/integer/binaryAxioms.key diff --git a/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/binaryLemmas.key b/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/integer/binaryLemmas.key similarity index 100% rename from key.core/src/main/resources/de/uka/ilkd/key/proof/rules/binaryLemmas.key rename to key.core/src/main/resources/de/uka/ilkd/key/proof/rules/integer/binaryLemmas.key diff --git a/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/bprod.key b/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/integer/bprod.key similarity index 100% rename from key.core/src/main/resources/de/uka/ilkd/key/proof/rules/bprod.key rename to key.core/src/main/resources/de/uka/ilkd/key/proof/rules/integer/bprod.key diff --git a/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/bsum.key b/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/integer/bsum.key similarity index 100% rename from key.core/src/main/resources/de/uka/ilkd/key/proof/rules/bsum.key rename to key.core/src/main/resources/de/uka/ilkd/key/proof/rules/integer/bsum.key diff --git a/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/intDiv.key b/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/integer/intDiv.key similarity index 100% rename from key.core/src/main/resources/de/uka/ilkd/key/proof/rules/intDiv.key rename to key.core/src/main/resources/de/uka/ilkd/key/proof/rules/integer/intDiv.key diff --git a/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/intPow.key b/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/integer/intPow.key similarity index 100% rename from key.core/src/main/resources/de/uka/ilkd/key/proof/rules/intPow.key rename to key.core/src/main/resources/de/uka/ilkd/key/proof/rules/integer/intPow.key diff --git a/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/intRules.key b/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/integer/intRules.key similarity index 100% rename from key.core/src/main/resources/de/uka/ilkd/key/proof/rules/intRules.key rename to key.core/src/main/resources/de/uka/ilkd/key/proof/rules/integer/intRules.key diff --git a/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/intRulesCheckedSemantics.key b/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/integer/intRulesCheckedSemantics.key similarity index 100% rename from key.core/src/main/resources/de/uka/ilkd/key/proof/rules/intRulesCheckedSemantics.key rename to key.core/src/main/resources/de/uka/ilkd/key/proof/rules/integer/intRulesCheckedSemantics.key diff --git a/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/intRulesJavaSemantics.key b/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/integer/intRulesJavaSemantics.key similarity index 100% rename from key.core/src/main/resources/de/uka/ilkd/key/proof/rules/intRulesJavaSemantics.key rename to key.core/src/main/resources/de/uka/ilkd/key/proof/rules/integer/intRulesJavaSemantics.key diff --git a/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/intRulesUncheckedSemantics.key b/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/integer/intRulesUncheckedSemantics.key similarity index 100% rename from key.core/src/main/resources/de/uka/ilkd/key/proof/rules/intRulesUncheckedSemantics.key rename to key.core/src/main/resources/de/uka/ilkd/key/proof/rules/integer/intRulesUncheckedSemantics.key diff --git a/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/integerAssignment2UpdateRules.key b/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/integer/integerAssignment2UpdateRules.key similarity index 100% rename from key.core/src/main/resources/de/uka/ilkd/key/proof/rules/integerAssignment2UpdateRules.key rename to key.core/src/main/resources/de/uka/ilkd/key/proof/rules/integer/integerAssignment2UpdateRules.key diff --git a/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/integer/integerHeader.key b/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/integer/integerHeader.key new file mode 100644 index 00000000000..c605ac1da86 --- /dev/null +++ b/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/integer/integerHeader.key @@ -0,0 +1,97 @@ +/* This file is part of KeY - https://key-project.org + * KeY is licensed under the GNU General Public License Version 2 + * SPDX-License-Identifier: GPL-2.0-only */ + +\sorts { + numbers; + int; + + // these sort are not axiomatised yet; to come in CHARTER + // they are here included to allow us to load Java program that + // contain some methods or fields of type float or double + + real; // TODO @Real +} + +\functions { + + // ---------------------------------------------------------------------------- + // The functions declared below preserve their semantics independently + // from the current integer semantics. + // ---------------------------------------------------------------------------- + + numbers #; + numbers 0(numbers); + numbers 1(numbers); + numbers 2(numbers); + numbers 3(numbers); + numbers 4(numbers); + numbers 5(numbers); + numbers 6(numbers); + numbers 7(numbers); + numbers 8(numbers); + numbers 9(numbers); + numbers neglit(numbers); + + int Z(numbers); + + // arithmetic operators on mathematical integers + int add(int, int); + int neg(int); + int sub(int, int); + int mul(int, int); + int div(int, int); + int mod(int, int); + int pow(int, int); + int log(int, int); + + // comprehensions + int bsum {false, false, true}(int, int, int); + int bprod {false, false, true}(int, int, int); + int sum {true, true}(boolean, int); + int prod {true, true}(boolean, int); + int min {true, true}(boolean, int); + int max {true, true}(boolean, int); + + // functions to indicate undefinedness + int undefinedPow(int, int); + int undefinedLog(int, int); + + // arithmetic operators with modulo semantics + int jmod(int, int); + int jdiv(int, int); + + // shift operations + + // left '>>' right + int shiftright(/* left */ int, /* right */ int); + // left '<<' right + int shiftleft(/* left */ int, /* right */ int); + + // left '>>' right with right >= 0 + int shiftrightPositiveShift(/* left */ int, /* right */ int); + // left '<<' right with right >= 0 + int shiftleftPositiveShift(/* left */ int, /* right */ int); + + // unsignedshift for arbitrary length bitvectors does not make much sense + // therefore only a version with an explicit bitvector size is supported + int unsignedshift(/* left */ int, /* right */ int, /* bitsize */ int); + + // bitmask operations &, |, ^ + int binaryAnd(/* left */ int, /* right */ int); + int binaryOr(/* left */ int, /* right */ int); + int binaryXOr(/* left */ int, /* right */ int); +} + +\predicates { + + // ---------------------------------------------------------------------------- + // The predicates declared below preserve their semantics independently + // from the current integer semantics. + // ---------------------------------------------------------------------------- + + leq(int, int); + lt(int, int); + geq(int, int); + gt(int, int); +} diff --git a/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/integerRulesCommon.key b/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/integer/integerRulesCommon.key similarity index 100% rename from key.core/src/main/resources/de/uka/ilkd/key/proof/rules/integerRulesCommon.key rename to key.core/src/main/resources/de/uka/ilkd/key/proof/rules/integer/integerRulesCommon.key diff --git a/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/integerSimplificationRules.key b/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/integer/integerSimplificationRules.key similarity index 100% rename from key.core/src/main/resources/de/uka/ilkd/key/proof/rules/integerSimplificationRules.key rename to key.core/src/main/resources/de/uka/ilkd/key/proof/rules/integer/integerSimplificationRules.key diff --git a/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/integerHeader.key b/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/integer/javaIntegerHeader.key similarity index 66% rename from key.core/src/main/resources/de/uka/ilkd/key/proof/rules/integerHeader.key rename to key.core/src/main/resources/de/uka/ilkd/key/proof/rules/integer/javaIntegerHeader.key index 73337d3d4d9..4e76e26fba3 100644 --- a/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/integerHeader.key +++ b/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/integer/javaIntegerHeader.key @@ -1,59 +1,6 @@ -/* This file is part of KeY - https://key-project.org - * KeY is licensed under the GNU General Public License Version 2 - * SPDX-License-Identifier: GPL-2.0-only */ - -\sorts { - numbers; - int; - - // these sort are not axiomatised yet; to come in CHARTER - // they are here included to allow us to load Java program that - // contain some methods or fields of type float or double - - real; // TODO @Real -} - \functions { - - // ---------------------------------------------------------------------------- - // The functions declared below preserve their semantics independently - // from the current integer semantics. - // ---------------------------------------------------------------------------- - - numbers #; - numbers 0(numbers); - numbers 1(numbers); - numbers 2(numbers); - numbers 3(numbers); - numbers 4(numbers); - numbers 5(numbers); - numbers 6(numbers); - numbers 7(numbers); - numbers 8(numbers); - numbers 9(numbers); - numbers neglit(numbers); - - int Z(numbers); int C(numbers); - // arithmetic operators on mathematical integers - int add(int, int); - int neg(int); - int sub(int, int); - int mul(int, int); - int div(int, int); - int mod(int, int); - int pow(int, int); - int log(int, int); - - // comprehensions - int bsum {false, false, true}(int, int, int); - int bprod {false, false, true}(int, int, int); - int sum {true, true}(boolean, int); - int prod {true, true}(boolean, int); - int min {true, true}(boolean, int); - int max {true, true}(boolean, int); - // max and min constants int byte_MAX; int byte_MIN; @@ -77,10 +24,6 @@ int short_HALFRANGE; int short_RANGE; - // functions to indicate undefinedness - int undefinedPow(int, int); - int undefinedLog(int, int); - // functions to indicate overflows int javaUnaryMinusIntOverFlow(int); int javaUnaryMinusLongOverFlow(int); @@ -102,8 +45,6 @@ int javaCastCharOverFlow(int); // arithmetic operators with modulo semantics - int jmod(int, int); - int jdiv(int, int); int unaryMinusJint(int); int unaryMinusJlong(int); int addJint(int, int); @@ -126,22 +67,6 @@ int bitwiseNegateJint(int); int bitwiseNegateJlong(int); - // shift operations - - // left '>>' right - int shiftright(/* left */ int, /* right */ int); - // left '<<' right - int shiftleft(/* left */ int, /* right */ int); - - // left '>>' right with right >= 0 - int shiftrightPositiveShift(/* left */ int, /* right */ int); - // left '<<' right with right >= 0 - int shiftleftPositiveShift(/* left */ int, /* right */ int); - - // unsignedshift for arbitrary length bitvectors does not make much sense - // therefore only a version with an explicit bitvector size is supported - int unsignedshift(/* left */ int, /* right */ int, /* bitsize */ int); - // bitvector operations as in Java with bitvector sizes 32 (int) and 64 (long) // right op only the lower 5 bits/6 bits (i.e., range is always 0..31 inclusive for int and 0..63 incl. for long int shiftrightJint(int, int); @@ -153,11 +78,6 @@ int unsignedshiftrightJint(int, int); int unsignedshiftrightJlong(int, int); - // bitmask operations &, |, ^ - int binaryAnd(/* left */ int, /* right */ int); - int binaryOr(/* left */ int, /* right */ int); - int binaryXOr(/* left */ int, /* right */ int); - // bitmask operations for Java int orJint(int, int); int orJlong(int, int); @@ -236,17 +156,6 @@ } \predicates { - - // ---------------------------------------------------------------------------- - // The predicates declared below preserve their semantics independently - // from the current integer semantics. - // ---------------------------------------------------------------------------- - - leq(int, int); - lt(int, int); - geq(int, int); - gt(int, int); - // ---------------------------------------------------------------------------- // The functions declared below change their semantics when switching the // used integer semantics. diff --git a/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/javaRules.key b/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/javaRules.key index 8786c5308b5..b0ea5496980 100644 --- a/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/javaRules.key +++ b/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/javaRules.key @@ -330,14 +330,13 @@ // ---------- rules for array store ---------------// - array_self_reference { \schemaVar \term Heap heapSV; \assumes(wellFormed(heapSV) ==> array = null) \find(arrayStoreValid(array, G::select(heapSV, array, arr(idx)))) \sameUpdateLevel \replacewith(true) - \heuristics(simplify) + \heuristics(simplify_java) }; // author: scheben; correctness proven in KeY for G = Object @@ -348,7 +347,7 @@ \find(arrayStoreValid(array, EQ)) \sameUpdateLevel \replacewith(true) - \heuristics(simplify) + \heuristics(simplify_java) }; null_can_always_be_stored_in_a_reference_type_array { @@ -357,14 +356,14 @@ \sameUpdateLevel \varcond(\isReferenceArray(array)) \replacewith(true) - \heuristics(simplify) + \heuristics(simplify_java) }; /* array_store_known_dynamic_array_type_prim { \find (arrayStoreValid(G::(idx), vint_val)) \varcond(\isReference(G)) \replacewith(#arrayBaseInstanceOf(G::(idx), vint_val) = TRUE) - \heuristics(simplify) + \heuristics(simplify_java) \displayname "known dynamic array type" }; */ @@ -376,7 +375,7 @@ \varcond(\isReference [non_null](J)) \replacewith(obj = null | #arrayBaseInstanceOf(J::exactInstance(array), obj) = TRUE) - \heuristics(simplify) + \heuristics(simplify_java) \displayname "known dynamic array type" }; @@ -1343,52 +1342,52 @@ ifEnterThen { \find(\modality{#allmodal}{.. #loc=true; if (#loc) #s0 ...}\endmodality (post)) \replacewith(\modality{#allmodal}{.. #loc=true; #s0 ...}\endmodality (post)) - \heuristics(simplify) + \heuristics(simplify_java) }; ifSkipThen { \find(\modality{#allmodal}{.. #loc=false; if (#loc) #s0 ...}\endmodality (post)) \replacewith(\modality{#allmodal}{.. #loc=false; ...}\endmodality (post)) - \heuristics(simplify) + \heuristics(simplify_java) }; ifElseSkipElse { \find(\modality{#allmodal}{.. #loc=true; if (#loc) #s0 else #s1 ...}\endmodality (post)) \replacewith(\modality{#allmodal}{.. #loc=true; #s0 ...}\endmodality (post)) - \heuristics(simplify) + \heuristics(simplify_java) }; ifElseSkipThen { \find(\modality{#allmodal}{.. #loc=false; if (#loc) #s0 else #s1 ...}\endmodality (post)) \replacewith(\modality{#allmodal}{.. #loc=false; #s1 ...}\endmodality (post)) - \heuristics(simplify) + \heuristics(simplify_java) }; ifEnterThenConditionInBlock { \find(\modality{#allmodal}{.. { #loc=true; } if (#loc) #s0 ...}\endmodality (post)) \replacewith(\modality{#allmodal}{.. { #loc=true; } #s0 ...}\endmodality (post)) - \heuristics(simplify) + \heuristics(simplify_java) \displayname "ifEnterThen" }; ifSkipThenConditionInBlock { \find(\modality{#allmodal}{.. { #loc=false; } if (#loc) #s0 ...}\endmodality (post)) \replacewith(\modality{#allmodal}{.. { #loc=false; } ...}\endmodality (post)) - \heuristics(simplify) + \heuristics(simplify_java) \displayname "ifSkipThen" }; ifElseSkipElseConditionInBlock { \find(\modality{#allmodal}{.. { #loc=true;} if (#loc) #s0 else #s1 ...}\endmodality (post)) \replacewith(\modality{#allmodal}{.. { #loc=true;} #s0 ...}\endmodality (post)) - \heuristics(simplify) + \heuristics(simplify_java) \displayname "ifElseSkipElse" }; ifElseSkipThenConditionInBlock { \find(\modality{#allmodal}{.. { #loc=false; } if (#loc) #s0 else #s1 ...}\endmodality (post)) \replacewith(\modality{#allmodal}{.. { #loc=false; } #s1 ...}\endmodality (post)) - \heuristics(simplify) + \heuristics(simplify_java) \displayname "ifElseSkipThen" }; @@ -1524,7 +1523,7 @@ insert_constant_value { \find(#cv) \replacewith(#constantvalue(#cv)) - \heuristics(concrete) + \heuristics(concrete_java) }; // ------------------------------------------------------------------------ @@ -4057,7 +4056,7 @@ \find(boolean::select(heap, null, alphaObj::)) \sameUpdateLevel \replacewith(TRUE) - \heuristics(confluence_restricted, simplify) + \heuristics(confluence_restricted, simplify_java) \displayname "initialized classes have been prepared" }; @@ -4066,7 +4065,7 @@ \find(boolean::select(heap, null, alphaObj::)) \sameUpdateLevel \replacewith(TRUE) - \heuristics(confluence_restricted, simplify) + \heuristics(confluence_restricted, simplify_java) \displayname "classes being initialized have been prepared" }; @@ -4075,7 +4074,7 @@ \find(boolean::select(heap, null, alphaObj::)) \sameUpdateLevel \replacewith(FALSE) - \heuristics(confluence_restricted, simplify) + \heuristics(confluence_restricted, simplify_java) \displayname "initialized class is not erroneous" }; @@ -4084,7 +4083,7 @@ \find(boolean::select(heap, null, alphaObj::)) \sameUpdateLevel \replacewith(FALSE) - \heuristics(confluence_restricted, simplify) + \heuristics(confluence_restricted, simplify_java) \displayname "initialisation process has already terminated" }; @@ -4093,7 +4092,7 @@ \find(boolean::select(heap, null, alphaObj::)) \sameUpdateLevel \replacewith(FALSE) - \heuristics(confluence_restricted, simplify) + \heuristics(confluence_restricted, simplify_java) \displayname "initialization process has already terminated (or never begun)" }; @@ -4103,7 +4102,7 @@ \sameUpdateLevel \varcond(\sub(betaObj, alphaObj)) \replacewith(FALSE) - \heuristics(confluence_restricted, simplify) + \heuristics(confluence_restricted, simplify_java) \displayname "erroneous classes have no initialized subclasses" }; @@ -4113,7 +4112,7 @@ \sameUpdateLevel \varcond(\isReference [non_null](betaObj), \strict \sub(betaObj, alphaObj)) \replacewith(TRUE) - \heuristics(simplify) + \heuristics(simplify_java) }; superclasses_of_initialized_classes_are_prepared { @@ -4122,6 +4121,6 @@ \sameUpdateLevel \varcond(\sub(betaObj, alphaObj)) \replacewith(TRUE) - \heuristics(simplify) + \heuristics(simplify_java) }; } diff --git a/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/ldt.key b/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/ldt.key index d54f2527f00..e5d9b942ccd 100644 --- a/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/ldt.key +++ b/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/ldt.key @@ -16,16 +16,17 @@ ruleSetsDeclarations, soundDefaultContracts, boolean, - integerHeader, + "./integer/integerHeader.key", + "./integer/javaIntegerHeader.key", javaHeader, - floatHeader, + "./float/floatHeader.key", heap, - locSets, - permission, + "./locset/locSets.key", + "./permission/permission.key", reach, - seq, + "./sequence/seq.key", map, freeADT, wellfound, - charListHeader, + "./string/charListHeader.key", types; diff --git a/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/locSets.key b/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/locset/locSets.key similarity index 100% rename from key.core/src/main/resources/de/uka/ilkd/key/proof/rules/locSets.key rename to key.core/src/main/resources/de/uka/ilkd/key/proof/rules/locset/locSets.key diff --git a/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/locSetsRules.key b/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/locset/locSetsRules.key similarity index 100% rename from key.core/src/main/resources/de/uka/ilkd/key/proof/rules/locSetsRules.key rename to key.core/src/main/resources/de/uka/ilkd/key/proof/rules/locset/locSetsRules.key diff --git a/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/permission.key b/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/permission/permission.key similarity index 100% rename from key.core/src/main/resources/de/uka/ilkd/key/proof/rules/permission.key rename to key.core/src/main/resources/de/uka/ilkd/key/proof/rules/permission/permission.key diff --git a/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/permissionRules.key b/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/permission/permissionRules.key similarity index 100% rename from key.core/src/main/resources/de/uka/ilkd/key/proof/rules/permissionRules.key rename to key.core/src/main/resources/de/uka/ilkd/key/proof/rules/permission/permissionRules.key diff --git a/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/ruleSetsDeclarations.key b/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/ruleSetsDeclarations.key index 8141bd44ac4..1be9befdfbd 100644 --- a/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/ruleSetsDeclarations.key +++ b/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/ruleSetsDeclarations.key @@ -24,6 +24,8 @@ modal_tautology; simplify_prog; + simplify_java; + concrete_java; // updates update_elim; diff --git a/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/seq.key b/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/sequence/seq.key similarity index 100% rename from key.core/src/main/resources/de/uka/ilkd/key/proof/rules/seq.key rename to key.core/src/main/resources/de/uka/ilkd/key/proof/rules/sequence/seq.key diff --git a/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/seqCoreRules.key b/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/sequence/seqCoreRules.key similarity index 100% rename from key.core/src/main/resources/de/uka/ilkd/key/proof/rules/seqCoreRules.key rename to key.core/src/main/resources/de/uka/ilkd/key/proof/rules/sequence/seqCoreRules.key diff --git a/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/seqEq.key b/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/sequence/seqEq.key similarity index 100% rename from key.core/src/main/resources/de/uka/ilkd/key/proof/rules/seqEq.key rename to key.core/src/main/resources/de/uka/ilkd/key/proof/rules/sequence/seqEq.key diff --git a/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/seqPerm.key b/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/sequence/seqPerm.key similarity index 100% rename from key.core/src/main/resources/de/uka/ilkd/key/proof/rules/seqPerm.key rename to key.core/src/main/resources/de/uka/ilkd/key/proof/rules/sequence/seqPerm.key diff --git a/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/seqPerm2.key b/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/sequence/seqPerm2.key similarity index 100% rename from key.core/src/main/resources/de/uka/ilkd/key/proof/rules/seqPerm2.key rename to key.core/src/main/resources/de/uka/ilkd/key/proof/rules/sequence/seqPerm2.key diff --git a/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/seqRules.key b/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/sequence/seqRules.key similarity index 100% rename from key.core/src/main/resources/de/uka/ilkd/key/proof/rules/seqRules.key rename to key.core/src/main/resources/de/uka/ilkd/key/proof/rules/sequence/seqRules.key diff --git a/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/standardRules.key b/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/standardRules.key index 96c6fc2136b..8ade92ee39c 100644 --- a/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/standardRules.key +++ b/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/standardRules.key @@ -10,29 +10,29 @@ // without a good reason. // general propositional and first-order rules -\include propRule; -\include firstOrderRules; +\include "./classicalLogic/propRule.key"; +\include "./classicalLogic/firstOrderRules.key"; \include ifThenElseRules; -\include formulaNormalisationRules; +\include "./classicalLogic/formulaNormalisationRules.key"; \include updateRules; // integer rules -\include integerRulesCommon; -\include intRules, - intRulesUncheckedSemantics, - intRulesCheckedSemantics, - intRulesJavaSemantics; -\include integerSimplificationRules; -\include intDiv; -\include bsum, bprod; -\include binaryAxioms, binaryLemmas; -\include intPow; +\include "./integer/integerRulesCommon.key"; +\include "./integer/intRules.key", + "./integer/intRulesUncheckedSemantics.key", + "./integer/intRulesCheckedSemantics.key", + "./integer/intRulesJavaSemantics.key"; +\include "./integer/integerSimplificationRules.key"; +\include "./integer/intDiv.key"; +\include "./integer/bsum.key", "./integer/bprod.key"; +\include "./integer/binaryAxioms.key", "./integer/binaryLemmas.key"; +\include "./integer/intPow.key"; // float rules -\include floatRulesCommon; -\include floatRules, - floatRulesVerifyNormal, - floatRulesAssumeStrictfp; +\include "./float/floatRulesCommon.key"; +\include "./float/floatRules.key", + "./float/floatRulesVerifyNormal.key", + "./float/floatRulesAssumeStrictfp.key"; // \include abs; @@ -40,13 +40,13 @@ \include genericRules; // must go before heap, seq \include booleanRules; \include epsilon; -\include locSetsRules; // must go before heap +\include "./locset/locSetsRules.key"; // must go before heap \include heapRules; -\include permissionRules; +\include "./permission/permissionRules.key"; \include reachRules; -\include seqCoreRules, seqRules; -\include seqPerm; -\include seqPerm2; +\include "./sequence/seqCoreRules.key", "./sequence/seqRules.key"; +\include "./sequence/seqPerm.key"; +\include "./sequence/seqPerm2.key"; // rules for Java (order does not matter, since not provable anyway) \include javaRules; @@ -54,20 +54,20 @@ \include activeUse; \include instanceAllocation; \include java5; -\include integerAssignment2UpdateRules; -\include floatAssignment2UpdateRules; -\include bigint; +\include "./integer/integerAssignment2UpdateRules.key"; +\include "./float/floatAssignment2UpdateRules.key"; +\include "./integer/bigint.key"; \include adtProgramDecompositionRules; // wellfounded relation \include precRules; // rules for strings and regular expressions -\include charListRules; -\include regExTheory; // TODO: fix rules and uncomment +\include "./string/charListRules.key"; +\include "./string/regExTheory.key"; // rules for information flow verification -\include seqEq; +\include "./sequence/seqEq.key"; \include infFlow; // size rules for maps diff --git a/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/charListHeader.key b/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/string/charListHeader.key similarity index 100% rename from key.core/src/main/resources/de/uka/ilkd/key/proof/rules/charListHeader.key rename to key.core/src/main/resources/de/uka/ilkd/key/proof/rules/string/charListHeader.key diff --git a/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/charListRules.key b/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/string/charListRules.key similarity index 100% rename from key.core/src/main/resources/de/uka/ilkd/key/proof/rules/charListRules.key rename to key.core/src/main/resources/de/uka/ilkd/key/proof/rules/string/charListRules.key diff --git a/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/regExAxioms.key b/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/string/regExAxioms.key similarity index 100% rename from key.core/src/main/resources/de/uka/ilkd/key/proof/rules/regExAxioms.key rename to key.core/src/main/resources/de/uka/ilkd/key/proof/rules/string/regExAxioms.key diff --git a/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/regExHeader.key b/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/string/regExHeader.key similarity index 100% rename from key.core/src/main/resources/de/uka/ilkd/key/proof/rules/regExHeader.key rename to key.core/src/main/resources/de/uka/ilkd/key/proof/rules/string/regExHeader.key diff --git a/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/regExLemma.key b/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/string/regExLemma.key similarity index 100% rename from key.core/src/main/resources/de/uka/ilkd/key/proof/rules/regExLemma.key rename to key.core/src/main/resources/de/uka/ilkd/key/proof/rules/string/regExLemma.key diff --git a/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/regExLemmaProven.key b/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/string/regExLemmaProven.key similarity index 100% rename from key.core/src/main/resources/de/uka/ilkd/key/proof/rules/regExLemmaProven.key rename to key.core/src/main/resources/de/uka/ilkd/key/proof/rules/string/regExLemmaProven.key diff --git a/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/regExTheory.key b/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/string/regExTheory.key similarity index 100% rename from key.core/src/main/resources/de/uka/ilkd/key/proof/rules/regExTheory.key rename to key.core/src/main/resources/de/uka/ilkd/key/proof/rules/string/regExTheory.key diff --git a/key.core/src/test/java/de/uka/ilkd/key/parser/TestParser.java b/key.core/src/test/java/de/uka/ilkd/key/parser/TestParser.java index 5bba4dd7fe9..a863637be54 100644 --- a/key.core/src/test/java/de/uka/ilkd/key/parser/TestParser.java +++ b/key.core/src/test/java/de/uka/ilkd/key/parser/TestParser.java @@ -6,6 +6,7 @@ import java.io.File; import java.io.IOException; import java.net.MalformedURLException; +import java.nio.file.Path; import de.uka.ilkd.key.control.DefaultUserInterfaceControl; import de.uka.ilkd.key.control.KeYEnvironment; @@ -48,7 +49,7 @@ public void testRelativeInclude() throws IOException { expected.put(include.toString(), RuleSourceFactory.initRuleFile(include.toURI().toURL())); final String keyFile = "\\include \"" + include.getPath() + "\";"; KeyAst.File file = ParsingFacade.parseFile(CharStreams.fromString(keyFile)); - Includes actual = file.getIncludes(new File(".").toURI().toURL()); + Includes actual = file.getIncludes(Path.of(".")); // `Includes` does not provide an `Object#equals()` redefinition for the // moment, at least compare the list of filenames diff --git a/key.core/src/test/java/de/uka/ilkd/key/proof/runallproofs/performance/DataRecordingStrategy.java b/key.core/src/test/java/de/uka/ilkd/key/proof/runallproofs/performance/DataRecordingStrategy.java index 301292fd168..d4723f0fec6 100644 --- a/key.core/src/test/java/de/uka/ilkd/key/proof/runallproofs/performance/DataRecordingStrategy.java +++ b/key.core/src/test/java/de/uka/ilkd/key/proof/runallproofs/performance/DataRecordingStrategy.java @@ -8,11 +8,11 @@ import de.uka.ilkd.key.proof.Goal; import de.uka.ilkd.key.proof.Proof; import de.uka.ilkd.key.strategy.JavaCardDLStrategy; -import de.uka.ilkd.key.strategy.RuleAppCostCollector; import org.key_project.prover.proof.ProofGoal; import org.key_project.prover.rules.RuleApp; import org.key_project.prover.sequent.PosInOccurrence; +import org.key_project.prover.strategy.RuleAppCostCollector; import org.key_project.prover.strategy.costbased.MutableState; import org.key_project.prover.strategy.costbased.RuleAppCost; @@ -44,10 +44,10 @@ class DataRecordingStrategy extends JavaCardDLStrategy { } @Override - public > RuleAppCost computeCost( - RuleApp app, PosInOccurrence pio, - Goal goal, - MutableState mState) { + public > @NonNull RuleAppCost computeCost( + @NonNull RuleApp app, @NonNull PosInOccurrence pio, + @NonNull GOAL goal, + @NonNull MutableState mState) { long begin = System.nanoTime(); RuleAppCost result = super.computeCost(app, pio, goal, mState); long end = System.nanoTime(); @@ -56,8 +56,9 @@ class DataRecordingStrategy extends JavaCardDLStrategy { } @Override - public void instantiateApp(RuleApp app, PosInOccurrence pio, Goal goal, - RuleAppCostCollector collector) { + public void instantiateApp(@NonNull RuleApp app, @NonNull PosInOccurrence pio, + @NonNull Goal goal, + @NonNull RuleAppCostCollector collector) { long begin = System.nanoTime(); super.instantiateApp(app, pio, goal, collector); long end = System.nanoTime(); diff --git a/key.core/src/test/java/de/uka/ilkd/key/proof/runallproofs/performance/DataRecordingTestFile.java b/key.core/src/test/java/de/uka/ilkd/key/proof/runallproofs/performance/DataRecordingTestFile.java index 1481b332aee..0122cb5e81a 100644 --- a/key.core/src/test/java/de/uka/ilkd/key/proof/runallproofs/performance/DataRecordingTestFile.java +++ b/key.core/src/test/java/de/uka/ilkd/key/proof/runallproofs/performance/DataRecordingTestFile.java @@ -15,9 +15,9 @@ import de.uka.ilkd.key.proof.runallproofs.proofcollection.TestFile; import de.uka.ilkd.key.proof.runallproofs.proofcollection.TestProperty; import de.uka.ilkd.key.prover.impl.ApplyStrategy; -import de.uka.ilkd.key.strategy.Strategy; import org.key_project.prover.engine.impl.ApplyStrategyInfo; +import org.key_project.prover.strategy.Strategy; import org.jspecify.annotations.NonNull; diff --git a/key.core/src/test/java/de/uka/ilkd/key/rule/TestApplyTaclet.java b/key.core/src/test/java/de/uka/ilkd/key/rule/TestApplyTaclet.java index 9e0c5b0d422..c0ecdcb5e7a 100644 --- a/key.core/src/test/java/de/uka/ilkd/key/rule/TestApplyTaclet.java +++ b/key.core/src/test/java/de/uka/ilkd/key/rule/TestApplyTaclet.java @@ -355,8 +355,8 @@ public void testNoFindTacletWithoutIf() { * proof=new Proof(); proof.setRoot(new Node(proof, initSeq)); IList * goals=ImmSLList.nil(); Goal goal=new Goal(proof.root(),new RuleAppIndex(index)); * goals=goals.prepend(goal); while (goals.size()!=0) { SequentFormula cfma=null; SequentFormula - * userCfma=null; // in the real system the //user would select this IList - * rapplist=ImmSLList.nil(); out="\n"+out+("Goals: "+goals+"\n"); goal=goals.head(); + * userCfma=null; // in the real system the //user would select this IList + * rapplist=ImmSLList.nil(); out="\n"+out+("Goals: "+goals+"\n"); goal=goals.head(); * Iterator it=goal.node().sequent().antecedent().iterator(); while * (it.hasNext()) { userCfma=it.next(); rapplist=rapplist.prepend(goal.ruleAppIndex(). * getTacletAppAtAndBelow(TacletFilter.TRUE, new PosInOccurrence(userCfma, PosInTerm.TOP_LEVEL, @@ -393,7 +393,7 @@ public void testNoFindTacletWithoutIf() { @Test public void testIncompleteNoFindTacletApp() { NoPosTacletApp cut = TacletForTests.getRules().lookup("TestApplyTaclet_cut"); - assertFalse(cut.complete(), "TacletApp should not be complete, as b is not instantiated"); + assertFalse(cut.complete(), "ITacletApp should not be complete, as b is not instantiated"); SchemaVariable b = TacletForTests.getSchemaVariables().lookup(new Name("b")); assertTrue(cut.uninstantiatedVars().contains(b), "b should be in the set of not instantiated SVs"); @@ -403,7 +403,7 @@ public void testIncompleteNoFindTacletApp() { public void testIncompleteSuccTacletApp() { TacletApp orright = TacletForTests.getRules().lookup("or_right"); assertFalse(orright.complete(), - "TacletApp should not be complete, as SVs are not instantiated"); + "ITacletApp should not be complete, as SVs are not instantiated"); Services services = TacletForTests.services(); SchemaVariable b = TacletForTests.getSchemaVariables().lookup(new Name("b")); @@ -413,14 +413,14 @@ public void testIncompleteSuccTacletApp() { "b and c should be in the set of not instantiated SVs"); orright = orright.addInstantiation(b, TacletForTests.parseTerm("A"), false, services); assertFalse(orright.complete(), - "TacletApp should not be complete, as B is not instantiated"); + "ITacletApp should not be complete, as B is not instantiated"); orright = orright.addInstantiation(c, TacletForTests.parseTerm("B"), false, services); - assertFalse(orright.complete(), "TacletApp should not be complete, as Position unknown"); + assertFalse(orright.complete(), "ITacletApp should not be complete, as Position unknown"); Sequent seq = proof[0].root().sequent(); orright = orright.setPosInOccurrence( new PosInOccurrence(seq.succedent().get(0), PosInTerm.getTopLevel(), false), services); assertTrue(orright.complete(), - "TacletApp should now be complete with Position set and SVs " + "instantiated"); + "ITacletApp should now be complete with Position set and SVs " + "instantiated"); } diff --git a/key.core/src/test/java/de/uka/ilkd/key/rule/TestCollisionResolving.java b/key.core/src/test/java/de/uka/ilkd/key/rule/TestCollisionResolving.java index 381b8b05b8b..a0f0f4aaad0 100644 --- a/key.core/src/test/java/de/uka/ilkd/key/rule/TestCollisionResolving.java +++ b/key.core/src/test/java/de/uka/ilkd/key/rule/TestCollisionResolving.java @@ -235,12 +235,12 @@ public void testNameConflict1() { /* * IList sviList=taclet.matchIf (seq, * taclet.match(semiseq.get(0).formula(), taclet.find(), - * MatchConditions.EMPTY_MATCHCONDITIONS, null, Constraint.BOTTOM), null); TacletApp app = + * MatchConditions.EMPTY_MATCHCONDITIONS, null, Constraint.BOTTOM), null); ITacletApp app = * PosTacletApp.createPosTacletApp(taclet, sviList.head(), pos); */ TacletApp app1 = app.prepareUserInstantiation(services); assertNotSame(app, app1, - "A different TacletApp should have been created to resolve" + " name conflicts"); + "A different ITacletApp should have been created to resolve" + " name conflicts"); assertNotEquals(((JTerm) app1.instantiations().getInstantiation(u)).op().name(), ((JTerm) app1.instantiations().getInstantiation(v)).op().name(), @@ -315,10 +315,10 @@ public void testNameConflictAfterInput() throws SVInstantiationException { * Sequent seq=Sequent.createSuccSequent(semiseq); PosInOccurrence pos=new * PosInOccurrence(semiseq.get(1), PosInTerm.TOP_LEVEL.down(0), seq); IList * sviList=taclet.matchIf (seq, taclet.match(semiseq.get(1).formula().sub(0), taclet.find(), - * taclet.createInitialInstantiation())); TacletApp app = - * PosTacletApp.createPosTacletApp(taclet, sviList.head(), pos); TacletApp + * taclet.createInitialInstantiation())); ITacletApp app = + * PosTacletApp.createPosTacletApp(taclet, sviList.head(), pos); ITacletApp * app1=app.prepareUserInstantiation(); - * assertTue("A different TacletApp should have been created to resolve" +" name conflicts", + * assertTue("A different ITacletApp should have been created to resolve" +" name conflicts", * app!=app1); assertTrue("The names of x and the instantiations of v should be different", * !(new Name("x")).equals (((Term)app1.instantiations().getInstantiation(v)).op().name())); * diff --git a/key.core/src/test/resources/de/uka/ilkd/key/nparser/taclets.old.txt b/key.core/src/test/resources/de/uka/ilkd/key/nparser/taclets.old.txt index a95305f3dbf..212869c6f5b 100644 --- a/key.core/src/test/resources/de/uka/ilkd/key/nparser/taclets.old.txt +++ b/key.core/src/test/resources/de/uka/ilkd/key/nparser/taclets.old.txt @@ -1,5 +1,5 @@ # This files contains representation of taclets, which are accepted and revised. -# Date: Tue Jul 29 22:37:48 CEST 2025 +# Date: Wed Nov 19 11:46:34 CET 2025 == abortJavaCardTransactionAPI (abortJavaCardTransactionAPI) ========================================= abortJavaCardTransactionAPI { @@ -1148,7 +1148,7 @@ array_self_reference { \assumes ([wellFormed(heapSV)]==>[equals(array,null)]) \find(arrayStoreValid(array,G::select(heapSV,array,arr(idx)))) \sameUpdateLevel\replacewith(true) -\heuristics(simplify) +\heuristics(simplify_java) Choices: programRules:Java} ----------------------------------------------------- == array_self_reference_eq (array_self_reference_eq) ========================================= @@ -1156,7 +1156,7 @@ array_self_reference_eq { \assumes ([wellFormed(heapSV),equals(G::select(heapSV,array,arr(idx)),EQ)]==>[equals(array,null)]) \find(arrayStoreValid(array,EQ)) \sameUpdateLevel\replacewith(true) -\heuristics(simplify) +\heuristics(simplify_java) Choices: programRules:Java} ----------------------------------------------------- == array_store_known_dynamic_array_type (known dynamic array type) ========================================= @@ -1165,7 +1165,7 @@ array_store_known_dynamic_array_type { \find(arrayStoreValid(array,obj)) \sameUpdateLevel\varcond(\isReference[non_null]( J )) \replacewith(or(equals(obj,null),equals(#arrayBaseInstanceOf(J::exactInstance(array),obj),TRUE))) -\heuristics(simplify) +\heuristics(simplify_java) Choices: programRules:Java} ----------------------------------------------------- == asinIsNaN (asinIsNaN) ========================================= @@ -10007,7 +10007,7 @@ ifElseSkipElse { #loc = true; #s0 ... }}| (post)) -\heuristics(simplify) +\heuristics(simplify_java) Choices: programRules:Java} ----------------------------------------------------- == ifElseSkipElseConditionInBlock (ifElseSkipElse) ========================================= @@ -10025,7 +10025,7 @@ ifElseSkipElseConditionInBlock { } #s0 ... }}| (post)) -\heuristics(simplify) +\heuristics(simplify_java) Choices: programRules:Java} ----------------------------------------------------- == ifElseSkipThen (ifElseSkipThen) ========================================= @@ -10039,7 +10039,7 @@ ifElseSkipThen { #loc = false; #s1 ... }}| (post)) -\heuristics(simplify) +\heuristics(simplify_java) Choices: programRules:Java} ----------------------------------------------------- == ifElseSkipThenConditionInBlock (ifElseSkipThen) ========================================= @@ -10057,7 +10057,7 @@ ifElseSkipThenConditionInBlock { } #s1 ... }}| (post)) -\heuristics(simplify) +\heuristics(simplify_java) Choices: programRules:Java} ----------------------------------------------------- == ifElseSplit (ifElseSplit) ========================================= @@ -10131,7 +10131,7 @@ ifEnterThen { #loc = true; #s0 ... }}| (post)) -\heuristics(simplify) +\heuristics(simplify_java) Choices: programRules:Java} ----------------------------------------------------- == ifEnterThenConditionInBlock (ifEnterThen) ========================================= @@ -10148,7 +10148,7 @@ ifEnterThenConditionInBlock { } #s0 ... }}| (post)) -\heuristics(simplify) +\heuristics(simplify_java) Choices: programRules:Java} ----------------------------------------------------- == ifEqualsInteger (ifEqualsInteger) ========================================= @@ -10337,7 +10337,7 @@ ifSkipThen { \replacewith(#allmodal ((modal operator))|{{ .. #loc = false; ... }}| (post)) -\heuristics(simplify) +\heuristics(simplify_java) Choices: programRules:Java} ----------------------------------------------------- == ifSkipThenConditionInBlock (ifSkipThen) ========================================= @@ -10353,7 +10353,7 @@ ifSkipThenConditionInBlock { #loc = false; } ... }}| (post)) -\heuristics(simplify) +\heuristics(simplify_java) Choices: programRules:Java} ----------------------------------------------------- == ifSplit (ifElseSplit) ========================================= @@ -11307,7 +11307,7 @@ Choices: true} insert_constant_value { \find(#cv) \replacewith(#constantvalue(#cv)) -\heuristics(concrete) +\heuristics(concrete_java) Choices: programRules:Java} ----------------------------------------------------- == insert_eq_all (insert_eq_all) ========================================= @@ -11633,12 +11633,6 @@ intersectionSetMinusItself_2 { \heuristics(concrete) Choices: programRules:Java} ----------------------------------------------------- -== introduceAxiom (introduceAxiom) ========================================= -introduceAxiom { -\add [cutFormula]==>[] - -Choices: true} ------------------------------------------------------ == irrflConcrete1 (irrflConcrete1) ========================================= irrflConcrete1 { \find(lt(i,i)==>) @@ -13931,7 +13925,7 @@ null_can_always_be_stored_in_a_reference_type_array { \find(arrayStoreValid(array,null)) \sameUpdateLevel\varcond(\isReferenceArray(array (GOS term))) \replacewith(true) -\heuristics(simplify) +\heuristics(simplify_java) Choices: programRules:Java} ----------------------------------------------------- == observerDependency (observerDependency) ========================================= diff --git a/key.ncore.calculus/src/main/java/org/key_project/prover/rules/IBuiltInRule.java b/key.ncore.calculus/src/main/java/org/key_project/prover/rules/IBuiltInRule.java new file mode 100644 index 00000000000..90c4c37cffa --- /dev/null +++ b/key.ncore.calculus/src/main/java/org/key_project/prover/rules/IBuiltInRule.java @@ -0,0 +1,29 @@ +/* This file is part of KeY - https://key-project.org + * KeY is licensed under the GNU General Public License Version 2 + * SPDX-License-Identifier: GPL-2.0-only */ +package org.key_project.prover.rules; + +import org.key_project.logic.LogicServices; +import org.key_project.prover.proof.ProofGoal; +import org.key_project.prover.sequent.PosInOccurrence; + +import org.jspecify.annotations.NonNull; + +public interface IBuiltInRule> extends Rule, RuleExecutor { + /** + * returns true iff a rule is applicable at the given position. This does not necessarily mean + * that a rule application will change the goal (this decision is made due to performance + * reasons) + */ + boolean isApplicable(GOAL goal, PosInOccurrence pio); + + boolean isApplicableOnSubTerms(); + + IBuiltInRuleApp createApp(PosInOccurrence pos, LogicServices services); + + @Override + default @NonNull RuleExecutor<@NonNull GOAL> getExecutor() { + return this; + } + +} diff --git a/key.ncore.calculus/src/main/java/org/key_project/prover/rules/IBuiltInRuleApp.java b/key.ncore.calculus/src/main/java/org/key_project/prover/rules/IBuiltInRuleApp.java new file mode 100644 index 00000000000..e616659de6c --- /dev/null +++ b/key.ncore.calculus/src/main/java/org/key_project/prover/rules/IBuiltInRuleApp.java @@ -0,0 +1,36 @@ +/* This file is part of KeY - https://key-project.org + * KeY is licensed under the GNU General Public License Version 2 + * SPDX-License-Identifier: GPL-2.0-only */ +package org.key_project.prover.rules; + +import org.key_project.prover.proof.ProofGoal; +import org.key_project.prover.sequent.PosInOccurrence; +import org.key_project.util.collection.ImmutableList; + +public interface IBuiltInRuleApp> extends RuleApp { + + /** + * Tries to complete the rule application from the available information. + */ + IBuiltInRuleApp tryToInstantiate(Goal goal); + + IBuiltInRuleApp forceInstantiate(Goal goal); + + /** + * returns true if tryToInstantiate is able to complete the app + * + * @return true if tryToInstantiate is able to complete the app + */ + boolean isSufficientlyComplete(); + + ImmutableList assumesInsts(); + + IBuiltInRuleApp setAssumesInsts(ImmutableList ifInsts); + + IBuiltInRuleApp replacePos(PosInOccurrence newPos); + + /** + * returns the built-in rule of this rule application + */ + IBuiltInRule rule(); +} diff --git a/key.ncore.calculus/src/main/java/org/key_project/prover/rules/ITacletApp.java b/key.ncore.calculus/src/main/java/org/key_project/prover/rules/ITacletApp.java new file mode 100644 index 00000000000..7f1bfa6d2a9 --- /dev/null +++ b/key.ncore.calculus/src/main/java/org/key_project/prover/rules/ITacletApp.java @@ -0,0 +1,45 @@ +/* This file is part of KeY - https://key-project.org + * KeY is licensed under the GNU General Public License Version 2 + * SPDX-License-Identifier: GPL-2.0-only */ +package org.key_project.prover.rules; + +import org.key_project.logic.op.sv.SchemaVariable; +import org.key_project.prover.rules.instantiation.AssumesFormulaInstantiation; +import org.key_project.prover.rules.instantiation.MatchResultInfo; +import org.key_project.prover.rules.instantiation.SVInstantiations; +import org.key_project.util.collection.ImmutableList; +import org.key_project.util.collection.ImmutableSet; + +import org.jspecify.annotations.NonNull; + +public interface ITacletApp extends RuleApp { + + /// returns the taclet associated with this taclet application + Taclet taclet(); + + /** + * returns the instantiations for the application of the Taclet at the specified position. + * + * @return the SVInstantiations needed to instantiate the Taclet + */ + default SVInstantiations instantiations() { + return matchConditions().getInstantiations(); + } + + @NonNull + MatchResultInfo matchConditions(); + + ImmutableList assumesFormulaInstantiations(); + + boolean assumesInstantionsComplete(); + + /** + * returns the variables that have not yet been instantiated and need to be instantiated to + * apply the Taclet. (These are not all SchemaVariables like the one that appear only in the + * addrule sections) + * + * @return ImmutableSet with SchemaVariables that have not been instantiated yet + */ + @NonNull + ImmutableSet uninstantiatedVars(); +} diff --git a/key.ncore.calculus/src/main/java/org/key_project/prover/rules/Rule.java b/key.ncore.calculus/src/main/java/org/key_project/prover/rules/Rule.java index 5fa42cd40ed..3d1ec7dbe13 100644 --- a/key.ncore.calculus/src/main/java/org/key_project/prover/rules/Rule.java +++ b/key.ncore.calculus/src/main/java/org/key_project/prover/rules/Rule.java @@ -3,6 +3,9 @@ * SPDX-License-Identifier: GPL-2.0-only */ package org.key_project.prover.rules; +import java.util.Collections; +import java.util.Iterator; + import org.key_project.logic.Named; import org.key_project.prover.proof.ProofGoal; @@ -11,6 +14,10 @@ /// It provides access to the rule application logic. public interface Rule extends Named { + default Iterator ruleSets() { + return Collections.emptyIterator(); + } + /// Returns the rule executor for this rule. /// The rule executor encapsulates the logic for rule applications. /// @@ -23,5 +30,4 @@ public interface Rule extends Named { default String displayName() { return name().toString(); } - } diff --git a/key.ncore.calculus/src/main/java/org/key_project/prover/rules/Taclet.java b/key.ncore.calculus/src/main/java/org/key_project/prover/rules/Taclet.java index fa599589f7e..9a8c547a060 100644 --- a/key.ncore.calculus/src/main/java/org/key_project/prover/rules/Taclet.java +++ b/key.ncore.calculus/src/main/java/org/key_project/prover/rules/Taclet.java @@ -297,6 +297,7 @@ public ChoiceExpr getChoices() { } /// @return an iterator over the rule sets. + @Override public Iterator ruleSets() { return ruleSets.iterator(); } diff --git a/key.ncore.calculus/src/main/java/org/key_project/prover/strategy/ComponentStrategy.java b/key.ncore.calculus/src/main/java/org/key_project/prover/strategy/ComponentStrategy.java new file mode 100644 index 00000000000..d580e260331 --- /dev/null +++ b/key.ncore.calculus/src/main/java/org/key_project/prover/strategy/ComponentStrategy.java @@ -0,0 +1,27 @@ +/* This file is part of KeY - https://key-project.org + * KeY is licensed under the GNU General Public License Version 2 + * SPDX-License-Identifier: GPL-2.0-only */ +package org.key_project.prover.strategy; + +import java.util.Set; + +import org.key_project.prover.proof.ProofGoal; +import org.key_project.prover.rules.IBuiltInRule; +import org.key_project.prover.rules.RuleSet; +import org.key_project.prover.strategy.costbased.feature.RuleSetDispatchFeature; + +public interface ComponentStrategy> extends Strategy { + enum StrategyAspect { + Cost, Instantiation, Approval; + } + + /// The strategy's cost dispatcher. + RuleSetDispatchFeature getDispatcher(StrategyAspect aspect); + + /// The rule sets this strategy is designed to handle. + Set getResponsibilities(StrategyAspect aspect); + + /// Whether this strategy is responsible for the given [IBuiltInRule]. This is necessary as + /// built-in rules have no rule sets. + boolean isResponsibleFor(IBuiltInRule rule); +} diff --git a/key.core/src/main/java/de/uka/ilkd/key/strategy/RuleAppCostCollector.java b/key.ncore.calculus/src/main/java/org/key_project/prover/strategy/RuleAppCostCollector.java similarity index 93% rename from key.core/src/main/java/de/uka/ilkd/key/strategy/RuleAppCostCollector.java rename to key.ncore.calculus/src/main/java/org/key_project/prover/strategy/RuleAppCostCollector.java index a4731236ff7..4173604d0c7 100644 --- a/key.core/src/main/java/de/uka/ilkd/key/strategy/RuleAppCostCollector.java +++ b/key.ncore.calculus/src/main/java/org/key_project/prover/strategy/RuleAppCostCollector.java @@ -1,7 +1,7 @@ /* This file is part of KeY - https://key-project.org * KeY is licensed under the GNU General Public License Version 2 * SPDX-License-Identifier: GPL-2.0-only */ -package de.uka.ilkd.key.strategy; +package org.key_project.prover.strategy; import org.key_project.prover.rules.RuleApp; import org.key_project.prover.strategy.costbased.RuleAppCost; diff --git a/key.core/src/main/java/de/uka/ilkd/key/strategy/Strategy.java b/key.ncore.calculus/src/main/java/org/key_project/prover/strategy/Strategy.java similarity index 64% rename from key.core/src/main/java/de/uka/ilkd/key/strategy/Strategy.java rename to key.ncore.calculus/src/main/java/org/key_project/prover/strategy/Strategy.java index 04d24c004b0..1ff614f9c02 100644 --- a/key.core/src/main/java/de/uka/ilkd/key/strategy/Strategy.java +++ b/key.ncore.calculus/src/main/java/org/key_project/prover/strategy/Strategy.java @@ -1,15 +1,12 @@ /* This file is part of KeY - https://key-project.org * KeY is licensed under the GNU General Public License Version 2 * SPDX-License-Identifier: GPL-2.0-only */ -package de.uka.ilkd.key.strategy; - -import de.uka.ilkd.key.proof.Goal; -import de.uka.ilkd.key.proof.Proof; -import de.uka.ilkd.key.settings.ProofSettings; +package org.key_project.prover.strategy; import org.key_project.logic.Named; import org.key_project.prover.proof.ProofGoal; import org.key_project.prover.rules.RuleApp; +import org.key_project.prover.rules.RuleSet; import org.key_project.prover.sequent.PosInOccurrence; import org.key_project.prover.strategy.costbased.MutableState; import org.key_project.prover.strategy.costbased.RuleAppCost; @@ -17,10 +14,6 @@ import org.jspecify.annotations.NonNull; - -/** - * Generic interface for evaluating the cost of a RuleApp with regard to a specific strategy - */ public interface Strategy> extends Named, Feature { /** * Evaluate the cost of a RuleApp. Starts a new independent computation. @@ -33,9 +26,7 @@ public interface Strategy> extends Named, * indicates that the rule shall not be applied at all (it is discarded by * the strategy). */ - default RuleAppCost computeCost(RuleApp app, PosInOccurrence pos, Goal goal) { - return computeCost(app, pos, goal, new MutableState()); - } + RuleAppCost computeCost(RuleApp app, PosInOccurrence pos, Goal goal); /** * Checks if the {@link Strategy} should stop at the first non-closeable {@link Goal}. @@ -62,21 +53,8 @@ default RuleAppCost computeCost(RuleApp app, PosInOccurrence pos, Goal goal) { void instantiateApp(RuleApp app, PosInOccurrence pio, Goal goal, RuleAppCostCollector collector); - /** - * Updates the {@link Strategy} for the given {@link Proof} by setting the {@link Strategy}'s - * {@link StrategyProperties} to the given ones. - * - * @param proof The {@link Proof} the strategy of which should be updated. - * @param p The new {@link StrategyProperties} - */ - static void updateStrategySettings(Proof proof, StrategyProperties p) { - final Strategy strategy = proof.getActiveStrategy(); - ProofSettings.DEFAULT_SETTINGS.getStrategySettings().setStrategy(strategy.name()); - ProofSettings.DEFAULT_SETTINGS.getStrategySettings().setActiveStrategyProperties(p); - - proof.getSettings().getStrategySettings().setStrategy(strategy.name()); - proof.getSettings().getStrategySettings().setActiveStrategyProperties(p); + boolean isResponsibleFor(RuleSet rs); - proof.setActiveStrategy(strategy); - } + RuleAppCost instantiateApp(RuleApp app, PosInOccurrence pio, + Goal goal, MutableState mState); } diff --git a/key.core/src/main/java/de/uka/ilkd/key/strategy/feature/CountBranchFeature.java b/key.ncore.calculus/src/main/java/org/key_project/prover/strategy/costbased/feature/CountBranchFeature.java similarity index 91% rename from key.core/src/main/java/de/uka/ilkd/key/strategy/feature/CountBranchFeature.java rename to key.ncore.calculus/src/main/java/org/key_project/prover/strategy/costbased/feature/CountBranchFeature.java index 1a95450ac3d..a15984aea2b 100644 --- a/key.core/src/main/java/de/uka/ilkd/key/strategy/feature/CountBranchFeature.java +++ b/key.ncore.calculus/src/main/java/org/key_project/prover/strategy/costbased/feature/CountBranchFeature.java @@ -1,17 +1,15 @@ /* This file is part of KeY - https://key-project.org * KeY is licensed under the GNU General Public License Version 2 * SPDX-License-Identifier: GPL-2.0-only */ -package de.uka.ilkd.key.strategy.feature; - -import de.uka.ilkd.key.rule.Taclet; +package org.key_project.prover.strategy.costbased.feature; import org.key_project.prover.proof.ProofGoal; import org.key_project.prover.rules.RuleApp; +import org.key_project.prover.rules.Taclet; import org.key_project.prover.sequent.PosInOccurrence; import org.key_project.prover.strategy.costbased.MutableState; import org.key_project.prover.strategy.costbased.NumberRuleAppCost; import org.key_project.prover.strategy.costbased.RuleAppCost; -import org.key_project.prover.strategy.costbased.feature.Feature; import org.jspecify.annotations.NonNull; diff --git a/key.core/src/main/java/de/uka/ilkd/key/strategy/feature/RuleSetDispatchFeature.java b/key.ncore.calculus/src/main/java/org/key_project/prover/strategy/costbased/feature/RuleSetDispatchFeature.java similarity index 75% rename from key.core/src/main/java/de/uka/ilkd/key/strategy/feature/RuleSetDispatchFeature.java rename to key.ncore.calculus/src/main/java/org/key_project/prover/strategy/costbased/feature/RuleSetDispatchFeature.java index 2040af28e8f..d40bcf5e31d 100644 --- a/key.core/src/main/java/de/uka/ilkd/key/strategy/feature/RuleSetDispatchFeature.java +++ b/key.ncore.calculus/src/main/java/org/key_project/prover/strategy/costbased/feature/RuleSetDispatchFeature.java @@ -1,14 +1,14 @@ /* This file is part of KeY - https://key-project.org * KeY is licensed under the GNU General Public License Version 2 * SPDX-License-Identifier: GPL-2.0-only */ -package de.uka.ilkd.key.strategy.feature; +package org.key_project.prover.strategy.costbased.feature; import java.util.LinkedHashMap; import java.util.Map; - -import de.uka.ilkd.key.rule.TacletApp; +import java.util.Set; import org.key_project.prover.proof.ProofGoal; +import org.key_project.prover.rules.ITacletApp; import org.key_project.prover.rules.RuleApp; import org.key_project.prover.rules.RuleSet; import org.key_project.prover.sequent.PosInOccurrence; @@ -16,11 +16,11 @@ import org.key_project.prover.strategy.costbased.NumberRuleAppCost; import org.key_project.prover.strategy.costbased.RuleAppCost; import org.key_project.prover.strategy.costbased.TopRuleAppCost; -import org.key_project.prover.strategy.costbased.feature.Feature; -import org.key_project.prover.strategy.costbased.feature.SumFeature; import org.key_project.util.collection.ImmutableList; +import org.checkerframework.checker.nullness.qual.KeyFor; import org.jspecify.annotations.NonNull; +import org.jspecify.annotations.Nullable; /** @@ -31,18 +31,22 @@ */ public class RuleSetDispatchFeature implements Feature { - private final Map rulesetToFeature = new LinkedHashMap<>(); + private final Map<@NonNull RuleSet, @NonNull Feature> rulesetToFeature = new LinkedHashMap<>(); + + public Set<@KeyFor("this.rulesetToFeature") RuleSet> ruleSets() { + return rulesetToFeature.keySet(); + } @Override public > RuleAppCost computeCost(RuleApp app, PosInOccurrence pos, Goal goal, MutableState mState) { - if (!(app instanceof TacletApp)) { + if (!(app instanceof ITacletApp tapp)) { return NumberRuleAppCost.getZeroCost(); } RuleAppCost res = NumberRuleAppCost.getZeroCost(); - ImmutableList ruleSetsOfAppliedTaclet = ((TacletApp) app).taclet().getRuleSets(); + ImmutableList ruleSetsOfAppliedTaclet = tapp.taclet().getRuleSets(); /* * do not use iterator here, as this method is called a lot when proving such that avoiding * object creation helps to reduce the load put on the garbage collector @@ -92,7 +96,18 @@ public void clear(RuleSet ruleSet) { * @return The {@link Feature} used for the given {@link RuleSet} or {@code null} if not * available. */ - public Feature get(RuleSet ruleSet) { + public @Nullable Feature get(@NonNull RuleSet ruleSet) { return rulesetToFeature.get(ruleSet); } + + /** + * Returns the used {@link Feature} for the given {@link RuleSet} and removes it. + * + * @param ruleSet The {@link RuleSet} to get its {@link Feature}. + * @return The {@link Feature} used for the given {@link RuleSet} or {@code null} if not + * available. + */ + public @Nullable Feature remove(@NonNull RuleSet ruleSet) { + return rulesetToFeature.remove(ruleSet); + } } diff --git a/key.ui/examples/redux/arrays/Arrays.copyOf.float.key b/key.ui/examples/redux/arrays/Arrays.copyOf.float.key index 71d0ba17029..9c3968be390 100644 --- a/key.ui/examples/redux/arrays/Arrays.copyOf.float.key +++ b/key.ui/examples/redux/arrays/Arrays.copyOf.float.key @@ -1,3 +1,77 @@ +\settings // Proof-Settings-Config-File +{ + "Choice" : { + "JavaCard" : "JavaCard:off", + "Strings" : "Strings:on", + "assertions" : "assertions:on", + "bigint" : "bigint:on", + "finalFields" : "finalFields:immutable", + "floatRules" : "floatRules:strictfpOnly", + "initialisation" : "initialisation:disableStaticInitialisation", + "intRules" : "intRules:arithmeticSemanticsIgnoringOF", + "integerSimplificationRules" : "integerSimplificationRules:full", + "javaLoopTreatment" : "javaLoopTreatment:efficient", + "mergeGenerateIsWeakeningGoal" : "mergeGenerateIsWeakeningGoal:off", + "methodExpansion" : "methodExpansion:modularOnly", + "modelFields" : "modelFields:showSatisfiability", + "moreSeqRules" : "moreSeqRules:off", + "permissions" : "permissions:off", + "programRules" : "programRules:Java", + "reach" : "reach:on", + "runtimeExceptions" : "runtimeExceptions:allow", + "sequences" : "sequences:on", + "soundDefaultContracts" : "soundDefaultContracts:on", + "wdChecks" : "wdChecks:off", + "wdOperator" : "wdOperator:L" + }, + "Labels" : { + "UseOriginLabels" : true + }, + "NewSMT" : { + + }, + "SMTSettings" : { + "SelectedTaclets" : [ + + ], + "UseBuiltUniqueness" : false, + "explicitTypeHierarchy" : false, + "instantiateHierarchyAssumptions" : true, + "integersMaximum" : 2147483645, + "integersMinimum" : -2147483645, + "invariantForall" : false, + "maxGenericSorts" : 2, + "useConstantsForBigOrSmallIntegers" : true, + "useUninterpretedMultiplication" : true + }, + "Strategy" : { + "ActiveStrategy" : "Modular JavaDL Strategy", + "MaximumNumberOfAutomaticApplications" : 10000, + "Timeout" : -1, + "options" : { + "AUTO_INDUCTION_OPTIONS_KEY" : "AUTO_INDUCTION_OFF", + "BLOCK_OPTIONS_KEY" : "BLOCK_CONTRACT_INTERNAL", + "CLASS_AXIOM_OPTIONS_KEY" : "CLASS_AXIOM_FREE", + "DEP_OPTIONS_KEY" : "DEP_ON", + "INF_FLOW_CHECK_PROPERTY" : "INF_FLOW_CHECK_FALSE", + "LOOP_OPTIONS_KEY" : "LOOP_SCOPE_INV_TACLET", + "METHOD_OPTIONS_KEY" : "METHOD_CONTRACT", + "MPS_OPTIONS_KEY" : "MPS_MERGE", + "NON_LIN_ARITH_OPTIONS_KEY" : "NON_LIN_ARITH_NONE", + "OSS_OPTIONS_KEY" : "OSS_ON", + "QUANTIFIERS_OPTIONS_KEY" : "QUANTIFIERS_NON_SPLITTING_WITH_PROGS", + "QUERYAXIOM_OPTIONS_KEY" : "QUERYAXIOM_OFF", + "QUERY_NEW_OPTIONS_KEY" : "QUERY_OFF", + "SPLITTING_OPTIONS_KEY" : "SPLITTING_DELAYED", + "STOPMODE_OPTIONS_KEY" : "STOPMODE_DEFAULT", + "USER_TACLETS_OPTIONS_KEY1" : "USER_TACLETS_OFF", + "USER_TACLETS_OPTIONS_KEY2" : "USER_TACLETS_OFF", + "USER_TACLETS_OPTIONS_KEY3" : "USER_TACLETS_OFF", + "VBT_PHASE" : "VBT_SYM_EX" + } + } + } + \javaSource "./src"; \chooseContract "Arrays[Arrays::copyOf([F,int)].JML normal_behavior operation contract.0"; diff --git a/key.ui/examples/redux/arrays/Arrays.copyOfRange.float.key b/key.ui/examples/redux/arrays/Arrays.copyOfRange.float.key index 85111ad87fa..371efe3289c 100644 --- a/key.ui/examples/redux/arrays/Arrays.copyOfRange.float.key +++ b/key.ui/examples/redux/arrays/Arrays.copyOfRange.float.key @@ -1,3 +1,77 @@ +\settings // Proof-Settings-Config-File +{ + "Choice" : { + "JavaCard" : "JavaCard:off", + "Strings" : "Strings:on", + "assertions" : "assertions:on", + "bigint" : "bigint:on", + "finalFields" : "finalFields:immutable", + "floatRules" : "floatRules:strictfpOnly", + "initialisation" : "initialisation:disableStaticInitialisation", + "intRules" : "intRules:arithmeticSemanticsIgnoringOF", + "integerSimplificationRules" : "integerSimplificationRules:full", + "javaLoopTreatment" : "javaLoopTreatment:efficient", + "mergeGenerateIsWeakeningGoal" : "mergeGenerateIsWeakeningGoal:off", + "methodExpansion" : "methodExpansion:modularOnly", + "modelFields" : "modelFields:showSatisfiability", + "moreSeqRules" : "moreSeqRules:off", + "permissions" : "permissions:off", + "programRules" : "programRules:Java", + "reach" : "reach:on", + "runtimeExceptions" : "runtimeExceptions:allow", + "sequences" : "sequences:on", + "soundDefaultContracts" : "soundDefaultContracts:on", + "wdChecks" : "wdChecks:off", + "wdOperator" : "wdOperator:L" + }, + "Labels" : { + "UseOriginLabels" : true + }, + "NewSMT" : { + + }, + "SMTSettings" : { + "SelectedTaclets" : [ + + ], + "UseBuiltUniqueness" : false, + "explicitTypeHierarchy" : false, + "instantiateHierarchyAssumptions" : true, + "integersMaximum" : 2147483645, + "integersMinimum" : -2147483645, + "invariantForall" : false, + "maxGenericSorts" : 2, + "useConstantsForBigOrSmallIntegers" : true, + "useUninterpretedMultiplication" : true + }, + "Strategy" : { + "ActiveStrategy" : "Modular JavaDL Strategy", + "MaximumNumberOfAutomaticApplications" : 10000, + "Timeout" : -1, + "options" : { + "AUTO_INDUCTION_OPTIONS_KEY" : "AUTO_INDUCTION_OFF", + "BLOCK_OPTIONS_KEY" : "BLOCK_CONTRACT_INTERNAL", + "CLASS_AXIOM_OPTIONS_KEY" : "CLASS_AXIOM_FREE", + "DEP_OPTIONS_KEY" : "DEP_ON", + "INF_FLOW_CHECK_PROPERTY" : "INF_FLOW_CHECK_FALSE", + "LOOP_OPTIONS_KEY" : "LOOP_SCOPE_INV_TACLET", + "METHOD_OPTIONS_KEY" : "METHOD_CONTRACT", + "MPS_OPTIONS_KEY" : "MPS_MERGE", + "NON_LIN_ARITH_OPTIONS_KEY" : "NON_LIN_ARITH_NONE", + "OSS_OPTIONS_KEY" : "OSS_ON", + "QUANTIFIERS_OPTIONS_KEY" : "QUANTIFIERS_NON_SPLITTING_WITH_PROGS", + "QUERYAXIOM_OPTIONS_KEY" : "QUERYAXIOM_OFF", + "QUERY_NEW_OPTIONS_KEY" : "QUERY_OFF", + "SPLITTING_OPTIONS_KEY" : "SPLITTING_DELAYED", + "STOPMODE_OPTIONS_KEY" : "STOPMODE_DEFAULT", + "USER_TACLETS_OPTIONS_KEY1" : "USER_TACLETS_OFF", + "USER_TACLETS_OPTIONS_KEY2" : "USER_TACLETS_OFF", + "USER_TACLETS_OPTIONS_KEY3" : "USER_TACLETS_OFF", + "VBT_PHASE" : "VBT_SYM_EX" + } + } + } + \javaSource "./src"; \chooseContract "Arrays[Arrays::copyOfRange([F,int,int)].JML normal_behavior operation contract.0"; diff --git a/key.ui/examples/redux/arrays/Arrays.fill.float.key b/key.ui/examples/redux/arrays/Arrays.fill.float.key index eb36cfd2209..bb60623d333 100644 --- a/key.ui/examples/redux/arrays/Arrays.fill.float.key +++ b/key.ui/examples/redux/arrays/Arrays.fill.float.key @@ -1,3 +1,77 @@ +\settings // Proof-Settings-Config-File +{ + "Choice" : { + "JavaCard" : "JavaCard:off", + "Strings" : "Strings:on", + "assertions" : "assertions:on", + "bigint" : "bigint:on", + "finalFields" : "finalFields:immutable", + "floatRules" : "floatRules:strictfpOnly", + "initialisation" : "initialisation:disableStaticInitialisation", + "intRules" : "intRules:arithmeticSemanticsIgnoringOF", + "integerSimplificationRules" : "integerSimplificationRules:full", + "javaLoopTreatment" : "javaLoopTreatment:efficient", + "mergeGenerateIsWeakeningGoal" : "mergeGenerateIsWeakeningGoal:off", + "methodExpansion" : "methodExpansion:modularOnly", + "modelFields" : "modelFields:showSatisfiability", + "moreSeqRules" : "moreSeqRules:off", + "permissions" : "permissions:off", + "programRules" : "programRules:Java", + "reach" : "reach:on", + "runtimeExceptions" : "runtimeExceptions:allow", + "sequences" : "sequences:on", + "soundDefaultContracts" : "soundDefaultContracts:on", + "wdChecks" : "wdChecks:off", + "wdOperator" : "wdOperator:L" + }, + "Labels" : { + "UseOriginLabels" : true + }, + "NewSMT" : { + + }, + "SMTSettings" : { + "SelectedTaclets" : [ + + ], + "UseBuiltUniqueness" : false, + "explicitTypeHierarchy" : false, + "instantiateHierarchyAssumptions" : true, + "integersMaximum" : 2147483645, + "integersMinimum" : -2147483645, + "invariantForall" : false, + "maxGenericSorts" : 2, + "useConstantsForBigOrSmallIntegers" : true, + "useUninterpretedMultiplication" : true + }, + "Strategy" : { + "ActiveStrategy" : "Modular JavaDL Strategy", + "MaximumNumberOfAutomaticApplications" : 10000, + "Timeout" : -1, + "options" : { + "AUTO_INDUCTION_OPTIONS_KEY" : "AUTO_INDUCTION_OFF", + "BLOCK_OPTIONS_KEY" : "BLOCK_CONTRACT_INTERNAL", + "CLASS_AXIOM_OPTIONS_KEY" : "CLASS_AXIOM_FREE", + "DEP_OPTIONS_KEY" : "DEP_ON", + "INF_FLOW_CHECK_PROPERTY" : "INF_FLOW_CHECK_FALSE", + "LOOP_OPTIONS_KEY" : "LOOP_SCOPE_INV_TACLET", + "METHOD_OPTIONS_KEY" : "METHOD_CONTRACT", + "MPS_OPTIONS_KEY" : "MPS_MERGE", + "NON_LIN_ARITH_OPTIONS_KEY" : "NON_LIN_ARITH_NONE", + "OSS_OPTIONS_KEY" : "OSS_ON", + "QUANTIFIERS_OPTIONS_KEY" : "QUANTIFIERS_NON_SPLITTING_WITH_PROGS", + "QUERYAXIOM_OPTIONS_KEY" : "QUERYAXIOM_OFF", + "QUERY_NEW_OPTIONS_KEY" : "QUERY_OFF", + "SPLITTING_OPTIONS_KEY" : "SPLITTING_DELAYED", + "STOPMODE_OPTIONS_KEY" : "STOPMODE_DEFAULT", + "USER_TACLETS_OPTIONS_KEY1" : "USER_TACLETS_OFF", + "USER_TACLETS_OPTIONS_KEY2" : "USER_TACLETS_OFF", + "USER_TACLETS_OPTIONS_KEY3" : "USER_TACLETS_OFF", + "VBT_PHASE" : "VBT_SYM_EX" + } + } + } + \javaSource "./src"; \chooseContract "Arrays[Arrays::fill([F,float)].JML normal_behavior operation contract.0"; \ No newline at end of file diff --git a/key.ui/examples/redux/arrays/Arrays.fillFromTo.float.key b/key.ui/examples/redux/arrays/Arrays.fillFromTo.float.key index 3d50ab9ea6a..5e5ef659672 100644 --- a/key.ui/examples/redux/arrays/Arrays.fillFromTo.float.key +++ b/key.ui/examples/redux/arrays/Arrays.fillFromTo.float.key @@ -1,3 +1,77 @@ +\settings // Proof-Settings-Config-File +{ + "Choice" : { + "JavaCard" : "JavaCard:off", + "Strings" : "Strings:on", + "assertions" : "assertions:on", + "bigint" : "bigint:on", + "finalFields" : "finalFields:immutable", + "floatRules" : "floatRules:strictfpOnly", + "initialisation" : "initialisation:disableStaticInitialisation", + "intRules" : "intRules:arithmeticSemanticsIgnoringOF", + "integerSimplificationRules" : "integerSimplificationRules:full", + "javaLoopTreatment" : "javaLoopTreatment:efficient", + "mergeGenerateIsWeakeningGoal" : "mergeGenerateIsWeakeningGoal:off", + "methodExpansion" : "methodExpansion:modularOnly", + "modelFields" : "modelFields:showSatisfiability", + "moreSeqRules" : "moreSeqRules:off", + "permissions" : "permissions:off", + "programRules" : "programRules:Java", + "reach" : "reach:on", + "runtimeExceptions" : "runtimeExceptions:allow", + "sequences" : "sequences:on", + "soundDefaultContracts" : "soundDefaultContracts:on", + "wdChecks" : "wdChecks:off", + "wdOperator" : "wdOperator:L" + }, + "Labels" : { + "UseOriginLabels" : true + }, + "NewSMT" : { + + }, + "SMTSettings" : { + "SelectedTaclets" : [ + + ], + "UseBuiltUniqueness" : false, + "explicitTypeHierarchy" : false, + "instantiateHierarchyAssumptions" : true, + "integersMaximum" : 2147483645, + "integersMinimum" : -2147483645, + "invariantForall" : false, + "maxGenericSorts" : 2, + "useConstantsForBigOrSmallIntegers" : true, + "useUninterpretedMultiplication" : true + }, + "Strategy" : { + "ActiveStrategy" : "Modular JavaDL Strategy", + "MaximumNumberOfAutomaticApplications" : 10000, + "Timeout" : -1, + "options" : { + "AUTO_INDUCTION_OPTIONS_KEY" : "AUTO_INDUCTION_OFF", + "BLOCK_OPTIONS_KEY" : "BLOCK_CONTRACT_INTERNAL", + "CLASS_AXIOM_OPTIONS_KEY" : "CLASS_AXIOM_FREE", + "DEP_OPTIONS_KEY" : "DEP_ON", + "INF_FLOW_CHECK_PROPERTY" : "INF_FLOW_CHECK_FALSE", + "LOOP_OPTIONS_KEY" : "LOOP_SCOPE_INV_TACLET", + "METHOD_OPTIONS_KEY" : "METHOD_CONTRACT", + "MPS_OPTIONS_KEY" : "MPS_MERGE", + "NON_LIN_ARITH_OPTIONS_KEY" : "NON_LIN_ARITH_NONE", + "OSS_OPTIONS_KEY" : "OSS_ON", + "QUANTIFIERS_OPTIONS_KEY" : "QUANTIFIERS_NON_SPLITTING_WITH_PROGS", + "QUERYAXIOM_OPTIONS_KEY" : "QUERYAXIOM_OFF", + "QUERY_NEW_OPTIONS_KEY" : "QUERY_OFF", + "SPLITTING_OPTIONS_KEY" : "SPLITTING_DELAYED", + "STOPMODE_OPTIONS_KEY" : "STOPMODE_DEFAULT", + "USER_TACLETS_OPTIONS_KEY1" : "USER_TACLETS_OFF", + "USER_TACLETS_OPTIONS_KEY2" : "USER_TACLETS_OFF", + "USER_TACLETS_OPTIONS_KEY3" : "USER_TACLETS_OFF", + "VBT_PHASE" : "VBT_SYM_EX" + } + } + } + \javaSource "./src"; \chooseContract "Arrays[Arrays::fill([F,int,int,float)].JML normal_behavior operation contract.0"; \ No newline at end of file diff --git a/key.ui/src/main/java/de/uka/ilkd/key/gui/ApplyTacletDialog.java b/key.ui/src/main/java/de/uka/ilkd/key/gui/ApplyTacletDialog.java index 5a8728ee6cf..f1744d03986 100644 --- a/key.ui/src/main/java/de/uka/ilkd/key/gui/ApplyTacletDialog.java +++ b/key.ui/src/main/java/de/uka/ilkd/key/gui/ApplyTacletDialog.java @@ -109,7 +109,7 @@ protected JPanel createInfoPanel() { protected JPanel createTacletDisplay() { JPanel panel = new JPanel(new BorderLayout()); panel.setBorder(new TitledBorder("Selected Taclet - " + model[0].taclet().name())); - LOGGER.debug("TacletApp: {}", model[0].taclet()); + LOGGER.debug("ITacletApp: {}", model[0].taclet()); Taclet taclet = model[0].taclet(); StringBuilder tacletSB = new StringBuilder(); diff --git a/key.ui/src/main/java/de/uka/ilkd/key/gui/StrategySelectionView.java b/key.ui/src/main/java/de/uka/ilkd/key/gui/StrategySelectionView.java index 37141d6090e..c3dc89ed468 100644 --- a/key.ui/src/main/java/de/uka/ilkd/key/gui/StrategySelectionView.java +++ b/key.ui/src/main/java/de/uka/ilkd/key/gui/StrategySelectionView.java @@ -22,11 +22,13 @@ import de.uka.ilkd.key.proof.init.Profile; import de.uka.ilkd.key.settings.ProofSettings; import de.uka.ilkd.key.strategy.JavaCardDLStrategy; -import de.uka.ilkd.key.strategy.Strategy; +import de.uka.ilkd.key.strategy.JavaStrategy; import de.uka.ilkd.key.strategy.StrategyFactory; import de.uka.ilkd.key.strategy.StrategyProperties; import de.uka.ilkd.key.strategy.definition.*; +import org.key_project.prover.strategy.Strategy; + import org.jspecify.annotations.NonNull; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -45,7 +47,7 @@ *

    * As future work this class should not show a fixed content defined by {@link #DEFINITION}. Instead * it should update the UI controls based on the currently active proof and its {@link Profile} - * since different {@link Profile}s support different {@link Strategy}s with different + * since different {@link Profile}s support different {@link JavaStrategy}s with different * {@link StrategyProperties}. For more information have a look at: * {@code http://i12www.ira.uka.de/~klebanov/mantis/view.php?id=1359} *

    diff --git a/key.ui/src/main/java/de/uka/ilkd/key/gui/nodeviews/DefaultTacletMenuItem.java b/key.ui/src/main/java/de/uka/ilkd/key/gui/nodeviews/DefaultTacletMenuItem.java index 0096566ec05..15633e281b0 100644 --- a/key.ui/src/main/java/de/uka/ilkd/key/gui/nodeviews/DefaultTacletMenuItem.java +++ b/key.ui/src/main/java/de/uka/ilkd/key/gui/nodeviews/DefaultTacletMenuItem.java @@ -30,7 +30,7 @@ class DefaultTacletMenuItem extends JMenuItem implements TacletMenuItem { /** * creates TacletMenuItem attached to a Taclet * - * @param connectedTo the TacletApp that is represented by the item + * @param connectedTo the ITacletApp that is represented by the item * @param notationInfo the NotationInfo used to print terms */ public DefaultTacletMenuItem(TacletApp connectedTo, NotationInfo notationInfo, diff --git a/key.ui/src/main/java/de/uka/ilkd/key/gui/nodeviews/InsertionTacletBrowserMenuItem.java b/key.ui/src/main/java/de/uka/ilkd/key/gui/nodeviews/InsertionTacletBrowserMenuItem.java index 39e8faaddbf..f3c06bada96 100644 --- a/key.ui/src/main/java/de/uka/ilkd/key/gui/nodeviews/InsertionTacletBrowserMenuItem.java +++ b/key.ui/src/main/java/de/uka/ilkd/key/gui/nodeviews/InsertionTacletBrowserMenuItem.java @@ -83,7 +83,7 @@ protected Collection createInsertionList() { * Adds a new taclet to be displayed by this component it is assumed that the app has been * tested before by {@link #isResponsible}. * - * @param app the TacletApp to be added + * @param app the ITacletApp to be added */ public void add(TacletApp app) { insertionTaclets.add(createListItem(app)); diff --git a/keyext.isabelletranslation/src/main/java/org/key_project/isabelletranslation/automation/IsabelleRule.java b/keyext.isabelletranslation/src/main/java/org/key_project/isabelletranslation/automation/IsabelleRule.java index dbd67ed6c5e..5656542be38 100644 --- a/keyext.isabelletranslation/src/main/java/org/key_project/isabelletranslation/automation/IsabelleRule.java +++ b/keyext.isabelletranslation/src/main/java/org/key_project/isabelletranslation/automation/IsabelleRule.java @@ -3,11 +3,11 @@ * SPDX-License-Identifier: GPL-2.0-only */ package org.key_project.isabelletranslation.automation; -import de.uka.ilkd.key.logic.TermServices; import de.uka.ilkd.key.proof.Goal; import de.uka.ilkd.key.rule.AbstractExternalSolverRuleApp; import de.uka.ilkd.key.rule.ExternalSolverRule; +import org.key_project.logic.LogicServices; import org.key_project.logic.Name; import org.key_project.prover.rules.RuleApp; import org.key_project.prover.sequent.PosInOccurrence; @@ -45,7 +45,7 @@ public AbstractExternalSolverRuleApp createApp } @Override - public IsabelleRuleApp createApp(PosInOccurrence pos, TermServices services) { + public IsabelleRuleApp createApp(PosInOccurrence pos, LogicServices services) { return new IsabelleRuleApp(this, null, "", ""); } diff --git a/keyext.proofmanagement/src/main/java/org/key_project/proofmanagement/check/KeYFacade.java b/keyext.proofmanagement/src/main/java/org/key_project/proofmanagement/check/KeYFacade.java index 6ccf66aed57..cf5d70720ad 100644 --- a/keyext.proofmanagement/src/main/java/org/key_project/proofmanagement/check/KeYFacade.java +++ b/keyext.proofmanagement/src/main/java/org/key_project/proofmanagement/check/KeYFacade.java @@ -29,7 +29,7 @@ import de.uka.ilkd.key.settings.Configuration; import de.uka.ilkd.key.speclang.Contract; import de.uka.ilkd.key.speclang.SLEnvInput; -import de.uka.ilkd.key.strategy.Strategy; +import de.uka.ilkd.key.strategy.JavaStrategy; import de.uka.ilkd.key.strategy.StrategyProperties; import de.uka.ilkd.key.util.ProgressMonitor; @@ -348,7 +348,7 @@ private static ReplayResult replayProof(CheckerData.ProofEntry line, EnvInput en .getActiveStrategyProperties(); newProps.setProperty(StrategyProperties.OSS_OPTIONS_KEY, StrategyProperties.OSS_ON); - Strategy.updateStrategySettings(proof, newProps); + JavaStrategy.updateStrategySettings(proof, newProps); OneStepSimplifier.refreshOSS(proof); // passing null is ok since ProblemLoader is only used for error reporting as origin @@ -384,7 +384,7 @@ private static ReplayResult replayProof(CheckerData.ProofEntry line, EnvInput en StrategyProperties newProps = proof.getSettings().getStrategySettings() .getActiveStrategyProperties(); newProps.setProperty(StrategyProperties.OSS_OPTIONS_KEY, ossStatus); - Strategy.updateStrategySettings(proof, newProps); + JavaStrategy.updateStrategySettings(proof, newProps); OneStepSimplifier.refreshOSS(proof); result = new ReplayResult(status, errors, lastTouchedNode);