Constantes em Java

Posted in Java with tags , on Abril 23, 2008 by maleiria

Qual a melhor forma de definir constantes para serem utilizadas numa aplicação?
Bem, há várias abordagens possíveis: a mais comum será definir um interface

public interface Constants {
  public static final double PI = 3.14159265;
  public static final String HELLO = "WORLD";
}

e implementar o interface,

public class AreaCirculo implements Constants {
  public static void main(String[] args) {
    int raio = 2;
    System.out.println("A area do circulo de raio 2 e " + PI*raio*raio);
  }
}

mas esta aproximação é considerada um “anti pattern” pois distorce o uso dos
interfaces, ou seja, os interfaces providenciam serviços que os
utilizadores desejem usar (providenciam uma funcionalidade).A classe
AreaCirculo não implementa nada, apenas descarrega
(inclui) uma série de constantes na classe.
Uma segunda abordagem será criar uma classe assim:

public class Constants {
  public static final double PI = 3.14159265;
  public static final String HELLO = "WORLD";
}

que é em tudo idêntica ao interface com a diferença que em vez de ser um
interface, é uma class. Neste caso, o class loader vai
carregar a classe hierarquicamente até ao Object. Um desperdício de
recursos só para ter umas constantes??!!
Voltemos à primeira abordagem:

public interface Constants {
  public static final double PI = 3.14159265;
  public static final String HELLO = "WORLD";
}

mas agora, em vez de implementarmos o interface na classe, vamos “importá-lo”:

import static Constants.*;

public class AreaCirculo{
  public static void main(String[] args) {
		int raio = 2;
    System.out.println("A area do circulo de raio 2 e " + PI*raio*raio);
  }
}

Agora temos uma boa solução! O único senão é, se tivermos vários import static
torna-se confuso sabermos de onde vem a constante PI. A solução é fácil: em vez
de import static Constants.*;, especificamos, i.e.,
import static Constants.PI;

Cálculo Matricial II

Posted in Java with tags , on Abril 23, 2008 by maleiria

Seguindo a continuação do post anterior sobre cálculo matricial em Java vou acrescentar mais alguns métodos úteis à class Matrix.

Se quisermos saber se a matriz é quadrada:

/**
* @return boolean
*/
public boolean isSquare(){
  return rows() == columns();
}

Multiplicar a matriz por um número:

     /**
     * @return Matrix produto da matriz por um numero fornecido
     * @param a double multiplicando.
     */
    public Matrix product(double a){
        return new Matrix(productComponents(a));
    }

onde o método productComponents(a) é dado por:
    /**
     * @return double[][]
     * @param a double
     */
    protected double[][] productComponents(double a){
        int n = this.rows();
        int m = this.columns();
        double[][] newComponents = new double[n][m];
        for(int i = 0; i < n; i++){
            for(int j = 0; j < m; j++)
                newComponents[i][j] = a * components[i][j];
        }
        return newComponents;
    }

Outro método, também bastante útil em cálculo matricial, será obter a matriz transposta da matriz dada:

    /**
     * @return Matrix transposta da receptora
     */
    public Matrix transpose(){
        int n = rows();
        int m = columns();
        double[][] newComponents = new double[m][n];
        for(int i = 0; i < n; i++){
            for(int j = 0; j < m; j++)
                newComponents[j][i] = components[i][j];
        }
        return new Matrix(newComponents);
    }

E que tal se quisermos cálcular o produto da matriz por um vector
(vector no sentido matematico porque na realidade é um array)?
Será algo assim:
    /**
     * Computa o produto da matriz por um
     * @return double[]
     * @param v double[]
     */
    public double[] product(double[] v) throws IllegalArgumentException
        int n = this.rows();
        int m = this.columns();
        if(v.lenght != m)
            throw new IllegalArgumentException("Erro no porduto: a matriz " + n +
             " por " + m + "nao pode ser multiplicada por um vector " +
             "de dimensao " + v.length));
        return secureProduct(v);
    }

onde secureProduct(v) é dado por
    /**
     * Computa o produto da matriz com um vector
     * @return double[]
     * @param v double[]
     */
    protected double[] secureProduct(double[] v){
        int n = this.rows();
        int m = this.columns();
        double[] vectorComponents = new double[n];
        for(int i = 0; i < n; i++){
            vectorComponents[i] = 0;
            for(int j = 0; j < m; j++)
                vectorComponents[i] += components[i][j] * v[j];
        }
        return vectorComponents;
    }

Continuo a trabalhar em mais alguns métodos.

Cálculo Matricial I

Posted in Java with tags , on Abril 22, 2008 by maleiria

Tenho ouvido, com frequência, pessoas a perguntar se o java tem algum suporte de cálculo matricial. Posso dizer-vos que não há, no entanto, existem alguns pacotes opensource que executam tais cálculos (ver referências). Não vou inventar a roda mas vou construir uma classe simples que faz as operações mais básicas. Esta classe tem uma variável de instância, protected double[][] elements; onde vamos guardar os
elementos da matriz.
public class Matrix{
protected double[][] elements;

/**
* Cria a matriz com os elementos dados
* NOTE: os elemntos nao podem ser alterados depois da definicao
* @param a double[][]
*/
public Matrix(double[][] a){
elements = a;
}
}


Agora precisamos de três métodos auxiliares:um para nos dar o número de linhas da matriz,

/**
* @return int o numero de linhas da matriz
*/
public int rows(){
return elements.length;
}

o número de colunas,

/**
* @return int o numero de colunas da matriz
*/
public int columns(){
return elements[0].length;
}

e um para nos retornar o elemento na linha i, coluna j

