using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Azimuth; using Azimuth.DenseLinearAlgebra; namespace Azimuth.UnitTests.DenseLinearAlgebra { public class NonNegativeLeastSquaresTests : UnitTestSharp.TestFixture { public class Basic_SquareTests : UnitTestSharp.TestFixture { public void Identity_NoneBad() { var matrix = new RectangularMatrix(new Scalar[,] { { 1, 0, 0, }, { 0, 1, 0, }, { 0, 0, 1, }, }); DenseVector f = new Scalar[] { 1, 1, 1, }; DenseVector expectedX = new Scalar[] { 1, 1, 1, }; DenseVector x = new Scalar[expectedX.Count]; NonNegativeLeastSquares.SolveBasicSolution(ref matrix, ref f, ref x); CheckEqual(expectedX, x); } public void Identity_OneBad() { var matrix = new RectangularMatrix(new Scalar[,] { { 1, 0, 0, }, { 0, 1, 0, }, { 0, 0, 1, }, }); DenseVector f = new Scalar[] { 1, -1, 1, }; DenseVector x = new Scalar[3]; DenseVector expectedX = new Scalar[] { 1, 0, 1, }; NonNegativeLeastSquares.SolveBasicSolution(ref matrix, ref f, ref x); CheckEqual(expectedX, x); } public void Identity_TwoBad() { var matrix = new RectangularMatrix(new Scalar[,] { { 1, 0, 0, }, { 0, 1, 0, }, { 0, 0, 1, }, }); DenseVector f = new Scalar[] { -1, -1, 1, }; DenseVector x = new Scalar[3]; DenseVector expectedX = new Scalar[] { 0, 0, 1, }; NonNegativeLeastSquares.SolveBasicSolution(ref matrix, ref f, ref x); CheckEqual(expectedX, x); } public void Identity_AllBad() { var matrix = new RectangularMatrix(new Scalar[,] { { 1, 0, 0, }, { 0, 1, 0, }, { 0, 0, 1, }, }); DenseVector f = new Scalar[] { -1, -1, -1, }; DenseVector x = new Scalar[3]; DenseVector expectedX = new Scalar[] { 0, 0, 0, }; NonNegativeLeastSquares.SolveBasicSolution(ref matrix, ref f, ref x); CheckEqual(expectedX, x); } public void FullRank() { var matrix = new RectangularMatrix(new Scalar[,] { { 1, 0, 1, }, { 0, 2, 1, }, { 1, 1, 1, }, }); DenseVector f = new Scalar[] { 1, 4, 3, }; DenseVector x = new Scalar[3]; DenseVector expectedX = new Scalar[] { 1, 2, 0, }; NonNegativeLeastSquares.SolveBasicSolution(ref matrix, ref f, ref x); CheckEqual(expectedX, x); } public void DegenerateColumnRank() { var matrix = new RectangularMatrix(new Scalar[,] { { 1, 2, 3, }, { 1, 2, 3, }, { 1, 2, 3, }, }); DenseVector f = new Scalar[] { 1, 1, 1, }; DenseVector x = new Scalar[3]; DenseVector expectedX = new Scalar[] { 0, 0, 1.0/3.0, }; NonNegativeLeastSquares.SolveBasicSolution(ref matrix, ref f, ref x); CheckEqual(expectedX, x); } public void DegenerateRowRank() { var matrix = new RectangularMatrix(new Scalar[,] { { 1, 1, 1, }, { 2, 2, 2, }, { 3, 3, 3, }, }); DenseVector f = new Scalar[] { 1, 1, 1, }; DenseVector x = new Scalar[3]; DenseVector expectedX = new Scalar[] { 3.0/7.0, 0, 0, }; NonNegativeLeastSquares.SolveBasicSolution(ref matrix, ref f, ref x); CheckEqual(expectedX, x); } public void RemovePivots() { var matrix = new RectangularMatrix(new Scalar[,] { { 4, -5, 1, -5, -5 }, { -6, 5, -6, 7, -4 }, { -6, 5, 4, -9, -7 }, { -9, 4, -4, -10, 5 }, { 2, -5, -2, -3, 4 }, }); DenseVector f = new Scalar[] { -1, -1, -1, -1, -1, }; DenseVector expectedX = new Scalar[] { 0.349693666023578, 0.386863403894351, 0.043246014119353, 0.000000000000000, 0.130219554542247, }; var x = new DenseVector(expectedX.Count); NonNegativeLeastSquares.SolveBasicSolution(ref matrix, ref f, ref x); CheckEqual(expectedX, x); } } public class Basic_TallTests : UnitTestSharp.TestFixture { public void x32() { var matrix = new RectangularMatrix(new Scalar[,] { { 1, 0, }, { 0, 1, }, { 1, 1, }, }); DenseVector f = new Scalar[] { 1, 1, 1, }; DenseVector expectedX = new Scalar[] { 2.0/3.0, 2.0/3.0, }; DenseVector x = new Scalar[expectedX.Count]; NonNegativeLeastSquares.SolveBasicSolution(ref matrix, ref f, ref x); CheckEqual(expectedX, x); } public void x63() { var matrix = new RectangularMatrix(new Scalar[,] { { 1, 0, 0, }, { 0, 1, 0, }, { 1, 1, 0, }, { 0, 1, 2, }, { 1, 0, 3, }, { 0, 1, 4, }, }); DenseVector f = new Scalar[] { 1, 1, 1, 1, 1, 1, }; DenseVector expectedX = new Scalar[] { 0.6729857819905211, 0.6824644549763032, 0.0995260663507108, }; DenseVector x = new Scalar[expectedX.Count]; NonNegativeLeastSquares.SolveBasicSolution(ref matrix, ref f, ref x); CheckEqual(expectedX, x); } public void x32Degenerate() { var matrix = new RectangularMatrix(new Scalar[,] { { 1, 2, }, { 0, 0, }, { 1, 2, }, }); DenseVector f = new Scalar[] { 1, 1, 1, }; DenseVector expectedX = new Scalar[] { 0, 0.5, }; DenseVector x = new Scalar[expectedX.Count]; NonNegativeLeastSquares.SolveBasicSolution(ref matrix, ref f, ref x); CheckEqual(expectedX, x); } public void x63Degenerate() { var matrix = new RectangularMatrix(new Scalar[,] { { 1, 0, 2, }, { 0, 0, 0, }, { 1, 0, 2, }, { 0, 2, 4, }, { 1, 3, 8, }, { 0, 4, 8, }, }); DenseVector f = new Scalar[] { 1, 1, 1, 1, 1, 1, }; DenseVector expectedX = new Scalar[] { 0.538461538461538, 0.000000000000000, 0.115384615384615, }; DenseVector x = new Scalar[expectedX.Count]; NonNegativeLeastSquares.SolveBasicSolution(ref matrix, ref f, ref x); CheckEqual(expectedX, x); } } public class Basic_FatTests : UnitTestSharp.TestFixture { public void x23() { var matrix = new RectangularMatrix(new Scalar[,] { { 1, 0, 7, }, { 0, 1, 5, }, }); DenseVector f = new Scalar[] { 1, 1, }; DenseVector expectedX = new Scalar[] { 0.000000000000000, 0.285714285714286, 0.142857142857143, }; DenseVector x = new Scalar[expectedX.Count]; NonNegativeLeastSquares.SolveBasicSolution(ref matrix, ref f, ref x); CheckEqual(expectedX, x); } public void x36() { var matrix = new RectangularMatrix(new Scalar[,] { { 1, 0, 1, 0, 1, 0, }, { 0, 1, 1, 1, 0, 1, }, { 0, 0, 0, 2, 3, 4, }, }); DenseVector f = new Scalar[] { 1, 1, 1, }; DenseVector expectedX = new Scalar[] { 0.000000000000000, 0.000000000000000, 0.857142857142857, 0.000000000000000, 0.142857142857143, 0.142857142857143, }; DenseVector x = new Scalar[expectedX.Count]; NonNegativeLeastSquares.SolveBasicSolution(ref matrix, ref f, ref x); CheckEqual(expectedX, x); } public void x23Degenerate() { var matrix = new RectangularMatrix(new Scalar[,] { { 1, 0, 2, }, { 0, 1, 2, }, }); DenseVector f = new Scalar[] { 1, 1, }; DenseVector expectedX = new Scalar[] { 0, 0, 0.5, }; DenseVector x = new Scalar[expectedX.Count]; NonNegativeLeastSquares.SolveBasicSolution(ref matrix, ref f, ref x); CheckEqual(expectedX, x); } public void x36Degenerate() { var matrix = new RectangularMatrix(new Scalar[,] { { 1, 0, 1, 0, 1, 0, }, { 0, 1, 1, 1, 0, 1, }, { 2, 2, 4, 2, 2, 2, }, }); DenseVector f = new Scalar[] { 1, 1, 1, }; DenseVector expectedX = new Scalar[] { 0, 0, 1.0/3.0, 0, 0, 0, }; DenseVector x = new Scalar[expectedX.Count]; NonNegativeLeastSquares.SolveBasicSolution(ref matrix, ref f, ref x); CheckEqual(expectedX, x); } } public class BoundsTesting : UnitTestSharp.TestFixture { public void ExtendedForm() { var matrix = new RectangularMatrix(new Scalar[,] { { 1, 0, 7, }, { 0, 1, 5, }, }); DenseVector f = new Scalar[] { 1, 1, }; DenseVector expectedX = new Scalar[] { 0.000000000000000, 0.285714285714286, 0.142857142857143, }; DenseVector x = new Scalar[expectedX.Count]; int progress = 10; NonNegativeLeastSquares.SolveBasicSolution(ref matrix, ref f, ref x, ref progress); var expectedPivots = new List(new int[] { 1, 2, }); CheckEqual(expectedX, x); CheckEqual(14, progress); // 3 + 1 for final work } public void Bad_f_Size() { var matrix = new RectangularMatrix(new Scalar[,] { { 1, 0, 7, }, { 0, 1, 5, }, }); DenseVector f = new Scalar[] { 1, 1, 1, }; DenseVector expectedX = new Scalar[] { 0.000000000000000, 0.285714285714286, 0.142857142857143, }; DenseVector x = new Scalar[expectedX.Count]; CheckThrow(typeof(Exception)); NonNegativeLeastSquares.SolveBasicSolution(ref matrix, ref f, ref x); } public void Bad_x_Size() { var matrix = new RectangularMatrix(new Scalar[,] { { 1, 0, 7, }, { 0, 1, 5, }, }); DenseVector f = new Scalar[] { 1, 1, 1, }; DenseVector expectedX = new Scalar[] { 0, 0, }; DenseVector x = new Scalar[expectedX.Count]; CheckThrow(typeof(Exception)); NonNegativeLeastSquares.SolveBasicSolution(ref matrix, ref f, ref x); } } public class EqualityTesting : UnitTestSharp.TestFixture { public void x11_SetZero() { RectangularMatrix matrix = new Scalar[,] { { 1, }, }; DenseVector f = new Scalar[] { 0, }; DenseVector expectedX = new Scalar[] { 0 }; DenseVector x = new Scalar[expectedX.Count]; int progress = 10; NonNegativeLeastSquares.SolveBasicSolution(ref matrix, ref f, ref x, ref progress, 1); CheckEqual(expectedX, x); CheckEqual(12, progress); } public void x11_SetPositive() { RectangularMatrix matrix = new Scalar[,] { { 1, }, }; DenseVector f = new Scalar[] { 2, }; DenseVector expectedX = new Scalar[] { 2 }; DenseVector x = new Scalar[expectedX.Count]; int progress = 10; NonNegativeLeastSquares.SolveBasicSolution(ref matrix, ref f, ref x, ref progress, 1); CheckEqual(expectedX, x); CheckEqual(12, progress); } public void x11_SetNegative() { RectangularMatrix matrix = new Scalar[,] { { 1, }, }; DenseVector f = new Scalar[] { -2, }; DenseVector expectedX = new Scalar[] { -2 }; DenseVector x = new Scalar[expectedX.Count]; int progress = 10; NonNegativeLeastSquares.SolveBasicSolution(ref matrix, ref f, ref x, ref progress, 1); CheckEqual(expectedX, x); CheckEqual(12, progress); } public void x22_Identity_SetNegative() { RectangularMatrix matrix = new Scalar[,] { { 1, 0, }, { 0, 1, }, }; DenseVector f = new Scalar[] { -2, -2, }; DenseVector expectedX = new Scalar[] { -2, 0, }; DenseVector x = new Scalar[expectedX.Count]; int progress = 10; NonNegativeLeastSquares.SolveBasicSolution(ref matrix, ref f, ref x, ref progress, 1); CheckEqual(expectedX, x); CheckEqual(13, progress); } public void x22_Redundant() { RectangularMatrix matrix = new Scalar[,] { { 1, 1, }, { 1, 0, }, }; DenseVector f = new Scalar[] { 0, 1, }; DenseVector expectedX = new Scalar[] { 0.5, 0, }; DenseVector x = new Scalar[expectedX.Count]; int progress = 10; NonNegativeLeastSquares.SolveBasicSolution(ref matrix, ref f, ref x, ref progress, 0); CheckEqual(expectedX, x); CheckEqual(13, progress); } public void x22_ForceNegative() { RectangularMatrix matrix = new Scalar[,] { { 1, 1, }, { 1, 0, }, }; DenseVector f = new Scalar[] { 0, 1, }; DenseVector expectedX = new Scalar[] { 1, -1, }; DenseVector x = new Scalar[expectedX.Count]; int progress = 10; NonNegativeLeastSquares.SolveBasicSolution(ref matrix, ref f, ref x, ref progress, 2); CheckEqual(expectedX, x); CheckEqual(13, progress); } public void x22_RedundantEquality() { RectangularMatrix matrix = new Scalar[,] { { 1, 1, }, { 1, 1, }, }; DenseVector f = new Scalar[] { 1, 1, }; // The basic solution DenseVector expectedX = new Scalar[] { 1, 0, }; DenseVector x = new Scalar[expectedX.Count]; int progress = 10; NonNegativeLeastSquares.SolveBasicSolution(ref matrix, ref f, ref x, ref progress, 2); CheckEqual(expectedX, x); CheckEqual(13, progress); } public void x22_Agree() { RectangularMatrix matrix = new Scalar[,] { { 1, 1, }, { 1, 1, }, }; DenseVector f = new Scalar[] { 0, 1, }; DenseVector x = new Scalar[2]; var expectedX = new Scalar[] { 0.5, 0, }; int progress = 10; NonNegativeLeastSquares.SolveBasicSolution(ref matrix, ref f, ref x, ref progress, 2); CheckEqual(expectedX, x); CheckEqual(13, progress); } public void x22_Disagree() { RectangularMatrix matrix = new Scalar[,] { { 1, 1, }, { 1, 2, }, }; DenseVector f = new Scalar[] { 0, 1, }; DenseVector x = new Scalar[2]; var expectedX = new Scalar[] { -1, 1, }; int progress = 10; NonNegativeLeastSquares.SolveBasicSolution(ref matrix, ref f, ref x, ref progress, 2); CheckEqual(expectedX, x); CheckEqual(13, progress); } public void x23_Disagree() { RectangularMatrix matrix = new Scalar[,] { { 1, 1, 1, }, { 1, 1, 2, }, }; DenseVector f = new Scalar[] { 0, 1, }; DenseVector x = new Scalar[3]; var expectedX = new Scalar[] { -1, 0, 1, }; int progress = 10; NonNegativeLeastSquares.SolveBasicSolution(ref matrix, ref f, ref x, ref progress, 3); CheckEqual(expectedX, x); CheckEqual(14, progress); } public void x22_ForceNegative2() { RectangularMatrix matrix = new Scalar[,] { { 1, 1, }, { 1, -1, }, }; DenseVector f = new Scalar[] { 0, 1, }; DenseVector expectedX = new Scalar[] { 0.5, -0.5, }; DenseVector x = new Scalar[expectedX.Count]; int progress = 10; NonNegativeLeastSquares.SolveBasicSolution(ref matrix, ref f, ref x, ref progress, 2); CheckEqual(expectedX, x); CheckEqual(13, progress); } public void x32_SetSum() { RectangularMatrix matrix = new Scalar[,] { { 1, 1, }, { 0, 1, }, { -1, 0, }, }; DenseVector f = new Scalar[] { -2, -2, 2, }; DenseVector expectedX = new Scalar[] { -2, 0, }; DenseVector x = new Scalar[expectedX.Count]; int progress = 10; NonNegativeLeastSquares.SolveBasicSolution(ref matrix, ref f, ref x, ref progress, 1); CheckEqual(expectedX, x); CheckEqual(13, progress); } public void x32_SetSum_XPositive() { RectangularMatrix matrix = new Scalar[,] { { 1, 1, }, { 0, 1, }, { -1, 0, }, }; DenseVector f = new Scalar[] { -2, 2, -2, }; DenseVector expectedX = new Scalar[] { 0, 0, }; DenseVector x = new Scalar[expectedX.Count]; int progress = 10; NonNegativeLeastSquares.SolveBasicSolution(ref matrix, ref f, ref x, ref progress, 1); CheckEqual(expectedX, x); CheckEqual(13, progress); } public void x32_NegativeSumLDP() { // x + y >= -0 // x = -1 RectangularMatrix matrix = new Scalar[,] { { 1, 1, }, { 0, 1, }, { -1, 0, }, }; DenseVector f = new Scalar[] { 0, 0, 1, }; DenseVector expectedX = new Scalar[] { -2.0/3, 1.0/3, }; DenseVector x = new Scalar[expectedX.Count]; int progress = 10; NonNegativeLeastSquares.SolveBasicSolution(ref matrix, ref f, ref x, ref progress, 1); CheckEqual(expectedX, x); CheckEqual(13, progress); } public void x32_SetSum_NonPositive() { // Given that x + y = -2, no solution will be in the 1st quadrant, so it will choose // an element to violate (x = -2), while maintaining the equality constraints, // and then set the remaining elements to be 0. RectangularMatrix matrix = new Scalar[,] { { 1, 1, }, { 0, 1, }, { 1, 0, }, }; DenseVector f = new Scalar[] { -2, -2, -2, }; DenseVector expectedX = new Scalar[] { -2, 0, }; DenseVector x = new Scalar[expectedX.Count]; int progress = 10; NonNegativeLeastSquares.SolveBasicSolution(ref matrix, ref f, ref x, ref progress, 1); CheckEqual(expectedX, x); CheckEqual(13, progress); } public void x42_SetPoint() { RectangularMatrix matrix = new Scalar[,] { { 1, 1, }, { 1, -1 }, { 0, 1, }, { 1, 0, }, }; DenseVector f = new Scalar[] { -2, 3, -2, -2, }; DenseVector expectedX = new Scalar[] { -1.0/3, -7.0/3.0, }; DenseVector x = new Scalar[expectedX.Count]; int progress = 10; NonNegativeLeastSquares.SolveBasicSolution(ref matrix, ref f, ref x, ref progress, 2); CheckEqual(expectedX, x); CheckEqual(13, progress); } public void x24_Basic() { RectangularMatrix matrix = new Scalar[,] { { 1, 1, 0, 1, }, { 1, -1, 1, 0 }, }; DenseVector f = new Scalar[] { 0, 1, }; DenseVector expectedX = new Scalar[] { 0, 0, 1, 0, }; DenseVector x = new Scalar[expectedX.Count]; int progress = 10; NonNegativeLeastSquares.SolveBasicSolution(ref matrix, ref f, ref x, ref progress, 1); CheckEqual(expectedX, x); CheckEqual(15, progress); } public void x24_Inconsistent() { RectangularMatrix matrix = new Scalar[,] { { 1, 1, 1, }, { 1, -1, 0 }, }; DenseVector f = new Scalar[] { 0, 1, }; DenseVector expectedX = new Scalar[] { 0, 0, 1, 0, }; DenseVector x = new Scalar[expectedX.Count]; int progress = 10; CheckThrow(typeof(Exception)); NonNegativeLeastSquares.SolveBasicSolution(ref matrix, ref f, ref x, ref progress, 2); } public void x24_Redundant() { RectangularMatrix matrix = new Scalar[,] { { 1, 1, 1, 0, }, { 1, 1, 0, 1, }, }; DenseVector f = new Scalar[] { 0, 1, }; DenseVector expectedX = new Scalar[] { 0.5, 0, 0, 0, }; DenseVector x = new Scalar[expectedX.Count]; int progress = 10; NonNegativeLeastSquares.SolveBasicSolution(ref matrix, ref f, ref x, ref progress, 2); CheckEqual(expectedX, x); CheckEqual(15, progress); } } } }