/// <summary> /// Check for inequality. /// </summary> /// <param name="b">The other operand.</param> /// <returns> /// A value representing true if not equal. /// </returns> public override Derivatives <Expression> NotEqual(Derivatives <Expression> b) { var result = new ExpressionTreeDerivatives(); result[0] = Expression.Condition(Expression.NotEqual(this[0], b[0]), One, Zero); return(result); }
/// <summary> /// Subtract derivatives. /// </summary> /// <param name="b">The other operand.</param> /// <returns> /// The difference. /// </returns> public override Derivatives <Expression> Subtract(Derivatives <Expression> b) { var size = Math.Max(Count, b.Count); var result = new ExpressionTreeDerivatives(size); for (var i = 0; i < size; i++) { if (this[i] == null) { if (b[i] == null) { result[i] = null; } else { result[i] = Expression.Negate(b[i]); } } else { if (b[i] == null) { result[i] = this[i]; } else { result[i] = Expression.Subtract(this[i], b[i]); } } } return(result); }
/// <summary> /// Multiply derivatives. /// </summary> /// <param name="b">The other operand.</param> /// <returns> /// The multiplied result. /// </returns> public override Derivatives <Func <double> > Multiply(Derivatives <Func <double> > b) { var size = Math.Max(Count, b.Count); var result = new DoubleDerivatives(size); var a0 = this[0]; var b0 = b[0]; result[0] = () => a0() * b0(); for (var i = 1; i < size; i++) { var arg1 = this[i]; var arg2 = b[i]; if (arg1 != null && arg2 != null) { result[i] = () => b0() * arg1() + arg2() * a0(); } else if (arg1 != null) { result[i] = () => arg1() * b0(); } else if (arg2 != null) { result[i] = () => a0() * arg2(); } } return(result); }
/// <summary> /// Nots the equal. /// </summary> /// <param name="other">The other.</param> /// <returns></returns> public override Derivatives <Func <double> > NotEqual(Derivatives <Func <double> > other) { var result = new DoubleDerivatives(); var arg1 = this[0]; var arg2 = other[0]; result[0] = () => arg1().Equals(arg2()) ? 0 : 1; return(result); }
/// <summary> /// And the derivatives. /// </summary> /// <param name="b">The other operand.</param> /// <returns> /// The derivatives. /// </returns> public override Derivatives <Func <double> > And(Derivatives <Func <double> > b) { var result = new DoubleDerivatives(); var arg1 = this[0]; var arg2 = b[0]; result[0] = () => arg1().Equals(0.0) || arg2().Equals(0.0) ? 0 : 1; return(result); }
/// <summary> /// Modulo operation on derivatives. /// </summary> /// <param name="b">The other operand.</param> /// <returns> /// The remainder of the division. /// </returns> public override Derivatives <Func <double> > Modulo(Derivatives <Func <double> > b) { var result = new DoubleDerivatives(); var a0 = this[0]; var b0 = b[0]; result[0] = () => a0() % b0(); return(result); }
/// <summary> /// Check greater than. /// </summary> /// <param name="b">The other operand.</param> /// <returns> /// A value representing true if this is greater. /// </returns> public override Derivatives <Func <double> > GreaterThan(Derivatives <Func <double> > b) { var result = new DoubleDerivatives(); var a0 = this[0]; var b0 = b[0]; result[0] = () => a0() > b0() ? 1 : 0; return(result); }
/// <summary> /// Check less or equal. /// </summary> /// <param name="b">The other operand.</param> /// <returns> /// A value representing true if this is less or equal. /// </returns> public override Derivatives <Func <double> > LessOrEqual(Derivatives <Func <double> > b) { var result = new DoubleDerivatives(); var a0 = this[0]; var b0 = b[0]; result[0] = () => a0() <= b0() ? 1 : 0; return(result); }
/// <summary> /// And the derivatives. /// </summary> /// <param name="b">The other operand.</param> /// <returns> /// The derivatives. /// </returns> public override Derivatives <Expression> And(Derivatives <Expression> b) { var result = new ExpressionTreeDerivatives(); result[0] = Expression.Condition( Expression.Or( Expression.Equal(this[0], Zero), Expression.Equal(b[0], Zero)), Zero, One); return(result); }
/// <summary> /// Divide derivatives. /// </summary> /// <param name="b">The other operand.</param> /// <returns> /// The divided result. /// </returns> public override Derivatives <Expression> Divide(Derivatives <Expression> b) { var size = Math.Max(Count, b.Count); var result = new ExpressionTreeDerivatives(size); Expression a0 = this[0], b0 = b[0]; if (a0 == null) { return(null); } if (b0 == null) { throw new DivideByZeroException(); } result[0] = Expression.Call(Division, a0, b0); for (var i = 1; i < size; i++) { if (this[i] == null) { if (b[i] == null) { result[i] = null; } else { // (a/gx)' = -a/gx^2*g'x result[i] = Expression.Call(Division, Expression.Negate(Expression.Multiply(a0, b[i])), Expression.Call(SquareInfo, b0)); } } else { if (b[i] == null) { // (fx/b)' = f'x/b result[i] = Expression.Call(Division, this[i], b0); } else { // (fx/gx)' = (f'x*gx-fx*g'x)/gx^2 result[i] = Expression.Call(Division, Expression.Subtract( Expression.Multiply(this[i], b0), Expression.Multiply(a0, b[i])), Expression.Call(SquareInfo, b0)); } } } return(result); }
/// <summary> /// Check greater or equal. /// </summary> /// <param name="b">The operand.</param> /// <returns> /// A value representing true if this is greater or equal. /// </returns> public override Derivatives <Expression> GreaterOrEqual(Derivatives <Expression> b) { var result = new ExpressionTreeDerivatives(); Expression a0 = this[0], b0 = b[0]; if (a0 == null && b0 == null) { return(result); } a0 = a0 ?? Zero; b0 = b0 ?? Zero; result[0] = Expression.Condition(Expression.GreaterThanOrEqual(a0, b0), One, Zero); return(result); }
/// <summary> /// Conditional derivatives. /// </summary> /// <param name="iftrue">Argument if true.</param> /// <param name="iffalse">Argument if false.</param> /// <returns> /// The derivatives. /// </returns> public override Derivatives <Func <double> > IfThenElse(Derivatives <Func <double> > iftrue, Derivatives <Func <double> > iffalse) { var size = Math.Max(iftrue.Count, iffalse.Count); var result = new DoubleDerivatives(size); var arg = this[0]; for (var i = 0; i < size; i++) { var arg2 = iftrue[i] ?? (() => 0.0); var arg3 = iffalse[i] ?? (() => 0.0); result[i] = () => arg().Equals(0.0) ? arg3() : arg2(); } return(result); }
/// <summary> /// Check equality. /// </summary> /// <param name="obj">The other object.</param> /// <returns></returns> public bool Equals(Derivatives <T> obj) { if (obj.Count != Count) { return(false); } for (var i = 0; i < Count; i++) { if (!this[i].Equals(obj[i])) { return(false); } } return(true); }
/// <summary> /// Modulo operation on derivatives. /// </summary> /// <param name="b">The other operand.</param> /// <returns> /// The remainder of the division. /// </returns> public override Derivatives <Expression> Modulo(Derivatives <Expression> b) { var result = new ExpressionTreeDerivatives(); if (this[0] == null) { return(result); } if (b[0] == null) { throw new Exception("Modulo by 0"); } result[0] = Expression.Modulo(this[0], b[0]); return(result); }
/// <summary> /// Raises the derivatives to a power. /// </summary> /// <param name="exponent">The exponent.</param> /// <returns> /// The raised power. /// </returns> public override Derivatives <Expression> Pow(Derivatives <Expression> exponent) { var size = Math.Max(Count, exponent.Count); var result = new ExpressionTreeDerivatives(size); Expression a0 = this[0], b0 = exponent[0]; if (a0 == null && b0 == null) { // This doesn't make much sense (0^0 is invalid) but Math.Pow does it like that so we will too result[0] = One; return(result); } if (a0 == null) { a0 = Zero; } if (b0 == null) { // (fx)^0 = 1 result[0] = One; return(result); } result[0] = Expression.Call(PowInfo, a0, b0); if (a0 != One && a0 != Zero) { a0 = Expression.Call(AbsInfo, a0); } for (var i = 1; i < size; i++) { // (fx^b)' = b * fx^(b-1) * f'x if (this[i] != null) { result[i] = Expression.Multiply(b0, Expression.Multiply(this[i], Expression.Call(PowInfo, a0, Expression.Subtract(b0, One)))); } // (fx^gx)' = (e^(gx*ln(fx)))' // = fx^(gx-1)*f'x + fx^gx*ln(fx)*g'x if (exponent[i] != null) { var contribution = Expression.Multiply(Expression.Call(PowInfo, a0, b0), Expression.Multiply(Expression.Call(LogInfo, a0), exponent[i])); result[i] = result[i] == null ? contribution : Expression.Add(result[i], contribution); } } return(result); }
/// <summary> /// Raises the derivatives to a power. /// </summary> /// <param name="exponent">The exponent.</param> /// <returns>The raised power.</returns> public override Derivatives <Func <double> > Pow(Derivatives <Func <double> > exponent) { var size = Math.Max(Count, exponent.Count); var result = new DoubleDerivatives(size); var a0 = this[0]; var b0 = exponent[0]; result[0] = () => SafePow(a0(), b0()); for (var i = 1; i < size; i++) { if (this[i] != null && exponent[i] != null) { // (fx^gx)' = (e^(gx*ln(fx)))' // = gx*fx^(gx-1)*f'x + fx^gx*ln(fx)*g'x var ai = this[i]; var bi = exponent[i]; result[i] = () => { var tmpa0 = Math.Abs(a0()); var tmpb0 = b0(); return(SafePow(tmpa0, tmpb0 - 1) * tmpb0 * ai() + SafePow(tmpa0, tmpb0) * Math.Log(tmpa0) * bi()); }; } else if (this[i] != null) { // (fx^b)' = b * fx^(b-1) * f'x var ai = this[i]; result[i] = () => { var tmpa0 = Math.Abs(a0()); var tmpb0 = b0(); return(SafePow(tmpa0, tmpb0 - 1) * tmpb0 * ai()); }; } else if (exponent[i] != null) { // (a^gx)' = a^gx * ln(a) * g'x var bi = exponent[i]; result[i] = () => { var tmpa0 = Math.Abs(a0()); var tmpb0 = b0(); return(SafePow(tmpa0, tmpb0) * Math.Log(tmpa0) * bi()); }; } } return(result); }
/// <summary> /// Multiply derivatives. /// </summary> /// <param name="b">The other operand.</param> /// <returns> /// The multiplied result. /// </returns> public override Derivatives <Expression> Multiply(Derivatives <Expression> b) { var size = Math.Max(Count, b.Count); var result = new ExpressionTreeDerivatives(size); Expression a0 = this[0], b0 = b[0]; if (a0 == null || b0 == null) { return(result); // x*0 = 0 and so is all its derivatives } else { result[0] = Expression.Multiply(a0, b0); } for (var i = 1; i < size; i++) { if (this[i] == null) { if (b[i] == null) { result[i] = null; } else { // (a*gx)' = a*g'x result[i] = Expression.Multiply(a0, b[i]); } } else { if (b[i] == null) { // (fx*b)' = f'x*b result[i] = Expression.Multiply(this[i], b0); } else { // (fx*gx)' = fx*g'x + f'x*gx result[i] = Expression.Add( Expression.Multiply(a0, b[i]), Expression.Multiply(this[i], b0)); } } } return(result); }
/// <summary> /// Conditional derivatives. /// </summary> /// <param name="iftrue">Argument if true.</param> /// <param name="iffalse">Argument if false.</param> /// <returns> /// The derivatives. /// </returns> public override Derivatives <Expression> IfThenElse(Derivatives <Expression> iftrue, Derivatives <Expression> iffalse) { if (this[0] == null) { return(iffalse); } var size = Math.Max(iftrue.Count, iffalse.Count); var result = new ExpressionTreeDerivatives(size); var notcondition = Expression.Equal(this[0], Zero); for (var i = 0; i < size; i++) { var iftruei = iftrue[i]; var iffalsei = iffalse[i]; if (iftruei == null && iffalsei == null) { continue; } result[i] = Expression.Condition(notcondition, iffalsei ?? Zero, iftruei ?? Zero); } return(result); }
/// <summary> /// Divide derivatives. /// </summary> /// <param name="b">The other operand.</param> /// <returns> /// The divided result. /// </returns> public override Derivatives <Func <double> > Divide(Derivatives <Func <double> > b) { var size = Math.Max(Count, b.Count); var result = new DoubleDerivatives(size); var a0 = this[0]; var b0 = b[0]; result[0] = () => SafeDivide(a0(), b0()); for (var i = 1; i < size; i++) { var ai = this[i]; var bi = b[i]; if (ai != null && bi != null) { result[i] = () => { var denom = b0(); return(SafeDivide(denom * ai() - a0() * bi(), denom * denom)); } } ; else if (ai != null) { result[i] = () => SafeDivide(ai(), b0()); } else if (bi != null) { result[i] = () => { var denom = b0(); return(-SafeDivide(a0() * bi(), denom * denom)); } } ; } return(result); }
/// <summary> /// Subtract derivatives. /// </summary> /// <param name="b">The other operand.</param> /// <returns> /// The difference. /// </returns> public override Derivatives <Func <double> > Subtract(Derivatives <Func <double> > b) { var size = Math.Max(Count, b.Count); var result = new DoubleDerivatives(size); for (var i = 0; i < size; i++) { var arg1 = this[i]; var arg2 = b[i]; if (arg1 != null && arg2 != null) { result[i] = () => arg1() - arg2(); } else if (arg1 != null) { result[i] = arg1; } else if (arg2 != null) { result[i] = () => - arg2(); } } return(result); }
/// <summary> /// Add derivatives. /// </summary> /// <param name="b">The other operand.</param> /// <returns> /// The sum. /// </returns> public override Derivatives <Func <double> > Add(Derivatives <Func <double> > b) { var size = Math.Max(Count, b.Count); var result = new DoubleDerivatives(size); for (var i = 0; i < size; i++) { var ai = this[i]; var bi = b[i]; if (ai != null && bi != null) { result[i] = () => ai() + bi(); } else if (ai != null) { result[i] = ai; } else if (bi != null) { result[i] = bi; } } return(result); }
/// <summary> /// Check less than. /// </summary> /// <param name="b">The other operand.</param> /// <returns>A value representing true if this is less.</returns> public abstract Derivatives <T> LessThan(Derivatives <T> b);
/// <summary> /// Subtract derivatives. /// </summary> /// <param name="b">The other operand.</param> /// <returns>The difference.</returns> public abstract Derivatives <T> Subtract(Derivatives <T> b);
/// <summary> /// Multiply derivatives. /// </summary> /// <param name="b">The other operand.</param> /// <returns>The multiplied result.</returns> public abstract Derivatives <T> Multiply(Derivatives <T> b);
/// <summary> /// Check greater or equal. /// </summary> /// <param name="b">The operand.</param> /// <returns>A value representing true if this is greater or equal.</returns> public abstract Derivatives <T> GreaterOrEqual(Derivatives <T> b);
/// <summary> /// Divide derivatives. /// </summary> /// <param name="b">The other operand.</param> /// <returns>The divided result.</returns> public abstract Derivatives <T> Divide(Derivatives <T> b);
/// <summary> /// Modulo operation on derivatives. /// </summary> /// <param name="b">The other operand.</param> /// <returns>The remainder of the division.</returns> public abstract Derivatives <T> Modulo(Derivatives <T> b);
/// <summary> /// Check less or equal. /// </summary> /// <param name="b">The other operand.</param> /// <returns>A value representing true if this is less or equal.</returns> public abstract Derivatives <T> LessOrEqual(Derivatives <T> b);
/// <summary> /// Check greater than. /// </summary> /// <param name="b">The other operand.</param> /// <returns>A value representing true if this is greater.</returns> public abstract Derivatives <T> GreaterThan(Derivatives <T> b);
/// <summary> /// Execute an operator. /// </summary> /// <param name="op">The operator.</param> protected override void ExecuteOperator(Operator op) { Derivatives <Expression> a, b; switch (op) { case TernaryOperator to: b = _stack.Pop(); a = _stack.Pop(); _stack.Push(_stack.Pop().IfThenElse(a, b)); break; case ClosingTernaryOperator _: break; case FunctionOperator fo: // Extract all arguments for the method var arguments = new Derivatives <Expression> [fo.Arguments]; for (var i = fo.Arguments - 1; i >= 0; i--) { arguments[i] = _stack.Pop(); } var args = new FunctionFoundEventArgs <Derivatives <Expression> >(fo.Name, null, arguments); // Ask around for the result of this method FunctionFound?.Invoke(this, args); if (!args.Found || args.Result == null) { throw new ParserException("Unrecognized method '{0}()'".FormatString(fo.Name), Input, Index); } _stack.Push(args.Result); break; case BracketOperator _: break; case ArgumentOperator _: break; case ArithmeticOperator ao: switch (ao.Type) { case OperatorType.Positive: break; case OperatorType.Negative: _stack.Push(_stack.Pop().Negate()); break; case OperatorType.Not: _stack.Push(_stack.Pop().Not()); break; case OperatorType.Add: b = _stack.Pop(); _stack.Push(_stack.Pop().Add(b)); break; case OperatorType.Subtract: b = _stack.Pop(); _stack.Push(_stack.Pop().Subtract(b)); break; case OperatorType.Multiply: b = _stack.Pop(); _stack.Push(_stack.Pop().Multiply(b)); break; case OperatorType.Divide: b = _stack.Pop(); _stack.Push(_stack.Pop().Divide(b)); break; case OperatorType.Power: b = _stack.Pop(); _stack.Push(_stack.Pop().Pow(b)); break; case OperatorType.ConditionalOr: b = _stack.Pop(); _stack.Push(_stack.Pop().Or(b)); break; case OperatorType.ConditionalAnd: b = _stack.Pop(); _stack.Push(_stack.Pop().And(b)); break; case OperatorType.GreaterThan: b = _stack.Pop(); _stack.Push(_stack.Pop().GreaterThan(b)); break; case OperatorType.LessThan: b = _stack.Pop(); _stack.Push(_stack.Pop().LessThan(b)); break; case OperatorType.GreaterThanOrEqual: b = _stack.Pop(); _stack.Push(_stack.Pop().GreaterOrEqual(b)); break; case OperatorType.LessThanOrEqual: b = _stack.Pop(); _stack.Push(_stack.Pop().LessOrEqual(b)); break; case OperatorType.IsEqual: b = _stack.Pop(); _stack.Push(_stack.Pop().Equal(b)); break; case OperatorType.IsNotEqual: b = _stack.Pop(); _stack.Push(_stack.Pop().NotEqual(b)); break; default: throw new ParserException("Unimplemented arithmetic operator", Input, Index); } break; default: throw new ParserException("Unimplemented operator", Input, Index); } }