// Copyright (C) 2011 Zeno Gantner // Copyright (C) 2012 Zeno Gantner, Chris Newell // // This file is part of MyMediaLite. // // MyMediaLite is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // MyMediaLite is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with MyMediaLite. If not, see <http://www.gnu.org/licenses/>. package org.mymedialite.datatype; import java.util.HashMap; /** * A skew symmetric (anti-symmetric) sparse matrix; consumes less memory. * * Be careful when accessing the matrix via the NonEmptyEntryIDs and * NonEmptyRows properties: these contain only the entries with x > y, * but not their antisymmetric counterparts. * * @version 2.03 */ public class SkewSymmetricSparseMatrix extends SymmetricSparseMatrix<Float> { /** * Create a skew symmetric sparse matrix with a given dimension. * @param dimension the dimension (number of rows/columns) */ public SkewSymmetricSparseMatrix(int dimension) { super(dimension, null); } /** * Get an element of the sparse matrix. * @param x the row ID * @param y the column ID * @return the value */ public Float get(int x, int y) { if (x < y) { if (x < row_list.size()) { Float result = row_list.get(x).get(y); if(result != null) return result; } } else if (x > y) { if (y < row_list.size()) { Float result = row_list.get(y).get(x); if(result != null) return -result; // minus for anti-symmetry } } return 0.0F; } /** * Set an element of the sparse matrix. * @param x the row ID * @param y the column ID * @param value the value to set */ public void set(int x, int y, Float value) { if (x < y) { if (x >= row_list.size()) for (int i = row_list.size(); i <= x; i++) row_list.add(new HashMap<Integer, Float>() ); row_list.get(x).put(y, value); } else if (x > y) { if (y >= row_list.size()) for (int i = row_list.size(); i <= y; i++) row_list.add(new HashMap<Integer, Float>() ); row_list.get(y).put(x, -value); } else { // All elements on the diagonal must be zero if (value != 0) throw new IllegalArgumentException("Elements of the diagonal of a skew symmetric matrix must equal 0"); } } /** * Only true if all entries are zero. * @return true only if all entries are zero */ public boolean isSymmetric() { for (int i = 0; i < row_list.size(); i++) for (Integer j : row_list.get(i).keySet()) if (get(i, j) != 0) return false; return true; } /** */ public IMatrix<Float> createMatrix(int num_rows, int num_columns) { if (num_rows != num_columns) throw new IllegalArgumentException("Skew symmetric matrices must have the same number of rows and columns."); return new SkewSymmetricSparseMatrix(num_rows); } }