mathhook_core/functions/properties/
rules.rs

1//! Derivative and Antiderivative Rules
2//!
3//! Defines rule types and structures for automatic differentiation and integration.
4//! These rules enable the Universal Function Intelligence System to compute derivatives
5//! and antiderivatives efficiently using pattern matching and rule-based evaluation.
6
7use crate::core::{Expression, Symbol};
8use std::sync::Arc;
9
10/// Derivative rule for automatic differentiation
11#[derive(Clone)]
12pub struct DerivativeRule {
13    /// Rule type for efficient computation
14    pub rule_type: DerivativeRuleType,
15
16    /// Result expression template (for documentation)
17    pub result_template: String,
18}
19
20/// Types of derivative rules for performance optimization
21pub enum DerivativeRuleType {
22    /// Simple function substitution: d/dx sin(x) = cos(x)
23    ///
24    /// Stores the derivative function name for simple cases where
25    /// the derivative is another elementary function of the same argument.
26    ///
27    /// Examples: sin → cos, exp → exp, sinh → cosh, cosh → sinh
28    ///
29    /// Note: For non-trivial derivatives (like ln → 1/x or sqrt → 1/(2√x)),
30    /// use the Custom variant instead to build the actual expression.
31    SimpleFunctionSubstitution(String),
32
33    /// Custom derivative with expression builder
34    ///
35    /// Stores a closure that constructs the derivative expression
36    /// given the function's argument. Used for complex derivatives like
37    /// arcsin, arctan, sqrt, and composite expressions.
38    ///
39    /// Example: d/dx arcsin(u) = builder(u) → 1/√(1-u²)
40    ///
41    /// The builder takes the argument expression and returns
42    /// the derivative with respect to that argument (without chain rule).
43    /// The chain rule (multiplying by du/dx) is applied externally.
44    Custom {
45        #[allow(clippy::type_complexity)]
46        builder: Arc<dyn Fn(&Expression) -> Expression + Send + Sync>,
47    },
48
49    /// Chain rule application: d/dx sin(u) = cos(u) * du/dx
50    ///
51    /// Legacy variant - prefer Custom for new implementations
52    ChainRule(String),
53
54    /// Product rule: d/dx (uv) = u'v + uv'
55    ProductRule,
56
57    /// Quotient rule: d/dx (u/v) = (u'v - uv')/v²
58    QuotientRule,
59}
60
61impl Clone for DerivativeRuleType {
62    fn clone(&self) -> Self {
63        match self {
64            DerivativeRuleType::SimpleFunctionSubstitution(name) => {
65                DerivativeRuleType::SimpleFunctionSubstitution(name.clone())
66            }
67            DerivativeRuleType::Custom { builder } => DerivativeRuleType::Custom {
68                builder: Arc::clone(builder),
69            },
70            DerivativeRuleType::ChainRule(name) => DerivativeRuleType::ChainRule(name.clone()),
71            DerivativeRuleType::ProductRule => DerivativeRuleType::ProductRule,
72            DerivativeRuleType::QuotientRule => DerivativeRuleType::QuotientRule,
73        }
74    }
75}
76
77impl std::fmt::Debug for DerivativeRuleType {
78    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
79        match self {
80            DerivativeRuleType::SimpleFunctionSubstitution(name) => f
81                .debug_struct("SimpleFunctionSubstitution")
82                .field("function", name)
83                .finish(),
84            DerivativeRuleType::Custom { .. } => f
85                .debug_struct("Custom")
86                .field("builder", &"<closure>")
87                .finish(),
88            DerivativeRuleType::ChainRule(name) => {
89                f.debug_struct("ChainRule").field("function", name).finish()
90            }
91            DerivativeRuleType::ProductRule => f.debug_struct("ProductRule").finish(),
92            DerivativeRuleType::QuotientRule => f.debug_struct("QuotientRule").finish(),
93        }
94    }
95}
96
97impl std::fmt::Debug for DerivativeRule {
98    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
99        f.debug_struct("DerivativeRule")
100            .field("rule_type", &self.rule_type)
101            .field("result_template", &self.result_template)
102            .finish()
103    }
104}
105
106/// Antiderivative rule for automatic integration
107///
108/// Stores the antiderivative formula for a function, analogous to DerivativeRule.
109/// Supports simple antiderivatives, substitution patterns, and special techniques.
110///
111/// # Examples
112///
113/// ```rust
114/// use mathhook_core::functions::properties::{AntiderivativeRule, AntiderivativeRuleType, ConstantOfIntegration};
115/// use mathhook_core::expr;
116///
117/// let sin_antiderivative = AntiderivativeRule {
118///     rule_type: AntiderivativeRuleType::Simple {
119///         antiderivative_fn: "cos".to_string(),
120///         coefficient: expr!(-1),
121///     },
122///     result_template: "-cos(x) + C".to_string(),
123///     constant_handling: ConstantOfIntegration::AddConstant,
124/// };
125/// ```
126#[derive(Debug, Clone)]
127pub struct AntiderivativeRule {
128    /// Rule type for efficient computation
129    pub rule_type: AntiderivativeRuleType,
130
131    /// Result expression template (for documentation and validation)
132    /// Example: "∫sin(x)dx = -cos(x) + C"
133    pub result_template: String,
134
135    /// Constant of integration behavior
136    pub constant_handling: ConstantOfIntegration,
137}
138
139/// Types of antiderivative rules for performance optimization
140///
141/// Each variant represents a different integration technique or pattern,
142/// enabling the registry to efficiently compute integrals based on function properties.
143pub enum AntiderivativeRuleType {
144    /// Simple substitution: ∫sin(x)dx = -cos(x) + C
145    ///
146    /// Contains the antiderivative function name and multiplicative coefficient.
147    /// This is the most common case for elementary functions.
148    Simple {
149        /// Name of the antiderivative function
150        antiderivative_fn: String,
151
152        /// Multiplicative coefficient (e.g., -1 for sin → -cos)
153        coefficient: Expression,
154    },
155
156    /// Custom antiderivative with expression builder
157    ///
158    /// Stores a closure that constructs the antiderivative expression
159    /// given the integration variable. Used for complex expressions like
160    /// tan, cot, sec, csc, ln, log, arcsin, arccos, arctan, tanh, sqrt.
161    ///
162    /// Example: ∫tan(x)dx = builder(x) → -ln|cos(x)|
163    Custom {
164        #[allow(clippy::type_complexity)]
165        builder: Arc<dyn Fn(Symbol) -> Expression + Send + Sync>,
166    },
167
168    /// Linear substitution: ∫f(ax)dx = (1/a)F(ax) + C
169    ///
170    /// Used for patterns like ∫sin(3x)dx = -(1/3)cos(3x) + C
171    /// where the inner function is a linear transformation.
172    LinearSubstitution {
173        coefficient: Expression,
174        inner_rule: Box<AntiderivativeRule>,
175    },
176
177    /// Trigonometric substitution patterns
178    ///
179    /// Used for integrals like ∫1/√(1-x²)dx = arcsin(x) + C
180    /// where a trigonometric substitution simplifies the integral.
181    TrigSubstitution { substitution_type: String },
182
183    /// Partial fraction decomposition (for rational functions)
184    ///
185    /// Indicates that the integral requires partial fraction decomposition
186    /// before integration can proceed.
187    PartialFractions { decomposition: Vec<Expression> },
188}
189
190impl Clone for AntiderivativeRuleType {
191    fn clone(&self) -> Self {
192        match self {
193            AntiderivativeRuleType::Simple {
194                antiderivative_fn,
195                coefficient,
196            } => AntiderivativeRuleType::Simple {
197                antiderivative_fn: antiderivative_fn.clone(),
198                coefficient: coefficient.clone(),
199            },
200            AntiderivativeRuleType::Custom { builder } => AntiderivativeRuleType::Custom {
201                builder: Arc::clone(builder),
202            },
203            AntiderivativeRuleType::LinearSubstitution {
204                coefficient,
205                inner_rule,
206            } => AntiderivativeRuleType::LinearSubstitution {
207                coefficient: coefficient.clone(),
208                inner_rule: inner_rule.clone(),
209            },
210            AntiderivativeRuleType::TrigSubstitution { substitution_type } => {
211                AntiderivativeRuleType::TrigSubstitution {
212                    substitution_type: substitution_type.clone(),
213                }
214            }
215            AntiderivativeRuleType::PartialFractions { decomposition } => {
216                AntiderivativeRuleType::PartialFractions {
217                    decomposition: decomposition.clone(),
218                }
219            }
220        }
221    }
222}
223
224impl std::fmt::Debug for AntiderivativeRuleType {
225    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
226        match self {
227            AntiderivativeRuleType::Simple {
228                antiderivative_fn,
229                coefficient,
230            } => f
231                .debug_struct("Simple")
232                .field("antiderivative_fn", antiderivative_fn)
233                .field("coefficient", coefficient)
234                .finish(),
235            AntiderivativeRuleType::Custom { .. } => f
236                .debug_struct("Custom")
237                .field("builder", &"<closure>")
238                .finish(),
239            AntiderivativeRuleType::LinearSubstitution {
240                coefficient,
241                inner_rule,
242            } => f
243                .debug_struct("LinearSubstitution")
244                .field("coefficient", coefficient)
245                .field("inner_rule", inner_rule)
246                .finish(),
247            AntiderivativeRuleType::TrigSubstitution { substitution_type } => f
248                .debug_struct("TrigSubstitution")
249                .field("substitution_type", substitution_type)
250                .finish(),
251            AntiderivativeRuleType::PartialFractions { decomposition } => f
252                .debug_struct("PartialFractions")
253                .field("decomposition", decomposition)
254                .finish(),
255        }
256    }
257}
258
259/// Constant of integration handling
260///
261/// Specifies how the constant of integration should be handled
262/// in the antiderivative result.
263#[derive(Debug, Clone, Copy, PartialEq)]
264pub enum ConstantOfIntegration {
265    /// Automatically add +C to result
266    AddConstant,
267
268    /// Definite integral (no constant)
269    DefiniteIntegral,
270
271    /// User will handle constant explicitly
272    UserHandled,
273}
274
275/// Recurrence relation for symbolic computation
276#[derive(Debug, Clone)]
277pub struct RecurrenceRule {
278    /// Recurrence relation name
279    pub name: String,
280
281    /// Relation template (e.g., "f_{n+1} = a*f_n + b*f_{n-1}")
282    pub relation: String,
283
284    /// Coefficients for computation
285    pub coefficients: Vec<Expression>,
286}
287
288/// Three-term recurrence for orthogonal polynomials
289#[derive(Debug, Clone)]
290pub struct ThreeTermRecurrence {
291    /// Forward coefficient: α_n in P_{n+1} = (α_n x + β_n)P_n - γ_n P_{n-1}
292    pub alpha_coeff: Expression,
293
294    /// Linear coefficient: β_n
295    pub beta_coeff: Expression,
296
297    /// Backward coefficient: γ_n
298    pub gamma_coeff: Expression,
299
300    /// Initial conditions: P_0, P_1
301    pub initial_conditions: (Expression, Expression),
302}
303
304/// Mathematical identity for symbolic computation
305#[derive(Debug, Clone)]
306pub struct MathIdentity {
307    /// Identity name for reference
308    pub name: String,
309
310    /// Left side of identity
311    pub lhs: Expression,
312
313    /// Right side of identity
314    pub rhs: Expression,
315
316    /// Conditions for identity validity
317    pub conditions: Vec<String>,
318}
319
320/// Special value for exact computation
321#[derive(Debug, Clone)]
322pub struct SpecialValue {
323    /// Input value (e.g., "0", "π/2", "1")
324    pub input: String,
325
326    /// Exact output value
327    pub output: Expression,
328
329    /// LaTeX representation for educational display
330    pub latex_explanation: String,
331}
332
333/// Domain and range information
334#[derive(Debug, Clone)]
335pub struct DomainRangeData {
336    /// Function domain
337    pub domain: Domain,
338
339    /// Function range
340    pub range: Range,
341
342    /// Singularities (if any)
343    pub singularities: Vec<Expression>,
344}
345
346/// Mathematical domain
347#[derive(Debug, Clone, PartialEq)]
348pub enum Domain {
349    Real,
350    Complex,
351    Integer,
352    PositiveInteger,
353    NonNegativeInteger,
354    Interval(Expression, Expression),
355    Union(Vec<Domain>),
356}
357
358/// Mathematical range
359#[derive(Debug, Clone)]
360pub enum Range {
361    Real,
362    Integer,
363    PositiveInteger,
364    NonNegativeInteger,
365    Boolean,
366    Bounded(Expression, Expression),
367    Unbounded,
368}
369
370/// Evaluation method for computational efficiency
371#[derive(Debug, Clone, Copy, PartialEq)]
372pub enum EvaluationMethod {
373    /// Direct formula evaluation
374    Direct,
375
376    /// Recurrence relation (most efficient for polynomials)
377    Recurrence,
378
379    /// Horner's method for polynomial evaluation
380    Horner,
381
382    /// Series expansion
383    Series,
384}