Repository navigation
Indefinite integration #229
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
14 commits
Select commit
Hold shift + click to select a range
43c83b9
started working on indefinite integration rules
MomoDeve f6d9697
added some standard integral patterns, integration by parts for polyn…
MomoDeve 487a9b4
oops, some mistake in sin/cos integral case
MomoDeve e3a6e52
more cases for standard integrals
MomoDeve 45403d0
Polynomial parser
WhiteBlackGoose bf3d756
more intergal solvers + refactoring thx to TryGetPolyLinear
MomoDeve 141c7e6
fixed trigonometric patterns
MomoDeve 638ab41
added basic exponential solver (still needs improvements)
MomoDeve 8aaa9b9
imporved exponential solver, now is solved equation when bases are equal
MomoDeve 6cabd2d
merged master to integration
MomoDeve 5307aa6
Tests for polynomial parser fixed
WhiteBlackGoose 1084013
Sequential integration
WhiteBlackGoose 34022e6
ifs -> switch
WhiteBlackGoose 82e2cc8
Merge branch 'poly-inequality' into integration
WhiteBlackGoose File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
97 changes: 97 additions & 0 deletions
97
AngouriMath/Functions/Continuous/Algebra/Integration/IndefiniteIntegralSolver.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,97 @@ | ||
| using System.Linq; | ||
|
|
||
| namespace AngouriMath.Functions.Algebra | ||
| { | ||
| static class IndefiniteIntegralSolver | ||
| { | ||
| internal static Entity? SolveBySplittingSum(Entity expr, Entity.Variable x) | ||
| { | ||
| var splitted = TreeAnalyzer.GatherLinearChildrenOverSumAndExpand(expr, e => e.ContainsNode(x)); | ||
| if (splitted is null || splitted.Count < 2) return null; // nothing to do, let other solvers do the work | ||
| splitted[0] = Integration.ComputeIndefiniteIntegral(splitted[0], x); // base case for aggregate | ||
| var result = splitted.Aggregate((e1, e2) => e1 + Integration.ComputeIndefiniteIntegral(e2, x)); | ||
| return result; | ||
| } | ||
|
|
||
| internal static Entity? SolveAsPolynomialTerm(Entity expr, Entity.Variable x) => expr switch | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Wouldn't it be simpler to use existing polynomial parser? |
||
| { | ||
| Entity.Mulf(var m1, var m2) => | ||
| !m1.ContainsNode(x) ? | ||
| m1 * Integration.ComputeIndefiniteIntegral(m2, x) : | ||
| !m2.ContainsNode(x) ? | ||
| m2 * Integration.ComputeIndefiniteIntegral(m1, x) : | ||
| null, | ||
|
|
||
| Entity.Divf(var div, var over) => | ||
| !div.ContainsNode(x) ? | ||
| over is Entity.Powf(var @base, var power) ? | ||
| div * Integration.ComputeIndefiniteIntegral(MathS.Pow(@base, -power), x) : | ||
| div * Integration.ComputeIndefiniteIntegral(MathS.Pow(over, -1), x) : | ||
| !over.ContainsNode(x) ? | ||
| Integration.ComputeIndefiniteIntegral(div, x) / over : | ||
| null, | ||
|
|
||
| Entity.Powf(var @base, var power) => | ||
| !power.ContainsNode(x) && @base == x ? | ||
| power == -1 ? | ||
| MathS.Ln(@base) : // TODO: here should be ln(abs(x)) but for now I left it as is | ||
| MathS.Pow(x, power + 1) / (power + 1) : | ||
| null, | ||
|
|
||
| Entity.Variable(var v) => | ||
| v == x ? MathS.Pow(x, 2) / 2 : v * x, | ||
|
|
||
| _ => null | ||
| }; | ||
|
|
||
| internal static Entity? SolveIntegratingByParts(Entity expr, Entity.Variable x) | ||
| { | ||
| static Entity? IntegrateByParts(Entity v, Entity u, Entity.Variable x, int currentRecursion = 0) | ||
| { | ||
| if (v == 0) return 0; | ||
| if (currentRecursion == MathS.Settings.MaxExpansionTermCount) return null; | ||
|
|
||
| var integral = Integration.ComputeIndefiniteIntegral(u, x); | ||
| var differential = v.Derive(x).InnerSimplify(); | ||
| var result = IntegrateByParts(differential, integral, x, currentRecursion + 1); | ||
| return (result is null) ? null : v * integral - result; | ||
| } | ||
|
|
||
| if (expr is Entity.Mulf(var f, var g)) | ||
| { | ||
| if (MathS.TryPolynomial(f, x, out var fPoly)) | ||
| { | ||
| return IntegrateByParts(fPoly, g, x); | ||
| } | ||
| if (MathS.TryPolynomial(g, x, out var gPoly)) | ||
| { | ||
| return IntegrateByParts(gPoly, f, x); | ||
| } | ||
| else return null; | ||
| } | ||
| else return null; | ||
| } | ||
|
|
||
| internal static Entity? SolveLogarithmic(Entity expr, Entity.Variable x) => expr switch | ||
| { | ||
| Entity.Logf(var @base, var arg) => | ||
| @base.ContainsNode(x) ? | ||
| Integration.ComputeIndefiniteIntegral(MathS.Ln(arg) / MathS.Ln(@base), x) : | ||
| arg is Entity.Powf(var y, var pow) ? // log(b, y^p) = ln(y^p) / ln(b) = ln(p) / ln(b) * ln(y) | ||
| Integration.ComputeIndefiniteIntegral(pow / MathS.Ln(@base) * MathS.Ln(y), x) : | ||
| null, | ||
|
|
||
| _ => null | ||
| }; | ||
|
|
||
| internal static Entity? SolveExponential(Entity expr, Entity.Variable x) => expr switch | ||
| { | ||
| Entity.Powf(var @base, var pow) => | ||
| @base.ContainsNode(x) ? | ||
| Integration.ComputeIndefiniteIntegral(MathS.Pow(MathS.e, MathS.Ln(@base) * pow), x) : | ||
| null, | ||
|
|
||
| _ => null | ||
| }; | ||
| } | ||
| } | ||
40 changes: 40 additions & 0 deletions
40
AngouriMath/Functions/Continuous/Algebra/Integration/IntegralPatterns.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,40 @@ | ||
| namespace AngouriMath.Functions.Algebra | ||
| { | ||
| internal static class IntegralPatterns | ||
| { | ||
| internal static Entity? TryStandardIntegrals(Entity expr, Entity.Variable x) => expr switch | ||
| { | ||
| Entity.Sinf(var arg) => | ||
| TreeAnalyzer.TryGetPolyLinear(arg, x, out var a, out _) ? | ||
| -MathS.Cos(arg) / a : | ||
| null, | ||
|
|
||
| Entity.Cosf(var arg) => | ||
| TreeAnalyzer.TryGetPolyLinear(arg, x, out var a, out _) ? | ||
| MathS.Sin(arg) / a : | ||
| null, | ||
|
|
||
| Entity.Tanf(var arg) => | ||
| TreeAnalyzer.TryGetPolyLinear(arg, x, out var a, out _) ? | ||
| -MathS.Ln(MathS.Cos(arg)) / a : | ||
| null, | ||
|
|
||
| Entity.Cotanf(var arg) => | ||
| TreeAnalyzer.TryGetPolyLinear(arg, x, out var a, out _) ? | ||
| MathS.Ln(MathS.Sin(arg)) / a : | ||
| null, | ||
|
|
||
| Entity.Logf(var @base, var arg) => | ||
| !@base.ContainsNode(x) && TreeAnalyzer.TryGetPolyLinear(arg, x, out var a, out var b) ? | ||
| ((b / a + x) * MathS.Ln(arg) - x) / MathS.Ln(@base) : | ||
| null, | ||
|
|
||
| Entity.Powf(var @base, var power) => | ||
| !@base.ContainsNode(x) && TreeAnalyzer.TryGetPolyLinear(power, x, out var a, out _) ? | ||
| MathS.Pow(@base, power) / (a * MathS.Ln(@base)) : | ||
| null, | ||
|
|
||
| _ => null | ||
| }; | ||
| } | ||
| } |
29 changes: 29 additions & 0 deletions
29
AngouriMath/Functions/Continuous/Algebra/Integration/Integration.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| namespace AngouriMath.Functions.Algebra | ||
| { | ||
| public static partial class Integration | ||
| { | ||
| public static Entity ComputeIndefiniteIntegral(Entity expr, Entity.Variable x) | ||
| { | ||
| if (!expr.ContainsNode(x)) return expr * x; // base case, handle here | ||
|
|
||
| Entity? answer = null; | ||
|
|
||
| answer = IntegralPatterns.TryStandardIntegrals(expr, x); | ||
| if (answer is { }) return answer; | ||
|
|
||
| answer = IndefiniteIntegralSolver.SolveBySplittingSum(expr, x); | ||
| if (answer is { }) return answer; | ||
|
|
||
| answer = IndefiniteIntegralSolver.SolveAsPolynomialTerm(expr, x); | ||
| if (answer is { }) return answer; | ||
|
|
||
| answer = IndefiniteIntegralSolver.SolveIntegratingByParts(expr, x); | ||
| if (answer is { }) return answer; | ||
|
|
||
| answer = IndefiniteIntegralSolver.SolveLogarithmic(expr, x); | ||
| if (answer is { }) return answer; | ||
|
|
||
| return new Entity.Integralf(expr, x, 1); // return as integral if nothing can be done with expression | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As with limits, we return null if cannot compute, although it might be reconsidered |
||
| } | ||
| } | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
92 changes: 92 additions & 0 deletions
92
AngouriMath/Functions/Continuous/Solvers/EquationSolver/ExponentialSolver.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,92 @@ | ||
| using AngouriMath.Extensions; | ||
| using System; | ||
| using System.Collections.Generic; | ||
| using System.Linq; | ||
| using System.Text; | ||
| using System.Xml; | ||
| using static AngouriMath.Entity.Set; | ||
|
|
||
| namespace AngouriMath.Functions.Algebra.AnalyticalSolving | ||
| { | ||
| class ExponentialSolver | ||
| { | ||
| internal static Entity.Set? SolveLinear(Entity expr, Entity.Variable x) | ||
| { | ||
| var replacement = Entity.Variable.CreateTemp(expr.Vars); | ||
|
|
||
| Func<Entity, Entity> preparator = e => e switch | ||
| { | ||
| Entity.Powf(var @base, var arg) when | ||
| TreeAnalyzer.TryGetPolyLinear(arg, x, out var a, out var b) => | ||
| MathS.Pow(MathS.e, b) * MathS.Pow(MathS.Pow(MathS.e, x), MathS.Ln(@base) * a), | ||
|
|
||
| _ => e, | ||
| }; | ||
|
|
||
| Func<Entity, Entity> replacer = e => e switch | ||
| { | ||
| Entity.Powf(var @base, var arg) | ||
| when @base == MathS.e && arg == x | ||
| => replacement, | ||
|
|
||
| _ => e, | ||
| }; | ||
|
|
||
| expr = expr.Replace(preparator); | ||
| expr = expr.Replace(replacer); | ||
|
|
||
| if (expr.ContainsNode(x)) return null; // cannot be solved, not a pure exponential | ||
|
|
||
| expr = expr.InnerSimplify(); | ||
| if (AnalyticalEquationSolver.Solve(expr, replacement) is FiniteSet els && els.Any()) | ||
| return (Entity.Set)els.Select(sol => MathS.Pow(MathS.e, x).Invert(sol, x).ToSet()).Unite().InnerSimplified; | ||
| else | ||
| return null; | ||
| } | ||
|
|
||
| internal static Entity.Set? SolveMultiplicative(Entity expr, Entity.Variable x) | ||
| { | ||
| Entity? substitution = null; | ||
| Entity ApplyPowerTransform(Entity @base, Entity arg) | ||
| { | ||
| var mults = Entity.Mulf.LinearChildren(arg); | ||
| if (mults.Count() == 0) return MathS.Pow(@base, arg); | ||
|
|
||
| Entity innerPower = 1; | ||
| Entity outerPower = 1; | ||
| foreach(var mult in mults) | ||
| { | ||
| if (mult.InnerSimplify() is Entity.Number) | ||
| outerPower = outerPower * mult; | ||
| else | ||
| innerPower = innerPower * mult; | ||
| } | ||
| substitution = MathS.Pow(@base, innerPower); | ||
| return MathS.Pow(substitution, outerPower.InnerSimplified); | ||
| } | ||
|
|
||
| Func<Entity, Entity> powerTransform = e => e switch | ||
| { | ||
| Entity.Powf(var @base, var arg) | ||
| when @base == x && !arg.ContainsNode(x) => | ||
| ApplyPowerTransform(@base, arg), | ||
|
|
||
| _ => e, | ||
| }; | ||
|
|
||
| expr = expr.Replace(powerTransform); | ||
| if (substitution is null) return null; | ||
|
|
||
| var replacement = Entity.Variable.CreateTemp(expr.Vars); | ||
| expr = expr.Substitute(substitution, replacement); | ||
|
|
||
| if (expr.ContainsNode(x)) return null; // cannot be solved, not a multiplicative exponenial equation | ||
|
|
||
| expr = expr.InnerSimplify(); | ||
| if (AnalyticalEquationSolver.Solve(expr, replacement) is FiniteSet els && els.Any()) | ||
| return (Entity.Set)els.Select(sol => substitution.Invert(sol, x).ToSet()).Unite().InnerSimplified; | ||
| else | ||
| return null; | ||
| } | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Better to keep this internal. Should be consistent with Limit, so that you expose it only in MathS.Compute