GithubHelp home page GithubHelp logo

abella-prover / abella Goto Github PK

View Code? Open in Web Editor NEW
89.0 10.0 18.0 4.45 MB

An interactive theorem prover based on lambda-tree syntax

Home Page: https://abella-prover.org/

License: GNU General Public License v3.0

Makefile 0.37% Emacs Lisp 1.17% Standard ML 3.17% OCaml 91.77% CSS 0.49% JavaScript 0.03% TypeScript 3.00%
lambda-calculus meta-theory interactive-theorem-proving

abella's Introduction

Quick Start

The easiest way to install Abella is using OPAM (version 2.1+).

  1. Go to the topmost directory of the clone of this repository, i.e., the location of this very README.md file.
  2. Run: opam pin abella . (note the final period)
  3. When prompted by OPAM, say yes to install Abella.
  4. Whenever you do a git pull, also do: opam reinstall abella.

To uninstall Abella using OPAM, do:

  1. Run: opam remove abella.
  2. Then run: opam unpin abella.

More Information

Use the following walkthrough for an introduction to using Abella:

https://abella-prover.org/walkthrough.html

More information on Abella is available at

https://abella-prover.org/

Bugs, Feature Requests, and Issues

Please report all bugs, feature requests, and issues on the GitHub issue tracker for Abella, available from:

https://github.com/abella-prover/abella/issues

Discussion of Abella and its uses happens on this mailing list.

http://groups.google.com/group/abella-theorem-prover

abella's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

abella's Issues

Command line argument for setting options

As a feature request, I propose adding an additional command-line switch to the Abella executable, with help string

-s <option> <value>   Set option at startup

that, as the help string says, performs the equivalent of command Set <option> <value> at start-up. This would be useful in situations like

% abella -s subgoals 0  -s witnesses on  -o theorems.out  theorems.thm

Grammar changes for definitions

Although the change from Define and CoDefine to Define Inductive and Define CoInductive was implemented, it was never merged into master. This is to homogenize the syntax with Bedwyr.

Build system fixes

The build system needs to be updated in preparation for the release.

  • OMakefiles need to be removed because OMake is no longer maintained/supported.
  • Need an ocp-build invocation so it can be built in Windows as well. This will replace the current ocamlbuild-based build system.
  • Create an OPAM package.

case is inconsistent if goal in an object sequent has a flexible head

This report comes from Claudio Sacerdoti Coen:

you can find in attachment a proof of false in Abella :-(

I can open a ticket on the bug-tracking system of Abella if you want.
However, it does not seem to be a small bug, but a rather severe
conceptual hole.

Briefly: the hard-coded { |- } predicate has hard-coded introduction
and elimination rules, but the elimination rule misses all the
invertible cases (for and, true and pi). The one for pi could not be
easily added because of lack of polymorphism of Abella. Missing the
cases, cut elimination does not hold and it is easy to exploit the
logical inconsistency.

false.thm

Query and search seem to disagree

This works:

Kind i type.
Type p i -> o.
Theorem foo : exists X, {p n1 |- p X}. search.

This doesn't work (produces no solutions).

Query {p n1 |- p X}.

Query command does not freshen logic variables correctly

For the existing stlc example, if we run this query:

Query forall x, {of x (arr A B) |- of (abs A y\ app x y) D}.

we get the output:

Found solution:
A = A
B = D
D = arr A D

No more solutions.

The apparent non-idempotent solution for D is caused due to the initial logic variables being freshened with respect to an empty list of logic variables, not the variables that actually occur in the initial query. This is only a matter of printing; the query itself runs correctly.

Inconsistency when backchaining on non-variable flexible head

This passes Abella.

Kind i type.
Type p i -> o.

Theorem incons_1 :
  forall F U, {[pi x:i\ F x] |- p U} -> exists X, F X = p U.
intros. case H1. witness x. search.

Theorem incons_2 :
  nabla u, {[pi x:i\ (p x => p x) => p u] |- p u}.
search.

Theorem incons : false.
apply incons_2 with u = n1.
apply incons_1 to H1.

Ping @yvting.

Show number of subgoals per level

Also, I would like to request that when using a non-infinite value of the subgoals flag, the message reporting the number of subgoals remaining should be broken out by how many subgoals are remaining at each level. This information is often a better summary of one's position in the proof than just the total number of subgoals remaining.

(From #44 by @lambdacalculator)

Using non-pattern equalities as rewrites

Currently if there is a non-pattern equation in the hypotheses, it cannot be directly used as a rewrite. This can be hacked by a temporary cut (assert) between a lemma of the form forall X Y, X = Y -> foo X -> foo Y---where foo is some formula that matches the thing we want to rewrite from/to---but there should be support for directly using the equality as a rewrite. We can steal the syntax from Coq.

apply tactic fails to do equivariant matching

This should work, but doesn't.

Kind i type.
Type p i -> prop.

Theorem bad : nabla x y, (p x -> false) -> (p y -> false).
intros. apply H1 to H2.

To make it work we need this proof.

Theorem works : nabla x y, (p x -> false) -> (p y -> false).
intros.
assert forall (z:i), nabla x, p x -> false.
apply H3 to H2.

Alternatively, use backchain instead of assert and apply.

The reason for the forall for the asserted formula there is an unrelated bug to be filed presently.

The .thc files should store a digest of the Abella binary

Currently, any .thc files that are loaded by Abella after its internal data structures change will risk a segmentation fault. This should be detected early by checking that the Abella binary digest matches the digest stored in the .thc file before using Marshal commands.

Ping @yvting.

Subgoal numbering can have duplicates

I would recommend additionally taking a careful look at the code that generates subgoal numbers. The other day, I came across a small bug in the middle of a big proof that involved two successive subgoals being given the same number. I didn't make a ticket for it because I didn't have the time to isolate the problem and extract a small portion of my large development that illustrated it at the time, and now I can't find it again, although I'm sure it was there. This was the only time I've seen it happen, however, so it seems quite rare. I'm passing along this information here just as a head's up, since, if you end up implementing my suggested features, then you will at least be looking at this code, and if you pay a little extra attention to the invariants there, you might spot the problem.

(From #44 by @lambdacalculator)

Missing line numbers in error messages

Using 2.0.3, I notice that a couple of error messages do not provide information on either the offending source file or line and character numbers:

  • Error: Failure("Unknown constant: ??")
  • Error: Failure("Illegal character ?? in input")

There may be other error message (as I seem to recall) that also do not report source file/line numbers.

Fix the ProofGeneral interaction

The ProofGeneral mode for Abella needs a lot of help to work with 4.2+.

I have it locally working on 4.3+ CVS trunk on Emacs 24.3. Not tested on any other Emacs or PG version.

Clement Houtmann's patches from ages ago need to be revived as well.

Make prune_arg automatic

Because member is a built-in predicate, prune_arg should be applied automatically to eliminate impossible cases in member hypotheses. Thus, for example, given

H4: member (of n1 A) (of n1 B :: G)
H5: member (of n1 A) (of n2 B :: G)

case H4 should unify A and B and produce no additional subgoals, and case H5 should succeed immediately.

Of course, this would eliminate the need for prune_arg and break a lot of developments (including all of my own), but it is arguably the right thing from a system perspective.

Message on failed search

Sometimes search finishes very quickly and without success. It would be useful to get a message saying that no proof was found to avoid confusion with other situations when a proof was trivial and the next case is shown.

Improving Not_found error message

If I use the tactic apply theorem_name to H1 H2 H3 H4 H5 H6 H7 H8 H9 H10 and I get Error: Not_found, I don't know immediately whether that's because I misspelled or used a non-existent theorem or hypothesis.

For convenience, the error message should include the offending identifier.

Hypothesis disappears on case error

When mistakenly performing, say, case H5 on a backchaining hypothesis where the bracketed formula is a variable, I get the usual error message ("Error: Failure("Head of backchained clause unknown...")"), but then the proof state I'm returned to is missing hypothesis H5.

Unfolding named clauses assumes range restriction invalidly

Consider this input:

sig bad.
kind i type.
type a,b1,b2,c i.
type p i -> i -> o. 
----
module bad.
%:pab1:
p a b1.
%:pb2c:
p b2 c.
%:trans:
p X Z :- p X Y, p Y Z.
----
Specification "bad".   
Theorem foo : {p a c}.
unfold trans. search. search.

The issue is that after the unfold we get two subgoals, one with {p a ?1} and the other with {p ?1 c}. Since logic variables in different subgoals have nothing to do with each other, each subgoal is individually proved.

The expected result of the unfold is exists L, {p a L} /\ {p L c}.

This bug is reported by Claudio Sacerdoti Coen.

Improve web page generation

  • Abella should output XML or sexps or something that doesn't require guesswork
  • Need to remove the dependency on OMake.
  • Consider rewriting the web-page generation code in OCaml

Cannot read clauses with propositional variables in their heads

Abella fails to read a specification containing containing clauses whose heads are propositional variables.

For instance, when reading the following specification

sig tst.
type  p         o.
-----------------------------------
module tst.
p.

Abella reports an error : "Error: Failed while reading specification".

However, it is OK for propostional variables to occur in the body of clauses. The following specification is accepted by Abella.

sig tst.
kind i     type.
type p     o.
type q     i -> o.
---------------------------------------
module tst.
q M :- p.

This is apparently a parsing error and should be easy to fix.

Precedence of \ vs ::

Now, with higher-order context assumptions, shouldn't \ get a higher precedence than ::? I'm thinking of examples like

Define ctx : olist -> prop by
  nabla x, (pi H\ hyp H x :: G) := ctx G.

which fails because :: has a higher precedence than \, requiring you to add parentheses. Are there other, similarly prevalent examples I'm not recalling where the current precedence is to be preferred?

I realize that this example is now perhaps better written as a Schema, but I could add a non-olist argument to the definition, which arises quite commonly, where schemas can't be used (as least for now).

Improved control over subgoal display

This is a feature request (and an incidental bug report).

Andrew Gacek graciously added nested subgoal numbering and the subgoals flag at my request when I was working on some large developments, but after continuing to work on large developments, I find myself wanting an additional axis of control: I would also like to be able to set a maximum number of subgoals (at any level) that are displayed at one time. The motivation is that the ideal number of subgoals to display is often independent of the nesting level but dependent on one's display size, and with predicates defined by dozens of clauses, the display often must either show no subgoals or an overwhelming number of them, to the point that the hypotheses and goal have long scrolled away.

Also, I would like to request that when using a non-infinite value of the subgoals flag, the message reporting the number of subgoals remaining should be broken out by how many subgoals are remaining at each level. This information is often a better summary of one's position in the proof than just the total number of subgoals remaining.

Finally, if these features are implemented, I would recommend additionally taking a careful look at the code that generates subgoal numbers. The other day, I came across a small bug in the middle of a big proof that involved two successive subgoals being given the same number. I didn't make a ticket for it because I didn't have the time to isolate the problem and extract a small portion of my large development that illustrated it at the time, and now I can't find it again, although I'm sure it was there. This was the only time I've seen it happen, however, so it seems quite rare. I'm passing along this information here just as a head's up, since, if you end up implementing my suggested features, then you will at least be looking at this code, and if you pay a little extra attention to the invariants there, you might spot the problem.

Accidentally capturing bound variables by the 'exists' tactic

This bug is illustrated by the following example:

Kind i type.

Type app   i -> i -> i.
Type abs   (i -> i) -> i.
Type p  i -> prop.

Theorem foo : exists M, forall (x:i), p (M x).
exists (y\ abs x\ app x y).

Applying the last tactic results in the goal:

 forall x, p (abs (x\app x x))

Where an occurrence of x bound by forall is accidentally captured by the binder x in the instance for exists.

Instantiations showing clause numbers/names

I find the new instantiations flag useful to help figure out what case I'm in during a proof. However, this would be even more useful if, in addition to the variable instantiation, it also showed the clause number or name (as reported by witnesses, for example) at which the instantiation occurred. Then there would be no doubt as to the case one was in, and moreover it would be quick to find out.

unfold tactic needs improvements

Need variants of the unfold tactic to control which clause is unfolded.

  • unfold by default will continue to mean the first succeeding match
  • unfold n means unfold using the nth clause of the definition (easy)
  • unfold * means unfold all matches and present a disjunction

The last option is hard to implement as the different branches may have overlapping substitutions. These substitutions will need to be reified into the relevant exists before making the disjunction. It is not entirely obvious how to do this without modifying the implementation of unification.

Improving the case tactic for backchaining object sequents

Matteo Cimini pointed out this issue.

When we have a hypothesis such as

Variables: X
H : {a, b, c, d, e |- X}

and do a case H, it produces:

H1 : {a, b, c, d, e, [F] |- X}
H2 : member F (e :: d :: c :: b :: a :: nil)

instead of one case for each member of the context. This is really annoying if the contexts have more than a few elements. Matteo ran into subgoals with numbers like 3.2.2.2.1.2.1.2.2.1.2.1 (not kidding).

The object-case-tweaks branch (commits starting with 96fce26) fixes this issue, but it breaks too many existing proofs. I have therefore backed it out of master and am postponing it to the 2.1 milestone.

Set a maximum number of subgoals to display

Andrew Gacek graciously added nested subgoal numbering and the subgoals flag at my request when I was working on some large developments, but after continuing to work on large developments, I find myself wanting an additional axis of control: I would also like to be able to set a maximum number of subgoals (at any level) that are displayed at one time. The motivation is that the ideal number of subgoals to display is often independent of the nesting level but dependent on one's display size, and with predicates defined by dozens of clauses, the display often must either show no subgoals or an overwhelming number of them, to the point that the hypotheses and goal have long scrolled away.

(From #44 by @lambdacalculator)

Allow reasoning level constraints in specifications

It is often very useful to be able to refer to reasoning formulas from the specification logic. A common use case is not and = in the spec, which are supported by Teyjus but not by Abella. To preserve stratification, such "callbacks", which I am calling constraints, must not themselves use the seq or prog definitions, i.e., they cannot involve the spec level provability relation. Moreover, in order to support inst, it must be the case that these formulas contain no nominal constants or nabla.

The proposed syntax is $(metaterm) as an allowed element of the body of a clause (i.e., adding $ : prop -> o in specification formulas), where the metaterm is constrained to be constructed out of: conjunction, true, disjunction, false, implication, equality, forall, and exists. Disallowed are nabla and {}.

The interpretation adds the following cases to the seq predicate:

{ G |- $(F) }  :=  F ;
{ G, [$(F)] |- C } := F -> { G |- C }

It remains to be proved but seems plausible that cut will hold.

"backchain" automatically follows up with search, which may loop

After the backchain tactic, search is automatically attempted on the generated subgoals. Unfortunately, this can easily loop in cases where the exponential cliff is encountered before the default depth of 5.

Proposal: add a form backchain N hyp_or_lemma where N is the depth bound for all subsequent searches.

This report is made by Horace Blanc.

Need modules for reasoning

The reasoning level of Abella has an extend-only pseudo module system. It could benefit from a real module system with support for proper lemmas and instantiating declared lemmas and constants with theorems and definitions.

This gets us 80% of the way to actual uses of higher-order reasoning without the unsoundness issues that have plagued that variant.

Schemas cannot allow for multiple terms per block

The following definition, contributed by Alberto Momigliano, illustrates a common pattern that is not currently supported by the schemas branch.

Define xadR :  olist -> olist -> olist -> prop by
  xadR nil nil nil ;
  nabla t, xadR (is_tm t :: Is) (aeq t t :: As)
        (deq t t :: is_tm t ::  Ds)
    := xadR Is As Ds.

There are two possibilities for this:

  • Add support for Lambda Prolog's & operator
  • Generalize the Schema grammar to allow lists of terms in blocks.

A new tactic "pick" for naming witnesses that are automatically found

Currently if we have a goal

 exists x, p x /\ q x

where search does not succeed, but it does succeed with exists x, p x, then we might want to use the witness found by the latter in order to prove the goal. Unfortunately, there is no way currently to use an assert to get access to this witness.

Proposal: add a tactic pick x, p x that generates two subgoals: the first is exists x, p x that is attempted to be automatically or manually solved. If it is solved, then suitable instantiations are added for x in the current scope.

This feature request comes from Horace Blanc.

unfold's arbitrary choices are unintuitive

Consider the following:

Kind i type.
Type f i -> i.

Define p : i -> prop by
  nabla x, p (F x) := nabla x, F x = f x.

Theorem works : forall F, p F -> p F.
intros. case H1. search.

Theorem fails : forall F, p F -> p F.
intros. case H1. unfold.

The second case leads to the unprovable goal

============================
 nabla x, f n1 = f x

Currently, even with clause selectors, there is no way to get access to the second conflict-free solution that Tactics.unfold_defs actually finds, which would be:

============================
 nabla x, f x = f x

Proposal: add a (all) cookie to unfold, similar to the (keep) cookie on case, that produces a disjunct of all the conflict-free solutions instead of arbitrarily picking the first.

This issue was brought to my notice by Claudio Sacerdoti Coen.

exists tactic renames but does not normalize

Consider the following Abella development:

Kind i type.

Type p i -> i -> i -> prop.

Theorem foo : forall X Y (X1:i),
  p X X Y -> exists Z X, p Z X X1.
intros.
exists X.

The final clause produces exists X1, p X X1 X1, which is incorrect. It should be exists X2, p X X2 X1.

This bug is reported by @matteocimini.

Cannot apply lemma/theorem with only a nabla prefix.

This should work, but doesn't.

Kind i type.
Type p i -> prop.

Theorem bad : (nabla x, p x -> false) -> p n1 -> false.
intros. apply H1 to H2.

The error we get is:

bad < apply H1 to H2.
Error: Structure of applied term must be a substructure of the following.
forall A1 ... Ai, nabla z1 ... zj, H1 -> ... -> Hk -> C

H1 : nabla x, p x -> false
H2 : p n1
============================
 false

Clearly, H1 fits the indicated pattern.

A new "reduce" tactic that is a bit more eager than "case"

If a definition has only "positive" clauses, meaning that the body of the definition consists of /\, \/, exists, =, and atoms, then there needs to be a tactic reduce that unfolds the definition eagerly on the left. This may loop if there is no fixed point, but that is fine. This would be roughly "level 0" of the Level 0/1 system.

Example: if we have

 H : member F (a :: b :: nil)

then running reduce H should produce two subgoals, with F united with a in one and with b in the other. In case of a loop, we could bound reduce like with search: the invocation reduce 5 H would unfold the definition of member at most 5 times.

This is related to but different from #21.

The name reduce may not be the best option. A less contentious choice might be "async".

Briefly discussed with @ThatDaleMiller.

Unfold on a higher order predicate drops coinductive restriction

Example:

Kind p type.

Define wrap : (p -> p -> prop) -> p -> p -> prop by
  wrap R P Q := R P Q.

CoDefine bisim : p -> p -> prop by
  bisim P Q := wrap bisim P Q.

Theorem foo : forall P Q, true -> bisim P Q.
coinduction. intros.
  unfold.

The last unfold should keep the annotation (# or +), but it is dropped.

This bug is reported by Matteo Cimini.

Variable capture in unfolding definitions

Consider the following Abella theory:

Kind p type.

Type one,up p -> p -> prop.

Define bup : p -> prop by
  bup Q :=
    exists Q1, one Q Q1 /\ exists Q2, up Q1 Q2.

Theorem foo : forall Q1 (Q2:p), bup Q1 -> false.
intros. case H1.

The final line produces: H2 : up Q3 Q3, which is invalid. Since both Q1 and Q2 are exists-bound, the new hypothesis should have different arguments to up.

Documentation fixes

Things to check off as they are updated.

  • README
  • Build instructions (website and an INSTALL file)
  • A changelog/introduction to the changes
  • Tutorials (website)
  • List of papers (website)
  • Updated list of contributors and maintainers (website)
  • Updated grants and support list (website)

Yuting is in charge in general.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.