As described in section IV.A. of the report.
Use the web interface.
- We use Poetry as a dependency manager. It is similar to Anaconda or Pipenv, but easier to use and officially supported.
- Install poetry, then
poetry install
to install project dependencies - Documentation for poetry
- Important commands:
poetry run mypy src --namespace-packages
for typecheckingpoetry run pytest src
for testing
The code consists of 5 main parts:
- A parser for propositional logic. It could easily be extended for defeasible logic. See
propositional_parser.py
. Tests ✔️ - A tableau for propositional logic. See
propositional_tableau.py
. Tests ✔️ - A tableau for defeasible logic. See
defeasible_tableau.py
. Some larger tests not terminating ✔️✖ - Decision support system. See
decision_support_system.py
. Tests exist, but are not automated due to I/O (✔️) - Datastructures and helper functions. See
reasoning_elements/
. Mostly tested (✔️)
The server is necessary for using the website as an interface for the code. The server is already hosted at xai.davidpomerenke.vercel.app.
Vercel is a commercial, yet not utterly evil company providing a service for easily starting a server from Python and other languages, and also for hosting it for free. Vercel uses two directories:
api/
contains the Python files specifying the API. Each fileapi/somefile.py
will make its API available viahttps://localhost:3000/api/somefile
when the server is running.public/
contains the HTML files etc. that make up the website which accesses the API. They are served statically, that is, just as they are and without any further processing. A filepublic/somefile.html
will be available viahttps://localhost:3000/somefile.html
when the server is running.
For running the server locally on your computer, install the Vercel CLI. (For this, you may first need to install one of the Node JS package managers, either npm or yarn.)
vercel dev
for running the server locally
Vercel does not work with poetry but requires a specification of the dependencies in the requirements.txt
format by pip. This can be exported from poetry as follows; the command needs only be run when some dependencies have changed:
poetry export -f requirements.txt --output requirements.txt
The data structures usually have at least some of the following methods:
__init__
__str__
for printing them withstr(...)
. If a datastructure is a compound of other data structures, this will callstr(...)
on these other data structures and combine the resulting strings in some way.__eq__
for defining equality between objects. Without this, two objects will always be different in Python, even if they have exactly the same content. For propositions, rules, arguments, etc., only the content matters, so we need to define__eq__
to make this clear. Usually,__eq__
will refer to the string representation of the object, since the string representation is already unique.__hash__
for allowing the construction of (hash) sets with objects of the class. Ususally this is just implemented ashash(str(..))
for simplicity.__lt__
("less than") for sorting the objects. By decorating the class with@functools.total_ordering
, this will automatically create the other ordering methods, such as__gt__
("greater than"), etc. This function is relevant for creating correct__eq__
instances for lists of objects that are really sets. (We create a unique ordering by sorting the string representations of the elements.) Maybe it would be better to actually make them sets. But then, we wouldn't have these nice pythonish list comprehensions.
There is a hierarchy between the classes: For example class And(ComplexProposition):
means that And
inherits all methods from ComplexProposition
. Furthermore, And
needs to implement all methods from ComplexProposition
that are decorated by @abstractmethod
.
The hierarchy of the Proposition
classes (see reasoning_elements/proposition.py
) is as follows:
Proposition
- (Propositional)
Variable
TruthValue
T
("true")F
("false")
ComplexProposition
And
Or
Implies
Equiv
Not
- (Propositional)
There is also a Test
class (in reasoning_elements/test.py
), but it is not considered a proposition, but rather just a wrapper for proposition (which is always negated).
The tableaux rules are implemented in the And
, Or
, Implies
, Equiv
, and Not
data structures. There is always one method decompose()
that applies the propositional tableaux rule if the proposition is not negated; and decompose_negated()
if the proposition is negated. These functions return a list of one or two lists (branches!) of one or two derived propositions (sequents) each. The is_forking()
method says whether a fork will happen when the positive decomposition is applied.
Since a rule can occur in a positions where there are usually propositions (in the conclusion of an argument, to be specific), it can also be decomposed: This means that just its consequence will be decomposed and the antecedence will stay the same.