it.grypho.scala.leonardo.logic

Members list

Type members

Classlikes

case class And(a: _Expression, b: _Expression) extends _Connective

Conjunction: a and b, evaluated as min over the operand degrees.

Conjunction: a and b, evaluated as min over the operand degrees.

Short-circuits on a false left operand exactly as Product.eval does on a zero left operand: false and X is false without evaluating X. The rule is sound in the graded table too — 0 annihilates min — so no many-valued special case is needed.

Value parameters

a

left operand

b

right operand

Attributes

Supertypes
trait Serializable
trait Product
trait Equals
trait _Connective
trait _Expression
class Object
trait Matchable
class Any
Show all
case class GaussMF(x: _Expression, mean: _Expression, sigma: _Expression) extends _Membership

Gaussian membership curve gaussmf(x, mean, sigma) = exp(-(x - mean)² / (2σ²)). A non-positive sigma leaves the node symbolic (no curve is defined).

Gaussian membership curve gaussmf(x, mean, sigma) = exp(-(x - mean)² / (2σ²)). A non-positive sigma leaves the node symbolic (no curve is defined).

Value parameters

mean

the centre, where the degree is one

sigma

the standard deviation; must be positive

x

the crisp input

Attributes

Supertypes
trait Serializable
trait Product
trait Equals
trait _Membership
trait _Expression
class Object
trait Matchable
class Any
Show all
case class Implies(a: _Expression, b: _Expression) extends _Connective

Material implication: a implies b, evaluated as max(1 - a, b).

Material implication: a implies b, evaluated as max(1 - a, b).

Short-circuits on a false left operand: false implies X is true without evaluating X (sound in the graded table, since 1 annihilates max).

Value parameters

a

antecedent

b

consequent

Attributes

Supertypes
trait Serializable
trait Product
trait Equals
trait _Connective
trait _Expression
class Object
trait Matchable
class Any
Show all
case class Not(a: _Expression) extends _Connective

Negation: not a, evaluated as 1 - a. unknown is the fixpoint.

Negation: not a, evaluated as 1 - a. unknown is the fixpoint.

Value parameters

a

the operand

Attributes

Supertypes
trait Serializable
trait Product
trait Equals
trait _Connective
trait _Expression
class Object
trait Matchable
class Any
Show all
case class Or(a: _Expression, b: _Expression) extends _Connective

Disjunction: a or b, evaluated as max over the operand degrees.

Disjunction: a or b, evaluated as max over the operand degrees.

