Source code for jlnn.nn.gates

#!/usr/bin/env python3

# Imports
import jax.numpy as jnp
from flax import nnx
from jlnn.nn import functional as F

# =====================================================================
# 1. TRADITIONAL PARAMETRIC LOGIC GATES (Learning Weights and Beta)
# =====================================================================

[docs] class WeightedOr(nnx.Module): """ Trainable parametric fuzzy OR gate supporting standard t-conorms. This module aggregates multiple input interval streams into a single truth interval using a parameterized t-conorm operation. It optimizes individual input importance via learnable weights and adjusts the global activation threshold using a learnable bias parameter (beta). Attributes: method (str): Target logical framework selector ('lukasiewicz', 'godel', 'kleene_dienes', 'product', 'reichenbach'). weights (nnx.Param): Trainable input importance weights structured as (num_inputs,). beta (nnx.Param): Trainable gate activation sensitivity threshold scalar (bias). """
[docs] def __init__(self, num_inputs: int, rngs: nnx.Rngs, method: str = 'lukasiewicz'): """ Initializes the stateful WeightedOr gate with corresponding optimization parameters. Args: num_inputs (int): Number of input streams to aggregate. rngs (nnx.Rngs): Flax NNX random number generator collection. method (str, optional): Fuzzy logic framework to employ. Defaults to 'lukasiewicz'. """ self.method = method self.weights = nnx.Param(jnp.ones((num_inputs,))) self.beta = nnx.Param(jnp.array(1.0))
[docs] def __call__(self, x: jnp.ndarray) -> jnp.ndarray: """ Executes the parameterized forward pass for the fuzzy OR operation. Args: x (jnp.ndarray): Input interval tensor structured as (..., num_inputs, 2), where the final dimension contains the lower and upper bounds [L, U]. Returns: jnp.ndarray: Evaluated collective truth interval structured as (..., 2). Raises: ValueError: If the specified `method` is not supported by the parametric OR layer. """ if self.method == 'lukasiewicz': return F.weighted_or(x, self.weights[...], self.beta[...]) elif self.method in ('godel', 'kleene_dienes'): return F.weighted_or_kleene_dienes(x, self.weights[...]) elif self.method in ('product', 'reichenbach'): return F.weighted_or_reichenbach(x, self.weights[...]) else: raise ValueError(f"Parametric OR method '{self.method}' is not supported.")
[docs] class WeightedAnd(nnx.Module): """ Trainable parametric fuzzy AND gate supporting standard t-norms. This module implements a stateful intersection layer that combines multiple input interval truth values into a single consolidated truth interval. It employs learnable weights to scale feature importance and a learnable beta parameter as an intensity bias. Attributes: method (str): Target logical framework selector ('lukasiewicz', 'godel', 'kleene_dienes', 'product', 'reichenbach'). weights (nnx.Param): Trainable input importance weights structured as (num_inputs,). beta (nnx.Param): Trainable gate activation sensitivity threshold scalar (bias). """
[docs] def __init__(self, num_inputs: int, rngs: nnx.Rngs, method: str = 'lukasiewicz'): """ Initializes the stateful WeightedAnd gate with corresponding optimization parameters. Args: num_inputs (int): Number of input streams to aggregate. rngs (nnx.Rngs): Flax NNX random number generator collection. method (str, optional): Fuzzy logic framework to employ. Defaults to 'lukasiewicz'. """ self.method = method self.weights = nnx.Param(jnp.ones((num_inputs,))) self.beta = nnx.Param(jnp.array(1.0))
[docs] def __call__(self, x: jnp.ndarray) -> jnp.ndarray: """ Executes the parameterized forward pass for the fuzzy AND operation. Args: x (jnp.ndarray): Input interval tensor structured as (..., num_inputs, 2), where the final dimension contains the lower and upper bounds [L, U]. Returns: jnp.ndarray: Evaluated collective truth interval structured as (..., 2). Raises: ValueError: If the specified `method` is not supported by the parametric AND layer. """ if self.method == 'lukasiewicz': return F.weighted_and(x, self.weights[...], self.beta[...]) elif self.method in ('godel', 'kleene_dienes'): return F.weighted_and_kleene_dienes(x, self.weights[...]) elif self.method in ('product', 'reichenbach'): return F.weighted_and_reichenbach(x, self.weights[...]) else: raise ValueError(f"Parametric AND method '{self.method}' is not supported.")
[docs] class WeightedNand(nnx.Module): """ Trainable parametric fuzzy NAND gate. This module performs a parametric fuzzy conjunction (AND) across multiple input interval channels, followed by a logical inversion (NOT) wrapper, using trainable logic mechanics. Attributes: method (str): Target logical framework selector ('lukasiewicz', 'godel', 'kleene_dienes', 'product', 'reichenbach'). weights (nnx.Param): Trainable input importance weights structured as (num_inputs,). beta (nnx.Param): Trainable gate activation sensitivity threshold scalar (bias). """
[docs] def __init__(self, num_inputs: int, rngs: nnx.Rngs, method: str = 'lukasiewicz'): """ Initializes the stateful WeightedNand gate with corresponding optimization parameters. Args: num_inputs (int): Number of input streams to aggregate. rngs (nnx.Rngs): Flax NNX random number generator collection. method (str, optional): Fuzzy logic framework to employ. Defaults to 'lukasiewicz'. """ self.method = method self.weights = nnx.Param(jnp.ones((num_inputs,))) self.beta = nnx.Param(jnp.array(1.0))
[docs] def __call__(self, x: jnp.ndarray) -> jnp.ndarray: """ Executes the parameterized forward pass for the fuzzy NAND operation. Args: x (jnp.ndarray): Input interval tensor structured as (..., num_inputs, 2), where the final dimension contains the lower and upper bounds [L, U]. Returns: jnp.ndarray: Inverted collective truth interval structured as (..., 2). Raises: ValueError: If the specified `method` is not supported by the parametric NAND layer. """ if self.method == 'lukasiewicz': return F.weighted_nand(x, self.weights[...], self.beta[...]) elif self.method in ('godel', 'kleene_dienes'): return F.weighted_nand_kleene_dienes(x, self.weights[...]) elif self.method in ('product', 'reichenbach'): return F.weighted_nand_reichenbach(x, self.weights[...]) else: raise ValueError(f"Parametric NAND method '{self.method}' is not supported.")
[docs] class WeightedNor(nnx.Module): """ Trainable parametric fuzzy NOR gate. This module performs a parametric fuzzy disjunction (OR) across multiple input interval channels, followed by a logical inversion (NOT) wrapper, using trainable logic mechanics. Attributes: method (str): Target logical framework selector ('lukasiewicz', 'godel', 'kleene_dienes', 'product', 'reichenbach'). weights (nnx.Param): Trainable input importance weights structured as (num_inputs,). beta (nnx.Param): Trainable gate activation sensitivity threshold scalar (bias). """
[docs] def __init__(self, num_inputs: int, rngs: nnx.Rngs, method: str = 'lukasiewicz'): """ Initializes the stateful WeightedNor gate with corresponding optimization parameters. Args: num_inputs (int): Number of input streams to aggregate. rngs (nnx.Rngs): Flax NNX random number generator collection. method (str, optional): Fuzzy logic framework to employ. Defaults to 'lukasiewicz'. """ self.method = method self.weights = nnx.Param(jnp.ones((num_inputs,))) self.beta = nnx.Param(jnp.array(1.0))
[docs] def __call__(self, x: jnp.ndarray) -> jnp.ndarray: """ Executes the parameterized forward pass for the fuzzy NOR operation. Args: x (jnp.ndarray): Input interval tensor structured as (..., num_inputs, 2), where the final dimension contains the lower and upper bounds [L, U]. Returns: jnp.ndarray: Inverted collective truth interval structured as (..., 2). Raises: ValueError: If the specified `method` is not supported by the parametric NOR layer. """ if self.method == 'lukasiewicz': return F.weighted_nor(x, self.weights[...], self.beta[...]) elif self.method in ('godel', 'kleene_dienes'): return F.weighted_nor_kleene_dienes(x, self.weights[...]) elif self.method in ('product', 'reichenbach'): return F.weighted_nor_reichenbach(x, self.weights[...]) else: raise ValueError(f"Parametric NOR method '{self.method}' is not supported.")
[docs] class WeightedXor(nnx.Module): """ Trainable parametric fuzzy XOR (Exclusive OR) gate. A binary trainable fuzzy logic layer that evaluates the strict difference or exclusive disjunction between two distinct truth interval vectors under parameterized conditions. Attributes: method (str): Target logical framework selector ('lukasiewicz', 'godel', 'kleene_dienes', 'product', 'reichenbach'). weights (nnx.Param): Trainable binary input interaction weights structured as (2,). beta (nnx.Param): Trainable activation sensitivity threshold scalar (bias). """
[docs] def __init__(self, rngs: nnx.Rngs, method: str = 'lukasiewicz'): """ Initializes the stateful WeightedXor gate with binary optimization attributes. Args: rngs (nnx.Rngs): Flax NNX random number generator collection. method (str, optional): Fuzzy logic framework to employ. Defaults to 'lukasiewicz'. """ self.method = method self.weights = nnx.Param(jnp.ones((2,))) self.beta = nnx.Param(jnp.array(1.0))
[docs] def __call__(self, int_a: jnp.ndarray, int_b: jnp.ndarray) -> jnp.ndarray: """ Executes the parameterized forward pass for the binary fuzzy XOR operation. Args: int_a (jnp.ndarray): First input interval tensor structured as (..., 2). int_b (jnp.ndarray): Second input interval tensor structured as (..., 2). Returns: jnp.ndarray: Evaluated XOR truth interval structured as (..., 2). Raises: ValueError: If the specified `method` is not supported by the parametric XOR layer. """ if self.method == 'lukasiewicz': return F.weighted_xor_lukasiewicz(int_a, int_b, self.weights[...], self.beta[...]) elif self.method in ('godel', 'kleene_dienes'): return F.weighted_xor_godel(int_a, int_b, self.weights[...]) elif self.method in ('product', 'reichenbach'): return F.weighted_xor_product(int_a, int_b, self.weights[...]) else: raise ValueError(f"Parametric XOR method '{self.method}' is not supported.")
[docs] class WeightedNot(nnx.Module): """ Trainable parametric fuzzy NOT inversion gate. Applies a parameterized logic negation to an incoming interval tensor, allowing the optimization routine to moderate or invert the intensity of the negative mapping via a learnable weight. Attributes: weight (nnx.Param): Trainable inversion scaling factor parameter. """
[docs] def __init__(self, rngs: nnx.Rngs): """ Initializes the stateful WeightedNot gate. Args: rngs (nnx.Rngs): Flax NNX random number generator collection. """ self.weight = nnx.Param(jnp.array(1.0))
[docs] def __call__(self, x: jnp.ndarray) -> jnp.ndarray: """ Executes the parameterized fuzzy inversion pass. Args: x (jnp.ndarray): Input interval tensor structured as (..., 2). Returns: jnp.ndarray: Modulated inverted truth interval structured as (..., 2). """ return F.weighted_not(x, self.weight[...])
[docs] class WeightedImplication(nnx.Module): """ Trainable parametric implication gate (A -> B). Maps a causal rule structure where an antecedent interval tensor (A) implies a consequent interval tensor (B). The gateway learns input relative scaling and standard bounds corrections to preserve fuzzy logical constraints. Attributes: method (str): Target implication framework selector (e.g., 'lukasiewicz', 'reichenbach', 'kleene_dienes'). weights (nnx.Param): Trainable rule component scaling weights structured as (2,). beta (nnx.Param): Trainable rule sensitivity threshold parameter (bias). """
[docs] def __init__(self, rngs: nnx.Rngs, method: str = 'lukasiewicz'): """ Initializes the stateful WeightedImplication layer with designated semantics. Args: rngs (nnx.Rngs): Flax NNX random number generator collection. method (str, optional): Implication model selection. Defaults to 'lukasiewicz'. """ self.method = method self.weights = nnx.Param(jnp.ones((2,))) self.beta = nnx.Param(jnp.array(1.0))
[docs] def __call__(self, int_a: jnp.ndarray, int_b: jnp.ndarray) -> jnp.ndarray: """ Computes the parametric fuzzy rule implication forward pass. Args: int_a (jnp.ndarray): Antecedent truth interval tensor structured as (..., 2). int_b (jnp.ndarray): Consequent truth interval tensor structured as (..., 2). Returns: jnp.ndarray: Calculated rule validity interval tensor structured as (..., 2). """ return F.weighted_implication( int_a, int_b, self.weights[...], self.beta[...], method=self.method )
# ===================================================================== # 2. PARAMETER-FREE PURE (BULK) REDUCTION GATES # =====================================================================
[docs] class BulkAnd(nnx.Module): """ Non-trainable pure stateless bulk AND reduction gate. Reduces a sequence of multiple truth intervals along the specified feature axis into a single intersection interval. This is an unparameterized structural block representing traditional multi-input fuzzy logic conjunction. Attributes: method (str): Pure fuzzy framework selector ('godel', 'kleene_dienes', 'product', 'reichenbach', 'lukasiewicz'). """
[docs] def __init__(self, method: str = 'kleene_dienes'): """ Initializes the stateless BulkAnd reduction layer. Args: method (str, optional): Target fuzzy logic semantics. Defaults to 'kleene_dienes'. """ self.method = method
[docs] def __call__(self, x: jnp.ndarray) -> jnp.ndarray: """ Performs structural bulk reduction using fuzzy AND axioms. Args: x (jnp.ndarray): Input multi-channel tensor structured as (..., num_inputs, 2). Returns: jnp.ndarray: Consolidated reduction interval structured as (..., 2). Raises: ValueError: If the provided `method` is unknown or unhandled. """ if self.method in ('godel', 'kleene_dienes'): return F.bulk_and_godel(x) elif self.method in ('product', 'reichenbach'): return F.bulk_and_product(x) elif self.method == 'lukasiewicz': inputs = [x[..., i, :] for i in range(x.shape[-2])] res = inputs[0] for item in inputs[1:]: res = F.and_lukasiewicz(res, item) return res else: raise ValueError(f"Bulk AND method '{self.method}' is not recognized.")
[docs] class BulkOr(nnx.Module): """ Non-trainable pure stateless bulk OR reduction gate. Reduces a sequence of multiple truth intervals along the specified feature axis into a single union interval. This is an unparameterized structural block representing traditional multi-input fuzzy logic disjunction. Attributes: method (str): Pure fuzzy framework selector ('godel', 'kleene_dienes', 'product', 'reichenbach', 'lukasiewicz'). """
[docs] def __init__(self, method: str = 'kleene_dienes'): """ Initializes the stateless BulkOr reduction layer. Args: method (str, optional): Target fuzzy logic semantics. Defaults to 'kleene_dienes'. """ self.method = method
[docs] def __call__(self, x: jnp.ndarray) -> jnp.ndarray: """ Performs structural bulk reduction using fuzzy OR axioms. Args: x (jnp.ndarray): Input multi-channel tensor structured as (..., num_inputs, 2). Returns: jnp.ndarray: Consolidated reduction interval structured as (..., 2). Raises: ValueError: If the provided `method` is unknown or unhandled. """ if self.method in ('godel', 'kleene_dienes'): return F.bulk_or_godel(x) elif self.method in ('product', 'reichenbach'): return F.bulk_or_product(x) elif self.method == 'lukasiewicz': inputs = [x[..., i, :] for i in range(x.shape[-2])] res = inputs[0] for item in inputs[1:]: res = F.or_lukasiewicz(res, item) return res else: raise ValueError(f"Bulk OR method '{self.method}' is not recognized.")
# ===================================================================== # 3. SPECIAL PHYSICAL GATES (Physical Fuzzy Logic - PFL) # =====================================================================
[docs] class PhysicalOr(nnx.Module): """ Space-curved entropic physical OR gate with localized field configurations. Implements a field-theoretic physical fuzzy logic (PFL) disjunction. It projects multi-input truth intervals into non-Euclidean space, evaluating field interactions using explicit physical hyperparameters rather than learnable structural weights. Attributes: method (str): Target physical framework ('physical_godel', 'physical_kleene_dienes', 'physical_product', 'physical_reichenbach', 'physical_lukasiewicz'). gamma (float): Space curvature dissipation coefficient parameter. mode (str): Activation field blending mode configuration (e.g., 'sigmoid'). slope (float): Physical boundary transition slope parameter. offset (float): Physical potential zero-point offset. """
[docs] def __init__(self, method: str = 'physical_kleene_dienes', gamma: float = 0.2, mode: str = 'sigmoid', slope: float = 1.0, offset: float = 0.5): """ Initializes the parameter-free PhysicalOr field gate. Args: method (str, optional): Selected PFL operational semantics. Defaults to 'physical_kleene_dienes'. gamma (float, optional): Field interaction scaling. Defaults to 0.2. mode (str, optional): Wave/field mapping activation mode. Defaults to 'sigmoid'. slope (float, optional): Curvature transition coefficient. Defaults to 1.0. offset (float, optional): Geometric field center shift. Defaults to 0.5. """ self.method = method self.gamma = gamma self.mode = mode self.slope = slope self.offset = offset
[docs] def __call__(self, x: jnp.ndarray) -> jnp.ndarray: """ Computes physical space-curved disjunction field dynamics. Args: x (jnp.ndarray): Input physical interval tensor structured as (..., num_inputs, 2). Returns: jnp.ndarray: Synthesized output field interval tensor structured as (..., 2). Raises: ValueError: If the selected physical OR setup is not recognized. """ inputs = [x[..., i, :] for i in range(x.shape[-2])] res = inputs[0] if self.method in ('physical_godel', 'physical_kleene_dienes'): for item in inputs[1:]: res = F.or_physical_kleene_dienes(res, item) return res elif self.method in ('physical_product', 'physical_reichenbach'): for item in inputs[1:]: res = F.or_physical_reichenbach(res, item) return res elif self.method == 'physical_lukasiewicz': for item in inputs[1:]: res = F.or_physical_lukasiewicz(res, item) return res else: raise ValueError(f"Physical OR method '{self.method}' is not supported.")
[docs] class PhysicalAnd(nnx.Module): """ Space-curved entropic physical AND gate with localized field configurations. Implements a field-theoretic physical fuzzy logic (PFL) conjunction. It simulates physical logic intersections across space-curved boundary zones using entropic hyperparameters. Attributes: method (str): Target physical framework ('physical_godel', 'physical_kleene_dienes', 'physical_product', 'physical_reichenbach', 'physical_lukasiewicz'). gamma (float): Space curvature dissipation coefficient parameter. mode (str): Activation field blending mode configuration (e.g., 'sigmoid'). slope (float): Physical boundary transition slope parameter. offset (float): Physical potential zero-point offset. """
[docs] def __init__(self, method: str = 'physical_kleene_dienes', gamma: float = 0.2, mode: str = 'sigmoid', slope: float = 1.0, offset: float = 0.5): """ Initializes the parameter-free PhysicalAnd field gate. Args: method (str, optional): Selected PFL operational semantics. Defaults to 'physical_kleene_dienes'. gamma (float, optional): Field interaction scaling. Defaults to 0.2. mode (str, optional): Wave/field mapping activation mode. Defaults to 'sigmoid'. slope (float, optional): Curvature transition coefficient. Defaults to 1.0. offset (float, optional): Geometric field center shift. Defaults to 0.5. """ self.method = method self.gamma = gamma self.mode = mode self.slope = slope self.offset = offset
[docs] def __call__(self, x: jnp.ndarray) -> jnp.ndarray: """ Computes physical space-curved conjunction field dynamics. Args: x (jnp.ndarray): Input physical interval tensor structured as (..., num_inputs, 2). Returns: jnp.ndarray: Synthesized output field interval tensor structured as (..., 2). Raises: ValueError: If the selected physical AND setup is not recognized. """ inputs = [x[..., i, :] for i in range(x.shape[-2])] res = inputs[0] if self.method in ('physical_godel', 'physical_kleene_dienes'): for item in inputs[1:]: res = F.and_physical_kleene_dienes(res, item) return res elif self.method in ('physical_product', 'physical_reichenbach'): for item in inputs[1:]: res = F.and_physical_reichenbach(res, item) return res elif self.method == 'physical_lukasiewicz': for item in inputs[1:]: res = F.and_physical_lukasiewicz(res, item) return res else: raise ValueError(f"Physical AND method '{self.method}' is not supported.")
[docs] class PhysicalImplication(nnx.Module): """ Parameter-free space-curved rule gateway (A -> B). Evaluates rule mappings based on Physical Fuzzy Logic (PFL) metrics. It monitors field potentials at logical boundary intersections (including continuous singularity zones) without utilizing learning states. Attributes: method (str): Selected physical implication kernel configuration. gamma (float): Space curvature dissipation coefficient parameter. mode (str): Activation field blending mode configuration. slope (float): Physical boundary transition slope parameter. offset (float): Physical potential zero-point offset. """
[docs] def __init__(self, method: str = 'physical_kleene_dienes', gamma: float = 0.2, mode: str = 'sigmoid', slope: float = 1.0, offset: float = 0.5): """ Initializes the non-parametric PhysicalImplication rule connector. Args: method (str, optional): Target PFL implication mapping. Defaults to 'physical_kleene_dienes'. gamma (float, optional): Field interaction scaling. Defaults to 0.2. mode (str, optional): Wave/field mapping activation mode. Defaults to 'sigmoid'. slope (float, optional): Curvature transition coefficient. Defaults to 1.0. offset (float, optional): Geometric field center shift. Defaults to 0.5. """ self.method = method self.gamma = gamma self.mode = mode self.slope = slope self.offset = offset
[docs] def __call__(self, int_a: jnp.ndarray, int_b: jnp.ndarray) -> jnp.ndarray: """ Computes the physical implication output based on causal field distributions. Args: int_a (jnp.ndarray): Physical antecedent field interval tensor structured as (..., 2). int_b (jnp.ndarray): Physical consequent field interval tensor structured as (..., 2). Returns: jnp.ndarray: Rules validity interval tensor structured as (..., 2). """ return F.implication(int_a, int_b, method=self.method)
[docs] class PhysicalNot(nnx.Module): """ Parameter-free physical inversion (NOT) gate. Provides a clean, static logic negation wrapper for structural logic field inversion without any trainable parameter constraints. """
[docs] def __init__(self): """Initializes the parameter-free PhysicalNot gate.""" pass
[docs] def __call__(self, x: jnp.ndarray) -> jnp.ndarray: """ Applies mathematical logical inversion across the interval bounds. Args: x (jnp.ndarray): Input interval tensor structured as (..., 2). Returns: jnp.ndarray: Fully inverted truth interval tensor structured as (..., 2). """ return F.weighted_not(x, jnp.ones(x.shape[:-2]))
[docs] class PhysicalNand(nnx.Module): """ Parameter-free physical NAND gate. Composes a non-parametric field-theoretic physical AND operation followed by a rigid physical inversion layer (NOT). Attributes: and_gate (PhysicalAnd): Internal physical intersection processor layer. not_gate (PhysicalNot): Internal physical logic negation layer. """
[docs] def __init__(self, method: str = 'physical_kleene_dienes', gamma: float = 0.2, mode: str = 'sigmoid', slope: float = 1.0, offset: float = 0.5): """ Initializes the compound PhysicalNand gate structure. Args: method (str, optional): Underlying PFL operational semantics. Defaults to 'physical_kleene_dienes'. gamma (float, optional): Field interaction scaling. Defaults to 0.2. mode (str, optional): Wave/field mapping activation mode. Defaults to 'sigmoid'. slope (float, optional): Curvature transition coefficient. Defaults to 1.0. offset (float, optional): Geometric field center shift. Defaults to 0.5. """ self.and_gate = PhysicalAnd(method=method, gamma=gamma, mode=mode, slope=slope, offset=offset) self.not_gate = PhysicalNot()
[docs] def __call__(self, x: jnp.ndarray) -> jnp.ndarray: """ Executes physical conjunction followed immediately by field negation. Args: x (jnp.ndarray): Input physical interval tensor structured as (..., num_inputs, 2). Returns: jnp.ndarray: Evaluated physical NAND interval tensor structured as (..., 2). """ and_res = self.and_gate(x) return self.not_gate(and_res)
[docs] class PhysicalNor(nnx.Module): """ Parameter-free physical NOR gate. Composes a non-parametric field-theoretic physical OR operation followed by a rigid physical inversion layer (NOT). Attributes: or_gate (PhysicalOr): Internal physical disjunction processor layer. not_gate (PhysicalNot): Internal physical logic negation layer. """
[docs] def __init__(self, method: str = 'physical_kleene_dienes', gamma: float = 0.2, mode: str = 'sigmoid', slope: float = 1.0, offset: float = 0.5): """ Initializes the compound PhysicalNor gate structure. Args: method (str, optional): Underlying PFL operational semantics. Defaults to 'physical_kleene_dienes'. gamma (float, optional): Field interaction scaling. Defaults to 0.2. mode (str, optional): Wave/field mapping activation mode. Defaults to 'sigmoid'. slope (float, optional): Curvature transition coefficient. Defaults to 1.0. offset (float, optional): Geometric field center shift. Defaults to 0.5. """ self.or_gate = PhysicalOr(method=method, gamma=gamma, mode=mode, slope=slope, offset=offset) self.not_gate = PhysicalNot()
[docs] def __call__(self, x: jnp.ndarray) -> jnp.ndarray: """ Executes physical disjunction followed immediately by field negation. Args: x (jnp.ndarray): Input physical interval tensor structured as (..., num_inputs, 2). Returns: jnp.ndarray: Evaluated physical NOR interval tensor structured as (..., 2). """ or_res = self.or_gate(x) return self.not_gate(or_res)