⇚ home

somerby.net/mack/logic

Introduction

This web application (herein referred to as "the software" or "application") decides the validity/satisfiablity/inconsistency of certain kinds of statements in symbolic logic.

Most of the software is written in C# and translated into JavaScript with Saltarelle. The source code is on GitHub. Viz.js is used to generate diagrams. The truth table feature is adapted from code written by Michael Rieppel.

Thanks to Maximiliano Paesani for his help in translating the web application into Spanish. Gracias a Maximiliano Paesani para su ayuda en la traducción de esta aplicación.

Instructions

To use this application, type a logical statement into the textbox on the main page, then click the "Decide" button. If the application can decide the statement, it will. Otherwise, it will show some kind of error message describing what went wrong. The language section explains how to write logical statements for this application. If you're looking for examples of statements, click on any of the buttons under the heading entitled "Examples" and the application will fill the text box with an example statement, ready to be decided.

If you click "Depict" button, the application will draw a diagram that shows how the application interprets the statement in the textbox. This diagram is a graphical representation of the data structure that the application actually uses to decide the statement.

If there is a syntactically valid propositional logic statement in the textbox, the "Truth Table" button will be enabled. Clicking this button will cause the application to draw a truth table for the statement.

Clicking the "Example" button will cause the application to attempt to find a kind of world where the statement is true. If it succeeds, it will show a description of that kind of world.

Clicking the "Counterexample" button will cause the application to attempt to find a kind of world where the statement is false. If it succeeds, it will show a description of that kind of world.

Clicking the "Tree Proof" button will pass the statement to wo's Tree Proof Generator. It is a web application that uses Semantic Tableaux to check the validity of a statement, and provides a proof if it finds that the statement is valid. The "Tree Proof" button will be enabled whenever there is a syntactically valid statement in the text box that does not contain identifications or modal operators. If you want to evaluate a statement that contains binary predicates (relations), use the Tree Proof Generator.

The Language

Elements of the Language

The language has these elements:

Logical Operators

The logical operators recognized by the software are:

OperatorSymbolDescription
negation ~ Logical NOT
conjunction & Logical AND
disjunction | Logical OR
material conditional -> if … then …
biconditional <=>Logical equivalence
joint denial ! Logical NOR
exclusive disjunction^ Logical XOR
strict implication-< necessarily if … then …

The binary logical operators all are left-associative and have the following precedences:

PrecedenceOperators
highest &, !
|
->, -<
lowest <=>, ^

For example,

A|B&C->D

is interpreted to mean the same as

(A|(B&C))->D

Negation is right-associative and has higher precedence than any of the binary operators, so

~P & ~Q

is interpreted to mean the same as

(~P) & (~Q)

Variables

A variable is a single lowercase letter that represents the object of a quantification. A lowercase letter in a predication will be interpreted as a variable if the predication is a subexpression of a quantifier. It will be bound to the nearest enclosing quantifier.

Individual Constants

Individual constants, like variables, are single lowercase letters. Any lowercase letter in a predication will be interpreted as an individual constant if the predication is not bound by a quantifier. As far as I can tell, individual constants are not necessary in a symbolic logic, in that the idea of a named individual could be expressed with other symbols. This argument

Hx->Mx // All men are mortal.
Hs     // Socrates is a man.
->     // Therefore
Ms     // Socrates is mortal.

could also be represented without individual constants as

Hx->Mx                                   // All men are mortal.
(3x,Sx) & ([]x,Sx->y,Sy->x=y) & x,Sx->Hx // Socrates is a man.
->                                       // Therefore
x,Sx->Mx                                 // Socrates is mortal.

It is more complicated, but it is in one respect better in that it makes explicit what we usually assume about Socrates, which is that he exists and he is, by definition, a unique individual. Even so, I think individual constants are too convenient a feature to be omitted from the software. The use of an individual constant implies that the object denoted by the individual constant exists. Because of this, the software will decide that 3x,x=g is necessarily true. This isn't the only way to interpret individual constants, but it is the easiest interpretation to implement in this software. Possible objects (ones which may or may not exist) and impossible objects (ones which could never exist), can be represented with unary predicates.

Since I have not yet found a satisfactory way to decide statements which contain both modal operators and individual constants, the software rejects any statement that contains both modal operators and individual constants.

Predicates on Zero Variables

A predicate on zero variables, which can be thought of as representing a true/false proposition, is represented by a single letter.

Predicates on One Variable

A predication on one variable, which can be thought of as the assertion that an object has some property, is represented by a single capital letter (the predicate) followed by a single lowercase letter (the variable). You can use the same capital letter as a predicate over one variable and as a predicate over zero variables in the same statement and the software will treat them as distinct predicates, for example

x,Fx->F

will be interpreted in the same way as

x,Fx->P

because the first "F" is interpreted as a unary predicate and the second "F" is interpreted as a nullary predicate.

Predicates on Two Variables

A predication on two variables, which can be thought of as the assertion that two objects have some relation to each other, is represented by a single capital letter (the predicate) followed by two lowercase letters (the variables). The decision algorithm does not support predicates on two variables, and will usually reject a statement that contains them. Statements that have predicates on two variables can, however, be evaluated with the Tree Proof Generator, if they do not also contain modal operators or identifications.

Grouping

Expressions can be grouped together with parentheses. They work just like parentheses do in algebra or in other symbolic logics.

Universal Generalizations

A universal generalization is a variable followed by a comma followed by the expression the generalization applies to. So you could type

