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
3 changes: 3 additions & 0 deletions Sources/.editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,9 @@ file_header_template=\nCopyright (c) 2019-2026 Angouri.\nAngouriMath is licensed
[Tests/UnitTests/Convenience/SpellingsAtRiskTest.cs]
file_header_template=\nCopyright (c) 2019-2026 Angouri.\nAngouriMath is licensed under MIT.\nDetails: https://github.com/asc-community/AngouriMath/blob/master/LICENSE.md.\nWebsite: https://am.angouri.org.\n

[Tests/UnitTests/Algebra/SolveTest/APolynomialHasARootTest.cs]
file_header_template=\nCopyright (c) 2019-2026 Angouri.\nAngouriMath is licensed under MIT.\nDetails: https://github.com/asc-community/AngouriMath/blob/master/LICENSE.md.\nWebsite: https://am.angouri.org.\n

[Tests/UnitTests/Convenience/RoundIsExactTest.cs]
file_header_template=\nCopyright (c) 2019-2026 Angouri.\nAngouriMath is licensed under MIT.\nDetails: https://github.com/asc-community/AngouriMath/blob/master/LICENSE.md.\nWebsite: https://am.angouri.org.\n

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,32 @@ private static Entity Minus(Entity left, Entity right)
/// equation as the caller wrote it.
/// </remarks>
internal static Set WithoutSpuriousRoots(Set roots, Entity equation, Variable x)
=> roots is FiniteSet finite && finite.Any(root => IsSpurious(equation, x, root))
? finite.Where(root => !IsSpurious(equation, x, root)).ToSet()
: roots;
{
if (roots is not FiniteSet finite || !finite.Any(root => IsSpurious(equation, x, root)))
return roots;
var kept = finite.Where(root => !IsSpurious(equation, x, root)).ToSet();
// A polynomial of degree one or more has a root over the complex numbers, so where every
// candidate for one fails, what failed is the solver, and the empty set left would claim
// there is no root: (x + 1)^3 = 2 was { } while Cardano's C was 0 for a shifted cube, and
// 31x^4 - 62x^3 + 33x^2 - 2x - 1 = 0 while a biquadratic quartic was shifted by -b a / 4.
// Left unsolved instead, which says only that the roots were not found.
if (kept.Count == 0 && IsAPolynomialWithARoot(equation, x))
return new ConditionalSet(x, equation is Minusf(var left, var right) ? left.Equalizes(right) : equation.Equalizes(0));
return kept;
}

/// <summary>
/// Whether <paramref name="equation"/> is a polynomial in <paramref name="x"/> with numbers
/// for coefficients and a degree of one or more, read over the complex numbers, where such a
/// polynomial has a root.
/// </summary>
private static bool IsAPolynomialWithARoot(Entity equation, Variable x)
=> MathS.Settings.Codomain.Value != Core.Domain.Real
&& TreeAnalyzer.TryGetPolynomial(equation, x, out var monomials)
&& monomials.Keys.All(power => power.Sign >= 0)
&& monomials.Where(monomial => monomial.Key.Sign > 0)
.Any(monomial => monomial.Value.Evaled is Number.Complex { IsZero: false })
&& monomials.Values.All(coefficient => coefficient.Evaled is Number.Complex { IsFinite: true });

/// <summary>
/// Answers the condition itself where a root denies the independence the calculus
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
//
// Copyright (c) 2019-2026 Angouri.
// AngouriMath is licensed under MIT.
// Details: https://github.com/asc-community/AngouriMath/blob/master/LICENSE.md.
// Website: https://am.angouri.org.
//

using AngouriMath.Core;
using AngouriMath.Extensions;
using AngouriMath.Functions.Algebra.AnalyticalSolving;
using Xunit;
using static AngouriMath.Entity;
using static AngouriMath.Entity.Set;

namespace AngouriMath.Tests.Algebra
{
/// <summary>
/// A polynomial of degree one or more has a root over the complex numbers, so where every
/// candidate a solver found for one fails its check, the solver failed, and the empty set
/// would claim there is no root. <c>(x + 1)^3 = 2</c> and
/// <c>31x^4 - 62x^3 + 33x^2 - 2x - 1 = 0</c> were answered <c>{ }</c> that way. Asked here of
/// the check itself, with candidates that fail, since no polynomial reaches it so any more.
/// </summary>
[Trait("Area", "Algebra")]
public sealed class APolynomialHasARootTest
{
[Theory]
[InlineData("x^2 - 2")]
[InlineData("(x + 1)^3 - 2")]
[InlineData("31x^4 - 62x^3 + 33x^2 - 2x - 1")]
public void APolynomialWhoseCandidatesAllFailIsLeftUnsolved(string polynomial)
=> Assert.IsType<ConditionalSet>(
StatementSolver.WithoutSpuriousRoots(new FiniteSet((Entity)5, (Entity)7), polynomial.ToEntity(), "x"));

/// <summary>The roots that hold are kept, as before.</summary>
[Fact]
public void TheRootsThatHoldAreKept()
=> Assert.Equal("{ 2 }".ToEntity(),
StatementSolver.WithoutSpuriousRoots(new FiniteSet((Entity)2, (Entity)5), "x^2 - 4".ToEntity(), "x").InnerSimplified);

/// <summary>
/// An equation that is not a polynomial can have no root, and its empty set is an answer:
/// <c>sqrt(x) = -1</c>. So can a polynomial over the reals: <c>x^2 + 1 = 0</c>.
/// </summary>
[Fact]
public void TheOthersCanHaveNoRoot()
{
Assert.Equal(Empty, StatementSolver.WithoutSpuriousRoots(new FiniteSet((Entity)1), "sqrt(x) + 1".ToEntity(), "x"));
using var _ = MathS.Settings.Codomain.Set(Domain.Real);
Assert.Equal(Empty, StatementSolver.WithoutSpuriousRoots(new FiniteSet((Entity)5), "x^2 + 1".ToEntity(), "x"));
}
}
}
Loading