CleanLogic
Logic toolbox in Clean. Features include:
- Straightforward types for (atomic) expressions, operators and truth tables
show
(toString
-like) instances for all types that take care of associativity- Substituting atomic expressions for constants
- Evaluating expressions without atomic expressions
- Generating truth tables for expressions, possibly with intermediate steps
- Displaying truth tables
- Parsing strings to expressions
- A web frontend to access the Clean program through, so only server-side installation is necessary
- Different output options (Plain / ASCII art, HTML, LaTeX)
Read further for examples.
Demo
A demo of the web frontend may be found on https://demo.camilstaps.nl/CleanLogic.
License
This program and the example are distributed under the MIT license. For more details, see the LICENSE file.
Installation
Set CLEAN_HOME
to your Clean installation directory. To install the parser
and the example program:
make
Types
Operators
There is one unary operator (Op1
): Not
. It binds stronger than all other
operators.
There are four binary operators (Op2
). In order of descending precedence:
And
, Or
, Impl
and Equiv
. And
is considered left-associative; all
others are considered right-associative. Associativity is only important in
toString
functions. Expr
itself is an unambiguous recursive type.
The operators are represented as:
- Negation (¬):
~
- Conjunction (∧):
&
- Disjunction (∨):
|
- Implication (→):
->
- Equivalence (↔):
<->
Expressions
Expressions are constants (B Bool
), atomic expressions (Atom Char
), or
applications of operators on other expressions (App1 Op1 Expr
or App2 Expr
Op2 Expr
).
Examples
// Some random examples
e1 = Atom 'p'
e2 = Atom 'q'
e3 = App1 Not e1
e4 = App2 e1 And e2
e5 = App2 e3 Or e2
e6 = App2 e3 Impl e3
e7 = App2 e4 Equiv e5
e8 = App2 (App2 (Atom 'p') And (Atom 'q')) Impl (Atom 'q')
e9 = App2 (Atom 'p') And (App2 (Atom 'q') Impl (Atom 'q'))
// To test associativity rules
e10 = App2 (App2 (Atom 'p') And (Atom 'q')) And (Atom 'r')
e11 = App2 (Atom 'p') And (App2 (Atom 'q') And (Atom 'r'))
e12 = App2 (App2 (Atom 'p') Or (Atom 'q')) Or (Atom 'r')
e13 = App2 (Atom 'p') Or (App2 (Atom 'q') Or (Atom 'r'))
e14 = App2 (App2 (Atom 'p') Impl (Atom 'q')) Impl (Atom 'r')
e15 = App2 (Atom 'p') Impl (App2 (Atom 'q') Impl (Atom 'r'))
e16 = App2 (App2 (Atom 'p') Equiv (Atom 'q')) Equiv (Atom 'r')
e17 = App2 (Atom 'p') Equiv (App2 (Atom 'q') Equiv (Atom 'r'))
Substitution
You can substitute all occurrences of Atom a
in an Expr e
by a Bool b
with substitute (a,b) e
. This yields a new Expr
, in which all occurrences
have been replaced by the constant B b
.
An alternative is substitute_all
, which takes a list of tuples (a ::
AtomName, b :: Bool)
and substitutes all atomnames with the corresponding
booleans.
Evaluation
An expression e
without atomic expressions may be evaluated to its result
by calling eval e
. This yields the empty list []
if e
did have atomic
expressions, or a singleton [b :: Bool]
with the result of the evaluation.
Truth tables
A TruthTable
has a list of expressions exprs
and a list of options
, which
has the type [[(AtomName,Bool)]]
and describes all the options the truth
table should list.
A simple truth table of an expression e
contains only the atomic expressions
in e
and e
itself. It may be built with simple_truthtable e
. A more
complex truth table lists all e
's subexpressions. In either table, the
expressions are roughly sorted by complexity.
A truth table table
can be shown with toString table
.
Examples
The simple_truthtable
of e10
:
p | q | r | p & q & r
-------+-------+-------+-----------
False | False | False | False
False | False | True | False
False | True | False | False
False | True | True | False
True | False | False | False
True | False | True | False
True | True | False | False
True | True | True | True
The truthtable
of e15
:
p | q | r | q -> r | p -> q -> r
-------+-------+-------+--------+-------------
False | False | False | True | True
False | False | True | True | True
False | True | False | False | True
False | True | True | True | True
True | False | False | True | True
True | False | True | True | True
True | True | False | False | False
True | True | True | True | True
Parsing
The parse
function may be used to read an expression from a String. The
following rules are used:
- Spaces are ignored.
- All Latin letters (
[a-zA-Z]
) are considered atomic expressions - Operators are expected in their representation described above
- True and False are expected as
1
and0
, respectively - Unknown characters will throw an error
A usage example is found in LogicParser.icl
. This file, once compiled, reads
the command line arguments and shows their truth tables:
$./LogicParser -e "~~(((A | (A -> B)) -> B) -> B)"
A | B | A -> B | A | (A -> B) | A | (A -> B) -> B | (A | (A -> B) -> B) -> B | ~((A | (A -> B) -> B) -> B) | ~~((A | (A -> B) -> B) -> B)
-------+-------+--------+--------------+-------------------+--------------------------+-----------------------------+------------------------------
False | False | True | True | False | True | False | True
False | True | True | True | True | True | False | True
True | False | False | True | False | True | False | True
True | True | True | True | True | True | False | True
The option -e
tells the parser to show the extended truth table. With this
option, only the first formula is considered. Without -e
, multiple formulas
may be given (possibly with different atomic expressions), and all will be
evaluated in one table:
$./LogicParser -b -nt "~~(((A | (A -> B)) -> B) -> B)" "A & B"
A | B | ~~((A | (A -> B) -> B) -> B) | A & B
-------+-------+------------------------------+-------
False | False | True | False
False | True | True | False
True | False | True | False
True | True | True | True
False | False | True | False
False | True | True | False
True | False | True | False
True | True | True | True
The parsers also recognises -html
and -latex
and will output an HTML or
LaTeX table if these arguments are present.
Web frontend
There is a simple web frontend in PHP and a basic HTML template which allows
one to connect to the Clean application through his browser. The files for this
are index.html
and request.php
, and a demo may be found on
https://demo.camilstaps.nl/CleanLogic. For this to work, the exec()
function
should be enabled in your PHP configuration.
Future ideas
- Different
toString
formats for booleans:0
and1
orT
andF
instead ofTrue
andFalse
- Simplifying expressions with atomic expressions as far as possible
- Testing equivalence or impliance of expressions with atomic expressions
- Add support for multi-letter atomic expressions
- Would it be easier / neater / more intuitive to get rid of
Op1
andOp2
and useNot
,And
, etc. as type constructors ofExpr
?