x,Ax

to mean "everything is awesome". The generalization will apply to everything in the expression that follows the comma, up until an enclosing parenthesis or the end of the line of text that the generalization is on. So

x,Fx & y,Jy

is a generalization over

Fx & y,Jy

and not just a generalization over Fx. I recommend adding parentheses to make things clear, like

(x, Fx & (y,Jy))

A variable is always bound to the nearest enclosing generalization, so for

x, (x,F->Px) & Jx

the x in Px is bound to the second universal generalization and the x in Jx is bound to the first universal generalization.

Existential Quantifications

An existential quantification is a "3" followed by a variable followed by a comma followed by the expression that the quantification applies to. For example,

3x, Fx & Bx

Could mean "There is a fountain filled with blood". The same rules for applicability and binding of variables that apply to universal generalizations also apply to existential quantifications.

Definite Description

A definite description is a "1" followed by a variable followed by a comma followed by an expression that is supposed to describe exactly one object. For example,

1x,Rx

Could mean "there is only one Roy Orbison".

Identity

An identification of two objects is just a lowercase letter followed by an equals sign followed by another lowercase letter, for example

x,y, (Fx & x=y) -> Fy

is a statement where "x=y" means x is the same object as y.

Modal Operators

The software recognizes two modal operators, "[]" for necessity and "<>" for possibility. They are right-associative and have the same precedence as negation. The kind of modality represented by these operators is alethic modality.

Two-term Propositions

The software recognizes the two-term propositions of what is variously called "term", "Aristotelian" or "traditional" logic. It treats two-term propositions as shorthand statements of unary predicate logic. They are a capital letter representing the subject term, followed by a lower-case letter representing the proposition's form, followed by a capital letter representing the predicate term.

SymbolPropositionDefinition
SaPAll S are P (x,Sx->Px)&(3x,Sx)
SePNo S are P x,Sx->~Px
SiPSome S is P 3x,Sx&Px
SoPNot all S are P (3x,Sx&~Px)|(~3x,Sx)
SuPEither all S are P or no S are P (x,Sx->Px)|(x,Sx->~Px)
SyPSome S are P and some S are not P(3x,Sx&Px)&(3x,Sx&~Px)

In order to make the traditional Square of Opposition hold true, the A-form proposition is given existential import and the O-form proposition is denied existential import, per what was argued by Terence Parsons. It also recognizes the U-form and Y-form of the Hexagon of Opposition.

Either term in a proposition can be negated by adding the "~" symbol, for instance, "~Aa~B" will be interpreted as "all non-A are non-B". A "~" at the front of the expression attaches to the first term and not to the whole expression, so "~Aa~B" is interpreted to mean the same as "(~Aa~B)" and not the same as "~(Aa~B)".

Assertions of Number

The language includes a means to make some simple assertions of number. I added them to the language just for convenience; they sometimes help when codifying the logic in certain logic puzzles. They don't belong to any symbolic logic that I know of.

A nonnegative integer n followed by a single capital letter Pis an assertion that exactly n objects have the property P.

A nonnegative integer n followed by more than one capital letter P, Q, … is an assertion that exactly n of the propositions P, Q, … are true.

ExampleMeaning
0PNo objects are P
1PExactly 1 object is P
2PExactly 2 objects are P
0PQRNone of P, Q and R are true
1PQROnly one of P, Q and R is true
2PQRExactly 2 of P, Q and R are true

Text Replacements

A line that begins with "#replace" will be interpreted as a directive to replace one string of letters or symbols with another in the lines below the directive. It's a way to define your own operator symbols or give meaningful names to predicates and variables. For example, when given the text

#replace => ->
#replace man H
#replace mortal M
#replace socrates s
#replace therefore .'.

x, man x => mortal x
man socrates
therefore
mortal socrates

the application will convert it to

x, H x -> M x
M s
.'.
M s

before parsing it.

The "Therefore" Symbol

The "therefore" symbol, ".'." (period apostrophe period) can be used to test logical arguments. It will be evaluated the same way as the material conditional, but the result displayed will be different. Instead of indicating if the argument is necessarily true, contingent, or impossible, the software will indicate if the argument is valid (necessarily true) or invalid (not necessarily true). Additionally, if the argument is valid, the software will indicate if the premises are inconsistent or the conclusion is tautological.

Valid Expressions

A valid expression in this language is just a true/false statement. It may be a single line, like

P&Q->R

or it may be multiple lines, like

Hx->Mx
Hs
->
Ms

If it is a single line, the software interprets the line as a statement and decides whether it is valid, satisfiable, or self-contradictory. If it is multiple lines, the software joins those lines to be a single expression and decides that statement. The software treats each line that is a statement as if it were conjoined to the other lines that are statements with a logical AND. This enables you to spread a long statement across multiple lines. For example,

P->Q
Q->R
P

is interpreted to mean the same as

(P->Q)&(Q->R)&P

If an expression has several lines and exactly one of them is a single binary logical operator or the "therefore" symbol, the software will join the lines before the operator with a logical AND, join the lines after the operator with a logical AND, and then join these two conjuncts with the single logical operator. For example,

Hx->Mx
Hs
->
Ms

is interpreted to mean the same as

( (Hx->Mx) & Hs ) -> (Ms)

This enables you to express a logical argument - several premises followed by a conclusion - in a familiar way, or test if one set of statements is equivalent to another set of statements without putting them all on one line.

Long statements can be broken up across several lines. The software will interpret text on several lines as one statement according to the following rules: