Skip to content

T-Norms

pysignet.tnorms.RProductTNorm

Bases: SProductTNorm

R-Product t-norm (R-logics: axiomatic residuum-based implication).

  • AND: prod(values) along dim=0 (inherited from S-Product)
  • OR: 1 - prod(1 - values) along dim=0 (inherited from S-Product)
  • IMPLIES: 1 if a <= b else b/a (residuum, overrides S-Product)

R-Product defines implication axiomatically using residua rather than treating it as disjunction. According to "Evaluating Relaxations of Logic for Neural Networks" (2107.13646v1.pdf): - R-Product empirically outperforms all other t-norms (Tables 3-9) - R-Product is self-consistent for all formulas (Proposition 1) - R-Product is the recommended default t-norm for neural networks

This is the default t-norm used by LogicCompiler.

recommended_postprocessing property

R-Product recommends logarithmic post-processing.

implication(a, b)

Relaxed IMPLIES using R-Product residuum.

R-Product implication: 1 if a <= b else b/a

This axiomatic definition makes R-Product self-consistent and more suitable for neural network training than S-Product.

Parameters:

Name Type Description Default
a Tensor

Antecedent tensor (values in [0, 1])

required
b Tensor

Consequent tensor (values in [0, 1])

required

Returns:

Type Description
Tensor

Implication result: 1 where a <= b, else b/a

pysignet.tnorms.SProductTNorm

Bases: TNorm

S-Product t-norm (S-logics: implication as disjunction).

  • AND: prod(values) along dim=0
  • OR: 1 - prod(1 - values) along dim=0
  • IMPLIES: 1 - a + a * b (treats implication as NOT(a) OR b)

S-Product uses the standard implication-as-disjunction approach. According to "Evaluating Relaxations of Logic for Neural Networks", S-Product is less consistent than R-Product and performs worse empirically, but is equivalent to cross-entropy for labeled data.

recommended_postprocessing property

S-Product recommends logarithmic post-processing.

conjunction(values)

Product conjunction: prod(values) along dim=0.

disjunction(values)

Product disjunction: 1 - prod(1 - values) along dim=0.

pysignet.tnorms.LukasiewiczTNorm

Bases: TNorm

Lukasiewicz t-norm (bounded difference).

  • AND: max(0, sum(values) - (n - 1))
  • OR: min(1, sum(values))

Good for enforcing stricter logical constraints.

recommended_postprocessing property

Lukasiewicz recommends linear post-processing.

conjunction(values)

Lukasiewicz conjunction: max(0, sum - (n-1)).

disjunction(values)

Lukasiewicz disjunction: min(1, sum).

pysignet.tnorms.GodelTNorm

Bases: TNorm

Godel t-norm (minimum/maximum).

  • AND: min(values) along dim=0
  • OR: max(values) along dim=0

Most conservative option, but can have gradient issues.

Uses torch.amin/amax rather than values.min(dim=0).values / values.max(dim=0).values: the latter also compute and discard an unused argmin/argmax index, which is far more expensive for no benefit (~60x slower, measured on small batches) and, for tied values, gives the entire gradient to a single arbitrary (first-occurring) index rather than splitting it fairly across every tied element.

recommended_postprocessing property

Godel recommends linear post-processing.

conjunction(values)

Godel conjunction: min along dim=0.

disjunction(values)

Godel disjunction: max along dim=0.

pysignet.tnorms.MixedTNorm

Bases: TNorm

Mixed t-norm: Godel for large arities, RProduct for small arities.

This t-norm switches behavior based on the number of arguments: - For arities <= threshold: uses RProduct (product/probabilistic sum) - For arities > threshold: uses Godel (min/max)

This addresses numerical stability issues with product t-norms when combining many values. For example, 0.9^20 = 0.12, which can cause gradient vanishing during training. Godel (min/max) is stable for large arities.

Binary operations (implication, equivalence) always use RProduct since they only involve 2 operands.

Parameters:

Name Type Description Default
threshold int

Maximum arity for RProduct. Arities > threshold use Godel. Default is 4.

4
Example
tnorm = MixedTNorm(threshold=4)
# Small conjunction (3 args) -> RProduct
values = torch.tensor([[0.8], [0.7], [0.6]])
tnorm.conjunction(values)  # 0.8 * 0.7 * 0.6 = 0.336
# Large conjunction (6 args) -> Godel
values = torch.tensor([[0.9], [0.8], [0.7], [0.6], [0.5], [0.4]])
tnorm.conjunction(values)  # min = 0.4

recommended_postprocessing property

Return recommended loss post-processing mode.

Returns 'log' since RProduct is used for small arities and binary operations (implication, equivalence).

__init__(threshold=4)

Initialize MixedTNorm.

Parameters:

Name Type Description Default
threshold int

Maximum arity for RProduct. Arities > threshold use Godel. Default is 4.

4

conjunction(values)

Relaxed AND operation, reducing along dim=0.

Uses RProduct (product) for small arities (<=threshold), Godel (min) for large arities (>threshold).

Parameters:

Name Type Description Default
values Tensor

Tensor of shape (n, ...) with values in [0, 1].

required

Returns:

Type Description
Tensor

Tensor of shape (...) with conjunction applied.

disjunction(values)

Relaxed OR operation, reducing along dim=0.

Uses RProduct (probabilistic sum) for small arities (<=threshold), Godel (max) for large arities (>threshold).

Parameters:

Name Type Description Default
values Tensor

Tensor of shape (n, ...) with values in [0, 1].

required

Returns:

Type Description
Tensor

Tensor of shape (...) with disjunction applied.

equivalence(a, b)

Relaxed EQUIVALENCE using RProduct.

Equivalence is conjunction of two implications (binary), so RProduct is used for better gradient properties.

Parameters:

Name Type Description Default
a Tensor

First operand tensor (values in [0, 1])

required
b Tensor

Second operand tensor (values in [0, 1])

required

Returns:

Type Description
Tensor

Equivalence result using RProduct.

implication(a, b)

Relaxed IMPLIES using RProduct residuum.

Implication is always binary, so RProduct is used for better gradient properties.

Parameters:

Name Type Description Default
a Tensor

Antecedent tensor (values in [0, 1])

required
b Tensor

Consequent tensor (values in [0, 1])

required

Returns:

Type Description
Tensor

Implication result using RProduct.