Fix: Unitary Decomposition -> Conj inplace not handled correct

This commit is contained in:
h z
2024-12-15 01:21:59 +00:00
parent 1f46ce1cf0
commit dc10d86866
9 changed files with 135 additions and 23 deletions

View File

@@ -172,7 +172,6 @@ public static class ComplexMatrixExtension
{
for (int i = 1; i <= a.Dim; i++)
a[i, i] /= (a[i, i] * Complex.Conjugate(a[i, i]));
}
else
{
@@ -186,7 +185,5 @@ public static class ComplexMatrixExtension
}
}
}

View File

@@ -1,4 +1,5 @@
using System.Numerics;
using Skeleton.Algebra.Extensions;
namespace Skeleton.Algebra.FieldStructures;
@@ -119,4 +120,11 @@ public class ComplexFieldStructure : FieldStructure<Complex>
/// <inheritdoc />
public override Complex Exp(Complex x) => Complex.Exp(x);
public override Complex Sign(Complex x)
{
if(x.IsEqualApprox(0))
return Complex.Zero;
return x / x.Magnitude;
}
}

View File

@@ -1,4 +1,5 @@
using System.Numerics;
using System.Reflection.Metadata;
using Skeleton.Algebra.Extensions;
using Skeleton.DataStructure.Packs;
@@ -81,6 +82,7 @@ public abstract class FieldStructure<TScalar> : FieldStructure
/// <returns></returns>
public virtual TScalar Division(TScalar self, TScalar other)
=> Multiplication(self, MultiplicationInverse(other));
/// <summary>
/// conjugate of the scalar
/// </summary>
@@ -261,23 +263,30 @@ public abstract class FieldStructure<TScalar> : FieldStructure
return new QuadraticRoots<TScalar>(x1, x2);
}
internal TScalar WilkinsonShift(TScalar a1, TScalar b1, TScalar b2, TScalar a2)
/// <summary>
///
/// </summary>
/// <param name="x"></param>
/// <returns></returns>
public virtual TScalar Sign(TScalar x) => MultiplicationUnit;
internal TScalar WilkinsonShift(TScalar a11, TScalar a12, TScalar a21, TScalar a22)
{
QuadraticRoots<TScalar> es = QuadraticRoot(
AdditionUnit,
AdditionInverse(Addition(a1, a2)),
Subtraction(Multiplication(a1, a2), Multiplication(b1, b2))
AdditionInverse(Addition(a11, a22)),
Subtraction(Multiplication(a11, a22), Multiplication(a12, a21))
);
TScalar k = a2;
TScalar s = Addition(Addition(Abs(a1), Abs(b1)), Addition(Abs(b2), Abs(a2)));
TScalar k = a22;
TScalar s = Addition(Addition(Abs(a11), Abs(a12)), Addition(Abs(a21), Abs(a22)));
if (IsEqualApprox(s, AdditionUnit))
return k;
TScalar q = Multiplication(Division(b1, s), Division(b2, s));
TScalar q = Multiplication(Division(a12, s), Division(a21, s));
if (IsEqualApprox(q, AdditionUnit))
return k;
TScalar p = Division(
Subtraction(Division(a1, s), Division(a2, s)),
Subtraction(Division(a11, s), Division(a22, s)),
Addition(MultiplicationUnit, MultiplicationUnit)
);
TScalar r = SquareRoot(Addition(Multiplication(p, p), q));
@@ -289,6 +298,36 @@ public abstract class FieldStructure<TScalar> : FieldStructure
return k;
}
internal TScalar WilkinsonShiftV2(TScalar a11, TScalar a12, TScalar a21, TScalar a22)
{
TScalar a = a11;
TScalar b = a12;
TScalar c = a22;
TScalar two = Addition(MultiplicationUnit, MultiplicationUnit);
TScalar delta = Division(Subtraction(a, c), two);
TScalar square(TScalar x) => Multiplication(x, x);
TScalar frb = Addition (
Abs(delta),
SquareRoot(
Addition(
square(delta),
square(Abs(b))
)
)
);
return Subtraction(
c,
Division(
Multiplication(
Sign(delta),
square(Abs(b))
),
frb
)
);
}
/// <summary>
/// homomorphism from complex to this field
/// </summary>
@@ -310,5 +349,6 @@ public abstract class FieldStructure<TScalar> : FieldStructure
/// <param name="x"></param>
/// <returns></returns>
public virtual TScalar Exp(TScalar x) => MultiplicationUnit;
}

View File

@@ -1,4 +1,5 @@
using System.Numerics;
using Skeleton.Algebra.Extensions;
namespace Skeleton.Algebra.FieldStructures;
@@ -70,6 +71,13 @@ public class RealFieldStructure : FieldStructure<double>
.ToArray()
);
public override double Sign(double x)
{
if (x.IsEqualApprox(0))
return 0;
return x > 0 ? 1 : -1;
}
/// <inheritdoc />
public override double MaxError(double a) => Math.Abs(a);

View File

