crowlogic / arb4j

arb4j is a Java API for the arbitrary precision ball arithmetic library found at http://arblib.org
Other
1 stars 0 forks source link

expr compiler: variable substitution #382

Closed crowlogic closed 4 months ago

crowlogic commented 5 months ago

  public void testSubstitution()
  {
    var expr = RealFunction.parse("2*x^2");
    var subs = RealFunction.parse("1/2-x/2");
    out.println("before: " + expr.syntaxTree());
    expr.substitute("x", subs);
    out.println("after: " + expr.syntaxTree());
    var f = expr.instantiate();
  }
crowlogic commented 5 months ago
java.lang.NoClassDefFoundError: 1Over2MinusxOver2
    at java.base/java.lang.Class.getDeclaredConstructors0(Native Method)
    at java.base/java.lang.Class.privateGetDeclaredConstructors(Class.java:3549)
    at java.base/java.lang.Class.getConstructor0(Class.java:3754)
    at java.base/java.lang.Class.getDeclaredConstructor(Class.java:2930)
    at arb4j/arb.expressions.Expression.getInstance(Expression.java:583)
    at arb4j/arb.expressions.Expression.instantiate(Expression.java:1286)
    at arb4j/arb.expressions.ExpressionTest.testSubstitution(ExpressionTest.java:34)
crowlogic commented 4 months ago

java.lang.NoClassDefFoundError: 1Over2MinuszOver2 at java.base/java.lang.Class.getDeclaredConstructors0(Native Method) at java.base/java.lang.Class.privateGetDeclaredConstructors(Class.java:3549) at java.base/java.lang.Class.getConstructor0(Class.java:3754) at java.base/java.lang.Class.getDeclaredConstructor(Class.java:2930) at arb4j/arb.expressions.Expression.getInstance(Expression.java:588) at arb4j/arb.expressions.Expression.instantiate(Expression.java:1285) at arb4j/arb.expressions.ExpressionTest.testSubstitution(ExpressionTest.java:34) at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) at java.base/java.lang.reflect.Method.invoke(Method.java:580) at junit@4.13.2/junit.framework.TestCase.runTest(TestCase.java:177) at junit@4.13.2/junit.framework.TestCase.runBare(TestCase.java:142) at junit@4.13.2/junit.framework.TestResult$1.protect(TestResult.java:122) at junit@4.13.2/junit.framework.TestResult.runProtected(TestResult.java:142) at junit@4.13.2/junit.framework.TestResult.run(TestResult.java:125) at junit@4.13.2/junit.framework.TestCase.run(TestCase.java:130) at junit@4.13.2/junit.framework.TestSuite.runTest(TestSuite.java:241) at junit@4.13.2/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:529) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:757) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:452) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:210) Caused by: java.lang.ClassNotFoundException: 1Over2MinuszOver2 missing , was {2Times1Over2MinuszOver2ToThePowerOf2=class 2Times1Over2MinuszOver2ToThePowerOf2} at arb4j/arb.expressions.CompiledExpressionClassLoader.findClass(CompiledExpressionClassLoader.java:34) at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:593) at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:526) ... 23 more

crowlogic commented 4 months ago

java.lang.NoSuchFieldError: Class 2Times1Over2MinuszOver2ToThePowerOf2 does not have member field 'arb.Integer cℤ2' at 2Times1Over2MinuszOver2ToThePowerOf2.evaluate(Unknown Source) at arb4j/arb.expressions.ExpressionTest.testSubstitution(ExpressionTest.java:40) at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) at java.base/java.lang.reflect.Method.invoke(Method.java:580) at junit@4.13.2/junit.framework.TestCase.runTest(TestCase.java:177) at junit@4.13.2/junit.framework.TestCase.runBare(TestCase.java:142) at junit@4.13.2/junit.framework.TestResult$1.protect(TestResult.java:122) at junit@4.13.2/junit.framework.TestResult.runProtected(TestResult.java:142) at junit@4.13.2/junit.framework.TestResult.run(TestResult.java:125) at junit@4.13.2/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:529) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:757) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:452) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:210)

crowlogic commented 4 months ago
resolveReference(reference=x)
Declaring x as the input node to x➔2*x^2
resolveReference(reference=z)

Declaring z as the input node to z➔1/2-z/2
BEFORE: x➔2*(x^2)
Expression.substitute z➔(1/2)-(z/2) for x into x➔2*(x^2)

Substituting (1/2)-(z/2) for x in x^2 of x➔2*(x^2)
resolveReference(reference=z)
Declaring z as the input node to z➔(1/2)-(z/2)
Changing input node from x to z
after: z➔2*((1/2)-(z/2))^2
Expression.compile() className=_2timesopenopen1over2closeminusopenzover2closeclosetoThePowerOf2
Generating 2*((1/2)-(z/2))^2

BinaryOperation.generate( this=2*((1/2)-(z/2))^2,
                          left=2,
                          left.type=class arb.Integer,
                          operation=mul,
                          right=((1/2)-(z/2))^2,
                          right.type=class arb.Real,
                          resultType=class arb.Real )

