All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.nuiton.math.matrix.MatrixHelper Maven / Gradle / Ivy

The newest version!
/* *##% NuitonMatrix
 * Copyright (C) 2004 - 2009 CodeLutin
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program 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 Lesser Public License for more details.
 *
 * You should have received a copy of the GNU General Lesser Public
 * License along with this program.  If not, see
 * . ##%*/

package org.nuiton.math.matrix;

import java.io.StreamTokenizer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.Stack;

/**
 * Contains usefull methods to get information on matrix.
 *
 * Created: 28 oct. 2004
 *
 * @author Benjamin Poussin 
 * @version $Revision: 187 $
 *
 * Mise a jour: $Date: 2009-10-16 19:17:29 +0200 (ven., 16 oct. 2009) $
 * par : $Author: tchemit $
 */
public class MatrixHelper { // MatrixHelper

    /**
     * Convert Matrix to identity matrix must have 2 dimensions. If dimension
     * haven't same length, then the small dimension is used.
     * 
     * @param mat matrix nd to convert
     * @return converted matrix
     */
    public static MatrixND convertToId(MatrixND mat) {
        int size = mat.getDim(0);
        if (size > mat.getDim(1)) {
            size = mat.getDim(1);
        }

        fill(mat, 0);

        for (int i = 0; i < size; i++) {
            mat.setValue(i, i, 1);
        }
        return mat;
    }

