Skip to content

Commit 2ec2d38

Browse files
Newton's solver improved
1 parent 2e805f6 commit 2ec2d38

7 files changed

Lines changed: 178 additions & 31 deletions

File tree

AngouriMath/Functions/Algebra/Integration.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ public static Number Integrate(Entity func, VariableEntity x, Number from, Numbe
6060
{
6161
var share = ((double)i) / stepCount;
6262
var tmp = new Number(ReFrom * share + ReTo * (1 - share), ImFrom * share + ImTo * (1 - share));
63-
res += cfunc.Eval(tmp);
63+
res += cfunc.Substitute(tmp);
6464
}
6565
return res / (stepCount + 1) * (to - from);
6666
}

AngouriMath/Functions/Algebra/NewtonSolver.cs

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,19 +18,17 @@ public Number GetValue()
1818
else
1919
throw new MathSException("Cannot get number from expression");
2020
}
21-
private Number NewtonIter(VariableEntity x, Number value, int precision)
21+
private Number NewtonIter(FastExpression f, FastExpression df, VariableEntity x, Number value, int precision)
2222
{
2323
Number prev = value;
24-
Func<NumberEntity, Number> f = subValue => this.Substitute(x, subValue).Eval().GetValue();
25-
Func<NumberEntity, Number> df = subValue => Derivative.Substitute(x, subValue).Eval().GetValue();
2624
int minCheckIters = (int)Math.Sqrt(precision);
2725
for (int i = 0; i < precision; i++)
2826
{
2927
if(i == precision - 1)
3028
prev = value.Copy();
3129
try
3230
{
33-
value = value - f(value) / df(value);
31+
value = value - f.Substitute(value) / df.Substitute(value);
3432
}
3533
catch(MathSException e)
3634
{
@@ -44,7 +42,6 @@ private Number NewtonIter(VariableEntity x, Number value, int precision)
4442
else
4543
return value;
4644
}
47-
private Entity Derivative { set; get; }
4845

4946
/// <summary>
5047
/// Searches for numerical solutions via Newton's method https://en.wikipedia.org/wiki/Newton%27s_method
@@ -87,15 +84,16 @@ public NumberSet SolveNt(VariableEntity v, Number from = null, Number to = null,
8784
xStep = (int)stepCount.Re;
8885
yStep = (int)stepCount.Im;
8986
}
90-
Derivative = this.Derive(v).Simplify();
87+
var df = this.Derive(v).Simplify().Compile(v);
88+
var f = this.Simplify().Compile(v);
9189
for (int x = 0; x < xStep; x++)
9290
for (int y = 0; y < yStep; y++)
9391
{
9492
double xShare = ((double)x) / xStep;
9593
double yShare = ((double)y) / yStep;
9694
var value = new Number(from.Re * xShare + to.Re * (1 - xShare),
9795
from.Im * yShare + to.Im * (1 - yShare));
98-
var root = NewtonIter(v, value, precision);
96+
var root = NewtonIter(f, df, v, value, precision);
9997
if (root != null)
10098
res.Include(root);
10199
}

AngouriMath/Functions/Evaluation/Compilation/FastExpression.cs

Lines changed: 45 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,32 @@ namespace AngouriMath
77
{
88
public abstract partial class Entity
99
{
10+
/// <summary>
11+
/// Compile function so you can evaluate numerical value 15x faster,
12+
/// than subsitution
13+
/// </summary>
14+
/// <param name="variables">
15+
/// List string names of variables in the same order
16+
/// as you will list them when evaluating
17+
/// </param>
18+
/// <returns></returns>
19+
public FastExpression Compile(params VariableEntity[] variables)
20+
{
21+
var strings = new List<string>();
22+
foreach (var varEnt in variables)
23+
strings.Add(varEnt.Name);
24+
return Compile(strings.ToArray());
25+
}
26+
27+
/// <summary>
28+
/// Compile function so you can evaluate numerical value 15x faster,
29+
/// than subsitution
30+
/// </summary>
31+
/// <param name="variables">
32+
/// List string names of variables in the same order
33+
/// as you will list them when evaluating
34+
/// </param>
35+
/// <returns></returns>
1036
public FastExpression Compile(params string[] variables)
1137
{
1238
var instructions = new InstructionSet();
@@ -36,19 +62,34 @@ private void InnerCompile(InstructionSet instructions, string[] variables, Dicti
3662
}
3763
public class FastExpression
3864
{
39-
//private Dictionary<string, Number> variables = new Dictionary<string, Number>();
4065
private Stack stack;
4166
private InstructionSet instructions;
4267
private int varCount;
4368
internal FastExpression(InstructionSet instructions, int varCount)
4469
{
45-
//foreach (var varName in variables)
46-
// this.variables[varName] = 0;
4770
this.varCount = varCount;
4871
stack = new Stack(instructions.Count);
4972
this.instructions = instructions;
5073
}
51-
public Number Eval(params Number[] variables)
74+
75+
/// <summary>
76+
/// Calls the compiled function (synonim to Substitute)
77+
/// </summary>
78+
/// <param name="variables">
79+
/// List arguments in the same order in which you compiled the function
80+
/// </param>
81+
/// <returns></returns>
82+
public Number Call(params Number[] variables)
83+
=> Substitute(variables);
84+
85+
/// <summary>
86+
/// Calls the compiled function (synonim to Call)
87+
/// </summary>
88+
/// <param name="variables">
89+
/// List arguments in the same order in which you compiled the function
90+
/// </param>
91+
/// <returns></returns>
92+
public Number Substitute(params Number[] variables)
5293
{
5394
if (variables.Length != varCount)
5495
throw new Exception("Wrong amount of parameters");

README.md

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,13 +86,22 @@ Only definite integral over single variable is supported yet :(
8686
```cs
8787
var x = MathS.Var("x");
8888
var expr = MathS.Sin(x) + MathS.Sqrt(x) / (MathS.Sqrt(x) + MathS.Cos(x)) + MathS.Pow(x, 3);
89-
Console.WriteLine(expr.DefiniteIntegral(expr, x, -3, 3));
89+
Console.WriteLine(expr.DefiniteIntegral(x, -3, 3));
9090
var expr2 = MathS.Sin(x);
91-
Console.WriteLine(expr2.DefiniteIntegral(expr2, x, 0, MathS.pi));
91+
Console.WriteLine(expr2.DefiniteIntegral(x, 0, MathS.pi));
9292
>>> 5.56669223384056 + 0.0889406793629381i
9393
>>> 1.98003515236381
9494
```
9595

96+
#### Compile functions
97+
Compiled functions work 15x faster
98+
```cs
99+
var x = MathS.Var("x");
100+
var expr = MathS.Sin(x) + MathS.Sqrt(x) / (MathS.Sqrt(x) + MathS.Cos(x)) + MathS.Pow(x, 3);
101+
var func = expr.Compile(x);
102+
Console.WriteLine(func.Substitute(3));
103+
```
104+
96105
### Full documentation
97106

98107
#### Function list

Samples/Program.cs

Lines changed: 70 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,23 +7,79 @@ namespace Samples
77
{
88
class Program
99
{
10-
static void Main(string[] args)
10+
static void Sample1()
11+
{
12+
var inp = "1 + 2 * log(9, 3)";
13+
var expr = MathS.FromString(inp);
14+
Console.WriteLine(expr.Eval());
15+
}
16+
static void Sample2()
1117
{
1218
var x = MathS.Var("x");
1319
var y = MathS.Var("y");
14-
15-
var expr = MathS.Sin(x) * MathS.Sqrt(x + MathS.Cos(x)) / 3;
16-
//Console.WriteLine(func.Eval(1, 2));
17-
//return;
18-
19-
var iter = 1000;
20-
var stopWatch = new Stopwatch();
21-
stopWatch.Start();
22-
for (int i = 0; i < iter; i++)
23-
expr.DefiniteIntegral(x, 1, 10);
24-
stopWatch.Stop();
25-
Console.Write(((double)stopWatch.ElapsedMilliseconds) / iter * 1000000);
26-
Console.WriteLine(" ns");
20+
var c = x * y + x / y;
21+
Console.WriteLine(MathS.Sqr(c));
22+
}
23+
static void Sample3()
24+
{
25+
var x = MathS.Var("x");
26+
var expr = x * 2 + MathS.Sin(x) / MathS.Sin(MathS.Pow(2, x));
27+
var subs = expr.Substitute(x, 0.3);
28+
Console.WriteLine(subs.Simplify());
29+
}
30+
static void Sample4()
31+
{
32+
var x = MathS.Var("x");
33+
var func = MathS.Sqr(x) + MathS.Ln(MathS.Cos(x) + 3) + 4 * x;
34+
var derivative = func.Derive(x);
35+
Console.WriteLine(derivative.Simplify());
36+
}
37+
static void Sample5()
38+
{
39+
var x = MathS.Var("x");
40+
var expr = (x + 3).Pow(x + 4);
41+
Func<NumberEntity, Entity> wow = v => expr.Substitute(x, v).Simplify();
42+
Console.WriteLine(wow(4));
43+
Console.WriteLine(wow(5));
44+
Console.WriteLine(wow(6));
45+
}
46+
static void Sample6()
47+
{
48+
var x = MathS.Var("x");
49+
var y = MathS.Var("y");
50+
var expr = x.Pow(y) + MathS.Sqrt(x + y / 4) * (6 / x);
51+
Console.WriteLine(expr.Latexise());
52+
}
53+
static void Sample7()
54+
{
55+
var expr = MathS.Pow(MathS.e, MathS.pi * MathS.i);
56+
Console.WriteLine(expr);
57+
Console.WriteLine(expr.Eval());
58+
}
59+
static void Sample8()
60+
{
61+
var x = MathS.Var("x");
62+
var equation = (x - 1) * (x - 2) * (MathS.Sqr(x) + 1);
63+
Console.Write(equation.SolveNt(x));
64+
}
65+
static void Sample9()
66+
{
67+
var x = MathS.Var("x");
68+
var expr = MathS.Sin(x) + MathS.Sqrt(x) / (MathS.Sqrt(x) + MathS.Cos(x)) + MathS.Pow(x, 3);
69+
Console.WriteLine(expr.DefiniteIntegral(x, -3, 3));
70+
var expr2 = MathS.Sin(x);
71+
Console.WriteLine(expr2.DefiniteIntegral(x, 0, MathS.pi));
72+
}
73+
static void Sample10()
74+
{
75+
var x = MathS.Var("x");
76+
var expr = MathS.Sin(x) + MathS.Sqrt(x) / (MathS.Sqrt(x) + MathS.Cos(x)) + MathS.Pow(x, 3);
77+
var func = expr.Compile(x);
78+
Console.WriteLine(func.Substitute(3));
79+
}
80+
static void Main(string[] args)
81+
{
82+
Sample1();
2783
}
2884
}
2985
}

UnitTests/Algebra/IntegrationTest.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,21 +13,21 @@ public void Test1()
1313
{
1414
var x = MathS.Var("x");
1515
var expr = x;
16-
Assert.IsTrue(Math.Abs(expr.DefiniteIntegral(expr, x, 0, 1).Re - 1.0/2) < 0.1);
16+
Assert.IsTrue(Math.Abs(expr.DefiniteIntegral(x, 0, 1).Re - 1.0/2) < 0.1);
1717
}
1818
[TestMethod]
1919
public void Test2()
2020
{
2121
var x = MathS.Var("x");
2222
var expr = MathS.Sin(x);
23-
Assert.IsTrue(expr.DefiniteIntegral(expr, x, -1, 1) == 0);
23+
Assert.IsTrue(expr.DefiniteIntegral(x, -1, 1) == 0);
2424
}
2525
[TestMethod]
2626
public void Test3()
2727
{
2828
var x = MathS.Var("x");
2929
var expr = MathS.Sin(x);
30-
Assert.IsTrue(expr.DefiniteIntegral(expr, x, 0, 3).Re > 1.5);
30+
Assert.IsTrue(expr.DefiniteIntegral(x, 0, 3).Re > 1.5);
3131
}
3232
}
3333
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
using AngouriMath;
2+
using AngouriMath.Core;
3+
using Microsoft.VisualStudio.TestTools.UnitTesting;
4+
5+
namespace UnitTests
6+
{
7+
[TestClass]
8+
public class CompilationTest
9+
{
10+
public static VariableEntity x = MathS.Var("x");
11+
public static VariableEntity y = MathS.Var("y");
12+
[TestMethod]
13+
public void Test1()
14+
{
15+
var func = (x + MathS.Sqrt(x)).Compile(x);
16+
Assert.IsTrue(func.Substitute(4) == 6);
17+
}
18+
[TestMethod]
19+
public void Test2()
20+
{
21+
var func = (MathS.Sin(x) + MathS.Cos(x)).Compile(x);
22+
Assert.IsTrue(func.Substitute(0) == 1);
23+
}
24+
[TestMethod]
25+
public void Test3()
26+
{
27+
var func = (x / y).Compile(x, y);
28+
Assert.IsTrue(func.Substitute(1, 2) == 0.5);
29+
}
30+
[TestMethod]
31+
public void Test4()
32+
{
33+
var func = (x / y).Compile(y, x);
34+
Assert.IsTrue(func.Substitute(1, 2) == 2.0);
35+
}
36+
[TestMethod]
37+
public void Test5()
38+
{
39+
var func = ((x + y) / (x - 3)).Compile(x, y);
40+
Assert.IsTrue(func.Substitute(4, 3) == 7.0);
41+
}
42+
}
43+
}

0 commit comments

Comments
 (0)