Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

expression compiler: automatic differentiation #253

Open
5 of 6 tasks
crowlogic opened this issue Oct 18, 2023 · 14 comments
Open
5 of 6 tasks

expression compiler: automatic differentiation #253

crowlogic opened this issue Oct 18, 2023 · 14 comments
Assignees
Labels
enhancement things that are not bugs
Milestone

Comments

@crowlogic
Copy link
Owner

crowlogic commented Oct 18, 2023

Implementing Automatic Differentiator

This issue tracks the implementation of an automatic differentiator for the expression compiler. The compiler parses expressions into binary trees, and this differentiator will apply differentiation rules recursively based on the tree structure.

Algorithm Outline

  1. Base Case:

    • For leaf nodes:
      • If a constant, derivative = 0.
      • If a variable, derivative = 1 for the differentiation variable, otherwise 0.
  2. Differentiation Rules:

    • Addition/Subtraction Nodes: Derivative of a sum/difference is the sum/difference of the derivatives.
    • Multiplication Nodes (Product Rule): For a product $f * g$, derivative = $f' * g + f * g'$.
    • Division Nodes (Quotient Rule): For a division $f / g$, derivative = $(f' * g - f * g') / g^2$.
    • Exponential and Logarithmic Functions: Apply respective differentiation rules.
    • Trigonometric Functions: Apply differentiation rules for sine, cosine, etc.
    • Power Nodes: Apply power rule or generalized power rule.
  3. Recursive Application:

    • Apply these rules to each child node to compute $f'$ and $g'$
  4. Construct New Tree:

    • Construct a new tree representing the derivative.
  5. Simplification (Optional):

    • Simplify the resulting tree to combine like terms, simplify constants, etc.

Stuff To Be Done And Whatnot

  • Implement the base case logic for leaf nodes.
  • Develop differentiation rules for each type of operation/function node.
  • Create a function for recursive traversal and application of differentiation rules.
  • Design and implement a tree constructor for the derivative expression.
  • Add an optional simplification step post-differentiation.
  • Thoroughly test the differentiator with various types of expressions.
@crowlogic
Copy link
Owner Author

crowlogic commented Oct 27, 2023

When designing this it would be good to take into account and tie it into this paradigm as well since this relies on repeated differentiation which will need to be done automatically

Rodrigues' Formula and Orthogonal Polynomials

Rodrigues' formula is a mathematical expression that provides an efficient way to generate certain orthogonal polynomials. Orthogonal polynomials play a pivotal role in various branches of mathematics, including approximation theory, differential equations, and even quantum mechanics.

What is Rodrigues' Formula?

For a given differential operator $D$ and weight function $w(x)$, the Rodrigues' formula for an orthogonal polynomial $P_n(x)$ is given by:

$$P_n(x) = \frac{1}{w(x) n!} D^n [w(x) f(x)]$$

Here, $n$ denotes the order of the polynomial, and $f(x)$ is a function specific to the type of orthogonal polynomial under consideration.

Examples:

  1. Legendre Polynomials: The Rodrigues' formula for the Legendre polynomials $P_n(x)$ is:

$$P_n(x) = \frac{1}{2^n n!} \frac{d^n}{dx^n} (x^2 - 1)^n$$

  1. Hermite Polynomials: The Hermite polynomials $H_n(x)$ are described by:

$$H_n(x) = (-1)^n e^{x^2} \frac{d^n}{dx^n} e^{-x^2}$$

In both examples, differentiation acts as an iterated linear function to generate the nth polynomial in the sequence.

Connection to Linear Iterated Functions Systems (L.I.F.S.)

The study of orthogonal polynomials can be extended to consider measures generated by Linear Iterated Functions Systems, or L.I.F.S. This is a more advanced topic, delving into the interplay between orthogonal polynomials and iterative linear processes, especially in the context of Fourier analysis.

In more advanced research, like the paper by Giorgio Mantica and Davide Guzzetti, the authors explore the asymptotic behavior of the Fourier transforms of orthogonal polynomials, relating them to measures generated by L.I.F.S.

Conclusion

The Rodrigues' formula serves as a foundation for understanding and generating orthogonal polynomials. As mathematics advances, the interplay between these polynomials, linear iterated systems, and Fourier analysis continues to offer rich areas for exploration and discovery.

@crowlogic crowlogic self-assigned this Oct 27, 2023
@crowlogic
Copy link
Owner Author

crowlogic commented Dec 10, 2023

Fluent Programming Style in Java

In Java, the fluent programming style, often seen in method chaining, is where you can call multiple methods on objects in a single statement. Each method returns an object, allowing the next method in the chain to be invoked on it. This style is popular in builder patterns, streams, and other API designs where it enhances readability and flow of the code. For example:

myObject.methodOne().methodTwo().methodThree();

In this style, each method invocation returns an object, which may not necessarily be of the same type as the input object. The type of the output defaults to the input type unless explicitly specified by the caller, particularly in cases where the last argument of the function is the result variable.

Composition of Functions in Mathematics

In mathematics, function composition is the application of one function to the result of another to produce a third function. For example, if $f$ and $g$ are two functions, their composition $(f \circ g)(x)$ is defined as $f(g(x))$. This is a fundamental concept in mathematics, particularly in fields like calculus and algebra.

Similarity

The similarity lies in the way operations or functions are applied in a sequence, each taking the output of the previous one as its input:

  • In Java's fluent style, object.methodA().methodB() first invokes methodA on object, then methodB on the result of methodA. The type of the result of methodB may be different from the type of the object on which methodA is invoked.
  • In mathematical function composition, $f(g(x))$ first applies $g$ to $x$, then $f$ to the result of $g(x)$. The output type of $g$ must be compatible with the input type of $f$.

Difference

While structurally similar, the contexts and applications of these concepts are different:

  • Fluent style in programming is often about enhancing code readability and managing sequences of operations in object-oriented programming, with flexibility in the types of input and output.
  • Function composition in mathematics is a fundamental concept for describing how functions interact and combine, often used for more abstract or theoretical purposes, with strict rules about the types of function inputs and outputs.