    /**
     * Permet de relire une chaine du type [[[1, 2], [3, 4]],[[3, 5], [1, 4]]]
     * 

* Remarque: une premiere implantantion avait ete faite en utilisant * {@link StreamTokenizer} mais en fait il y a un bug dedans, il ne sait pas * parser les chiffres avec un exposant: 5.0E-7 par exemple est lu comme 5.0 * :( *

* Remarque: une autre implantation de remplacement a ete faite en utilisant * le {@link org.nuiton.util.StringUtil#split(String, String)} mais elle * etait moins performante (x2) * * @param s la chaine representant les listes de liste * @return une liste de liste ... de Double */ public static List convertStringToList(String s) { List result = null; Stack> stack = new Stack>(); StringBuffer number = new StringBuffer(20); // initial to 20 char for (int i = 0; i < s.length(); i++) { char c = s.charAt(i); if (c == ' ') { // skip space } if (c == '[') { stack.push(new ArrayList()); } else if (c == ',') { if (number.length() != 0) { // on a une ',' on doit donc avoir un nombre dans number // a moins que ce ne soit une ',' entre deux listes Double value = Double.valueOf(number.toString()); stack.peek().add(value); } number.setLength(0); } else if (c == ']') { // fin d'une liste, il doit rester un nombre dans number // a mois que la liste etait vide if (number.length() != 0) { Double value = Double.valueOf(number.toString()); stack.peek().add(value); number.setLength(0); } List current = stack.pop(); if (stack.empty()) { result = current; } else { stack.peek().add(current); } } else { // pas un '[' ou ']', pas une ',' devrait etre // un bout du nombre, si c un espace qui traine n'importe ou // c pas grace car Double.valueOf gere les espaces number.append(c); } } return result; } /** * permet de donner une représentation String d'un tableau de coordonnées * * @param coordinates les coordonnées * @return la chaine demandée de la forme 1,3,34,23 */ public static String coordinatesToString(int[] coordinates) { StringBuffer sb = new StringBuffer(); for (int i = 0; i < coordinates.length; i++) { sb.append(coordinates[i]); if (i + 1 < coordinates.length) { sb.append(','); } } return sb.toString(); } /** * permet de donner une représentation String d'un tableau de coordonnées * * @param coordinates les coordonnées * @return la chaine demandée de la forme "Ob1","Ob2,"Ob3", ... la chaine * prise pour l'objet est celle retournée par la méthode toString de * l'objet */ public static String coordinatesToString(Object[] coordinates) { StringBuffer sb = new StringBuffer(); for (int i = 0; i < coordinates.length; i++) { sb.append(coordinates[i]); if (i + 1 < coordinates.length) { sb.append(','); } } return sb.toString(); } /** * Permet de savoir si deux dimension sont identiques. * * @param dim1 first dimensions * @param dim2 second dimensions * @return dimension equality */ public static boolean sameDimension(int[] dim1, int[] dim2) { return Arrays.equals(dim1, dim2); } /** * Permet de convertir des coordonnées définies par des entiers en coordonnées * semantique par des objets * * @param semantics la semantique à utilisé pour la conversion * @param coordinates les coordonnées à convertir * @return un tableau donnant les coordonnées sous forme semantique s'il n'y * a pas de semantique (liste pleine de null) alors un objet Integer * est créer pour représenter la semantique de la dimension. */ public static Object[] dimensionToSemantics(List[] semantics, int[] coordinates) { Object[] result = new Object[coordinates.length]; for (int i = 0; i < result.length; i++) { result[i] = semantics[i].get(coordinates[i]); if (result[i] == null) { result[i] = Integer.valueOf(coordinates[i]); } } return result; } /** * Permet de convertir des coordonnées sémantiques en coordonnées défini par * des entiers. Cette fonction est l'inverse de * {@link #dimensionToSemantics}. * * @param semantics la semantique à utiliser pour la conversion * @param coordinates les coordonnées sémantique * @return les coordonnées en entier. Si la sémantique est représentéé par un * Integer alors la valeur de l'integer est utilisé pour la * conversion. */ public static int[] semanticsToDimension(List[] semantics, Object[] coordinates) { int[] result = new int[coordinates.length]; for (int i = 0; i < coordinates.length; i++) { if (coordinates[i] == null) { result[i] = -1; } else { result[i] = indexOf(semantics, i, coordinates[i]); } } return result; } /** * Permet de retrouver la position d'un objet dans une liste * * @param semantics la semantique à utilisé pour la recherche * @param dim la dimension dans lequel il faut faire la recherche * @param o l'objet à rechercher * @return la position de l'objet dans la dimension demandée * * @throws NoSuchElementException If element doesn't exists */ public static int indexOf(List[] semantics, int dim, Object o) throws NoSuchElementException { if (o instanceof Integer) { return ((Integer) o).intValue(); } int result = -1; if ((0 <= dim) && (dim < semantics.length)) { result = semantics[dim].indexOf(o); } if (result == -1) { throw new NoSuchElementException( "L'objet passé en argument n'a pas été retrouvé ou la dimension donnée ne convient pas:" + o + " in " + semantics[dim]); } return result; } /** * Permet de remplir toute la matrice avec la même donnée * * @param mat la matrice à remplir * @param value la valeur de remplissage * @return la matrice passé en paramêtre */ public static MatrixND fill(MatrixND mat, final double value) { mat.map(new MapFunction() { @Override public double apply(double v) { return value; } }); return mat; } /** * Retourne la valeur la plus courrement rencontrer dans un tableau. si * plusieurs valeurs ont le même nombre d'occurence la plus petite valeur * est retournée. * * @param tab le tableau de valeur * @return la valeur la plus nombreuse dans le tableau */ public static double maxOccurence(double[] tab) { double[] tmp = new double[tab.length]; System.arraycopy(tab, 0, tmp, 0, tab.length); return maxOccurence1(tmp); } public static double maxOccurence(float[] tab) { double[] tmp = new double[tab.length]; for (int i = 0; i < tab.length; i++) { tmp[i] = tab[i]; } return maxOccurence1(tmp); } /** * le tableau en entre est trie durant l'execution de la methode, il est * donc modifié * @param tmp TODO * @return TODO */ protected static double maxOccurence1(double[] tmp) { if (tmp.length == 0) { throw new IllegalArgumentException("Array must be not empty"); } // double [] tmp = new double[tab.length]; // System.arraycopy(tab, 0, tmp, 0, tab.length); Arrays.sort(tmp); // le nombre de fois que l'on a rencontrer la valeur la plus nombreuse int max = 1; // le nombre de fois que l'on a rencontrer la valeur courante int count = 1; // la valeur la plus rencontrer double result = tmp[0]; // la valeur que l'on vient de traiter précédement double old = tmp[0]; // la valeur courante lu dans le tableaux double current = tmp[0]; // tant que l'on peut encore trouve un element plus nombreux dans le // tableau on le parcours for (int i = 1; max < tmp.length - i + count && i < tmp.length; i++) { current = tmp[i]; if (current == old) { count++; } else { if (count > max) { max = count; result = old; } count = 1; old = current; } } if (count > max) { max = count; result = current; } return result; } } // MatrixHelper