/// <summary> /// /// </summary> /// <param name="A"></param> /// <param name="indexes"></param> /// <param name="work"></param> /// <returns></returns> public static DoubleMatrix1D Permute(DoubleMatrix1D A, int[] indexes, double[] work) { // check validity int size = A.Size; if (indexes.Length != size) { throw new IndexOutOfRangeException("invalid permutation"); } /* * int i=size; * int a; * while (--i >= 0 && (a=indexes[i])==i) if (a < 0 || a >= size) throw new IndexOutOfRangeException("invalid permutation"); * if (i<0) return; // nothing to permute */ if (work == null || size > work.Length) { work = A.ToArray(); } else { A.ToArray(ref work); } for (int i = size; --i >= 0;) { A[i] = work[indexes[i]]; } return(A); }
/// <summary> /// Update the SVD with the addition of a new column. /// </summary> /// <param name="c"> /// The new column. /// </param> /// <param name="wantV"> /// Whether the matrix V is needed. /// </param> public void Update(DoubleMatrix1D c, bool wantV) { int nRows = c.Size - _m; if (nRows > 0) { _u = DoubleFactory2D.Dense.AppendRows(_u, new SparseDoubleMatrix2D(nRows, _n)); _m = c.Size; } else if (nRows < 0) { c = DoubleFactory1D.Sparse.AppendColumns(c, DoubleFactory1D.Sparse.Make(-nRows)); } var d = DoubleFactory2D.Dense.Make(c.ToArray(), c.Size); // l = U'd is the eigencoding of d var l = _u.ViewDice().ZMult(d, null); ////var uu = _u.ZMult(_u.ViewDice(), null); // Ul = UU'd ////var ul = uu.ZMult(d, null); var ul = _u.ZMult(l, null); // h = d - UU'd = d - Ul is the component of d orthogonal to the subspace spanned by U ////var h = d.Copy().Assign(uu.ZMult(d, null), BinaryFunctions.Minus); ////var h = d.Copy().Assign(ul, BinaryFunctions.Minus); // k is the projection of d onto the subspace othogonal to U var k = Math.Sqrt(d.Aggregate(BinaryFunctions.Plus, a => a * a) - (2 * l.Aggregate(BinaryFunctions.Plus, a => a * a)) + ul.Aggregate(BinaryFunctions.Plus, a => a * a)); // truncation if (k == 0 || double.IsNaN(k)) { return; } _n++; // j = d - UU'd = d - Ul is an orthogonal basis for the component of d orthogonal to the subspace spanned by U ////var j = h.Assign(UnaryFunctions.Div(k)); var j = d.Assign(ul, BinaryFunctions.Minus).Assign(UnaryFunctions.Div(k)); // Q = [ S, l; 0, ||h||] var q = DoubleFactory2D.Sparse.Compose( new[] { new[] { S, l }, new[] { null, DoubleFactory2D.Dense.Make(1, 1, k) } }); var svdq = new SingularValueDecomposition(q, true, wantV, true); _u = DoubleFactory2D.Dense.AppendColumns(_u, j).ZMult(svdq.U, null); _s = svdq.SingularValues; if (wantV) { _v = DoubleFactory2D.Dense.ComposeDiagonal(_v, DoubleFactory2D.Dense.Identity(1)).ZMult( svdq.V, null); } }
/// <summary> /// 3-d OLAP cube operator; Fills all cells of the given vectors into the given histogram. /// If you use Hep.Aida.Ref.Converter.ToString(histo) on the result, the OLAP cube of x-"column" vsd y-"column" vsd z-"column", summing the weights "column" will be printed. /// For example, aggregate sales by product by region by time. /// <p> /// Computes the distinct values of x and y and z, yielding histogram axes that capture one distinct value per bin. /// Then fills the histogram. /// </summary> /// <param name="x"></param> /// <param name="y"></param> /// <param name="z"></param> /// <param name="weights"></param> /// <returns>the histogram containing the cube.</returns> /// <excption cref="ArgumentException">if <i>x.Count != y.Count || x.Count != z.Count || x.Count != weights.Count</i>.</excption> public static Hep.Aida.IHistogram3D cube(DoubleMatrix1D x, DoubleMatrix1D y, DoubleMatrix1D z, DoubleMatrix1D weights) { if (x.Size != y.Size || x.Size != z.Size || x.Size != weights.Size) { throw new ArgumentException("vectors must have same size"); } var epsilon = 1.0E-9; var distinct = new DoubleArrayList(); var vals = new double[x.Size]; var sorted = new DoubleArrayList(vals); // compute distinct values of x vals = x.ToArray(); // copy x into vals sorted.Sort(); Cern.Jet.Stat.Descriptive.Frequencies(sorted, distinct, null); // since bins are right-open [from,to) we need an additional dummy bin so that the last distinct value does not fall into the overflow bin if (distinct.Count > 0) { distinct.Add(distinct[distinct.Count - 1] + epsilon); } distinct.TrimToSize(); Hep.Aida.IAxis xaxis = new Hep.Aida.Ref.VariableAxis(distinct.ToArray()); // compute distinct values of y vals = y.ToArray(); sorted.Sort(); Cern.Jet.Stat.Descriptive.Frequencies(sorted, distinct, null); // since bins are right-open [from,to) we need an additional dummy bin so that the last distinct value does not fall into the overflow bin if (distinct.Count > 0) { distinct.Add(distinct[distinct.Count - 1] + epsilon); } distinct.TrimToSize(); Hep.Aida.IAxis yaxis = new Hep.Aida.Ref.VariableAxis(distinct.ToArray()); // compute distinct values of z vals = z.ToArray(); sorted.Sort(); Cern.Jet.Stat.Descriptive.Frequencies(sorted, distinct, null); // since bins are right-open [from,to) we need an additional dummy bin so that the last distinct value does not fall into the overflow bin if (distinct.Count > 0) { distinct.Add(distinct[distinct.Count - 1] + epsilon); } distinct.TrimToSize(); Hep.Aida.IAxis zaxis = new Hep.Aida.Ref.VariableAxis(distinct.ToArray()); Hep.Aida.IHistogram3D histo = new Hep.Aida.Ref.Histogram3D("Cube", xaxis, yaxis, zaxis); return(Histogram(histo, x, y, z, weights)); }
/// <summary> /// Initializes a new instance of the <see cref="SingularValueDecomposition"/> class with a vector (the first column). /// </summary> /// <param name="arg"> /// A vector. /// </param> /// <exception cref="ArgumentException"> /// If <code>a.Rows < a.Columns</code>. /// </exception> public SingularValueDecomposition(DoubleMatrix1D arg) { BatchSVD(DoubleFactory2D.Dense.Make(arg.ToArray(), arg.Size), true, true, true); }