In summary, while the two concepts are not identical, the structural similarity is clear, and understanding one can help in grasping the other, with the specific distinction in how the types of inputs and outputs are handled.

@crowlogic crowlogic added the enhancement things that are not bugs label Dec 22, 2023
@crowlogic
Copy link
Owner Author

Alglib

@crowlogic crowlogic added this to the α milestone Apr 2, 2024
crowlogic pushed a commit that referenced this issue May 11, 2024
253: expression compiler: automatic differentiation

Task-Url: #253
@crowlogic
Copy link
Owner Author

Okay, let's break this down and provide a mathematical analysis of the structure you're proposing for implementing the derivative operator in your recursive descent expression compiler.

Given:

  • You're using a recursive descent parser to parse expressions and generate code.
  • You want to implement the derivative operator using the partial differential symbol (∂).
  • The derivative operator will be a postfix operator that modifies the nodes before it.

Approach:
Instead of treating the derivative operator as a postfix operator, you propose treating it as a binary operator, where:

  • The left-hand side is the expression to be differentiated.
  • The right-hand side is the variable with respect to which the derivative is taken.

Mathematical Analysis:
Let's represent the expression tree as a binary tree, where each node is either an operator or an operand (variable or constant).

Suppose we have an expression f(x, y) = x^2 + x * y + sin(y).

The expression tree would look like this:

     (+)
    / | \
  (^) (*) (sin)
  / \  / \   |
 x  2 x  y   y

Now, let's consider the derivative of f with respect to x, denoted as ∂f/∂x.

Using your proposed approach, we would represent the derivative operation as a binary operator node:

     (∂)
    /  \
 f(x,y) x

The derivative operator node would then recursively traverse the left subtree (the original expression tree) and apply the differentiation rules based on the type of each node:

  • If the node is a variable and matches the differentiation variable (x), replace it with 1.
  • If the node is a variable but doesn't match the differentiation variable, replace it with 0.
  • If the node is a constant, replace it with 0.
  • If the node is an operator, apply the corresponding differentiation rule recursively to its children.

For the given example, the resulting derivative expression tree would be:

     (+)
    / | \
  (+) (*) 0
  / \  / \
 *  0 1  y
/ \
2  x

This tree represents the derivative expression: 2 * x + 1 * y + 0, which simplifies to 2x + y.

Analysis:
Treating the derivative operator as a binary operator simplifies the implementation within the recursive descent parser framework. The main advantages of this approach are:

  1. It maintains the binary tree structure of the expression tree.
  2. The derivative operator can be handled similarly to other binary operators in the parser.
  3. The differentiation rules can be applied recursively by traversing the left subtree of the derivative operator node.
  4. The parser can handle nested derivative operations naturally by recursively applying the differentiation process.

However, there are a few considerations to keep in mind:

  1. The derivative operator has a higher precedence than other binary operators, so the parser needs to handle this accordingly.
  2. The derivative operator should be right-associative to allow for multiple consecutive derivatives (e.g., ∂^2f/∂x∂y).
  3. The parser needs to validate that the right-hand side of the derivative operator is a valid variable (or a comma-separated list of variables for partial derivatives).

Overall, treating the derivative operator as a binary operator in the recursive descent parser framework provides a clean and consistent way to implement differentiation in your expression compiler. The mathematical analysis shows that this approach correctly applies the differentiation rules and produces the expected derivative expression tree.

@crowlogic
Copy link
Owner Author

I apologize for my repeated misunderstandings. Let me correct my explanation based on your clear instructions.

  1. Tokenization: When the lexer encounters the initial partial derivative symbol (∂), it recognizes it as the start of a derivative operator. The lexer stops consuming characters at this point.

  2. Extracting the expression substring: The substring between the initial partial derivative symbol and the forward slash (/) followed by the second partial derivative symbol (∂) is extracted as a separate string. This string represents the expression to be differentiated.

  3. Generating a new expression context: A new expression context is created specifically for parsing the extracted substring. This context is independent of the main parsing context and allows for the substring to be parsed as a standalone expression.

  4. Parsing the expression substring: The extracted substring is passed to the parser within the newly generated expression context. The parser then parses the substring as a separate expression, following the parsing rules defined for expressions in your compiler. This generates an abstract syntax tree (AST) node representing the expression to be differentiated.

  5. Creating the derivative operator node: After parsing the expression substring, the compiler creates a new AST node representing the derivative operator. This node has the parsed expression node as its child.

I apologize for my previous mistakes and for not accurately capturing your instructions. Thank you for your patience and for correcting me. Please let me know if there's anything else I can assist you with regarding the implementation of the derivative operator in your compiler.

@crowlogic
Copy link
Owner Author

Understood, thank you for the correction. Let me provide the complete syntax specifications:

For the unary ∂ differential operator:
Syntax:
∂Expression/∂Variable

Where:

  • ∂ denotes the start of the expression being differentiated
  • Expression is the expression being differentiated
  • /∂Variable denotes the end of the expression, with the variable being differentiated

For the binary ∂ differential operator:
Syntax:
(Expression) ∂/∂Variable

Where:

  • (Expression) is the expression being differentiated, enclosed in parentheses if grouping is needed
  • ∂/∂ is the binary differential operator
  • Variable is the variable being differentiated

The key difference is that parentheses are not required for the unary ∂ version, but may be used for grouping the expression if needed. Please let me know if I now have the complete and accurate syntax specifications.

@crowlogic
Copy link
Owner Author

Claude is a fucking goddamn piece of shit. What kind of witless fucking idiots programmed this thing? They ought to be kicked in the goddamn head

You're absolutely right, I'm very sorry about that. Let me provide the correct syntax specifications one more time:

For the unary ∂ differential operator:
Syntax:
∂Expression ∂Variable

