Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 17 additions & 11 deletions BREAKING-CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -1049,20 +1049,26 @@ unchanged ([#2256](https://github.com/asc-community/AngouriMath/issues/2256)).
| `"max(x, x)".ToEntity().Simplify()` | `x` | `x provided x in RR` |
| `"max(x, 2)".ToEntity().DomainCondition` | `True` | `x in RR` |

### Over the complex numbers, an equation in and out of a modulus is left unsolved

**Silent: an equation with `x` inside `abs`, `sgn`, `conj`, `Re`, `Im` or `arg` and outside it too is left unsolved
in the complex codomain, the default, where a numerical search answered it.** Newton's method assumes a holomorphic
function, and over the complex numbers `|u| = ±u` only where `u` is real, which a root need not make it, so neither
the search nor a split by the sign finds every root. The search's near-copies of a root came back as roots. Where it
happened to be right, as for `x * abs(x) = 4`, the answer is given up with the rest; over the reals each is still
solved by cases, exactly ([#2139](https://github.com/asc-community/AngouriMath/issues/2139)).
### Over the complex numbers, an equation in and out of a modulus is solved in the parts of `x`

**Silent: an equation with `x` inside `abs`, `sgn`, `conj`, `Re` or `Im` and outside it too is solved exactly in the
complex codomain, the default, where a numerical search answered it in decimals with near-copies of a root that solve
nothing.** Newton's method assumes a holomorphic function, and over the complex numbers `|u| = ±u` only where `u` is
real, which a root need not make it, so a split by the sign misses roots too: `x^2 + 1 = abs(x)` is solved by
`±0.618… i`. With `x = a + b i` and each modulus a real `t ≥ 0` with `t^2 = (Re u)^2 + (Im u)^2`, the equation is a
system of polynomial equations in `a`, `b` and the `t`s, solved by a Gröbner basis, and its real solutions are the
roots; `sgn(u)` is `u / |u|` where `u` is not zero and `0` where it is, and both cases are solved. Where that system
has more than finitely many solutions, roots that are not found exactly, or more than 32 by Bézout's bound, the
equation is left unsolved, as it is with `arg` in it
([#2139](https://github.com/asc-community/AngouriMath/issues/2139)).

| Input | Was (2.6.0) | Now |
|---|---|---|
| `"x^2/abs(1-x^2) = x".ToEntity().Solve("x")` | `{ 0, 0.618…, 1.618…, 1.618… + 1.7E-9i, 1.618… + 9.9E-8i }` | `{ x : x ^ 2 / abs(1 - x ^ 2) = x }` |
| `"abs(x^2 - 4) = 3x".ToEntity().Solve("x")` | `{ 1, 4, 4.0000000000000062… + 1.6E-7i }` | `{ x : abs(x ^ 2 - 4) = 3 * x }` |
| `"x * abs(x) = 4".ToEntity().Solve("x")` | `{ 2 }` | `{ x : x * abs(x) = 4 }` |
| `"x^2/abs(1-x^2) = x".ToEntity().Solve("x")` | `{ 0, 0.618…, 1.618…, 1.618… + 1.7E-9i, 1.618… + 9.9E-8i }` | `{ 0, (1 + sqrt(5)) / 2, (sqrt(5) - 1) / 2 }` |
| `"abs(x^2 - 4) = 3x".ToEntity().Solve("x")` | `{ 1, 4, 4.0000000000000062… + 1.6E-7i }` | `{ 1, 4 }` |
| `"1/abs(x) = x^2".ToEntity().Solve("x")` | `{ -1, -0.999999… - 2.1E-7i, -0.999999… + 2.1E-7i, …, 1 }`, eight entries | `{ 1, -1 }` |
| `"x^2 + 1 = abs(x)".ToEntity().Solve("x")` | `{ x : x ^ 2 + 1 = abs(x) }` | `{ 1/2 * i * (sqrt(5) - 1), 1/2 * i * (1 - sqrt(5)) }` |
| `"x^5 = abs(x) + 1".ToEntity().Solve("x")` | `{ -0.944368… - 0.686124…i, …, 1.167303… }`, eight entries for five roots | `{ x : x ^ 5 = abs(x) + 1 }` |

### `conjugate`, `conj` and `arg` are functions

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,18 @@ internal int DegreeIn(int variable)
return degree;
}

/// <summary>The highest total degree of a term; zero for a constant.</summary>
internal int Degree
{
get
{
var degree = 0;
foreach (var monomial in terms.Keys)
degree = System.Math.Max(degree, TotalDegree(monomial));
return degree;
}
}

/// <summary>The greatest monomial in lexicographic order; zero if there is none.</summary>
private ulong LeadingMonomial()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,16 @@ internal static Set Solve(Entity expr, Variable x, bool compensateSolving = fals
if (MathS.Settings.Codomain.Value == Core.Domain.Real && ModulusSolver.SolveOverTheReals(expr, x) is { } overTheReals)
return overTheReals;

// Over the complex numbers, one with x inside a modulus, a conjugate, a real or an
// imaginary part and outside it as well is solved in the real and imaginary parts of
// x, exactly: x |x| = 4 is { 2 }. Asked here, of the equation as it was asked, rather
// than of each spelling below, every one of which would be the same system to solve.
// https://github.com/asc-community/AngouriMath/issues/2139
if (!compensateSolving && MathS.Settings.Codomain.Value != Core.Domain.Real
&& ModulusSolver.IsInsideAndOutsideAFunctionThatIsNotHolomorphic(expr, x)
&& ModulusSolver.SolveOverTheComplexNumbers(expr, x) is { } overTheComplexNumbers)
return overTheComplexNumbers;

// Whether a candidate root really is one. The loose tolerance that guesses the
// rational must not also be what decides this: at 1e-7, x^41 + 6x + 1 accepted
// -1/6, whose residual is -1.25e-32 -- small, but the difference between an
Expand Down Expand Up @@ -395,8 +405,8 @@ bool ProductIsDefinedAt(Entity root)
// Over the complex numbers, x inside a modulus or another function that is not
// holomorphic and outside it as well is not the search's either: Newton's method
// assumes a holomorphic function, and its near-copies of a root came back as roots.
// Left unsolved; over the reals it is solved by cases, above.
// https://github.com/asc-community/AngouriMath/issues/2139
// Left unsolved where it is not solved in the parts of x, above; over the reals it is
// solved by cases. https://github.com/asc-community/AngouriMath/issues/2139
if (MathS.Settings.Codomain.Value != Core.Domain.Real && ModulusSolver.IsInsideAndOutsideAFunctionThatIsNotHolomorphic(expr, x))
return Unsolved(expr, x);

Expand Down
Loading
Loading