use crate as pr4xis;
use crate::ontology::{Axiom, Ontology, Quality};
pr4xis::ontology! {
name: "PropositionalLogic",
source: "Boole (1854); Frege (1879); Russell & Whitehead (1910–13); Post (1921); Sheffer (1913); Aristotle Metaphysics Γ; Tarski (1936); Kleene (1952)",
concepts: [
Proposition,
Formula,
Atom,
TruthValue,
Connective,
Conjunction,
Disjunction,
Negation,
Implication,
Biconditional,
ExclusiveOr,
NAND,
NOR,
Tautology,
Contradiction,
Satisfiable,
Valid,
TruthTable,
Row,
Assignment,
Measurable,
Comparison,
Threshold,
DeMorgansLaws,
DoubleNegation,
ModusPonens,
Contrapositive,
ExcludedMiddle,
NonContradiction,
ShefferCompleteness,
],
labels: {
Proposition: ("en", "Proposition",
"Anything that has a truth value. Boole (1854); Frege (1879) — the atomic unit of logical discourse."),
Formula: ("en", "Formula",
"A compound proposition built from atoms via connectives. Post (1921)."),
Atom: ("en", "Atomic proposition",
"A proposition with no internal logical structure — a propositional variable. Russell & Whitehead (1910) *PM* *1."),
TruthValue: ("en", "Truth value",
"The semantic value of a proposition — True or False. Frege (1892) 'Über Sinn und Bedeutung' — propositions denote truth values."),
Connective: ("en", "Connective",
"A function that combines propositions into compound formulae. Boole (1854); Post (1921)."),
Conjunction: ("en", "Conjunction (∧, AND)",
"The binary connective true iff both operands are true. Boole's logical product."),
Disjunction: ("en", "Disjunction (∨, OR)",
"The binary connective true iff at least one operand is true (inclusive). Boole's logical sum."),
Negation: ("en", "Negation (¬, NOT)",
"The unary connective that flips truth value. Aristotle *De Interpretatione*."),
Implication: ("en", "Implication (→)",
"The binary connective false iff the antecedent is true and the consequent is false; material conditional. Frege (1879) §5."),
Biconditional: ("en", "Biconditional (↔, IFF)",
"The binary connective true iff both operands have the same truth value."),
ExclusiveOr: ("en", "Exclusive disjunction (⊕, XOR)",
"The binary connective true iff exactly one operand is true."),
NAND: ("en", "NAND (Sheffer stroke, ↑)",
"Negated conjunction — Sheffer (1913) showed it is functionally complete (all other connectives definable from NAND)."),
NOR: ("en", "NOR (Peirce arrow, ↓)",
"Negated disjunction — also functionally complete (Peirce 1880). Dual to NAND."),
Tautology: ("en", "Tautology",
"A formula true under every truth assignment. Wittgenstein (1921) *Tractatus* 4.46; Post (1921)."),
Contradiction: ("en", "Contradiction",
"A formula false under every truth assignment — dual to tautology. Aristotle *Metaphysics* Γ.3."),
Satisfiable: ("en", "Satisfiable",
"A formula true under at least one truth assignment."),
Valid: ("en", "Valid argument form",
"An argument form whose conclusion is a tautological consequence of its premises. Tarski (1936) semantic consequence."),
TruthTable: ("en", "Truth table",
"Post (1921): the finite tabulation of a formula's truth value under every possible assignment of its atoms."),
Row: ("en", "Truth-table row",
"A single assignment-to-result entry in a truth table."),
Assignment: ("en", "Truth assignment",
"A mapping from atomic propositions to truth values. Tarski (1936) — the ground of semantic evaluation."),
Measurable: ("en", "Measurable quantity",
"A context-dependent quantity that can be compared against a threshold (pr4xis-specific composition primitive)."),
Comparison: ("en", "Comparison",
"A relation between two measurables and a comparison operator (< ≤ = ≠ ≥ >)."),
Threshold: ("en", "Threshold",
"A cut-off value for a measurable, yielding a proposition (above/below)."),
DeMorgansLaws: ("en", "De Morgan's laws",
"¬(A ∧ B) ≡ (¬A ∨ ¬B) and ¬(A ∨ B) ≡ (¬A ∧ ¬B). Attributed to De Morgan (1847)."),
DoubleNegation: ("en", "Double negation",
"¬¬A ≡ A (classical; constructively, only one direction). Classical since Aristotle."),
ModusPonens: ("en", "Modus ponens",
"From A and (A → B), derive B. The canonical inference rule. Stoic logic; Frege (1879). See also `reasoning::InferenceRule` and `formal::logic::inference_rules::ModusPonens`."),
Contrapositive: ("en", "Contrapositive",
"(A → B) ≡ (¬B → ¬A). Classical equivalence."),
ExcludedMiddle: ("en", "Excluded middle (tertium non datur)",
"A ∨ ¬A — every proposition is either true or false, no third option. Aristotle *Metaphysics* Γ.7."),
NonContradiction: ("en", "Non-contradiction",
"¬(A ∧ ¬A) — no proposition is both true and false. Aristotle *Metaphysics* Γ.3 — 'the most certain of all principles'."),
ShefferCompleteness: ("en", "Sheffer functional completeness",
"Every propositional connective is definable in terms of NAND alone (equivalently NOR). Sheffer (1913)."),
},
is_a: [
(Conjunction, Connective),
(Disjunction, Connective),
(Negation, Connective),
(Implication, Connective),
(Biconditional, Connective),
(ExclusiveOr, Connective),
(NAND, Connective),
(NOR, Connective),
(Atom, Proposition),
(Formula, Proposition),
(Tautology, Formula),
(Contradiction, Formula),
(Satisfiable, Formula),
(Valid, Formula),
(DeMorgansLaws, Tautology),
(DoubleNegation, Tautology),
(ModusPonens, Tautology),
(Contrapositive, Tautology),
(ExcludedMiddle, Tautology),
(NonContradiction, Tautology),
],
has_a: [
(Formula, Atom),
(Formula, Connective),
(TruthTable, Row),
(Row, Assignment),
(Assignment, TruthValue),
(Assignment, Atom),
(Comparison, Measurable),
(Threshold, Measurable),
],
opposes: [
(Tautology, Contradiction),
(Contradiction, Tautology),
(Conjunction, Disjunction),
(Disjunction, Conjunction),
(NAND, NOR),
(NOR, NAND),
],
}
#[derive(Debug, Clone)]
pub struct PropositionalTradition;
impl Quality for PropositionalTradition {
type Individual = PropositionalLogicConcept;
type Value = &'static str;
fn get(&self, c: &PropositionalLogicConcept) -> Option<&'static str> {
use PropositionalLogicConcept as P;
Some(match c {
P::Proposition | P::Formula | P::Atom | P::TruthValue => "frege-1879",
P::Connective
| P::Conjunction
| P::Disjunction
| P::Negation
| P::Implication
| P::Biconditional
| P::ExclusiveOr => "boole-1854",
P::NAND | P::NOR | P::ShefferCompleteness => "sheffer-1913",
P::Tautology | P::Satisfiable | P::Valid => "post-1921",
P::Contradiction | P::ExcludedMiddle | P::NonContradiction => "aristotle",
P::TruthTable | P::Row | P::Assignment => "post-1921",
P::Measurable | P::Comparison | P::Threshold => "pr4xis-specific",
P::DeMorgansLaws => "de-morgan-1847",
P::DoubleNegation | P::Contrapositive => "classical",
P::ModusPonens => "stoic-frege",
})
}
}
impl Ontology for PropositionalLogicOntology {
type Cat = PropositionalLogicCategory;
type Qual = PropositionalTradition;
fn axioms() -> Vec<Box<dyn Axiom>> {
crate::ontology::reasoning::structural_axioms_for::<Self::Cat>()
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::category::laws::assert_category_laws;
use crate::category::{Arrow, Category, Concept};
use proptest::prelude::*;
#[test]
fn category_laws() {
assert_category_laws::<PropositionalLogicCategory>();
}
#[test]
fn ontology_validates() {
PropositionalLogicOntology::validate()
.unwrap_or_else(|c| panic!("validation failed: {}", c.meta().description.as_str()));
}
#[test]
fn eight_connectives_are_connectives() {
let connectives = [
PropositionalLogicConcept::Conjunction,
PropositionalLogicConcept::Disjunction,
PropositionalLogicConcept::Negation,
PropositionalLogicConcept::Implication,
PropositionalLogicConcept::Biconditional,
PropositionalLogicConcept::ExclusiveOr,
PropositionalLogicConcept::NAND,
PropositionalLogicConcept::NOR,
];
let sub: Vec<_> = PropositionalLogicCategory::morphisms()
.iter()
.filter(|m| m.kind() == PropositionalLogicRelationKind::Subsumption)
.map(|m| (m.source(), m.target()))
.collect();
for c in connectives {
assert!(
sub.contains(&(c, PropositionalLogicConcept::Connective)),
"{:?} should be-a Connective",
c
);
}
}
#[test]
fn classical_theorems_are_tautologies() {
let theorems = [
PropositionalLogicConcept::DeMorgansLaws,
PropositionalLogicConcept::DoubleNegation,
PropositionalLogicConcept::ModusPonens,
PropositionalLogicConcept::Contrapositive,
PropositionalLogicConcept::ExcludedMiddle,
PropositionalLogicConcept::NonContradiction,
];
let sub: Vec<_> = PropositionalLogicCategory::morphisms()
.iter()
.filter(|m| m.kind() == PropositionalLogicRelationKind::Subsumption)
.map(|m| (m.source(), m.target()))
.collect();
for t in theorems {
assert!(
sub.contains(&(t, PropositionalLogicConcept::Tautology)),
"{:?} should be-a Tautology",
t
);
}
}
#[test]
fn tautology_opposes_contradiction() {
let opp: Vec<_> = PropositionalLogicCategory::morphisms()
.iter()
.filter(|m| m.kind() == PropositionalLogicRelationKind::Opposition)
.map(|m| (m.source(), m.target()))
.collect();
assert!(opp.contains(&(
PropositionalLogicConcept::Tautology,
PropositionalLogicConcept::Contradiction
)));
assert!(opp.contains(&(
PropositionalLogicConcept::Contradiction,
PropositionalLogicConcept::Tautology
)));
}
#[test]
fn every_concept_has_tradition() {
let q = PropositionalTradition;
for c in PropositionalLogicConcept::variants() {
assert!(q.get(&c).is_some(), "{:?} missing tradition", c);
}
}
fn arb_concept() -> impl Strategy<Value = PropositionalLogicConcept> {
proptest::sample::select(PropositionalLogicConcept::variants())
}
proptest! {
#[test]
fn prop_tradition_total(c in arb_concept()) {
prop_assert!(PropositionalTradition.get(&c).is_some());
}
#[test]
fn prop_every_arrow_is_named(_seed in any::<u32>()) {
for m in PropositionalLogicCategory::morphisms() {
prop_assert!(!m.meta().name.as_str().is_empty());
}
}
#[test]
fn prop_structural_axioms_hold(_seed in any::<u32>()) {
for axiom in PropositionalLogicOntology::axioms() {
match axiom.verify() {
Ok(_) => {}
Err(c) => prop_assert!(
false,
"structural axiom failed: {}",
c.meta().name.as_str()
),
}
}
}
#[test]
fn prop_subsumption_targets_valid(_seed in any::<u32>()) {
let variants: Vec<_> = PropositionalLogicConcept::variants();
for m in PropositionalLogicCategory::morphisms() {
if m.kind() == PropositionalLogicRelationKind::Subsumption {
prop_assert!(variants.contains(&m.source()));
prop_assert!(variants.contains(&m.target()));
}
}
}
}
}