Think about logic as a generic way of writing rules: proving formulas and answering questions is a way of detecting what follows from the rules we wrote.
The predicate logic toolkit is built around a high-performance reasoner gkc (see the paper) and runs in the browser using Wasm without any server involvement. For more advanced use you may want to download the command-line version.
Use these tools for learning logic and experimenting with reasoners.
A good way to learn syntax and meaning is to go through the explanations in the simple examples. Nevertheless, the following presents a compact description.
The simple syntax is an extension of the TPTP FOF and CNF syntaxes as described in the TPTP technical manual, combining them into one and extending with a list type and a few convenience predicates and constructions.
The simple syntax input is a list of logical formulas, each terminated with a period. The whole list is interpreted as a big conjunction (and) of formulas.
Each formula is either a literal (a positive or a negative atom) or is constructed from simpler formulas using logical operators like
&for conjunction (and),
|for disjunction (or),
~for negation (not),
=>for implication (if-then),
! [variables] : formula(example
! [X,Y] : p(X,Y))
? [variables] : formula.
Additional logical operators will be described later.
An atom is a predicate symbol applied to a number of term arguments like
father(john,pete) and denoting a relation between the arguments.
A negated atom has a minus sign prepended
Equality is a special predicate written like
and meaning, as expected, that the term on the left side is equal to the term on the
right side. Inequality is another special predicate written like
The terms denote objects. A simplest term is just a symbol/constant
john: think of it as a post-it note glued to some real thing or idea:
a real object may have many such notes glued to it. A variable like
is also a term: think of it as placeholder which can be replaced by any other term.
Variables must start with an upper-case character, other symbols with a lower-case character. There are also other options for symbols, more about these below.
A variable which is not in the scope of a for all
? is treated as if it is bound by the
for all quantifier. In fact, explicit quantifiers can be skipped
altogether: they are just a convenience construction.
Numbers like 12 or 3.45 can be also used as constant terms.
More complex terms can be constructed from simpler terms using functions like
$sum(X,$multiply(2,X)). A value of
such a function is not always defined: it can be used just as a constructor for
complex terms. A function may also be defined on some other terms, like
is defined on numbers, but not on lists. You may define functions yourself using equality
Both line comments
% and multi-line comments
/* ... */
Think about an atom like
father(john,pete) as saying
that there is a row with two cells
john,pete in a two-column
father. In fact, the core ideas of relational database systems
and SQL stem from this interpretation, although they branch off into specific
directions. For example, in conventional logic notation all the elements
in row columns are given positionally, one after another, while in SQL columns have names.
Each predicate like
father should be seen as giving rise
to two different tables: one for positive facts and another for negative
-father(john,mike) means that in the negative -father
table there is a row
john,mike. Importantly, the facts
we state only say that there are these-and-these rows, but they do not
say that there cannot be other rows, unknown to us. This inpreretation
is called open world
assumption contrasting the
assumption used in database systems and Prolog.
Logical formulas are then understood as rules for deriving new rows in
the tables. For example.
father(X,Y) => child(Y,X) means that
if there is a row in the
father table, the corresponding row with
arguments exchanged must be put into the
A rule like
-father(X,X) can be seen as saying that the
-father table contains rows like
for all objects. Since
we could potentially have infinitely many objects (think numbers and terms
constructed from functions) we cannot always physically fill in all the rows.
A contradiction occurs when a row in the positive table also occurs
in the corresponding negative table. For example, saying
would contradict the row
john,john in the negative
table, given the rule
Finding a contradiction is used as one convenient way of finding whether some
fact/row follows from our rules. Suppose we have two statements
father(X,Y) => child(Y,X)
and we want to prove an obvious fact that
from these two. Let us denote these three statements as a, b, c. Then
we really want to prove that
a & b => c is true,
which is equivalent to the question of whether the negated form
-(a & b => c) is contradictory, which is equivalent
to the question of whether the conjunction
a & b & -c is contradictory. Hence we could add
the negated form
-child(pete,john) to our two initial statements
and check whether a contradiction can be found.
Finally, an important principle of logic as used here is that no common knowledge
- or rather, no knowledge at all - is assumed. Everything we want to use
must be written explicitly as logical facts and rules. The names of the predicates
mean nothing in itself: a reasoner knows nothing about the
predicate except what is explicitly written in the problem statement. You could
replace all the nice human-understandable names with meaningless names and the
logical meaning of the problem statement would be exactly the same.
Ordinary symbols must start with lower-case character and
must not contain any whitespace or non-alphanumeric characters
(, -, ~, =, " etc: however, underscore
$ are allowed.
You can put whitespace or any symbol except a single quote
into symbols by surrounding the symbol with single quote symbols like this:
'John Smith'. Internal quotes must be prefixed by a backslash
Additionally you can make a symbol variable by prefixing it with a question
mark like this:
Double quotes surrounding a symbol like
have a special meaning: the symbol is treated as distinct (essentially,
a string) meaning that it is known to be unequal to any syntactically
different distinct symbols, numbers and lists. This has real effect for
equality and string predicates, but not otherwise.
In addition to the typically used constructions
? the syntax provides a number of additional infix logical
constructions with two arguments. The full list is:
<=for reverse implication,
<~>for non-equivalence (XOR),
~|for negated disjunction (NOR),
~&for negated conjunction (NAND),
@for application, used mainly in the higher-order context in TPTP.
$ans is used for finding the actual terms we look for as answers: see the
The numbers and arithmetic functions and predicates are defined following the TPTP arithmetic system plus a few convenience operators for writing infix terms:
Note: these comparison predicates and arithmetic functions take exactly two arguments.
Note: these convenience functions take also exactly two arguments.
NB! Do not use a variable or a non-numeric constant as a first element of the
infix arithmetic expression like
the whole expression will be parsed as a single variable X*2. No such restrictions
apply for the prefix form.
You can use the list syntax like
 for the empty list and
for a three-element list. The bracket notation is syntactic sugar for
$nil and functional list-constructing term
constructs a list by prepending
X0 to the list
which is generally different from a two-element list
Terms constructed using
$nil are interpreted as having a
$is_list(L)evaluates to true if A is a list and false is A is a number or a distinct symbol.
$first(L)returns the first element of the list.
$rest(L)returns the rest of the list, i.e. the result of removing the first element.
Symbols in double quotes like in
"person" stand for
for distinct symbols
which can be viewed as a string type. A distinct symbol is not equal to any
other syntactically different symbol and not equal to any numbers or lists.
Gkc defines a function and three predicates on distinct symbols:
$strlen(S)returns the integer length of a distinct symbol S as a string.
$substr(A,B)evaluates to true if a distinct symbol A is a substring of a distinct symbol B, and false otherwise, provided that A and B are distinct symbols.
$substrat(A,B,C)evaluates to true if a distinct symbol A is a substring of a distinct symbol B exactly at the integer position C (starting from 0), and false otherwise, provided that A and B are distinct symbols and C is an integer.
$is_distinct(A)evaluates to true if A is a distinct symbol and false if A is a number or a list.
Automated reasoners prove logical theorems, answer questions and (sometimes) can detect unprovability. Basically, they are highly optimized search systems often encompassing a large number of different search strategies.
Most of the reasoners are specialized to perform well on some specific kinds of problems or are extended with additional special capabilities. For example, the gkc prover used in this site is specialized for very large problems, although this capability cannot be used well in the confined browser environment. Hint: you may want to download the command-line version for more advanced use.
Good reading material for predicate logic provers:
For the generic reasoners, mostly niche applications so far. The eighties-hype of expert systems and symbolic A.I. with little practical value lead to the famous A.I. winter. This said, the propositional and SMT provers are seriously used for verification, test generation and configuration management.
The main obstacles for wider use: (a) it is very hard, or practically impossible (although theoretically possible) to hand-encode most of human expert knowledge in logical rules, (b) proof search without intelligent guidance is really hard, (c) basic predicate logic without probabilities, default reasoning etc etc is extremely impractical for encoding commonsense knowledge.
There is hope for a new rise of reasoners as parts of a machine-learning-and-reasoning hybrid systems performing common sense reasoning. Check out a preprint proposing several mechanisms in this direction.
Use either a conventional formula syntax like
or a dimacs version of the clause normal form syntax like
(a -> b) & a & -b
which is a conjunction of disjunction lines with numbers standing for variables: the last example means simply (-x1 v x2) & x1 & -x2
-1 2 1 -2
For conventional formula syntax:
For dimacs you may use or skip the initial comment lines starting with c, the special p line and the final 0 symbols at the end of each disjunct. We allow the trailing 0-s only at the end of a line.
I.e. you may use the full dimacs version like
c comment p cnf 2 3 -1 2 0 1 0 -2 0
-1 2 1 -2
Solving a classical propositional formula means looking for such values of variables that the formula becomes true. For example, (a -> b) & a becomes true if and only if both a and b are assigned true.You can select and try out several solver algorithms: the "DPLL better" is the best solver amongst the options offered on our page. Read the "Methods for solving formulas" section below about the differences between algorithms. One single suitable set of values is enough as a solution: our solver algorithms stop and do not try to find additional solutions. Some of the solver algorithms output the suitable values, but some do not, or output a partial set. It may also happen that the formula is false for all possible values of variables: if so, the solver algorithms report that after exhausting the search options. For example, (a -> b) & a & -b is always false. Notice that you can check whether some formula F is always true by trying to solve the negated formula -F: in case -F is always false, F must be always true. Our solvers may optionally output a trace of the search process. Select "html trace" to see the search process. For formula-syntax input our solvers first convert the formula to a clause normal form: for certain kinds of formulas this conversion step may create a huge output, but in most cases it is a sensible simplification before actual search.
The options for the type of a problem are:
For DPLL try out 200 variables or more. Truth table solvers start running into trouble with more than 20 variables. The resolution provers are a bit better than the truth table solvers, yet much worse than the DPLL solvers.
You can also browse and read the contents of a file into the input area: essentially copy-paste from a file.