/* Copyright (C) 2002 Univ. of Massachusetts Amherst, Computer Science Dept. This file is part of "MALLET" (MAchine Learning for LanguagE Toolkit). http://www.cs.umass.edu/~mccallum/mallet This software is provided under the terms of the Common Public License, version 1.0, as published by http://www.opensource.org. For further information, see the file `LICENSE' included with this distribution. */ /** @author Andrew McCallum <a href="mailto:mccallum@cs.umass.edu">mccallum@cs.umass.edu</a> */ package cc.mallet.types; import java.util.logging.*; import java.util.Arrays; import cc.mallet.types.Matrix; import cc.mallet.util.MalletLogger; @Deprecated // This class is very sparsely used, and I think we can get rid of it. -akm 1/2008 // TODO Remove this class public final class Matrix2 extends DenseMatrix { private static Logger logger = MalletLogger.getLogger(Matrix2.class.getName()); int nr, nc; public Matrix2 (double[] values, int nr, int nc) { assert (values.length == nr * nc); this.values = values; this.nr = nr; this.nc = nc; } public Matrix2 (int nr, int nc) { this (new double[nr * nc], nr, nc); } public Matrix2 (double[][] values) { this.nr = values.length; this.nc = values[0].length; for (int i = 1; i < nr; i++) if (values[i].length != nc) throw new IllegalArgumentException ("Trying to initialize Matrix with array having columns to different lengths."); this.values = new double[nr * nc]; for (int i = 0; i < nr; i++) System.arraycopy (values[i], 0, values, i*nc, nc); } public Matrix2 (double value, int nr, int nc) { this.nr = nr; this.nc = nc; this.values = new double[nr * nc]; Arrays.fill (this.values, value); } public int getNumDimensions () { return 2; } public int getDimensions (int[] sizes) { sizes[0] = nr; sizes[1] = nc; return 2; } public double value (int rowIndex, int colIndex) { return values[(nc * rowIndex) + colIndex]; } public final void arrayCopyInto (double[] array, int startingArrayIndex) { System.arraycopy (values, 0, array, startingArrayIndex, values.length); } // Copy the contents of double[] array into this Matrix2, starting // at index i in the array, and continuing to fill all of this Matrix2. public final void arrayCopyFrom (double[] array, int startingArrayIndex) { System.arraycopy (array, startingArrayIndex, values, 0, values.length); } public void setValue (int rowIndex, int colIndex, double value) { values[(nc * rowIndex) + colIndex] = value; } public boolean sizeMatches (ConstantMatrix m) { if (m instanceof Matrix2) return (((Matrix2)m).nr == nr && ((Matrix2)m).nc == nc); int[] otherDims = new int[10]; int numDimensions = getDimensions (otherDims); return (numDimensions == 2 && otherDims[0] == nr && otherDims[1] == nc); } public boolean sizeMatches (Matrix2 m) { return (m.nr == nr && m.nc == nc); } public int getNumRows () { return nr; } public int getNumCols () { return nc; } public Matrix2 transpose () { Matrix2 ret = new Matrix2 (nc, nr); for (int i = 0; i < nr; i++) for (int j = 0; j < nc; j++) ret.values[j*nr+i] = values[i*nc+j]; return ret; } // The Matrix interface public final double value (int[] indices) { assert (indices.length == 2); return values[indices[0]*nc+indices[1]]; } public final void setValue (int[] indices, double val) { assert (indices.length == 2); values[indices[0]*nc+indices[1]] = val; } // Access using a single index public final int singleIndex (int[] indices) { assert (indices.length == 2); return indices[indices[0]*nc+indices[1]]; } public final void singleToIndices (int i, int[] indices) { assert (indices.length == 2); assert (i < nc * nr); indices[0] = i/nc; indices[1] = i%nc; } public final double singleValue (int i) { return values[i]; } public final void setSingle (int i, double value) { values[i] = value; } public final int singleSize () { return nc * nr; } public final ConstantMatrix cloneMatrix () { return cloneMatrix2 (); } public final Matrix2 cloneMatrix2 () { Matrix2 ret = new Matrix2 (nr, nc); System.arraycopy (values, 0, ret.values, 0, values.length); return ret; } public final void setAll (double v) { for (int i = 0; i < values.length; i++) values[i] = v; } /** If "ifSelected" is false, it reverses the selection. If "fselection" is null, this implies that all features are selected; all values will be changed unless "ifSelected" is false. */ public final void setAll (double v, FeatureSelection fselection, boolean ifSelected) { if (fselection == null) { if (ifSelected == true) { logger.info ("Matrix2.setAll using FeatureSelection==null"); setAll (v); } } else { logger.info ("Matrix2.setAll using FeatureSelection"); for (int i = 0; i < values.length; i++) if (fselection.contains(i) ^ !ifSelected) values[i] = v; } } /** If "ifSelected" is false, it reverses the selection. If "fselection" is null, this implies that all features are selected; all values in the row will be changed unless "ifSelected" is false. */ public final void rowSetAll (int ri, double v, FeatureSelection fselection, boolean ifSelected) { assert (ri < nr); if (fselection == null) { if (ifSelected == true) { for (int ci = 0; ci < nc; ci++) values[ri*nc+ci] = v; } } else { // xxx Temporary check for full selection //assert (fselection.nextDeselectedIndex (0) == nc); for (int ci = 0; ci < nc; ci++) if (fselection.contains(ci) ^ !ifSelected) values[ri*nc+ci] = v; } } public final void plusEquals (int ri, int ci, double value) { assert (ri < nr); assert (ci < nc); values[ri*nc+ci] += value; } public final void rowPlusEquals (int ri, Vector v, double factor) { assert (ri < nr); for (int vli = 0; vli < v.numLocations(); vli++) { //System.out.println ("Matrix2 values.length="+values.length+" index="+(ri*nc+v.indexAtLocation(vli))+" ri="+ri+" nc="+nc+" v.indexAtLocation("+vli+")="+v.indexAtLocation(vli)); values[ri*nc+v.indexAtLocation(vli)] += v.valueAtLocation(vli) * factor; } } //added by Fuchun public final void rowPlusEquals (int ri, double v, double factor) { assert (ri < nr); for (int vli = 0; vli < nc; vli++) { values[ri*nc+vli] += v * factor; } } public final void columnPlusEquals (int ci, Vector v, double factor) { assert (ci < nc); for (int vli = 0; vli < v.numLocations(); vli++) values[v.indexAtLocation(vli)*nc+ci] += v.valueAtLocation(vli) * factor; } //added by Fuchun public final void columnPlusEquals (int ci, double v, double factor) { assert (ci < nc); for (int vli = 0; vli < nr; vli++) values[vli*nc+ci] += v* factor; } public final double rowDotProduct (int ri, Vector v) { double ret = 0; for (int cil = 0; cil < v.numLocations(); cil++) { int ci = v.indexAtLocation (cil); // Just skip it if ci is beyond the boundaries of this matrix; // everything outside is assumed to have zero value. if (ci < nc) ret += values[ri*nc+ci] * v.valueAtLocation(cil); } return ret; } /** Skip all column indices higher than "maxCi". This lets you store non-vocabulary based parameters in the high column indices, without fearing that they may later be included by accident if the dictionary grows. You may pass null for selection. */ public final double rowDotProduct (int ri, Vector v, int maxCi, FeatureSelection selection) { double ret = 0; if (selection != null) { for (int cil = 0; cil < v.numLocations(); cil++) { int ci = v.indexAtLocation (cil); if (selection.contains(ci) && ci < nc && ci <= maxCi) ret += values[ri*nc+ci] * v.valueAtLocation(cil); } } else { for (int cil = 0; cil < v.numLocations(); cil++) { int ci = v.indexAtLocation (cil); if (ci < nc && ci <= maxCi) ret += values[ri*nc+ci] * v.valueAtLocation(cil); } } return ret; } public final double twoNormSquared () { double ret = 0; for (int i = 0; i < values.length; i++) ret += values[i] * values[i]; return ret; } public void print () { for (int i = 0; i < nr; i++) { for (int j = 0; j < nc; j++) System.out.print (" " + values[i*nc+j]); System.out.println (""); } } public String toString () { StringBuffer sb = new StringBuffer(); for (int i = 0; i < nr; i++) { for (int j = 0; j < nc; j++) sb.append (" " + values[i*nc+j]); sb.append ("\n"); } return sb.toString(); } }