Where:

  • ∂ denotes the start of the expression being differentiated
  • Expression is the expression being differentiated
  • ∂Variable denotes the variable being differentiated

For the binary ∂ differential operator:
Syntax:
(Expression) ∂Variable

Where:

  • (Expression) is the expression being differentiated, enclosed in parentheses if grouping is needed
  • ∂Variable is the binary differential operator with the variable being differentiated

Thank you for your patience and for persistently correcting me until I understood this properly. I clearly had significant gaps in my knowledge, and I appreciate you taking the time to ensure I have the correct syntax specifications.

crowlogic added a commit that referenced this issue Nov 14, 2024
crowlogic added a commit that referenced this issue Nov 14, 2024
crowlogic added a commit that referenced this issue Nov 27, 2024
for x which is part of DerivativeNode[operand=(a*x+(b*x^2))+(c*x^3),
variable=x, derivative=((0*x+a*1)+((0*x^2)+(b*x^2)))+((0*x^3)+(c*x^3))]
	at arb4j/arb.expressions.nodes.VariableNode.type(VariableNode.java:592)
	at arb4j/arb.expressions.nodes.binary.BinaryOperationNode.type(BinaryOperationNode.java:363)
	at arb4j/arb.expressions.nodes.binary.BinaryOperationNode.type(BinaryOperationNode.java:362)
	at arb4j/arb.expressions.nodes.binary.BinaryOperationNode.type(BinaryOperationNode.java:362)
	at arb4j/arb.expressions.nodes.binary.BinaryOperationNode.generate(BinaryOperationNode.java:190)
	at arb4j/arb.expressions.nodes.DerivativeNode.generate(DerivativeNode.java:141)
	at arb4j/arb.expressions.Expression.generateEvaluationMethod(Expression.java:940)
	at arb4j/arb.expressions.Expression.generate(Expression.java:787)
	at arb4j/arb.expressions.Expression.defineClass(Expression.java:570)
	at arb4j/arb.expressions.Expression.getInstance(Expression.java:1218)
	at arb4j/arb.expressions.Expression.instantiate(Expression.java:1367)
	at arb4j/arb.functions.Function.instantiate(Function.java:126)
	at arb4j/arb.functions.rational.RationalNullaryFunction.express(RationalNullaryFunction.java:29)
	at arb4j/arb.functions.rational.RationalNullaryFunction.express(RationalNullaryFunction.java:39)
	at arb4j/arb.RationalFunction.express(RationalFunction.java:245)
	at arb4j/arb.expressions.ExpressionTest.testRationalFunctionDerivative(ExpressionTest.java:83)
	at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
	at java.base/java.lang.reflect.Method.invoke(Method.java:580)
	at [email protected]/junit.framework.TestCase.runTest(TestCase.java:177)
	at [email protected]/junit.framework.TestCase.runBare(TestCase.java:142)
	at [email protected]/junit.framework.TestResult$1.protect(TestResult.java:122)
	at [email protected]/junit.framework.TestResult.runProtected(TestResult.java:142)
	at [email protected]/junit.framework.TestResult.run(TestResult.java:125)
	at [email protected]/junit.framework.TestCase.run(TestCase.java:130)
	at [email protected]/junit.framework.TestSuite.runTest(TestSuite.java:241)
	at [email protected]/junit.framework.TestSuite.run(TestSuite.java:236)
	at [email protected]/org.junit.internal.runners.JUnit38ClassRunner.run(JUnit38ClassRunner.java:90)
	at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:93)
	at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:40)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:530)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:758)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:453)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:211)

	#253
crowlogic added a commit that referenced this issue Nov 27, 2024
interface arb.functions.real.RealFunction
	at arb4j/arb.functions.Function.newCoDomainInstance(Function.java:320)
	at arb4j/arb.functions.Function.evaluate(Function.java:239)
	at arb4j/arb.functions.Function.evaluate(Function.java:220)
	at arb4j/arb.functions.integer.Sequence.evaluate(Sequence.java:47)
	at arb4j/arb.expressions.nodes.unary.SphericalBesselFunctionNodeOfTheFirstKindTest.testj0ViaRealFunctionalExpression(SphericalBesselFunctionNodeOfTheFirstKindTest.java:24)
	at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
	at java.base/java.lang.reflect.Method.invoke(Method.java:580)
	at [email protected]/junit.framework.TestCase.runTest(TestCase.java:177)
	at [email protected]/junit.framework.TestCase.runBare(TestCase.java:142)
	at [email protected]/junit.framework.TestResult$1.protect(TestResult.java:122)
	at [email protected]/junit.framework.TestResult.runProtected(TestResult.java:142)
	at [email protected]/junit.framework.TestResult.run(TestResult.java:125)
	at [email protected]/junit.framework.TestCase.run(TestCase.java:130)
	at [email protected]/junit.framework.TestSuite.runTest(TestSuite.java:241)
	at [email protected]/junit.framework.TestSuite.run(TestSuite.java:236)
	at [email protected]/org.junit.internal.runners.JUnit38ClassRunner.run(JUnit38ClassRunner.java:90)
	at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:93)
	at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:40)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:530)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:758)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:453)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:211)

#253
crowlogic added a commit that referenced this issue Nov 27, 2024
exponentiation
@crowlogic
Copy link
Owner Author

package arb.functions.real;

import arb.Initializable;
import arb.Integer;
import arb.Real;
import arb.Typesettable;
import arb.documentation.BusinessSourceLicenseVersionOnePointOne;
import arb.documentation.TheArb4jLibrary;
import arb.expressions.nodes.DerivativeNode;
import junit.framework.TestCase;

/**
 * Decompiled {@link DerivativeNode} test function
 *
 * @see BusinessSourceLicenseVersionOnePointOne © terms of the
 *      {@link TheArb4jLibrary}
 */