loadFieldOntoStack cℤ1 of type Larb/Integer;
BinaryOperation.generate( this=((1/2)-(z/2))^2,
                          left=(1/2)-(z/2),
                          left.type=class arb.Real,
                          operation=pow,
                          right=2,
                          right.type=class arb.Integer,
                          resultType=class arb.Real )

BinaryOperation.generate( this=(1/2)-(z/2),
                          left=1/2,
                          left.type=class arb.Real,
                          operation=sub,
                          right=z/2,
                          right.type=class arb.Real,
                          resultType=class arb.Real )

BinaryOperation.generate( this=1/2,
                          left=1,
                          left.type=class arb.Integer,
                          operation=div,
                          right=2,
                          right.type=class arb.Integer,
                          resultType=class arb.Real )

loadFieldOntoStack cℤ1 of type Larb/Integer;
loadFieldOntoStack cℤ1 of type Larb/Integer;
loadFieldOntoStack ℝ1 of type Larb/Real;
BinaryOperation.generate( this=z/2,
                          left=z,
                          left.type=class arb.Real,
                          operation=div,
                          right=2,
                          right.type=class arb.Integer,
                          resultType=class arb.Real )

Variable.generate( this=z, resultType=class arb.Real)

loadFieldOntoStack cℤ1 of type Larb/Integer;
loadFieldOntoStack ℝ2 of type Larb/Real;
loadFieldOntoStack ℝ3 of type Larb/Real;
loadFieldOntoStack cℤ1 of type Larb/Integer;
loadFieldOntoStack ℝ4 of type Larb/Real;
Expression.defineClass(className=_2timesopenopen1over2closeminusopenzover2closeclosetoThePowerOf2, instructions=[B@5b0abc94, context=arb.expressions.Context@75c072cb)
Compiler.loadFunctionClass _2timesopenopen1over2closeminusopenzover2closeclosetoThePowerOf2
defineClass( className=_2timesopenopen1over2closeminusopenzover2closeclosetoThePowerOf2, ... )
crowlogic commented 4 months ago

the cloning is boning the variable names

arb.exceptions.ExpressionCompilerException: a LiteralConstant named cℤ1 already exists
    at arb4j/arb.expressions.nodes.LiteralConstant.<init>(LiteralConstant.java:124)
    at arb4j/arb.expressions.nodes.LiteralConstant.clone(LiteralConstant.java:301)
    at arb4j/arb.expressions.nodes.binary.Division.clone(Division.java:56)
    at arb4j/arb.expressions.nodes.binary.Subtraction.clone(Subtraction.java:65)
    at arb4j/arb.expressions.nodes.binary.BinaryOperation.substitute(BinaryOperation.java:80)
    at arb4j/arb.expressions.nodes.binary.BinaryOperation.substitute(BinaryOperation.java:47)
    at arb4j/arb.expressions.nodes.binary.BinaryOperation.substitute(BinaryOperation.java:91)
    at arb4j/arb.expressions.nodes.binary.BinaryOperation.substitute(BinaryOperation.java:48)
    at arb4j/arb.expressions.Expression.substitute(Expression.java:1756)
    at arb4j/arb.expressions.ExpressionTest.testSubstitution(ExpressionTest.java:34)
    at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
    at java.base/java.lang.reflect.Method.invoke(Method.java:580)
    at junit@4.13.2/junit.framework.TestCase.runTest(TestCase.java:177)
    at junit@4.13.2/junit.framework.TestCase.runBare(TestCase.java:142)
    at junit@4.13.2/junit.framework.TestResult$1.protect(TestResult.java:122)
    at junit@4.13.2/junit.framework.TestResult.runProtected(TestResult.java:142)
    at junit@4.13.2/junit.framework.TestResult.run(TestResult.java:125)
    at junit@4.13.2/junit.framework.TestCase.run(TestCase.java:130)
    at junit@4.13.2/junit.framework.TestSuite.runTest(TestSuite.java:241)
    at junit@4.13.2/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:529)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:757)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:452)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:210)
crowlogic commented 4 months ago

Done. What needs to be done is that the call to subs.rootNode.accept should be done by expr.substitute so its just one call from an API perspective but that can be done easily when its apparent what the optimal way to do it is

  public void testSubstitution() throws ReflectiveOperationException
  {
    var expr = RealFunction.parse("2*x^2");
    var subs = RealFunction.parse("1/2-z/2");

    subs.rootNode.accept(node -> node.expression = expr);

    out.println("BEFORE: " + expr);

    expr.substitute("x", subs);

    out.println("after: " + expr);
    assertTrue(expr.instructions == null);

    var f = expr.compile();
    var g = f.instantiate();
    System.out.println("testSubstitution: instantiated " + g);
    var x = new Real("8.08",
                     256);
    assertEquals(25.0632, g.evaluate(x, 0, 256, x).doubleValue());
  }