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
15 changes: 15 additions & 0 deletions BREAKING-CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -521,6 +521,21 @@ around a principal `n`-th root of an `n`-th power, for a whole `n >= 2`, establi
|---|---|---|
| `"forall t in RR : t >= 0 implies sqrt(t^2) = t".ToEntity().Simplify()` | `forall t in RR : t >= 0 implies sqrt(t ^ 2) = t` | `True` |

### Membership in a union is not decided by one side alone

**Silent: a membership answered `False` is left open, where it was wrong; and some left open are decided.** Membership
in a union, an intersection and a set difference is decided from each side's by Kleene's connectives. A union was
`False` where one side left membership open and the other excluded the element: `2^89 - 1` is a Mersenne prime past
the machine word, `PP` leaves its membership open, and it was outside `PP \/ [0; 1]`. An intersection and a difference
were decided only where both sides were, and are now decided where one side settles it
([#2219](https://github.com/asc-community/AngouriMath/issues/2219)).

| Input | Was (2.6.0) | Now |
|---|---|---|
| `"(2^89 - 1) in (PP \/ [0; 1])".ToEntity().Evaled` | `False` | `618970019642690137449562111 in PP \/ [0; 1]` |
| `"(2^89 - 1) in ([0; 1] \ PP)".ToEntity().Evaled` | `618970019642690137449562111 in [0; 1] \ PP` | `False` |
| `"(2^89 - 1) in (PP \ [0; 10^30])".ToEntity().Evaled` | `618970019642690137449562111 in PP \ [0; 1000000000000000000000000000000]` | `False` |

### A system is not answered with a copy of one of its rows

**Silent: a repeated row goes.** Two branches of an elimination can reach one solution, and each was answered: two
Expand Down
3 changes: 3 additions & 0 deletions Sources/.editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -466,6 +466,9 @@ file_header_template=\nCopyright (c) 2019-2026 Angouri.\nAngouriMath is licensed
[Tests/UnitTests/Core/Sets/PrimeSetTest.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/Core/Sets/MembershipInASetOperationTest.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/Calculus/InverseHyperbolicSecantIntegralTest.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
50 changes: 37 additions & 13 deletions Sources/AngouriMath/Core/Entity/Omni/Entity.Omni.Classes.cs
Original file line number Diff line number Diff line change
Expand Up @@ -827,9 +827,23 @@ public override bool TryContains(Entity entity, out bool contains)
{
contains = false;
if (Left is not Set left || Right is not Set right) return false;
if (left.TryContains(entity, out contains) && contains) return true;
if (right.TryContains(entity, out contains)) return true;
return false;
// Kleene's or: a member of either side is a member, and an element is outside only
// where both sides decide it is. One side undecided and the other excluding it leaves
// it undecided: 2^89 - 1 in PP \/ [0; 1] is not False, the number being prime.
// https://github.com/asc-community/AngouriMath/issues/2219
var leftDecided = left.TryContains(entity, out var inLeft);
if (leftDecided && inLeft)
{
contains = true;
return true;
}
var rightDecided = right.TryContains(entity, out var inRight);
if (rightDecided && inRight)
{
contains = true;
return true;
}
return leftDecided && rightDecided;
}

internal override Priority Priority => Priority.Union;
Expand Down Expand Up @@ -876,12 +890,17 @@ public override bool TryContains(Entity entity, out bool contains)
contains = false;
if (Left is not Set left || Right is not Set right)
return false;
if (left.TryContains(entity, out var leftContains) && right.TryContains(entity, out var rightContains))
{
contains = leftContains && rightContains;
// Kleene's and: an element either side decides is outside is outside, whatever the
// other says, and a member only where both decide it is.
// https://github.com/asc-community/AngouriMath/issues/2219
var leftDecided = left.TryContains(entity, out var inLeft);
if (leftDecided && !inLeft)
return true;
}
return false;
var rightDecided = right.TryContains(entity, out var inRight);
if (rightDecided && !inRight)
return true;
contains = leftDecided && rightDecided;
return contains;
}

internal override Priority Priority => Priority.Intersection;
Expand Down Expand Up @@ -930,12 +949,17 @@ public override bool TryContains(Entity entity, out bool contains)
contains = false;
if (Left is not Set left || Right is not Set right)
return false;
if (left.TryContains(entity, out var leftContains) && right.TryContains(entity, out var rightContains))
{
contains = leftContains && !rightContains;
// In the left and not in the right, by Kleene's and: outside where the left decides it
// is not a member or the right decides it is, whatever the other says.
// https://github.com/asc-community/AngouriMath/issues/2219
var leftDecided = left.TryContains(entity, out var inLeft);
if (leftDecided && !inLeft)
return true;
}
return false;
var rightDecided = right.TryContains(entity, out var inRight);
if (rightDecided && inRight)
return true;
contains = leftDecided && rightDecided;
return contains;
}

internal override Priority Priority => Priority.SetMinus;
Expand Down
4 changes: 3 additions & 1 deletion Sources/Tests/UnitTests/Core/Sets/Contains.cs
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,9 @@ public sealed class Contains
[InlineData("{x} \\ {x}", "x", false)]
[InlineData("{x} \\ {y}", "1", false, false)]
[InlineData("{x} \\ {y}", "z", false, false)]
[InlineData("{x} \\ {1}", "1", false, false)]
// 1 is in {1}, and so outside the difference whatever x is: decided, by Kleene's and.
// https://github.com/asc-community/AngouriMath/issues/2219
[InlineData("{x} \\ {1}", "1", false)]
[InlineData("{x} \\ {1}", "x", false, false)]

// A closed non-leaf is not a number and not a boolean, so it is a member of
Expand Down
54 changes: 54 additions & 0 deletions Sources/Tests/UnitTests/Core/Sets/MembershipInASetOperationTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
//
// 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;
using AngouriMath.Extensions;
using Xunit;
using static AngouriMath.Entity;

namespace AngouriMath.Tests.Core.Sets
{
/// <summary>
/// Membership in a union, an intersection and a difference of sets is decided from each side's by Kleene's
/// connectives, where a side may leave it open: <c>2^89 - 1</c>, a Mersenne prime, is past the machine word
/// and its membership in <c>PP</c> is left open. A union of <c>PP</c> with a set excluding it was
/// <c>False</c>. <a href="https://github.com/asc-community/AngouriMath/issues/2219">#2219</a>
/// </summary>
[Trait("Area", "Core")]
public sealed class MembershipInASetOperationTest
{
[Theory]
// One side open, the other excluding it: open, in either order.
[InlineData("(2^89 - 1) in (PP \\/ [0; 1])")]
[InlineData("(2^89 - 1) in ([0; 1] \\/ PP)")]
[InlineData("(2^89 - 1) in (PP \\/ (-oo; 0))")]
[InlineData("(2^89 - 1) in (PP \\/ ({2} \\/ [5; 7]))")]
// One side open, the other containing it: open for an intersection, and for a difference whose right side is open.
[InlineData("(2^89 - 1) in (PP /\\ [0; 10^30])")]
[InlineData("(2^89 - 1) in ([0; 10^30] \\ PP)")]
[InlineData("(2^89 - 1) in (PP \\ [0; 1])")]
public void LeftOpen(string input)
=> Assert.IsType<Set.Inf>(input.ToEntity().Evaled);

[Theory]
// A union holds where either side does.
[InlineData("(2^89 - 1) in (PP \\/ [0; 10^30])", "True")]
[InlineData("2 in (PP \\/ [5; 7])", "True")]
[InlineData("6 in (PP \\/ [5; 7])", "True")]
[InlineData("4 in (PP \\/ [5; 7])", "False")]
// An intersection fails where either side does.
[InlineData("(2^89 - 1) in (PP /\\ (-oo; 0))", "False")]
[InlineData("(2^89 - 1) in (PP /\\ [0; 1])", "False")]
[InlineData("7 in (PP /\\ [5; 10^30])", "True")]
// A difference fails where its left side does, or its right side holds.
[InlineData("(2^89 - 1) in ([0; 1] \\ PP)", "False")]
[InlineData("(2^89 - 1) in (PP \\ [0; 10^30])", "False")]
[InlineData("7 in (PP \\ [0; 5])", "True")]
public void Decided(string input, string expected)
=> Assert.Equal(expected.ToEntity(), input.ToEntity().Evaled);
}
}
Loading