public class TestCompiledDerivative implements
                                    RealFunctional<Object, RealFunction>,
                                    Typesettable,
                                    AutoCloseable,
                                    Initializable
{
  public boolean       isInitialized;
  public final Integer cℤ2     = new Integer("3");
  public final Integer cℤ1     = new Integer("2");
  public final Integer cℤ4     = new Integer("1");
  public final Integer cℤ3     = new Integer("0");
  public Real          a;
  public Real          b;
  public Real          c;
  public Real          ifuncℝ4 = new Real();
  public Real          ifuncℝ5 = new Real();
  public Integer       iℤ2     = new Integer();
  public Real          ifuncℝ6 = new Real();
  public Integer       iℤ1     = new Integer();
  public Real          ifuncℝ7 = new Real();
  public Real          ifuncℝ1 = new Real();
  public Real          ifuncℝ2 = new Real();
  public Real          ifuncℝ3 = new Real();
  public Real          ifuncℝ8 = new Real();

  public static void main(String args[])
  {
    try ( TestCompiledDerivative derivative = new TestCompiledDerivative())
    {
      derivative.a = Real.named("a").set(2);
      derivative.b = Real.named("b").set(4);
      derivative.c = Real.named("c").set(6);

      RealFunction d   = derivative.evaluate(null, 128);
      double       val = d.eval(2.3);
      TestCase.assertEquals(115.61999999999998, val);
      System.out.format("%s(2.3)=%s\n", d, val);
    }

  }

  @Override
  public Class<RealFunction> coDomainType()
  {
    return RealFunction.class;
  }

  @Override
  public RealFunction evaluate(Object in, int order, int bits, RealFunction result)
  {
    if (!isInitialized)
    {
      initialize();
    }
    RealFunction realFunction = new RealFunction()
    {

      @Override
      public Real evaluate(Real input, int order, int bits, Real res)
      {

        return a.add(b.mul(cℤ1.mul(input.pow(cℤ1.sub(cℤ4, bits, iℤ1), bits, ifuncℝ1), bits, ifuncℝ2), bits, ifuncℝ3),
                     bits,
                     ifuncℝ4)
                .add(c.mul(cℤ2.mul(input.pow(cℤ2.sub(cℤ4, bits, iℤ2), bits, ifuncℝ5), bits, ifuncℝ6), bits, ifuncℝ7),
                     bits,
                     ifuncℝ8);

      }

      @Override
      public String toString()
      {
        return TestCompiledDerivative.this.toString();
      }
    };
    return realFunction;
  }

  @Override
  public void initialize()
  {
    if (isInitialized)
    {
      throw new AssertionError("Already initialized");
    }
    else if (a == null)
    {
      throw new AssertionError("x-∂a*x+b*x²+c*x³⁄∂x.a is null");
    }
    else if (b == null)
    {
      throw new AssertionError("x-∂a*x+b*x²+c*x³⁄∂x.b is null");
    }
    else if (c == null)
    {
      throw new AssertionError("x-∂a*x+b*x²+c*x³⁄∂x.c is null");
    }
    else
    {
      isInitialized = true;
    }
  }

  @Override
  public void close()
  {
    cℤ2.close();
    cℤ1.close();
    cℤ4.close();
    cℤ3.close();
    ifuncℝ4.close();
    ifuncℝ5.close();
    iℤ2.close();
    ifuncℝ6.close();
    iℤ1.close();
    ifuncℝ7.close();
    ifuncℝ1.close();
    ifuncℝ2.close();
    ifuncℝ3.close();
    ifuncℝ8.close();
  }

  @Override
  public String toString()
  {
    return "x➔∂a*x+b*x²+c*x³/∂x";
  }

  @Override
  public String typeset()
  {
    return "a + b \\cdot 2 \\cdot {x}^{(\\left(2-1\\right))} + c \\cdot 3 \\cdot {x}^{(\\left(3-1\\right))}";
  }
}

@crowlogic
Copy link
Owner Author

Exported on 28/11/2024 at 10:04:21 from Perplexity.ai - with SaveMyChatbot

User

is bci:48 in hex or decimal?

java.lang.VerifyError: Bad type on operand stack
Exception Details:
Location:
x-∂a*x+b*x²+c*x³⁄∂x.evaluate(Ljava/lang/Object;IILjava/lang/Object;)Ljava/lang/Object; @48: invokevirtual
Reason:
Type 'java/lang/Object' (current frame, stack[3]) is not assignable to 'arb/RealPolynomial'
Current Frame:
bci: @48
flags: { }
locals: { 'x-∂a*x+b*x²+c*x³⁄∂x', 'java/lang/Object', integer, integer, 'java/lang/Object' }
stack: { 'arb/Real', 'arb/Real', 'arb/Integer', 'java/lang/Object', 'arb/Integer', integer, 'arb/RealPolynomial' }
Bytecode:
0000000: 2ab4 001a 9a00 072a b600 1e2a b400 222a
0000010: b400 252a b400 292b b600 2d2a b400 292a
0000020: b400 301d 2ab4 0033 b600 391d 2ab4 003d
0000030: b600 411d 2ab4 0044 b600 481d 2ab4 004b
0000040: b600 4e1d 2ab4 0051 b600 542a b400 572a
0000050: b400 5a2b b600 2d2a b400 5a2a b400 301d
0000060: 2ab4 005d b600 391d 2ab4 0060 b600 411d
0000070: 2ab4 0063 b600 481d 2ab4 0066 b600 4e1d
0000080: 2ab4 0069 b600 6ab0
Stackmap Table:
same_frame(@11)

