|
2 | 2 | |:-----------------:|:----------------:|:----------------:| |
3 | 3 | | [![][travis-img]][travis-url] | [![][appveyor-img]][appveyor-url] | [![][codecov-img]][codecov-url] | |
4 | 4 |
|
5 | | -# FirstOrderLogic |
| 5 | +# FirstOrderLogic.jl |
6 | 6 |
|
7 | 7 | This is a Julia package for parsing, manipulating and evaluating formulas in first-order logic. |
8 | 8 |
|
| 9 | +## Overview |
| 10 | + |
| 11 | +`FirstOrderLogic.jl` follows the standard structure for Julia projects. |
| 12 | + |
| 13 | +### Functionality |
| 14 | + |
| 15 | +`FirstOrderLogic.jl` currently provides the following: |
| 16 | + |
| 17 | +* An intuitive type system for formulas in first-order logic. |
| 18 | + |
| 19 | +* Various methods for converting formulas in special forms: |
| 20 | + * prenex normal form |
| 21 | + * skolem normal form |
| 22 | + * conjunctive normal form |
| 23 | + * ... |
| 24 | + |
| 25 | +* A prover for formulas in first-order logic. |
| 26 | + |
| 27 | +### Purpose |
| 28 | + |
| 29 | +`FirstOrderLogic.jl` may prove useful for the following: |
| 30 | + |
| 31 | +* Easily verifying the unsatisfiability of short formulas in first-order logic. |
| 32 | + * The `is_satisfiable()` function is made for this very purpose. |
| 33 | + |
| 34 | +* Learning basic first-order logic concepts and algorithms. |
| 35 | + * The whole code base is well-designed and documented. |
| 36 | + |
| 37 | +* *Coming soon!* Quickly verifying the unsatisfiability of long formulas in first-order logic. |
| 38 | + * A highly optimized, parallelizable version of `is_satisfiable()` is in progress. |
| 39 | + |
| 40 | +## Installation |
| 41 | + |
| 42 | +1. Run |
| 43 | +``` |
| 44 | +julia |
| 45 | +``` |
| 46 | +2. In your Julia shell, run |
| 47 | +``` |
| 48 | +Pkg.clone("git@github.com:roberthoenig/FirstOrderLogic.jl.git") |
| 49 | +``` |
| 50 | + |
| 51 | +## Usage |
| 52 | + |
| 53 | +### Quick walkthrough |
| 54 | + |
| 55 | +Say we have a formula `∀x(P(x) ∧ ¬P(f(x)))`. We want to verify that this formula is unsatisfiable. |
| 56 | +To do so, we do the following: |
| 57 | +1. Type the formula in `FirstOrderLogic.jl` syntax: `*{x}(P(x) & P(f(x)))`. |
| 58 | +2. Run |
| 59 | +``` |
| 60 | +julia |
| 61 | +``` |
| 62 | +3. Import `FirstOrderLogic.jl`: |
| 63 | +``` |
| 64 | +using FirstOrderLogic |
| 65 | +``` |
| 66 | +4. Run `is_satisfiable(<our formula>)`: |
| 67 | +``` |
| 68 | +is_satisfiable("*{x}(P(x) & ~P(f(x)))") |
| 69 | +``` |
| 70 | +If everything works correctly, the program should print "false" and terminate. This means that `∀x(P(x) ∧ ¬P(f(x)))` |
| 71 | +is unsatisfiable. We have verified what we wanted to verify. |
| 72 | + |
| 73 | +### Formula syntax |
| 74 | + |
| 75 | +`FirstOrderLogic.jl` currently uses its own syntax for representing formulas |
| 76 | +in first-order logic. A parser for latex symbols is in progress. |
| 77 | + |
| 78 | +The following is a list of all currently supported syntactic elements. |
| 79 | + |
| 80 | +| Mathematical syntax | `FirstOrderLogic.jl` syntax | Semantic | |
| 81 | +| ------------------- |:------------------------:| --------:| |
| 82 | + x | x | variable |
| 83 | + f(x,y) | f(x,y) | function |
| 84 | + f(x,y) | f(x,y) | predicate |
| 85 | + ∃x | ?{x} | existential quantification |
| 86 | + ∀x | *{x} | universal quantification |
| 87 | + ¬x | ~x | negation |
| 88 | + x ∧ y | x & y | conjunction |
| 89 | + x ∨ y | x | y | disjunction |
| 90 | + (x ∧ y) ∨ z | (x & y) | z | precedence grouping |
| 91 | + |
| 92 | +#### Example |
| 93 | + |
| 94 | +Formula in mathematical notation: |
| 95 | +``` |
| 96 | +∀x∃yA(x,g(y,z)) ∧ (¬B() ∨ ∃dC(d)) |
| 97 | +``` |
| 98 | +The same formula in `FirstOrderLogic.jl` notation: |
| 99 | +``` |
| 100 | +*{x}?{y}A(x,g(y,z)) & (~B() | ?{d}C(d)) |
| 101 | +``` |
| 102 | + |
| 103 | +### Some important functions |
| 104 | + |
| 105 | +| Function | Purpose | |
| 106 | +|:--------:|:-------:| |
| 107 | + `is_satisfiable(formula; maxsearchdepth)` | Checks if `formula` is satisfiable. |
| 108 | + `get_conjunctive_normal_form(formula)` | Returns `formula` in the conjunctive normal form, expressed as clauses. |
| 109 | + `get_prenex_normal_form(formula)` | Returns the prenex normal form of `formula`. |
| 110 | + `get_skolem_normal_form(formula)` | Returns the skolem normal form of `formula`. |
| 111 | + `Formula(str)` | Parse str to a `Formula` object and return that object. |
| 112 | + |
| 113 | +Each available function comes with a concise docstring. |
| 114 | + |
| 115 | +## How is this different from PROLOG? |
| 116 | + |
| 117 | +The PROLOG programming language can be used to prove seemingly arbitrary statements in first-order logic. PROLOG differs from `FirstOrderLogic.jl` in two ways: |
| 118 | +* Syntax: PROLOG code is written in in facts. These facts represent horn clauses. In doing so, |
| 119 | + PROLOG hides the first-order logic syntax from the user. This proves convenient for real |
| 120 | + world applications, but it's not mathematically pure. `FirstOrderLogic.jl` uses a direct |
| 121 | + mathematical syntax for expressing formulas. |
| 122 | +* Expressive power: PROLOG works on a limited set of all valid formulas in first-order logic, namely |
| 123 | + only formulas that can be expressed as a conjunction of [horn clauses] |
| 124 | + (https://en.wikipedia.org/wiki/Horn_clause). This is sufficient for many real world applications, |
| 125 | + but it's not mathematically complete. PROLOG thereby trades completeness for computation time. |
| 126 | + `FirstOrderLogic.jl` does not make that trade. It is slow, but complete. |
| 127 | + |
9 | 128 | [codecov-img]: https://codecov.io/gh/roberthoenig/FirstOrderLogic.jl/branch/master/graph/badge.svg |
10 | 129 | [codecov-url]: https://codecov.io/gh/roberthoenig/FirstOrderLogic.jl |
11 | 130 | [travis-img]: https://travis-ci.org/roberthoenig/FirstOrderLogic.jl.svg?branch=master |
|
0 commit comments