diff --git a/BREAKING-CHANGES.md b/BREAKING-CHANGES.md index b23a3d5b6..c29b33258 100644 --- a/BREAKING-CHANGES.md +++ b/BREAKING-CHANGES.md @@ -53,6 +53,8 @@ read first. | loud | `round(x)`, `min(a, b)`, `max(a, b)`, `gcd(a, b)` | `UnrecognizedFunctionParseException` | the functions | | loud | 28 members deprecated since 1.x | obsolete but present | removed | | loud | `Latexise`, `ILatexiseable`, `entity_latexise` | the British spelling | `Latexize`, `ILatexizeable`, `entity_latexize` | +| loud | `MathS.Quantum.Factorise` | one letter from the unrelated `Entity.Factorize` | `MathS.Quantum.TensorFactorize` | +| loud | `MathS.Quantum.IsNormalised` | the British spelling | `MathS.Quantum.IsNormalized` | | loud | the target frameworks | `net7.0;netstandard2.0` | `netstandard2.0;net8.0;net10.0` | | **silent** | `abs(x) = c` for a negative `c` | a set of non-solutions | the empty set | @@ -144,17 +146,42 @@ forwarding member: this release is the one that removed 28 members that accumula so adding a permanent one here would undo that on the same day. The compiler reports each site, and the fix is mechanical. -`MathS.Quantum.Factorise` keeps its spelling for now. Renaming it to `Factorize` would give the -library two public `Factorize` methods doing unrelated things — expression factoring on `Entity`, -tensor factorisation on a quantum state — which is a worse outcome than the inconsistency. It wants -a distinguishing name rather than a spelling change, and that is not decided here. - **Downstream.** [`CSharpMath.Evaluation`](https://github.com/verybadcat/CSharpMath) reads LaTeX produced here back into an `Entity` and calls this method. It is unaffected until it moves to 2.0, at which point it needs the new name. [#840](https://github.com/asc-community/AngouriMath/issues/840). +### `MathS.Quantum.Factorise` is now `MathS.Quantum.TensorFactorize` + +| | was | is | +|---|---|---| +| the method | `MathS.Quantum.Factorise(Entity)` | `MathS.Quantum.TensorFactorize(Entity)` | + +The old name differed by one letter from `Entity.Factorize`, which does something else entirely — +algebraic factoring of an expression, against tensor factorisation of a quantum state. Both take an +`Entity` and return an `Entity`, so nothing but the name distinguished them, and the name barely +did. + +Renaming it to `Factorize` would have made the spelling uniform and the API worse: two public +`Factorize` methods doing unrelated things. `MathS.Quantum` already holds the inverse operation as +`TensorExpand`, so `TensorFactorize` states the domain and the direction, pairs with its inverse, +and ends the collision. The spelling is fixed as a side effect rather than as the point. + +**What breaks.** Every call to `MathS.Quantum.Factorise`. There is no forwarding member, for the +same reason as above. The compiler reports each site. + +`MathS.Quantum.IsNormalised` is renamed to `IsNormalized` in the same pass. It carries no collision, +only the spelling — but it is a public member, so 2.0 is equally the last release that can change +it, and leaving it would have meant shipping one British member after two renames made expressly to +remove them. + +With these two, the public surface has one spelling throughout. That is checkable rather than +asserted: `PublicApi.txt` is the recorded surface, and it now contains no `-ise`, `-ised` or +`-isation` member. + +[#843](https://github.com/asc-community/AngouriMath/issues/843). + --- ## Parsing diff --git a/Sources/AngouriMath/Convenience/MathS.cs b/Sources/AngouriMath/Convenience/MathS.cs index 7412b1415..3b0b1856c 100644 --- a/Sources/AngouriMath/Convenience/MathS.cs +++ b/Sources/AngouriMath/Convenience/MathS.cs @@ -6867,30 +6867,30 @@ public static Entity Ket(params int[] qubits) /// all, and a product state such as (|0>+|1>)(|0>+|1>), whose /// separability this does not yet detect. /// - public static Entity Factorise(Entity state) - => Functions.Quantum.Factorisation.Factorise(state) ?? state; + public static Entity TensorFactorize(Entity state) + => Functions.Quantum.Factorization.TensorFactorize(state) ?? state; /// /// A product of states over consecutive qubits multiplied back out into a single - /// superposition -- the inverse of Factorise -- or the expression unchanged + /// superposition -- the inverse of TensorFactorize -- or the expression unchanged /// where it is not such a product. /// public static Entity TensorExpand(Entity state) - => Functions.Quantum.Factorisation.TensorExpand(state) ?? state; + => Functions.Quantum.Factorization.TensorExpand(state) ?? state; /// /// Whether the amplitudes square-sum to one, or where that /// cannot be settled -- a symbolic amplitude need not have a decidable modulus. /// - public static bool? IsNormalised(Entity state) - => Functions.Quantum.Factorisation.IsNormalised(state); + public static bool? IsNormalized(Entity state) + => Functions.Quantum.Factorization.IsNormalized(state); /// /// Whether two states differ only by a global phase, which is the difference no /// measurement can see -- or where that cannot be settled. /// public static bool? EqualUpToGlobalPhase(Entity left, Entity right) - => Functions.Quantum.Factorisation.EqualUpToGlobalPhase(left, right); + => Functions.Quantum.Factorization.EqualUpToGlobalPhase(left, right); } /// diff --git a/Sources/AngouriMath/Functions/Quantum/Factorisation.cs b/Sources/AngouriMath/Functions/Quantum/Factorization.cs similarity index 97% rename from Sources/AngouriMath/Functions/Quantum/Factorisation.cs rename to Sources/AngouriMath/Functions/Quantum/Factorization.cs index b5abf5972..50097890d 100644 --- a/Sources/AngouriMath/Functions/Quantum/Factorisation.cs +++ b/Sources/AngouriMath/Functions/Quantum/Factorization.cs @@ -35,13 +35,13 @@ namespace AngouriMath.Functions.Quantum /// is a rank-one test on the amplitudes across a bipartition -- a different algorithm, /// belonging to this file rather than to the spine, and not written yet. /// - internal static class Factorisation + internal static class Factorization { /// /// The state rewritten as a product, or where it is not a state /// or has no qubit in a definite basis state at either end. /// - internal static Entity? Factorise(Entity expr) + internal static Entity? TensorFactorize(Entity expr) { if (QuantumState.TryRead(expr) is not { } state || state.IsEmpty) return null; @@ -76,7 +76,7 @@ internal static class Factorisation /// superposition, or where the expression is not such a product. /// /// - /// The inverse of , and the reason it is here rather than on the + /// The inverse of , and the reason it is here rather than on the /// spine: within one state the qubits are a fixed width and combining two kets overlays /// them, while a *product* of states concatenates their widths. Those are two different /// monoids on the same type, and only the first is what @@ -143,7 +143,7 @@ private static SparseTerms Slice(SparseTerms state, int from, int to) /// the library. Left to Simplify to settle rather than evaluated numerically, /// so 1/sqrt(2) is recognised exactly. /// - internal static bool? IsNormalised(Entity expr) + internal static bool? IsNormalized(Entity expr) { if (QuantumState.TryRead(expr) is not { } state || state.IsEmpty) return null; diff --git a/Sources/Tests/UnitTests/Algebra/QuantumStateTest.cs b/Sources/Tests/UnitTests/Algebra/QuantumStateTest.cs index f387ed2ac..259daaaae 100644 --- a/Sources/Tests/UnitTests/Algebra/QuantumStateTest.cs +++ b/Sources/Tests/UnitTests/Algebra/QuantumStateTest.cs @@ -57,12 +57,12 @@ public void OppositeAmplitudesCancel() => [Theory] [InlineData(true)] - public void TheStandardStatesAreNormalised(bool _) + public void TheStandardStatesAreNormalized(bool _) { - Assert.True(MathS.Quantum.IsNormalised(Bell)); - Assert.True(MathS.Quantum.IsNormalised(Product)); - Assert.True(MathS.Quantum.IsNormalised(Ghz)); - Assert.True(MathS.Quantum.IsNormalised(Ket(0, 1))); + Assert.True(MathS.Quantum.IsNormalized(Bell)); + Assert.True(MathS.Quantum.IsNormalized(Product)); + Assert.True(MathS.Quantum.IsNormalized(Ghz)); + Assert.True(MathS.Quantum.IsNormalized(Ket(0, 1))); } /// @@ -73,23 +73,23 @@ public void TheStandardStatesAreNormalised(bool _) [Fact] public void AnAmplitudeInFrontIsReadTheSameAsADivisor() { - Assert.True(MathS.Quantum.IsNormalised(1 / Sqrt2 * (Ket(0, 0) + Ket(1, 1)))); + Assert.True(MathS.Quantum.IsNormalized(1 / Sqrt2 * (Ket(0, 0) + Ket(1, 1)))); AssertSame(Ket(0) * (Ket(0) + Ket(1)) * 2, - MathS.Quantum.Factorise(2 * (Ket(0, 0) + Ket(0, 1)))); + MathS.Quantum.TensorFactorize(2 * (Ket(0, 0) + Ket(0, 1)))); } [Fact] - public void AnUnnormalisedStateIsNotNormalised() + public void AnUnnormalizedStateIsNotNormalized() { - Assert.False(MathS.Quantum.IsNormalised(Ket(0, 0) + Ket(1, 1))); - Assert.False(MathS.Quantum.IsNormalised(2 * Ket(0))); + Assert.False(MathS.Quantum.IsNormalized(Ket(0, 0) + Ket(1, 1))); + Assert.False(MathS.Quantum.IsNormalized(2 * Ket(0))); } [Fact] public void SomethingThatIsNotAStateHasNoAnswer() { - Assert.Null(MathS.Quantum.IsNormalised("x + 1".ToEntity())); - Assert.Null(MathS.Quantum.IsNormalised("apply(ket, 5)".ToEntity())); + Assert.Null(MathS.Quantum.IsNormalized("x + 1".ToEntity())); + Assert.Null(MathS.Quantum.IsNormalized("apply(ket, 5)".ToEntity())); } // ---- factorisation ---- @@ -102,13 +102,13 @@ public void SomethingThatIsNotAStateHasNoAnswer() [Fact] public void ADefiniteQubitAtEitherEndFactorsOut() { - var factored = MathS.Quantum.Factorise(Ket(0, 0, 1) + Ket(0, 1, 1)); + var factored = MathS.Quantum.TensorFactorize(Ket(0, 0, 1) + Ket(0, 1, 1)); AssertSame(Ket(0) * (Ket(0) + Ket(1)) * Ket(1), factored); } [Fact] public void ADefiniteLeadingQubitFactorsOutAlone() => - AssertSame(Ket(0) * (Ket(0) + Ket(1)) / Sqrt2, MathS.Quantum.Factorise(Product)); + AssertSame(Ket(0) * (Ket(0) + Ket(1)) / Sqrt2, MathS.Quantum.TensorFactorize(Product)); /// /// **Entanglement is the absence of this.** Neither qubit of a Bell state has a @@ -118,8 +118,8 @@ public void ADefiniteLeadingQubitFactorsOutAlone() => [Fact] public void AnEntangledStateDoesNotFactor() { - AssertSame(Bell, MathS.Quantum.Factorise(Bell)); - AssertSame(Ghz, MathS.Quantum.Factorise(Ghz)); + AssertSame(Bell, MathS.Quantum.TensorFactorize(Bell)); + AssertSame(Ghz, MathS.Quantum.TensorFactorize(Ghz)); } /// @@ -132,7 +132,7 @@ public void AnEntangledStateDoesNotFactor() public void SeparabilityWithoutADefiniteQubitIsNotYetDetected() { var uniform = Ket(0, 0) + Ket(0, 1) + Ket(1, 0) + Ket(1, 1); - AssertSame(uniform, MathS.Quantum.Factorise(uniform)); + AssertSame(uniform, MathS.Quantum.TensorFactorize(uniform)); } // ---- round trip ---- @@ -147,7 +147,7 @@ public void SeparabilityWithoutADefiniteQubitIsNotYetDetected() [InlineData("(0,0,1)+(0,1,1)")] [InlineData("(0,0)+(0,1)")] [InlineData("(1,0,0)+(1,0,1)")] - public void ExpandingAFactorisationReturnsTheOriginal(string which) + public void ExpandingATensorFactorizationReturnsTheOriginal(string which) { var original = which switch { @@ -155,7 +155,7 @@ public void ExpandingAFactorisationReturnsTheOriginal(string which) "(0,0)+(0,1)" => Ket(0, 0) + Ket(0, 1), _ => Ket(1, 0, 0) + Ket(1, 0, 1), }; - var roundTripped = MathS.Quantum.TensorExpand(MathS.Quantum.Factorise(original)); + var roundTripped = MathS.Quantum.TensorExpand(MathS.Quantum.TensorFactorize(original)); AssertSame(original, roundTripped); } diff --git a/Sources/Tests/UnitTests/Common/PublicApi.txt b/Sources/Tests/UnitTests/Common/PublicApi.txt index 8b018d2c0..b8f1bc72f 100644 --- a/Sources/Tests/UnitTests/Common/PublicApi.txt +++ b/Sources/Tests/UnitTests/Common/PublicApi.txt @@ -2300,10 +2300,10 @@ AngouriMath.MathS+Numbers.Create(System.Int64) : AngouriMath.Entity+Number+Integ AngouriMath.MathS+Numbers.Create(System.Numerics.Complex) : AngouriMath.Entity+Number+Complex AngouriMath.MathS+Numbers.CreateRational(PeterO.Numbers.EInteger, PeterO.Numbers.EInteger) : AngouriMath.Entity+Number+Rational AngouriMath.MathS+Quantum.EqualUpToGlobalPhase(AngouriMath.Entity, AngouriMath.Entity) : System.Nullable -AngouriMath.MathS+Quantum.Factorise(AngouriMath.Entity) : AngouriMath.Entity -AngouriMath.MathS+Quantum.IsNormalised(AngouriMath.Entity) : System.Nullable +AngouriMath.MathS+Quantum.IsNormalized(AngouriMath.Entity) : System.Nullable AngouriMath.MathS+Quantum.Ket(System.Int32[]) : AngouriMath.Entity AngouriMath.MathS+Quantum.TensorExpand(AngouriMath.Entity) : AngouriMath.Entity +AngouriMath.MathS+Quantum.TensorFactorize(AngouriMath.Entity) : AngouriMath.Entity AngouriMath.MathS+Series.Maclaurin(AngouriMath.Entity, System.Int32, AngouriMath.Entity+Variable[]) : AngouriMath.Entity AngouriMath.MathS+Series.Taylor(AngouriMath.Entity, System.Int32, System.ValueTuple[]) : AngouriMath.Entity AngouriMath.MathS+Series.Taylor(AngouriMath.Entity, System.Int32, System.ValueTuple[]) : AngouriMath.Entity