/** * Tries to fix a structural problem leading to an evaluation error, e.g. x(x+1) is interpreted as * xcoord(x+1). This can be fixed by changing the structure to x*(x+1) for example. */ private void fixStructure() { // get function variables for x, y, z FunctionVariable xVar = null, yVar = null, zVar = null; for (FunctionVariable fVar : fVars) { if ("x".equals(fVar.toString())) xVar = fVar; else if ("y".equals(fVar.toString())) yVar = fVar; else if ("z".equals(fVar.toString())) zVar = fVar; } // try to replace x(x+1) by x*(x+1) expression.replaceXYZnodes(xVar, yVar, zVar); }
/** * Call this function to resolve variables and init the function. May throw MyError * (InvalidFunction). */ public void initFunction() { // replace function variables in tree for (int i = 0; i < fVars.length; i++) { FunctionVariable fVar = fVars[i]; // look for Variable objects with name of function variable and // replace them int replacements = expression.replaceVariables(fVar.getSetVarString(), fVar); isConstantFunction = isConstantFunction && replacements == 0; if (replacements == 0) { // x, y got polynomials while parsing replacements = expression.replacePolynomials(fVar); isConstantFunction = isConstantFunction && replacements == 0; } } // replace variable names by objects expression.resolveVariables(); // the idea here was to allow something like: Derivative[f] + 3x // but wrapping the GeoFunction objects as ExpressionNodes of type // FUNCTION // leads to Derivative[f](x) + 3x // expression.wrapGeoFunctionsAsExpressionNode(); // replace all polynomials in expression (they are all equal to "1x" if // we got this far) // by an instance of MyDouble // simplify constant parts in expression expression.simplifyConstantIntegers(); // evaluate expression to find out about the type of function ExpressionValue ev; try { ev = expression.evaluate(); } catch (MyError err) { // Evaluation failed: DESPERATE MODE try { // try to fix structure of expression and then try evaluation again fixStructure(); ev = expression.evaluate(); } catch (Throwable th) { // throw original error when desperate mode failed throw err; } } // initialize type as boolean or numeric function initType(ev); }
// Map f to coefficients and arg public Algebraic map(LambdaAlgebraic f) throws JasymcaException { Algebraic x = var instanceof SimpleVariable ? new Polynomial(var) : FunctionVariable.create( ((FunctionVariable) var).fname, f.f_exakt(((FunctionVariable) var).arg)); Algebraic r = Zahl.ZERO; for (int i = coef.length - 1; i > 0; i--) { r = r.add(f.f_exakt(coef[i])).mult(x); } if (coef.length > 0) r = r.add(f.f_exakt(coef[0])); return r; }
// return a vektor of all different solutions public Vektor solvepoly() throws JasymcaException { Vector s = new Vector(); switch (degree()) { case 0: break; case 1: s.addElement(Zahl.MINUS.mult(coef[0].div(coef[1]))); break; case 2: Algebraic p = coef[1].div(coef[2]); Algebraic q = coef[0].div(coef[2]); p = Zahl.MINUS.mult(p).div(Zahl.TWO); q = p.mult(p).sub(q); if (q.equals(Zahl.ZERO)) { s.addElement(p); break; } q = FunctionVariable.create("sqrt", q); s.addElement(p.add(q)); s.addElement(p.sub(q)); break; /* case 3: Algebraic a = r.coef[2]; Algebraic b = r.coef[1]; Algebraic c = r.coef[0]; Zahl drei = new Exakt(3.0); // p=(3b-a^2)/3 p = drei.mult(b).sub(a.mult(a)).div(drei); // q = c + 2a^3/27 -ab/3 q = c.add(Zahl.TWO.mult(a.pow_n(3)).div(new Exakt(27.))). sub(a.mult(b).div(drei)); // D^2 = (p/3)^3 + (q/2)^2 Algebraic D = new Polynomial(new FunctionVariable("sqrt", p.div(drei).pow_n(3).add(q.div(Zahl.TWO).pow_n(2)))); Algebraic u = new Polynomial(new FunctionVariable("csqrt", Zahl.MINUS.mult(q).div(Zahl.TWO).add(D))); Algebraic v = new Polynomial(new FunctionVariable("csqrt", Zahl.MINUS.mult(q).div(Zahl.TWO).sub(D))); Algebraic r0 = Zahl.MINUS.mult(a).div(drei).add(u).add(v); Algebraic r1 = Zahl.MINUS.mult(a).div(drei).sub(u.add(v).div(Zahl.TWO)); Algebraic w = new Unexakt(Math.sqrt(3.)).mult(u.sub(v)). div(Zahl.TWO).mult(Zahl.IONE); Algebraic r2 = r1.sub(w); r1 = r1.add(w); s.addElement(r0); s.addElement(r1); s.addElement(r2); break;*/ default: // Maybe biquadratic/bicubic etc // Calculate gcd of exponents for nonzero coefficients int gcd = -1; for (int i = 1; i < coef.length; i++) { if (!coef[i].equals(Zahl.ZERO)) { if (gcd < 0) gcd = i; else gcd = gcd(i, gcd); } } int deg = degree() / gcd; if (deg < 3) { // Solveable Algebraic cn[] = new Algebraic[deg + 1]; for (int i = 0; i < cn.length; i++) cn[i] = coef[i * gcd]; Polynomial pr = new Polynomial(var, cn); Vektor sn = pr.solvepoly(); if (gcd == 2) { // sol = +/-sqrt(sn) cn = new Algebraic[sn.coord.length * 2]; for (int i = 0; i < sn.coord.length; i++) { cn[2 * i] = FunctionVariable.create("sqrt", sn.coord[i]); cn[2 * i + 1] = cn[2 * i].mult(Zahl.MINUS); } } else { // sol = sn^(1/gcd); cn = new Algebraic[sn.coord.length]; Zahl wx = new Unexakt(1. / gcd); for (int i = 0; i < sn.coord.length; i++) { Algebraic exp = FunctionVariable.create("log", sn.coord[i]); cn[i] = FunctionVariable.create("exp", exp.mult(wx)); } } return new Vektor(cn); } throw new JasymcaException("Can't solve expression " + this); } return Vektor.create(s); }
public Algebraic integrate(Variable var) throws JasymcaException { Algebraic in = Zahl.ZERO; for (int i = 1; i < coef.length; i++) { if (!coef[i].depends(var)) if (var.equals(this.var)) // c*x^n -->1/(n+1)*x^(n+1) in = in.add(coef[i].mult(new Polynomial(var).pow_n(i + 1).div(new Unexakt(i + 1)))); else if (this.var instanceof FunctionVariable && ((FunctionVariable) this.var).arg.depends(var)) // f(x) if (i == 1) in = in.add(((FunctionVariable) this.var).integrate(var).mult(coef[1])); // (f(x))^2, (f(x))^3 etc // give up here but try again after exponential normalization else throw new JasymcaException("Integral not supported."); else // Constant: c --> c*x in = in.add(coef[i].mult(new Polynomial(var).mult(new Polynomial(this.var).pow_n(i)))); else if (var.equals(this.var)) // c(x)*x^n , should not happen if this is canonical throw new JasymcaException("Integral not supported."); else if (this.var instanceof FunctionVariable && ((FunctionVariable) this.var).arg.depends(var)) { if (i == 1 && coef[i] instanceof Polynomial && ((Polynomial) coef[i]).var.equals(var)) { // poly(x)*f(x) // First attempt: try to isolate inner derivative // poly(x)*f(w(x)) --> check poly(x)/w' == q : const? // yes --> Int f dw * q p("Trying to isolate inner derivative " + this); try { FunctionVariable f = (FunctionVariable) this.var; Algebraic w = f.arg; // Innere Funktion Algebraic q = coef[i].div(w.deriv(var)); if (q.deriv(var).equals(Zahl.ZERO)) { // q - constant SimpleVariable v = new SimpleVariable("v"); Algebraic p = FunctionVariable.create(f.fname, new Polynomial(v)); Algebraic r = p.integrate(v).value(v, w).mult(q); in = in.add(r); continue; } } catch (JasymcaException je) { // Didn't work, try more methods } p("Failed."); // Some partial integrations follow. To // avoid endless loops, we flag this section // Coefficients of coef[i] must not depend on var for (int k = 0; k < ((Polynomial) coef[i]).coef.length; k++) if (((Polynomial) coef[i]).coef[k].depends(var)) throw new JasymcaException("Function not supported by this method"); if (loopPartial) { loopPartial = false; p("Partial Integration Loop detected."); throw new JasymcaException("Partial Integration Loop: " + this); } // First attempt: x^n*f(x) , n-times diff! // works for exp,sin,cos p("Trying partial integration: x^n*f(x) , n-times diff " + this); try { loopPartial = true; Algebraic p = coef[i]; Algebraic f = ((FunctionVariable) this.var).integrate(var); Algebraic r = f.mult(p); while (!(p = p.deriv(var)).equals(Zahl.ZERO)) { f = f.integrate(var).mult(Zahl.MINUS); r = r.add(f.mult(p)); } loopPartial = false; in = in.add(r); continue; } catch (JasymcaException je) { loopPartial = false; } p("Failed."); // Second attempt: x^n*f(x) , 1-times int! // works for log, atan p("Trying partial integration: x^n*f(x) , 1-times int " + this); try { loopPartial = true; Algebraic p = coef[i].integrate(var); Algebraic f = new Polynomial((FunctionVariable) this.var); Algebraic r = p.mult(f).sub(p.mult(f.deriv(var)).integrate(var)); loopPartial = false; in = in.add(r); continue; } catch (JasymcaException je3) { loopPartial = false; } p("Failed"); // Add more attempts.... throw new JasymcaException("Function not supported by this method"); } else throw new JasymcaException("Integral not supported."); } else // mainvar independend of var, treat as constant and integrate coef in = in.add(coef[i].integrate(var).mult(new Polynomial(this.var).pow_n(i))); } if (coef.length > 0) in = in.add(coef[0].integrate(var)); return in; }