Short-circuits on a true left operand (the dual of And's rule): true or X is true without evaluating X. Sound in the graded table — 1 annihilates max.

Value parameters

a

left operand

b

right operand

Attributes

Supertypes
trait Serializable
trait Product
trait Equals
trait _Connective
trait _Expression
class Object
trait Matchable
class Any
Show all
case class SigMF(x: _Expression, a: _Expression, c: _Expression) extends _Membership

Sigmoid membership curve sigmf(x, a, c) = 1 / (1 + exp(-a(x - c))). A positive a opens to the right, a negative one to the left.

Sigmoid membership curve sigmf(x, a, c) = 1 / (1 + exp(-a(x - c))). A positive a opens to the right, a negative one to the left.

Value parameters

a

the slope

c

the inflection point, where the degree is one half

x

the crisp input

Attributes

Supertypes
trait Serializable
trait Product
trait Equals
trait _Membership
trait _Expression
class Object
trait Matchable
class Any
Show all
case class Somewhat(a: _Expression) extends _Membership

The dilation hedge somewhat(a) = √a: softens a degree towards the middle.

The dilation hedge somewhat(a) = √a: softens a degree towards the middle.

Value parameters

a

the degree expression

Attributes

Supertypes
trait Serializable
trait Product
trait Equals
trait _Membership
trait _Expression
class Object
trait Matchable
class Any
Show all

Trapezoidal membership curve trapmf(x, a, b, c, d): rises from a to b, is one on the plateau [b, c], falls from c to d, and is zero outside [a, d]. Requires a <= b <= c <= d; otherwise the node stays symbolic.

Trapezoidal membership curve trapmf(x, a, b, c, d): rises from a to b, is one on the plateau [b, c], falls from c to d, and is zero outside [a, d]. Requires a <= b <= c <= d; otherwise the node stays symbolic.

Value parameters

a

left foot

b

left shoulder

c

right shoulder

d

right foot

x

the crisp input

Attributes

Supertypes
trait Serializable
trait Product
trait Equals
trait _Membership
trait _Expression
class Object
trait Matchable
class Any
Show all
case class TriMF(x: _Expression, a: _Expression, b: _Expression, c: _Expression) extends _Membership

Triangular membership curve trimf(x, a, b, c): rises from a to the apex b, falls from b to c, and is zero outside [a, c].

Triangular membership curve trimf(x, a, b, c): rises from a to the apex b, falls from b to c, and is zero outside [a, c].

Degenerate shoulders (a == b or b == c) give a vertical edge rather than a division by zero. Requires a <= b <= c; otherwise the node stays symbolic.

Value parameters

a

left foot

b

apex

c

right foot

x

the crisp input

Attributes

Supertypes
trait Serializable
trait Product
trait Equals
trait _Membership
trait _Expression
class Object
trait Matchable
class Any
Show all
case class Very(a: _Expression) extends _Membership

The concentration hedge very(a) = a²: sharpens a degree towards its extremes.

The concentration hedge very(a) = a²: sharpens a degree towards its extremes.

Value parameters

a

the degree expression

Attributes

Supertypes
trait Serializable
trait Product
trait Equals
trait _Membership
trait _Expression
class Object
trait Matchable
class Any
Show all
case class Xor(a: _Expression, b: _Expression) extends _Connective

Exclusive disjunction: a xor b, evaluated as the lattice reading of (a and not b) or (not a and b) (see kleeneXor). No short-circuit is possible: both operands always matter.

Exclusive disjunction: a xor b, evaluated as the lattice reading of (a and not b) or (not a and b) (see kleeneXor). No short-circuit is possible: both operands always matter.

Value parameters

a

left operand

b

right operand

Attributes

Supertypes
trait Serializable
trait Product
trait Equals
trait _Connective
trait _Expression
class Object
trait Matchable
class Any
Show all
sealed trait _Connective extends _Expression

Marker trait for the five logical connectives: And, Or, Not, Implies, and Xor.

Marker trait for the five logical connectives: And, Or, Not, Implies, and Xor.

Operands are untyped core._Expressions so equations and other domains compose without cross-domain imports. eval runs the shared Kleene/Zadeh min–max rule table (kleeneAnd, kleeneOr, kleeneNot, kleeneImplies, kleeneXor) over operands widened by asTruth, so core._Bool and core._Truth operands mix freely and the boolean behaviour is a special case of the graded table rather than a separate branch. The result is rebuilt through _Truth.of, which collapses a crisp degree back to _Bool. Any other concrete operand (a _Number, a matrix) leaves the node symbolic.

eval consults its Environment for two knobs, neither of which is a second node hierarchy: the truth-value encoding (symmetricLogic, which additionally admits the digits {-1, 0, 1} as truth values -- a change of digits, never a change of meaning) and the semantics (LogicSemantics, selecting the t-norm / t-conorm pair: min-max, product, or Lukasiewicz). All three semantics agree with classical logic on the crisp values, so the boolean and three-valued tiers are unaffected by the default.

Deliberately NOT marked core._ElementWise: that marker means derive/simplify/ expand/integrate distribute over children (linear containers only), and the connectives are not linear -- derive(a and b, x) must stay symbolic.

Attributes

Supertypes
trait _Expression
class Object
trait Matchable
class Any
Known subtypes
class And
class Implies
class Not
class Or
class Xor
case class _Defuzzify(e: _Expression, v: _Variable, lo: _Expression, hi: _Expression) extends _Expression

Defuzzification of a membership expression to a crisp value: defuzz(e, v, lo, hi).

Defuzzification of a membership expression to a crisp value: defuzz(e, v, lo, hi).

Evaluates by centroid once lo and hi fold to numbers; stays symbolic otherwise (the fixpoint convention shared with the transforms and _ODE). v is a binder, so it is excluded from children — the same convention as _DefIntegral.

Value parameters

e

the membership expression

hi

right endpoint

lo

left endpoint of the universe

v

the variable ranging over the universe of discourse

Attributes

Supertypes
trait Serializable
trait Product
trait Equals
trait _Expression
class Object
trait Matchable
class Any
Show all
sealed trait _Membership extends _Expression

Marker trait for the nodes that produce a truth degree from crisp input: the hedges (Very, Somewhat) and the membership curves (TriMF, TrapMF, GaussMF, SigMF), plus the explicit conversion _TruthOf.

Marker trait for the nodes that produce a truth degree from crisp input: the hedges (Very, Somewhat) and the membership curves (TriMF, TrapMF, GaussMF, SigMF), plus the explicit conversion _TruthOf.

These are the fuzzy tier's entry points: a membership function maps a crisp measurement into [0, 1], and everything downstream is an ordinary truth value that the connectives already understand. Their eval therefore returns _Truth.of(degree) rather than a plain number — a membership degree is a truth value, and returning one is what lets very(trimf(t, 0, 10, 20)) and somewhat(x) compose without an explicit cast at every step.

Arguments are read with asDegree, which accepts a bare number in [0, 1] as well as a _Bool/_Truth: a hedge has no other domain, so there is none of the ambiguity that makes the connectives insist on asTruth. An argument outside the domain, or one that does not reduce, leaves the node symbolic.

Attributes

Supertypes
trait _Expression
class Object
trait Matchable
class Any
Known subtypes
class GaussMF
class SigMF
class Somewhat
class TrapMF
class TriMF
class Very
class _TruthOf
Show all
case class _TruthOf(a: _Expression) extends _Membership

Explicit conversion of a scalar degree into a truth value: truth(x).

Explicit conversion of a scalar degree into a truth value: truth(x).

Also the printed form of a graded core._Truth (truth(0.25)), which is what makes a fuzzy degree round-trip through toString and through a :save/:load — without it a degree would print as a bare number and re-parse as a plain _Number. The Kleene midpoint keeps its own literal, unknown.

This is also how a custom membership function is written: the argument is an arbitrary scalar expression, so truth(1 / (1 + (x - 5)^2)) is a perfectly good curve and composes with the hedges, the connectives, and defuzz exactly like the built-in ones.

An argument outside [0, 1] is not a degree, so the node stays symbolic rather than clamping — the same "domain errors stay symbolic" rule the rest of the library follows, and a useful signal that a custom curve has left the unit interval.

Value parameters

a

the degree expression

Attributes

Supertypes
trait Serializable
trait Product
trait Equals
trait _Membership
trait _Expression
class Object
trait Matchable
class Any
Show all

Value members

Concrete methods

def bisector(membership: _Expression, v: _Variable, lo: Double, hi: Double, n: Int, env: Environment): Option[Double]

Defuzzifies by the bisector: the sampled point at which the cumulative membership first reaches half of the total, splitting the area in two.

Defuzzifies by the bisector: the sampled point at which the cumulative membership first reaches half of the total, splitting the area in two.

Value parameters

env

environment for resolving any other free variables

hi

right endpoint

lo

left endpoint of the universe

membership

the membership expression in v

n

number of grid points

v

the variable ranging over the universe of discourse

Attributes

Returns

the crisp representative, or None when nothing was sampled or the total membership is zero

def centroid(membership: _Expression, v: _Variable, lo: Double, hi: Double, n: Int, env: Environment): Option[Double]

Defuzzifies by the centre of gravity: Σ x·μ(x) / Σ μ(x) over the sampled curve.

Defuzzifies by the centre of gravity: Σ x·μ(x) / Σ μ(x) over the sampled curve.

The most common defuzzifier, and the one defuzz(...) uses in the grammar.

Value parameters

env

environment for resolving any other free variables

hi

right endpoint

lo

left endpoint of the universe

membership

the membership expression in v

n

number of grid points

v

the variable ranging over the universe of discourse

Attributes

Returns

the crisp representative, or None when nothing was sampled or the total membership is zero (no centroid is defined)

def kleeneTable(e: _Expression, vars: List[_Variable], env: Environment): Vector[(Map[String, _Value], Option[_Value])]

Enumerates every three-valued (Kleene) assignment of vars and evaluates e under each.

Enumerates every three-valued (Kleene) assignment of vars and evaluates e under each.

The three-valued counterpart of truthTable: each variable ranges over KleeneValues (false, unknown, true) for 3^n rows, ordered with the first variable as the most significant digit. The result column is Some(v) when the row reduces to a truth-valued result (_Bool or _Truth) and None otherwise.

Value parameters

e

the expression to tabulate

env

base environment for each row's evaluation (row bindings shadow it)

vars

the variables to enumerate; an empty list yields a single row with the empty assignment

Attributes

Returns

one (assignment, result) pair per row, or an empty vector when vars exceeds MaxKleeneTableVars

def meanOfMaxima(membership: _Expression, v: _Variable, lo: Double, hi: Double, n: Int, env: Environment): Option[Double]

Defuzzifies by the mean of maxima: the average of the sampled points that attain the greatest membership.

Defuzzifies by the mean of maxima: the average of the sampled points that attain the greatest membership.

Points within 1e-9 of the maximum count as maximal, so a plateau is averaged rather than resolved by floating-point noise.

Value parameters

env

environment for resolving any other free variables

hi

right endpoint

lo

left endpoint of the universe

membership

the membership expression in v

n

number of grid points

v

the variable ranging over the universe of discourse

Attributes

Returns

the crisp representative, or None when nothing was sampled or the curve is everywhere zero

def sampleDegrees(membership: _Expression, v: _Variable, lo: Double, hi: Double, n: Int, env: Environment): Vector[(Double, Double)]

Samples a membership expression over a uniform grid of n points in [lo, hi].

Samples a membership expression over a uniform grid of n points in [lo, hi].

Fast path: when the expression is pure scalar arithmetic it scalar.compiles to a Double => Double closure — the same fast path _DefIntegral.eval uses for Simpson's rule. A membership or connective node is not something compile can lower, so it returns None and the fallback evaluates the tree per point, reading the result with asDegree so a truth-valued degree counts (scalar.sample would drop it, since it keeps only _Number results).

A point is kept only when its value is an actual membership degree — finite and inside [0, 1]. The range test matters for the fast path: the tree path already reads through asDegree, which rejects anything outside the interval, so without it the same curve would be treated differently depending on whether compile happened to lower it. Points outside the interval are dropped, following the sample convention for values that are not results.

Value parameters

env

environment for resolving any other free variables

hi

right endpoint

lo

left endpoint

membership

the membership expression in v

n

number of grid points

v

the variable ranging over the grid

Attributes

Returns

(x, degree) pairs in ascending x order

def simplifyLogic(e: _Expression, simplifyLeaf: _Expression => _Expression, symmetric: Boolean, semantics: LogicSemantics): _Expression

Single-pass structural simplification of the logical connectives.

Single-pass structural simplification of the logical connectives.

Rules: constant folding through the shared kernels, double negation (not not a = a), idempotence (a and a = a), complement (a and not a = false), and absorption (a or (a and b) = a). De Morgan and the implies/xor desugarings are deliberately NOT applied here -- they reshape rather than shrink, and belong to the normal forms (toCNF/toDNF).

Many-valued soundness, in two layers. Four rules — complement in and and in or, a implies a = true, and a xor a = false — hold only in classical logic: they fail at unknown (unknown and not unknown = unknown, not false) and are gated on isCrisp. Two more — idempotence and absorption — hold throughout a lattice but not under the product or Lukasiewicz t-norms (a and a is a squared there), so they are additionally gated on the semantics being LogicSemantics.MinMax. Everything else (constant folding, the identity and annihilator elements, double negation) is valid under every t-norm and fires unconditionally.

Free variables count as crisp: the classical rules assume boolean-valued atoms, the documented domain restriction of this pass (the Asin convention). Bind a variable to unknown and use eval, not simplify, to get the many-valued answer.

Non-connective sub-expressions are handed to simplifyLeaf. The default is identity; the REPL passes scalar.simplifyFully so a scalar body nested inside a connective is simplified too -- logic itself imports core only, so the scalar pass is injected rather than imported. simplifyLeaf must be idempotent for simplifyLogicFully's fixpoint to terminate.

Value parameters

e

the expression to simplify

semantics

the t-norm family the constant folding and the lattice-only rules are judged against (default LogicSemantics.MinMax)

simplifyLeaf

pass applied to non-connective sub-expressions (default: identity)

symmetric

whether the symmetric ternary digits {-1, 0, 1} are in scope (the REPL passes its session toggle); this pass takes no Environment, by the same design that makes scalar.simplify ignore bindings

Attributes

Returns

the simplified expression; never larger than the input

def simplifyLogicFully(e: _Expression, simplifyLeaf: _Expression => _Expression, symmetric: Boolean, semantics: LogicSemantics): _Expression

Iterates simplifyLogic until the result stops changing (fixpoint).

Iterates simplifyLogic until the result stops changing (fixpoint).

Terminates because simplifyLogic never increases expression size (given an idempotent simplifyLeaf).

Value parameters

e

the expression to simplify

semantics

the t-norm family (default LogicSemantics.MinMax)

simplifyLeaf

pass applied to non-connective sub-expressions (default: identity)

symmetric

whether the symmetric ternary digits {-1, 0, 1} are in scope

Attributes

Returns

the fully simplified expression

def toCNF(e: _Expression, symmetric: Boolean): _Expression

Rewrites e into conjunctive normal form: a conjunction of disjunctions of literals.

Rewrites e into conjunctive normal form: a conjunction of disjunctions of literals.

Pipeline: simplifyLogic fixpoint (folds connective-level constants away), desugar implies/xor, push not to the leaves via De Morgan, then distribute or over and. Trivially-true clauses (containing a complementary literal pair) and duplicate literals/clauses are dropped; when every clause is trivially true the result is _Bool(true).

Crisp-only (the Asin convention): valid for _Bool operands only. Non-connective sub-expressions (equations, scalar bodies) are treated as opaque atoms. Returns the input unchanged when distribution would exceed MaxNormalFormClauses, or when the expression carries a _Truth degree (normal forms are a two-valued notion).

Value parameters

e

the expression to normalise

symmetric

whether the symmetric ternary digits {-1, 0, 1} are in scope

Attributes

Returns

the CNF of e, or e unchanged when it is not crisp or the distribution blows up

def toDNF(e: _Expression, symmetric: Boolean): _Expression

Rewrites e into disjunctive normal form: a disjunction of conjunctions of literals.

Rewrites e into disjunctive normal form: a disjunction of conjunctions of literals.

The exact dual of toCNF -- and distributes over or, trivially-false terms are dropped, and an empty term set collapses to _Bool(false). Same crisp-only domain restriction and clause cap.

Value parameters

e

the expression to normalise

symmetric

whether the symmetric ternary digits {-1, 0, 1} are in scope

Attributes

Returns

the DNF of e, or e unchanged when it is not crisp or the distribution blows up

def truthTable(e: _Expression, vars: List[_Variable], env: Environment): Vector[(Map[String, Boolean], Option[Boolean])]

Enumerates every boolean assignment of vars and evaluates e under each.

Enumerates every boolean assignment of vars and evaluates e under each.

Rows are ordered with the first variable as the most significant bit, i.e. from all-false to all-true. The result column is Some(b) when the expression fully reduces to _Bool(b) under that assignment and None otherwise (free variables outside vars, non-boolean operands, or a row that reduces to a graded _Truth degree — use kleeneTable for those).

Crisp-only (the Asin convention): assignments range over _Bool values only.

Value parameters

e

the expression to tabulate

env

base environment for each row's evaluation (row bindings shadow it)

vars

the variables to enumerate (each bound to _Bool per row); an empty list yields a single row with the empty assignment

Attributes

Returns

one (assignment, result) pair per row, or an empty vector when vars exceeds MaxTruthTableVars

Concrete fields

Default number of grid points used when defuzzifying; odd so the midpoint of the range is always sampled.

Default number of grid points used when defuzzifying; odd so the midpoint of the range is always sampled.

Attributes

val KleeneValues: Vector[_Value]

The three Kleene truth values in ascending order: false, unknown, true. The enumeration alphabet of kleeneTable.

The three Kleene truth values in ascending order: false, unknown, true. The enumeration alphabet of kleeneTable.

Attributes

Maximum number of variables kleeneTable enumerates (3^10 = 59049 rows) — the three-valued counterpart of MaxTruthTableVars, set to the same row budget.

Maximum number of variables kleeneTable enumerates (3^10 = 59049 rows) — the three-valued counterpart of MaxTruthTableVars, set to the same row budget.

Attributes

Maximum number of variables truthTable enumerates (2^16 = 65536 rows). Beyond this the table is rejected (empty result) rather than attempted.

Maximum number of variables truthTable enumerates (2^16 = 65536 rows). Beyond this the table is rejected (empty result) rather than attempted.

Attributes