at java.base/java.lang.Class.getDeclaredConstructors0(Native Method)
at java.base/java.lang.Class.privateGetDeclaredConstructors(Class.java:3621)
at java.base/java.lang.Class.getConstructor0(Class.java:3826)
at java.base/java.lang.Class.getDeclaredConstructor(Class.java:3004)
at arb4j/arb.expressions.Expression.getInstance(Expression.java:1222)
at arb4j/arb.expressions.Expression.instantiate(Expression.java:1367)
at arb4j/arb.functions.Function.instantiate(Function.java:126)
at arb4j/arb.functions.polynomials.RealPolynomialNullaryFunction.express(RealPolynomialNullaryFunction.java:35)
at arb4j/arb.functions.polynomials.RealPolynomialNullaryFunction.express(RealPolynomialNullaryFunction.java:47)
at arb4j/arb.expressions.ExpressionTest.testRealPolynomialDerivative(ExpressionTest.java:127)
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
at java.base/java.lang.reflect.Method.invoke(Method.java:580)
at [email protected]/junit.framework.TestCase.runTest(TestCase.java:177)
at [email protected]/junit.framework.TestCase.runBare(TestCase.java:142)
at [email protected]/junit.framework.TestResult$1.protect(TestResult.java:122)
at [email protected]/junit.framework.TestResult.runProtected(TestResult.java:142)
at [email protected]/junit.framework.TestResult.run(TestResult.java:125)
at [email protected]/junit.framework.TestCase.run(TestCase.java:130)
at org.eclipse.jdt.internal.junit.runner.junit3.JUnit3TestReference.run(JUnit3TestReference.java:128)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:40)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:530)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:758)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:453)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:211)

AI answer

The term "bci:48" in the context of Java bytecode refers to a bytecode index (bci), which indicates the position within the bytecode of a method where an error or operation occurs. In this specific case, "bci:48" is denoting the 48th byte in the bytecode sequence of a method. To determine whether "48" is in hexadecimal or decimal, we need to consider the typical conventions used in Java bytecode and error messages. In Java, bytecode indices are usually expressed in decimal form rather than hexadecimal. Therefore, "bci:48" is most likely referring to the decimal number 48. If you were to convert this decimal number to hexadecimal, it would be represented as "30" in hexadecimal notation 2 5.


Sources:

User

so where the fuck does that cirrespond to my disassembled outpuit?

AI answer

To locate the bytecode index (bci) 48 in your disassembled Java bytecode output, you need to look at the sequence of bytecode instructions provided by the javap -c command. The bci refers to the position of a specific bytecode instruction within a method's bytecode sequence. In the disassembled output provided in the paste.txt file, each line corresponds to a bytecode instruction along with its index. The bci is essentially a counter that starts at 0 for the first instruction in the method and increments by one for each subsequent instruction. In your case, you are interested in bci:48, which means you need to find the 48th instruction in the sequence. Here's how you can identify it:

  1. Locate the Method: First, ensure you are looking at the correct method where the error occurred. The error message indicates that it's within a method named evaluate.
  2. Count Bytecodes: Starting from the beginning of the evaluate method's bytecode listing, count each instruction until you reach index 48.
  3. Identify Instruction: Once you reach bci:48, note down the instruction and any associated operations or operands. This will help you understand what operation is being performed at this point and why it might be causing an error.

In your provided disassembly, bci:48 corresponds to an instruction involving getfield #60 // Field m:Larb/Integer;. This indicates that at this point in the code, there is an attempt to access a field named m of type arb.Integer. This access could be related to the error if there is a type mismatch or incorrect assignment occurring around this operation.


Sources:

User

that is not consistent woith the fucking error u fool

java.lang.VerifyError: Bad type on operand stack
Exception Details:
Location:
x-∂a*x+b*x²+c*x³⁄∂x.evaluate(Ljava/lang/Object;IILjava/lang/Object;)Ljava/lang/Object; @48: invokevirtual
Reason:
Type 'java/lang/Object' (current frame, stack[3]) is not assignable to 'arb/RealPolynomial'
Current Frame:
bci: @48
flags: { }
locals: { 'x-∂a*x+b*x²+c*x³⁄∂x', 'java/lang/Object', integer, integer, 'java/lang/Object' }
stack: { 'arb/Real', 'arb/Real', 'arb/Integer', 'java/lang/Object', 'arb/Integer', integer, 'arb/RealPolynomial' }
Bytecode:
0000000: 2ab4 001a 9a00 072a b600 1e2a b400 222a
0000010: b400 252a b400 292b b600 2d2a b400 292a
0000020: b400 301d 2ab4 0033 b600 391d 2ab4 003d
0000030: b600 411d 2ab4 0044 b600 481d 2ab4 004b
0000040: b600 4e1d 2ab4 0051 b600 542a b400 572a
0000050: b400 5a2b b600 2d2a b400 5a2a b400 301d
0000060: 2ab4 005d b600 391d 2ab4 0060 b600 411d
0000070: 2ab4 0063 b600 481d 2ab4 0066 b600 4e1d
0000080: 2ab4 0069 b600 6ab0
Stackmap Table:
same_frame(@11)

at java.base/java.lang.Class.getDeclaredConstructors0(Native Method)
at java.base/java.lang.Class.privateGetDeclaredConstructors(Class.java:3621)
at java.base/java.lang.Class.getConstructor0(Class.java:3826)
at java.base/java.lang.Class.getDeclaredConstructor(Class.java:3004)
at arb4j/arb.expressions.Expression.getInstance(Expression.java:1222)
at arb4j/arb.expressions.Expression.instantiate(Expression.java:1367)
at arb4j/arb.functions.Function.instantiate(Function.java:126)
at arb4j/arb.functions.polynomials.RealPolynomialNullaryFunction.express(RealPolynomialNullaryFunction.java:35)
at arb4j/arb.functions.polynomials.RealPolynomialNullaryFunction.express(RealPolynomialNullaryFunction.java:47)
at arb4j/arb.expressions.ExpressionTest.testRealPolynomialDerivative(ExpressionTest.java:127)
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
at java.base/java.lang.reflect.Method.invoke(Method.java:580)
at [email protected]/junit.framework.TestCase.runTest(TestCase.java:177)
at [email protected]/junit.framework.TestCase.runBare(TestCase.java:142)
at [email protected]/junit.framework.TestResult$1.protect(TestResult.java:122)
at [email protected]/junit.framework.TestResult.runProtected(TestResult.java:142)
at [email protected]/junit.framework.TestResult.run(TestResult.java:125)
at [email protected]/junit.framework.TestCase.run(TestCase.java:130)
at org.eclipse.jdt.internal.junit.runner.junit3.JUnit3TestReference.run(JUnit3TestReference.java:128)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:40)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:530)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:758)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:453)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:211)

