[17295] | 1 | using System;
|
---|
| 2 | using System.Diagnostics;
|
---|
| 3 |
|
---|
| 4 | namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
|
---|
| 5 | public class Dual<V> : IAlgebraicType<Dual<V>>
|
---|
[17303] | 6 | where V : IComparableAlgebraicType<V> {
|
---|
[17295] | 7 | [DebuggerBrowsable(DebuggerBrowsableState.Never)]
|
---|
| 8 | private V v;
|
---|
| 9 | public V Value => v;
|
---|
| 10 |
|
---|
| 11 | [DebuggerBrowsable(DebuggerBrowsableState.Never)]
|
---|
| 12 | private V dv;
|
---|
| 13 | public V Derivative => dv;
|
---|
| 14 |
|
---|
| 15 | public Dual(V v, V dv) { this.v = v; this.dv = dv; }
|
---|
| 16 |
|
---|
| 17 | [DebuggerBrowsable(DebuggerBrowsableState.Never)]
|
---|
| 18 | public Dual<V> Zero => new Dual<V>(Value.Zero, Derivative.Zero);
|
---|
| 19 | [DebuggerBrowsable(DebuggerBrowsableState.Never)]
|
---|
| 20 | public Dual<V> One => new Dual<V>(Value.One, Derivative.Zero);
|
---|
| 21 |
|
---|
| 22 | public Dual<V> Assign(Dual<V> a) { v.Assign(a.v); dv.Assign(a.dv); return this; }
|
---|
| 23 | public Dual<V> Scale(double s) { v.Scale(s); dv.Scale(s); return this; }
|
---|
| 24 | public Dual<V> Add(Dual<V> a) { v.Add(a.v); dv.Add(a.dv); return this; }
|
---|
| 25 | public Dual<V> Sub(Dual<V> a) { v.Sub(a.v); dv.Sub(a.dv); return this; }
|
---|
| 26 | public Dual<V> AssignNeg(Dual<V> a) { v.AssignNeg(a.v); dv.AssignNeg(a.dv); return this; }
|
---|
[17307] | 27 | public Dual<V> AssignInv(Dual<V> a) { v.AssignInv(a.v); dv.AssignNeg(a.dv).Mul(v.IntPower(2).Inv()); return this; } // (1/f(x))' = - f(x)' / f(x)^2
|
---|
[17295] | 28 |
|
---|
| 29 | // (a(x) * b(x))' = b(x)*a(x)' + b(x)'*a(x);
|
---|
| 30 | public Dual<V> Mul(Dual<V> a) {
|
---|
| 31 | var t1 = a.dv.Clone().Mul(v);
|
---|
| 32 | var t2 = dv.Clone().Mul(a.v);
|
---|
| 33 | dv.Assign(t1).Add(t2);
|
---|
| 34 |
|
---|
| 35 | v.Mul(a.v);
|
---|
| 36 | return this;
|
---|
| 37 | }
|
---|
[17307] | 38 | public Dual<V> Div(Dual<V> a) { Mul(a.Inv()); return this; } // f(x) / g(x) = f(x) * 1/g(x)
|
---|
[17295] | 39 |
|
---|
| 40 | public Dual<V> AssignExp(Dual<V> a) { v.AssignExp(a.v); dv.Assign(a.dv).Mul(v); return this; } // exp(f(x)) = exp(f(x))*f(x)'
|
---|
| 41 | public Dual<V> AssignLog(Dual<V> a) { v.AssignLog(a.v); dv.Assign(a.dv).Div(a.v); return this; } // log(x)' = 1/f(x) * f(x)'
|
---|
| 42 |
|
---|
| 43 | public Dual<V> AssignIntPower(Dual<V> a, int p) { v.AssignIntPower(a.v, p); dv.Assign(a.dv).Scale(p).Mul(a.v.Clone().IntPower(p - 1)); return this; }
|
---|
[17307] | 44 | public Dual<V> AssignIntRoot(Dual<V> a, int r) { v.AssignIntRoot(a.v, r); dv.Assign(a.dv).Scale(1.0 / r).Div(a.v.IntRoot(r).IntPower(r-1)); return this; }
|
---|
[17295] | 45 |
|
---|
| 46 | public Dual<V> AssignSin(Dual<V> a) { v.AssignSin(a.v); dv.Assign(a.dv).Mul(a.v.Clone().Cos()); return this; }
|
---|
| 47 | public Dual<V> AssignCos(Dual<V> a) { v.AssignCos(a.v); dv.AssignNeg(a.dv).Mul(a.v.Clone().Sin()); return this; }
|
---|
| 48 | public Dual<V> AssignTanh(Dual<V> a) { v.AssignTanh(a.v); dv.Assign(a.dv.Mul(v.Clone().IntPower(2).Neg().Add(Value.One))); return this; }
|
---|
| 49 |
|
---|
| 50 | public Dual<V> AssignAbs(Dual<V> a) { v.AssignAbs(a.v); dv.Assign(a.dv).Mul(a.v.Clone().Sgn()); return this; } // abs(f(x))' = f(x)*f'(x) / |f(x)|
|
---|
| 51 | public Dual<V> AssignSgn(Dual<V> a) { v.AssignSgn(a.v); dv.Assign(a.dv.Zero); return this; }
|
---|
| 52 |
|
---|
| 53 | public Dual<V> Clone() { return new Dual<V>(v.Clone(), dv.Clone()); }
|
---|
| 54 |
|
---|
| 55 | public Dual<V> AssignMin(Dual<V> other) {
|
---|
[17303] | 56 | if(v.CompareTo(other.v) > 0) {
|
---|
| 57 | v.Assign(other.v);
|
---|
| 58 | dv.Assign(other.dv);
|
---|
| 59 | }
|
---|
| 60 | return this;
|
---|
[17295] | 61 | }
|
---|
| 62 |
|
---|
| 63 | public Dual<V> AssignMax(Dual<V> other) {
|
---|
[17303] | 64 | if (v.CompareTo(other.v) <= 0) {
|
---|
| 65 | v.Assign(other.v);
|
---|
| 66 | dv.Assign(other.dv);
|
---|
| 67 | }
|
---|
| 68 | return this;
|
---|
[17295] | 69 | }
|
---|
| 70 | }
|
---|
| 71 | } |
---|