@@ -455,12 +455,15 @@ public abstract class Matrix<TScalar, TVector, TMatrix> : Matrix<TVector, TMatri
internal override void SelfHermitian()
{
for(int i = 1; i <= Dim; i++)
for(int j = 1; j<i;j++)
{
for (int j = 1; j < i; j++)
{
TScalar hij = Structure.Conj(this[i, j]);
TScalar hji = Structure.Conj(this[j, i]);
(this[i, j], this[j, i]) = (hji, hij);
}
this[i, i] = Structure.Conj(this[i, i]);
}
}
/// <inheritdoc />
@@ -1253,7 +1256,7 @@ public abstract class Matrix<TScalar, TVector, TMatrix> : Matrix<TVector, TMatri
return new JDPair<TMatrix>(u, d);
}
internal JDPair<TMatrix> InternalUnitaryDecomposition(bool triangle = false)
public JDPair<TMatrix> InternalUnitaryDecompositionV1(bool triangle = false)
{
int maxIters = 5000;
double firstTol = 1E-6;
@@ -1320,6 +1323,18 @@ public abstract class Matrix<TScalar, TVector, TMatrix> : Matrix<TVector, TMatri
Console.WriteLine(a.PythonRepresentation);
throw new Exception("CONVERGE MIGHT FAILED");
}
internal JDPair<TMatrix> InternalUnitaryDecomposition(bool triangle = false)
{
JDPair<TMatrix> jd = InternalUnitaryDecompositionV1(triangle);
if (IsEqualApprox(jd.J * jd.D * jd.J.Hermitian()))
return jd;
throw new Exception("IDK");
}
/// <summary>
/// eigen values of the matrix

View File

@@ -27,12 +27,21 @@ public partial class CategoryOf<TDimension>
public FNormalMatrix() { }
/// <inheritdoc />
public FNormalMatrix(IEnumerable<FVector> es, bool row = true) : base(es, row) =>
public FNormalMatrix(IEnumerable<FVector> es, bool row = true) : base(es, row)
{
if (NeedPreNormalFix())
PreNormalConstructionFix();
this.PostConstructionFix();
}
/// <inheritdoc />
public FNormalMatrix(params TScalar[] es) : base(es) =>
public FNormalMatrix(params TScalar[] es) : base(es)
{
if(NeedPreNormalFix())
PreNormalConstructionFix();
this.PostConstructionFix();
}
/// <summary>
/// construct by unitary matrix and diagonal matrix
@@ -99,6 +108,18 @@ public partial class CategoryOf<TDimension>
/// <inheritdoc />
public override IEnumerable<TScalar> EigenValues() => D.Diagonals;
protected virtual bool NeedPreNormalFix() => Property.IsNormal;
protected virtual void PreNormalConstructionFix()
{
SelfAdd(Hermitian());
TScalar two = Structure.Addition(Structure.MultiplicationUnit, Structure.MultiplicationUnit);
for (int i = 1; i <= Dim; i++)
for (int j = 1; j <= Dim; j++)
this[i, j] = Structure.Division(this[i, j], two);
}
}
}
}

View File

@@ -1,6 +1,8 @@
using System.Numerics;
using Skeleton.Algebra.AdditionalProperties;
using Skeleton.Algebra.Extensions;
using Skeleton.Algebra.FixableObjects;
using Skeleton.DataStructure.Packs.MatrixDecompositions;
namespace Skeleton.Algebra;
@@ -88,7 +90,7 @@ public static partial class CategoryOf<TDimension>
/// <returns></returns>
public static FSpecialUnitaryMatrix operator /(FSpecialUnitaryMatrix a, FSpecialUnitaryMatrix b) =>
a * b.Hermitian();
}
}

View File

@@ -110,10 +110,31 @@ public static partial class CategoryOf<TDimension>
return new(U, logd);
}
/*/// <inheritdoc />
public override JDPair<OnField<Complex>.FMatrix> EigenDecomposition() => this.UnitaryDecomposition();*/
/*
* /// <inheritdoc />
* public override JDPair<OnField<Complex>.FMatrix> EigenDecomposition() => this.UnitaryDecomposition();
* */
internal override void UnitaryFix(OnField<Complex>.FMatrix a) => a.UnitaryFix();
protected override bool NeedPreNormalFix() => !Property.IsUnitary;
protected override void PreNormalConstructionFix()
{
if (Property.IsDiagonal)
{
for (int i = 1; i <= Dim; i++)
this[i, i] /= (this[i, i] * Complex.Conjugate(this[i, i]));
}
else
{
this[1] = this[1].Normalize;
for (int i = 2; i <= Dim; i++)
{
for (int j = 1; j < i; j++)
this[i] -= this[i].ProjectionOn(this[j]);
this[i] = this[i].Normalize;
}
}
}
}
}

View File

@@ -33,15 +33,15 @@ public class CacheItem<TObject> : CacheItem
/// construct by provide a method to update the value
/// </summary>
/// <param name="rec"></param>
public CacheItem(Func<CacheItem?, TObject> rec) => ProxyCalculator = rec;
public CacheItem(Func<CacheItem, TObject> rec) => ProxyCalculator = rec;
public CacheItem() => ProxyCalculator = c => default;
protected TObject? Value { get; set; }
protected TObject Value { get; set; }
/// <summary>
/// return cached/updated value when reference is not used to calculate another cache item
/// </summary>
public virtual TObject? Get
public virtual TObject Get
{
get
{
@@ -57,14 +57,14 @@ public class CacheItem<TObject> : CacheItem
/// <summary>
/// provide trace information while calculating
/// </summary>
public Func<CacheItem, TObject?> ProxyCalculator { get; set; }
public Func<CacheItem, TObject> ProxyCalculator { get; set; }
/// <summary>
/// trace the dependency and return cached value/updated value
/// </summary>
/// <param name="d"></param>
/// <returns></returns>
public TObject? GetFrom(CacheItem d)
public TObject GetFrom(CacheItem d)
{
References.Add(d);
d.Dependencies.Add(this);
@@ -74,7 +74,7 @@ public class CacheItem<TObject> : CacheItem
/// update the formula of item value
/// </summary>
/// <param name="val"></param>
public void UpdateCalculation(Func<CacheItem, TObject?> val)
public void UpdateCalculation(Func<CacheItem, TObject> val)
{
Expire();
foreach (CacheItem item in Dependencies)