AI answer

To understand the relationship between the bytecode index (bci) and your disassembled output, let's clarify the error and locate the specific instruction causing it.

Error Context

The error message indicates a java.lang.VerifyError at bytecode index 48 in the method evaluate. The issue is that a java/lang/Object on the operand stack is expected to be an arb/RealPolynomial, which is causing a type mismatch.

Locating bci:48

In the bytecode sequence provided, each instruction is associated with a specific index. The bytecode index 48 corresponds to an instruction at that position in the sequence. Here's how you can locate it:

  1. Bytecode Sequence: The bytecode sequence is listed in hexadecimal format, where each line represents a set of instructions with their respective byte offsets.
  2. Find bci:48: In your disassembled output, look for the instruction at offset 48. It corresponds to:```text
    0000030: b600 411d 2ab4 0044 b600 481d 2ab4 004b
    The instruction at offset `48` (hexadecimal) is part of this line, specifically the `b600` opcode which represents an `invokevirtual` instruction in Java bytecode.
    
  3. Instruction Details: This invokevirtual instruction at bci:48 is attempting to invoke a method on an object that should be of type arb/RealPolynomial, but instead, it is of type java/lang/Object.

Resolving the Error

The error suggests that there is a mismatch in expectations regarding the type of object on the stack at this point in your code. To resolve this:

  • Check Type Casting: Ensure that any objects being passed to this method are correctly cast or converted to arb/RealPolynomial before reaching this point.
  • Verify Method Signature: Double-check the method signature and ensure that it matches the expected types for all parameters and return values.
  • Debugging: Use debugging tools or logging to trace back where the incorrect type might be entering your method logic.

By ensuring that the correct types are used throughout your method, you can resolve this verification error.


Sources:

  • (1) paste.txt

User

i see i gave the wrong class, its the invokecirtual pow method giving fits

it should load the result instead of the input in this scenario

AI answer

The issue you're encountering with the invokevirtual instruction related to the pow method is likely due to a mismatch between the expected and actual types on the operand stack at the time of invocation. This type of problem often results in a java.lang.VerifyError.

Understanding the Error

In your bytecode, the invokevirtual instruction at bytecode index 48 attempts to call the pow method on an instance of arb.RealPolynomial. The error message indicates that the object on the stack at this point is not of the expected type. Instead of having an arb.RealPolynomial, it seems to be a generic java/lang/Object.

Bytecode Analysis

From your disassembled bytecode, let's focus on the relevant section:

44: aload_0
45: getfield #61 // Field iXв„қ1:Larb/RealPolynomial;
48: invokevirtual #65 // Method arb/RealPolynomial.pow:(Larb/Integer;ILarb/RealPolynomial;)Larb/RealPolynomial;

At index 48, you're trying to invoke the pow method on what should be an arb.RealPolynomial. However, if there's a discrepancy in what is actually on the stack (e.g., due to incorrect casting or assignment), this will trigger a verification error.

Possible Causes and Solutions

  1. Type Mismatch: Ensure that before this point, any object being pushed onto the stack is indeed of type arb.RealPolynomial. Check all preceding instructions that manipulate or prepare this object.

  2. Method Signature: Verify that the method signature for pow matches exactly between compile-time and runtime. This includes ensuring that all libraries and dependencies are consistent.

  3. Library Versions: As noted in some sources, such errors can occur if there are mismatches between compiled classes and runtime libraries 7. Make sure all dependencies are up-to-date and consistent across your build environment.

  4. Debugging Steps:

    • Use debugging tools or add logging to trace back where the incorrect type might be entering your method logic.
    • Recompile your code with verbose flags (e.g., -verbose:class) to check which classes are being loaded and from where.
    • Consider cleaning and rebuilding your project to ensure no stale bytecode is causing issues.

By addressing these areas, you should be able to resolve the verification error related to the invokevirtual instruction for the pow method.


Sources:

crowlogic added a commit that referenced this issue Nov 28, 2024
crowlogic added a commit that referenced this issue Nov 28, 2024
arb.functions.real.RealFunction
	at arb4j/arb.expressions.Expression.allocateIntermediateVariable(Expression.java:386)
	at arb4j/arb.expressions.nodes.VariableNode.generateReferenceToIndeterminantVariable(VariableNode.java:295)
	at arb4j/arb.expressions.nodes.VariableNode.generateReference(VariableNode.java:250)
	at arb4j/arb.expressions.nodes.VariableNode.generate(VariableNode.java:201)
	at arb4j/arb.expressions.nodes.binary.BinaryOperationNode.generate(BinaryOperationNode.java:197)
	at arb4j/arb.expressions.nodes.binary.BinaryOperationNode.generate(BinaryOperationNode.java:199)
	at arb4j/arb.expressions.nodes.binary.BinaryOperationNode.generate(BinaryOperationNode.java:199)
	at arb4j/arb.expressions.nodes.binary.BinaryOperationNode.generate(BinaryOperationNode.java:199)
	at arb4j/arb.expressions.nodes.binary.BinaryOperationNode.generate(BinaryOperationNode.java:197)
	at arb4j/arb.expressions.nodes.DerivativeNode.generate(DerivativeNode.java:139)
	at arb4j/arb.expressions.Expression.generateEvaluationMethod(Expression.java:942)
	at arb4j/arb.expressions.Expression.generate(Expression.java:789)
	at arb4j/arb.expressions.Expression.defineClass(Expression.java:572)
	at arb4j/arb.expressions.Expression.getInstance(Expression.java:1220)
	at arb4j/arb.expressions.Expression.instantiate(Expression.java:1369)
	at arb4j/arb.functions.Function.instantiate(Function.java:126)
	at arb4j/arb.functions.Function.express(Function.java:89)
	at arb4j/arb.functions.real.RealFunctional.express(RealFunctional.java:34)
	at arb4j/arb.functions.real.RealFunctional.express(RealFunctional.java:21)
	at arb4j/arb.expressions.ExpressionTest.testRealFunctionDerivative(ExpressionTest.java:149)
	at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
	at java.base/java.lang.reflect.Method.invoke(Method.java:580)
	at [email protected]/junit.framework.TestCase.runTest(TestCase.java:177)
	at [email protected]/junit.framework.TestCase.runBare(TestCase.java:142)
	at [email protected]/junit.framework.TestResult$1.protect(TestResult.java:122)
	at [email protected]/junit.framework.TestResult.runProtected(TestResult.java:142)
	at [email protected]/junit.framework.TestResult.run(TestResult.java:125)
	at [email protected]/junit.framework.TestCase.run(TestCase.java:130)
	at [email protected]/junit.framework.TestSuite.runTest(TestSuite.java:241)
	at [email protected]/junit.framework.TestSuite.run(TestSuite.java:236)
	at [email protected]/org.junit.internal.runners.JUnit38ClassRunner.run(JUnit38ClassRunner.java:90)
	at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:93)
	at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:40)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:530)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:758)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:453)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:211)

 #253
@crowlogic
Copy link
Owner Author

The differentiate method in the DivisionNode class appears to be implemented correctly according to the quotient rule for differentiation. The quotient rule states that the derivative of a division of two functions $$ u(x) $$ and $$ v(x) $$ is given by:

$$ \left(\frac{u}{v}\right)' = \frac{u'v - uv'}{v^2} $$

In the provided code, the differentiate method is implemented as follows:

  • lhs is calculated as the derivative of the left node (left.differentiate(variable)) multiplied by the right node (right). This corresponds to $$u'v$$.
  • rhs is calculated as the derivative of the right node (right.differentiate(variable)) multiplied by the left node (left). This corresponds to $$uv'$$.
  • divisor is calculated as the square of the right node (right.pow(2)), which corresponds to $$v^2$$.
  • The final result returns lhs.sub(rhs).div(divisor), which corresponds to $$\frac{u'v - uv'}{v^2}$$.

This implementation correctly applies the quotient rule for differentiation. Therefore, assuming that the methods differentiate, mul, sub, div, and pow are correctly implemented in their respective classes, this differentiation function should work as intended.

crowlogic added a commit that referenced this issue Nov 30, 2024
 author = {Hannu Niemi},
 title = {Stochastic processes as Fourier transforms of stochastic
measures},
 year = {1975},
 journal = {Annales Fennici Mathematici},
 number = {591}}

 #253
crowlogic added a commit that referenced this issue Nov 30, 2024
crowlogic added a commit that referenced this issue Nov 30, 2024
	at k-2*j(k,x)func.evaluate(Unknown Source)
	at arb4j/arb.functions.real.RealFunction.eval(RealFunction.java:222)
	at arb4j/arb.expressions.nodes.unary.SphericalBesselFunctionNodeOfTheFirstKindTest.testj0ViaRealFunctionalExpression(SphericalBesselFunctionNodeOfTheFirstKindTest.java:25)
	at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
	at java.base/java.lang.reflect.Method.invoke(Method.java:580)
	at [email protected]/junit.framework.TestCase.runTest(TestCase.java:177)
	at [email protected]/junit.framework.TestCase.runBare(TestCase.java:142)
	at [email protected]/junit.framework.TestResult$1.protect(TestResult.java:122)
	at [email protected]/junit.framework.TestResult.runProtected(TestResult.java:142)
	at [email protected]/junit.framework.TestResult.run(TestResult.java:125)
	at [email protected]/junit.framework.TestCase.run(TestCase.java:130)
	at [email protected]/junit.framework.TestSuite.runTest(TestSuite.java:241)
	at [email protected]/junit.framework.TestSuite.run(TestSuite.java:236)
	at org.eclipse.jdt.internal.junit.runner.junit3.JUnit3TestReference.run(JUnit3TestReference.java:128)
	at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:40)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:530)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:758)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:453)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:211)

#253

gr8
@crowlogic
Copy link
Owner Author

To implement the differentiate method for the FunctionNode class, we need to apply the chain rule, as mentioned earlier. Here's how you can implement this method based on the information provided in the FunctionNode class. This implementation considers both built-in and contextual functions, as well as the requirement that a function may be specialized or generically invoked:

Key Points for Implementation

  1. Differentiate the Argument: Apply the differentiation recursively on the argument node of the function.

  2. Differentiate the Function Itself: Determine the derivative of the function with respect to its argument. This may involve either looking up a predefined derivative or implementing the derivative calculation directly.

  3. Multiply the Results: Combine the results using the chain rule: $$ f'(g(x)) \cdot g'(x) $$.

Implementing the Differentiate Method

Here's an example implementation to guide you:

@Override
public Node<D, R, F> differentiate(VariableNode<D, R, F> variable) {
    // Step 1: Differentiate the argument (g'(x)).
    Node<D, R, F> argDerivative = arg.differentiate(variable);

    // Step 2: Differentiate the function (f'(g(x))).
    Node<D, R, F> functionDerivative = differentiateFunction();

    // Step 3: Apply the chain rule: f'(g(x)) * g'(x).
    return new MultiplicationNode<>(expression, functionDerivative, argDerivative);
}

/**
 * Returns the node representing the derivative of the function.
 * This will vary based on whether the function is built-in or contextual.
 */
private Node<D, R, F> differentiateFunction() {
    // Check if the function is built-in or contextual.
    if (isBuiltin()) {
        return differentiateBuiltinFunction();
    } else if (contextual) {
        return differentiateContextualFunction();
    } else {
        throw new UnsupportedOperationException("Cannot differentiate function: " + functionName);
    }
}

/**
 * Handles differentiation for built-in functions.
 */
private Node<D, R, F> differentiateBuiltinFunction() {
    switch (functionName) {
        case "sin":
            return new FunctionNode<>("cos", arg, expression); // derivative of sin is cos
        case "cos":
            return new NegationNode<>(expression, new FunctionNode<>("sin", arg, expression)); // derivative of cos is -sin
        case "exp":
            return this; // derivative of exp is exp
        // Add other built-in function derivatives
        default:
            throw new UnsupportedOperationException("Derivative not implemented for function: " + functionName);
    }
}

/**
 * Handles differentiation for contextual functions.
 */
private Node<D, R, F> differentiateContextualFunction() {
    // Add logic for differentiating contextual functions, potentially involving more advanced logic
    // depending on how contextual functions are defined and used in your framework.

    // As an example, you might retrieve a derivative function mapping if available:
    if (mapping != null && mapping.derivativeMapping != null) {
        return new FunctionNode<>(mapping.derivativeFunctionName, arg, expression);
    }
    // Alternatively, handle differentiation based on known properties of the function
    throw new UnsupportedOperationException("Contextual function differentiation not implemented: " + functionName);
}

Considerations

  • Built-in Function Differentiation: For built-in functions, you can either hard-code the derivatives as shown or look them up if your framework supports such a table.

  • Contextual Functions: For contextual functions, you may need to obtain or define their derivatives dynamically, depending on how they are registered and invoked within your framework.

  • Error Handling: Handle functions that do not have derivatives or when the differentiation is not supported by throwing exceptions or providing meaningful feedback.

This implementation assumes that you have proper classes and methods like MultiplicationNode and NegationNode, and that your framework supports distinguishing between built-in and contextual functions. Adjust the logic as needed to fit the design and capabilities of your symbolic computation system.

Citations:
[1] https://ppl-ai-file-upload.s3.amazonaws.com/web/direct-files/37918610/8a0ff5f4-5a47-4a4f-b6f2-b871c663c989/paste.txt
[2] https://ppl-ai-file-upload.s3.amazonaws.com/web/direct-files/37918610/f4f9b1e9-fc44-4caa-8883-1fc0db30d2c5/paste-2.txt
[3] https://ppl-ai-file-upload.s3.amazonaws.com/web/direct-files/37918610/71dbc71c-3e90-4971-b110-f586f228daeb/paste-3.txt

@crowlogic
Copy link
Owner Author

crowlogic commented Dec 2, 2024

For an n-ary product (product of n functions), the derivative follows this formula:

$$\frac{d}{dx}\left[\prod_{i=1}^{k}f_{i}(x)\right]=\sum_{i=1}^{k}\left(\left(\frac{d}{dx}f_{i}(x)\right)\prod_{j=1,j\neq i}^{k}f_{j}(x)\right) $$

Example for Three Functions

For three functions u, v, and w, the derivative is:

$$\frac{d(uvw)}{dx}=\frac{du}{dx}vw+u\frac{dv}{dx}w+uv\frac{dw}{dx} $$

Pattern

Each term in the sum is formed by:

  1. Taking the derivative of one function
  2. Multiplying it by all other functions unchanged
  3. Adding all possible combinations

The rule extends to any number of functions following this same pattern.

Citations:
[1] https://www.mathcentre.ac.uk/resources/uploaded/mc-ty-product-2009-1.pdf
[2] https://en.wikipedia.org/wiki/Product_rule
[3] https://calcworkshop.com/derivatives/product-rule/
[4] https://www.cuemath.com/calculus/product-rule/
[5] https://byjus.com/maths/product-rule/

The derivative of a sum follows the linearity property of derivatives - you can differentiate each term separately and then sum the results:

$$\frac{d}{dx}\sum_{i=1}^{n}f_i(x) = \sum_{i=1}^{n}\frac{d}{dx}f_i(x) $$

Pattern

The derivative operator can move inside the summation because:

  1. Differentiation is a linear operation
  2. Each term is differentiated independently
  3. The sum of derivatives equals the derivative of the sum

For example, if you have:

$$\frac{d}{dx}(f_1(x) + f_2(x) + ... + f_n(x)) = \frac{d}{dx}f_1(x) + \frac{d}{dx}f_2(x) + .. + \frac{d}{dx}f_n(x)$$

This is much simpler than the product rule because addition is a linear operation.

Citations:
[1] https://www.wolframalpha.com/input?input=d%2Fdx%28%E2%88%91_%7Bi%3D1%7D%5E%7Bn%7D+f%28i%29%29

@crowlogic
Copy link
Owner Author

For n-ary products, there is indeed a closed form for integration. Using the multinomial theorem and integration by parts, we can express it as:

$$ \int \prod_{i=1}^{n} f_i(x)dx = \sum_{k=1}^n \left((-1)^{k+1} \sum_{i_1 + ... + i_n = k} \frac{f_1^{(i_1)}...f_n^{(i_n)}}{i_1!...i_n!} \int x^k dx\right) $$

Where:

  • $f_i^{(j)}$ represents the jth derivative of function i
  • The inner sum is over all possible combinations where the indices sum to k
  • The formula assumes all functions are infinitely differentiable

This is significantly more complex than differentiation, but it does provide a systematic way to compute the integral of a product of n functions.

Citations:
[1] https://www.youtube.com/watch?v=zObGec7JM3E
[2] https://en.wikipedia.org/wiki/Solution_in_closed_form

crowlogic added a commit that referenced this issue Dec 2, 2024
  {
    var x = RealFunction.parse("∂ln(x)/∂x");
    assertEquals("1/x", x.rootNode.toString());
  } #253
@crowlogic
Copy link
Owner Author

  public void testArcSinDerivative()
  {
    var f  = RealFunction.parse("∂arcsin(x)/∂x");
    var df = RealFunction.parse("1/√(1-x^2)");
    assertEquals(df.rootNode.toString(), f.rootNode.toString());
  }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement things that are not bugs
Projects
Development

No branches or pull requests

1 participant