/**
* @return double
* @param i int
* @param j int
*/
public double element(int i, int j){
return element[i][j];
}

Portanto, adicionar uma matriz a outra, equivale a adicionar os elementos, ou seja,

/**
* @return Matrix soma do receptor com a matriz fornecida
* @param a Matrix
* @exception IllegalArgumentException se a matriz fornecida nao tiver as mesmas dimensoes
*/
public Matrix add(Matrix a) throws IllegalArgumentException{
if(a.rows() != rows() || a.columns() != columns())
throw new IllegalArgumentException("Erro de operacao: nao posso adicionar uma matriz " + a.rows() + " por " + a.columns() + " a uma matriz " + rows() + " por " + columns());
return new Matrix(addElements(a));
}

onde o método addElements(a) adiciona os elementos das duas matrizes,

/**
* Computa os componentes do receptor e da matriz fornecida
* @return double[][] os elementos da matriz soma
* @param a Matrix
*/
protected double[][] addElements(Matrix a){
int n = this.rows();
int m = this.columns();
double[][] newElements = new double[n][m];
for(int i = 0; i < n; i++){
for(int j = 0; j < n; j++)
newElements[i][j] = elements[i][j] + a.elements[i][j];
}
return newElements;
}

Simples! Vamos fazer um teste: Supondo que tenho duas matrizes 2X2:

public class Starter{
public static void main(String[] args) {
//Construir os elementos da matriz m
double m[][] = new double[2][2];
m[0][0] = 1;
m[0][1] = 2;
m[1][0] = 3;
m[1][1] = 4;
//Construir os elementos da matriz m1
double m1[][] = new double[2][2];
m1[0][0] = 5;
m1[0][1] = 6;
m1[1][0] = 7;
m1[1][1] = 8;
//Criar os objectos Matriz passando os elementos no construtor
Matrix matrixA = new Matrix(m);
Matrix matrixB = new Matrix(m1);
try {
//Fazer a soma
Matrix result = matrixA.add(matrixB);//Matriz resultado da soma
for(int i = 0; i < result.rows(); i++){
for(int j = 0; j < result.columns(); j++)
System.out.print(result.element(i, j) + " ");
System.out.println();
}
} catch (IllegalArgumentException e) {
System.out.println(e.getMessage());
}
}
}

O resultado é:

6.0 8.0 10.0 12.0

Ok. So far so good. Vamos avançar para a multiplicação. Então, se quiser multiplicar
uma matriz A por uma matriz B, A x B o número de linhas da matriz A tem de ser
igual ao número de colunas da matriz B. Tendo em conta esta regra, o método será:

/**
* @return Matrix produto do receptor pela matriz fornecida
* @param a Matrix
* @exception IllegalArgumentException se o numero de colunas do receptor nao for igual ao numero de linhas da matriz fornecida
*/
public Matrix product(Matrix a) throws IllegalArgumentException{
if(a.rows() != columns())
throw new IllegalArgumentException("Erro de operacao: nao posso multiplicar uma matriz " + rows() + " por " + columns() + " com uma matriz " + a.rows() + " por " + a.columns());
return new Matrix(productElements(a));
}

e o método productElements(a) multiplica os elementos das matrizes:

/**
* @return double[][] os elementos do produto do receptor com a matriz fornecida
* @param a Matrix
*/
protected double[][] productElements(Matrix a){
int p = this.columns();
int n = this.rows();
int m = a.columns();
double[][] newElements = new double[n][m];
for(int i = 0; i < n; i++){
for(int j = 0; j < m; j++){
double sum = 0;
for(int k = 0; k < p; k++)
sum += elements[i][k] * a.elements[k][j];
newElements[i][j] = sum;
}
}
return newElements;
}

Que tal? Tem bom aspecto! E para subtrair duas matrizes? o processo é semelhante à soma,

/**
* @return Matrix subtrai a matriz fornecida ao receptor
* @param a Matrix
* @exception IllegalArgumentException se a matriz fornecida nao tiver a mesmas dimensoes
*/
public Matrix subtract(Matrix a) throws IllegalArgumentException{
if(a.rows() != rows() || a.columns() != columns())
throw new IllegalArgumentException("Erro de produto: nao posso subtrair a matriz " + a.rows() + " por " + a.columns() + " a matriz " + rows() + " por "+columns());
return new Matrix( subtractElements(a));
}
/**
* @return double[][]
* @param a Matrix
*/
protected double[][] subtractElements(Matrix a){
int n = this.rows();
int m = this.columns();
double[][] newElements = new double[n][m];
for(int i = 0; i < n; i++){
for(int j = 0; j < n; j++)
newElements[i][j] = elements[i][j] - a.elements[i][j];
}
return newElements;
}

e se quisermos saber se a matriz é quadrada,

/**
* @return boolean
*/
public boolean isSquare(){
return rows() == columns();
}

Por agora é tudo. Estou a trabalhar em mais algumas funcionalidades, tais como calcular a matriz transposta, decomposição LUP, produto por um vector…

P.S. Pacotes open source para cálculo matricial

JAMA – A Java Matrix package:

http://math.nist.gov/javanumerics/jama/

COLT Project

http://dsd.lbl.gov/~hoschek/colt/

Glider (Conway’s life)

Posted in Ciência on Abril 21, 2008 by maleiria

O Glider é um padrão do jogo da vida de Conway que se movimenta num tabuleiro. É a nave mais pequena e movimenta-se na diagonal.

Os Gliders são importantes no jogo da vida porque são fáceis de criar e podem colidir uns com os outros para formar objectos mais complicados. Podem, ainda, ser utilizados para transmitir informação através de distâncias longas.

Mais informação em Jogo da Vida