Sequent Prover Developer Guide
Programmer's Guide
Welcome to Event-B Sequent Prover
The Event-B sequent prover is a plug-in for the Eclipse platform which provides different proof rules to be used within the Rodin Tool. The following sections discuss the issues when extending the Event-B sequent prover.
Sequent Prover Core
Sequents
TODO
Proof Rules
TODO
Proof Trees
TODO
Reasoners
Concepts
Reasoners are used in the Event-B sequent prover to generate proof rules. A reasoner is provided with the sequent to prove as well as some extra optional input. The reasoner is implemented by a computer program and it is the job of the developers to ensure that the reasoners either fail or generate logically valid proof rules.
An example of a reasoner is the "conjI" reasoner that generates the conjI proof rules, which splits a conjunctive goal into two sub-goals. Here, assume that the input sequent is , the conjI reasoner produces the following proof rules.
Adding a reasoner
A reasoner is added into the Event-B sequent prover using the extension point org.eventb.core.seqprover.reasoners. Below is an example of how to contribute to the extension point.
<extension point="org.eventb.core.seqprover.reasoners"> <reasoner class="org.eventb.contributors.seqprover.reasoners.Hyp" id="hyp" name="%hypName"/> </extension>
The above declaration defines a reasoner with a specific id (which will be automatically prefixed by the project name, e.g. org.eventb.contributors.seqprover). The name is an externalised string which is used for display purpose.
The class attribute must be a valid Java class name which will be used to create an instance of the reasoner. This class must implement the org.eventb.core.seqprover.IReasoner interface.
However, most of the time, developers only need to extend one of the abstract implementation (depending on the type of the reasoner). For this implementation purpose, the type of the reasoners are specified below:
- Automatic rewriting reasoners: Reasoners which apply some rewriting rules automatically to simplify the sequent.
- Automatic inference reasoners: Reasoners which apply an inference rule automatically.
- Manual rewriters: Reasoners which apply a rewriting rule at a given position.
- Manual inference: Reasoner which apply an inference rule manually.
- General reasoners: If the reasoner does not fall into the above categories, clients need to implement the interface IReasoner directly.
Implementing a reasoner is only a first step of contributing to the sequent prover. In order to use a reasoner, the reasoner needs to be wrapped around by a tactic.
Automatic Rewriting Reasoners
Concepts
The reasoners of this type does not have any extra input (except the sequent) and automatically rewrite all the occurrences of certain formulas into other ones. An example of this is the rewriter which rewrites according to the following rules:
Implementation
Step by step:
- Create a new plug-in project, e.g. org.eventb.contributor.seqprover.arith
- Added dependency: org.eventb.core.seqprover.
- Add an extension to the point org.eventb.core.seqprover.reasoners, e.g.,
class="org.eventb.core.seqprover.arith.ArithRewrites" id="org.eventb.core.seqprover.arithmetic" name="%arithRewritesName"
- Implement the class: Click on the class attribute of the extension, a dialog will appear for new class wizard.
- This class should extend the import org.eventb.internal.core.seqprover.eventbExtensions.rewriters.AbstractAutoRewrites. For the moment, the class is internal within the project and subjected to be changed. Clients can make a copy of this class to develop their own implementation.
- An example is as follows:
import org.eventb.core.ast.IFormulaRewriter; import org.eventb.core.seqprover.SequentProver; public class ArithRewrites extends AbstractAutoRewrites { private static final IFormulaRewriter rewriter = new ArithRewriterImpl(); public AutoRewrites() { super(rewriter, true); } public static String REASONER_ID = SequentProver.PLUGIN_ID + ".autoRewrites"; public String getReasonerID() { return REASONER_ID; } @Override protected String getDisplayName() { return "simplification rewrites"; } }
- The constructor shall call the super constructor super(IFormulaRewriter, boolean) to specify the formula rewriter to be used, and the reasoner shall hide the source of the rewritten hypothesis or not. Clients need to implement two methods:
- The first one, namely getReasonerID(), returns the string ID of this reasoner. It must be the same ID as the one declared in the XML file (do not forget the project name prefix).
- The second method is getDisplayName(). It returns the display name of the reasoner, which will be used for display purpose in the UI.
- In order to implement the formula rewriter, clients are suggested to use Tom. The instructions are as follows:
- Create a file named build-tom.xml within your project. The best way to do this is to copy from org.eventb.core.seqprover, and modify this accordingly.
- Right click on the name of your project and choose "Properties".
- Choose "Builders", then click on "New" and choose "Ant Build" and click "OK". A dialog will open for the new builder wizard.
- At the "Main" tab:
- Enter the name of the builder (e.g., Tom).
- Buildfile: "Browse Workspace" to your build-tom.xml.
- Base Directory: "Variables" and choose "build_project".
- At the "Targets" tab:
- Auto Build: Click "Set Targets" and choose "tom" from the list.
- During a "clean": Click "Set Targets" and choose "clean" (unchecked "tom").
- You will come back to this builder later on.
- Implementing the rules:
- Create a file called ArithRewriterImpl.t (the name should be consistent with the step above).
- The content of the file should look like this:
package org.eventb.core.seqprover.arith; import java.util.ArrayList; import java.util.Collection; import java.math.BigInteger; import org.eventb.core.ast.AssociativeExpression; import org.eventb.core.ast.AssociativePredicate; import org.eventb.core.ast.AtomicExpression; import org.eventb.core.ast.BinaryExpression; import org.eventb.core.ast.BinaryPredicate; import org.eventb.core.ast.BoolExpression; import org.eventb.core.ast.BoundIdentDecl; import org.eventb.core.ast.BoundIdentifier; import org.eventb.core.ast.DefaultRewriter; import org.eventb.core.ast.Expression; import org.eventb.core.ast.Formula; import org.eventb.core.ast.FormulaFactory; import org.eventb.core.ast.FreeIdentifier; import org.eventb.core.ast.Identifier; import org.eventb.core.ast.IntegerLiteral; import org.eventb.core.ast.LiteralPredicate; import org.eventb.core.ast.Predicate; import org.eventb.core.ast.QuantifiedExpression; import org.eventb.core.ast.QuantifiedPredicate; import org.eventb.core.ast.RelationalPredicate; import org.eventb.core.ast.SetExtension; import org.eventb.core.ast.SimplePredicate; import org.eventb.core.ast.UnaryExpression; import org.eventb.core.ast.UnaryPredicate; import org.eventb.core.seqprover.eventbExtensions.Lib; @SuppressWarnings("unused") public class ArithRewriterImpl extends DefaultRewriter { public ArithRewriterImpl() { super(true, FormulaFactory.getDefault()); } ... }
- See for example org.eventb.internal.core.seqprover.eventbExtensions.rewriters.AutoRewriterImpl.t, which implements most of the automatic rewriting rules supplied by the Rodin platform.
Testing
The abstract automatic rewriting reasoners have been tested, so clients only need to test if the reasoner has been declared correctly (testing the reasoner ID), and if the formula rewriter used for this reasoner has been implemented correctly.
Testing the reasoner ID
This test based on the abstract class org.eventb.core.seqprover.rewriterTests.AbstractAutomaticReasonerTests. An example is as follows.
import org.eventb.core.seqprover.SequentProver; public class ArithRewriterReasonerTests extends AbstractAutomaticReasonerTests { @Override protected SuccessfulTest[] getSuccessfulTests() { // No need to test this. This should be guaranteed by testing the // abstract automatic rewrite reasoner and the formula rewriter itself. return new SuccessfulTest [] { }; } @Override protected String[] getUnsuccessfulTests() { // No need to test this. This should be guaranteed by testing the // abstract automatic rewrite reasoner and the formula rewriter itself. return new String [] { }; } @Override public String getReasonerID() { return "org.eventb.core.seqprover.arithmetic"; } }
In this test, clients only need to provide the reasoner ID under test.
Testing the formula rewriter
This test based on the abstract class org.eventb.core.seqprover.rewriterTests.AbstractFormulaRewriterTests. An example is as follows.
import org.eventb.internal.core.seqprover.eventbExtensions.rewriters.AutoRewriterImpl; import org.junit.Test; public class ArithFormulaRewriterTests extends AbstractFormulaRewriterTests { // The automatic rewriter for testing. private static final IFormulaRewriter rewriter = new ArithRewriterImpl(); /** * Constructor. * * Create an abstract formula rewriter test with the input is the automatic * rewriter. */ public ArithFormulaRewriterTests() { super(rewriter); } /** * Tests for rewriting conjunctions. */ @Test public void testRewrite() { // Test rewriting predicate predicateTest("⊥", "x = 1 ∧ ⊥"); // Test rewriting expression expressionTest("1", "card({x + 1})"); } }
More instructions about how to use the method predicateTest and expressionTest (along with some other utility methods) can be found in the org.eventb.core.seqprover.rewriterTests.AbstractFormulaRewriterTests class.
Automatic Inference Reasoners
Concepts
The reasoners of this type does not have any extra input (except the sequent) and implements an inference rule or a collection of inference rules. For example, a reasoner can implement the following inference rules which dealing with conjunction in the hypothesis and in goal.
H, P |- Q
H |- P => Q
Implementation
In order to implement a reasoner of this type, clients extends the abstract class org.eventb.core.seqprover.reasonerInputs.EmptyInputReasoner. Example include org.eventb.internal.core.seqprover.eventbExtensions.ImpI which implements the above proof rule.
Testing
TODO