package dr.inference.model;
import dr.xml.*;
import java.util.StringTokenizer;
//import org.w3c.dom.Document;
//import org.w3c.dom.Element;
//import dr.xml.*;
/**
* @author Marc Suchard
*/
public class NewMatrixParameter extends Parameter.Default {
public final static String MATRIX_PARAMETER = "matrixParameter";
public NewMatrixParameter(String name) {
super(name);
}
public NewMatrixParameter(String name, double[] parameter, int numRows, int numCols) {
super(parameter);
this.numRows = numRows;
this.numCols = numCols;
}
private int numRows = 0;
private int numCols = 0;
public double getParameterValue(int row, int col) {
return getParameterValue(row * numCols + col); // Stores in row-major
}
public double[][] getParameterAsMatrix() {
// final int I = getRowDimension();
// final int J = getColumnDimension();
// double[][] parameterAsMatrix = new double[I][J];
// for (int i = 0; i < I; i++) {
// for (int j = 0; j < J; j++)
// parameterAsMatrix[i][j] = getParameterValue(i, j);
// }
// return parameterAsMatrix;
double[][] parameterAsMatris = new double[numRows][numCols];
for (int i = 0; i < numRows; i++) {
for (int j = 0; j < numCols; j++) {
parameterAsMatris[i][j] = getParameterValue(i * numCols + j);
}
}
return parameterAsMatris;
}
public int getColumnDimension() {
return numCols;
}
public int getRowDimension() {
return numRows;
}
public String toSymmetricString() {
StringBuffer sb = new StringBuffer("{");
int dim = getRowDimension();
int total = dim * (dim + 1) / 2;
for (int i = 0; i < dim; i++) {
for (int j = i; j < dim; j++) {
sb.append(String.format("%5.4e", getParameterValue(i, j)));
total--;
if (total > 0)
sb.append(",");
}
}
sb.append("}");
return sb.toString();
}
public static NewMatrixParameter parseFromSymmetricString(String string) {
String clip = string.replace("{", "").replace("}", "").trim();
StringTokenizer st = new StringTokenizer(clip, ",");
int count = st.countTokens();
int dim = (-1 + (int) Math.sqrt(1 + 8 * count)) / 2;
// Parameter[] parameter = new Parameter[dim];
// for (int i = 0; i < dim; i++)
// parameter[i] = new Parameter.Default(dim);
// for (int i = 0; i < dim; i++) {
// for (int j = i; j < dim; j++) {
// double datum = new Double(st.nextToken());
// parameter[i].setParameterValue(j, datum);
// parameter[j].setParameterValue(i, datum);
// }
// }
double[] data = new double[dim * dim];
for (int i = 0; i < dim; i++) {
for (int j = i; j < dim; j++) {
double datum = new Double(st.nextToken());
data[i * dim + j] = datum;
data[j * dim + i] = datum;
}
}
return new NewMatrixParameter(null, data, dim, dim);
}
public static NewMatrixParameter parseFromSymmetricDoubleArray(Object[] inData) {
int dim = (-1 + (int) Math.sqrt(1 + 8 * inData.length)) / 2;
// Parameter[] parameter = new Parameter[dim];
// for (int i = 0; i < dim; i++)
// parameter[i] = new Parameter.Default(dim);
int index = 0;
// for (int i = 0; i < dim; i++) {
// for (int j = i; j < dim; j++) {
// double datum = (Double) data[index++];
// parameter[i].setParameterValue(j, datum);
// parameter[j].setParameterValue(i, datum);
// }
// }
// return new MatrixParameter(null, parameter);
double[] data = new double[dim * dim];
for (int i = 0; i < dim; i++) {
for (int j = i; j < dim; j++) {
double datum = (Double) inData[index++];
data[i * dim + j] = datum;
data[j * dim + i] = datum;
}
}
return new NewMatrixParameter(null, data, dim, dim);
}
// **************************************************************
// XMLElement IMPLEMENTATION
// **************************************************************
// public Element createElement(Document d) {
// throw new RuntimeException("Not implemented yet!");
// }
public static XMLObjectParser PARSER = new AbstractXMLObjectParser() {
public String getParserName() {
return MATRIX_PARAMETER;
}
public Object parseXMLObject(XMLObject xo) throws XMLParseException {
// MatrixParameter matrixParameter = new MatrixParameter(MATRIX_PARAMETER);
int numRows = xo.getChildCount();
int numCols = 0;
double[] values = null;
for (int i = 0; i < numRows; i++) {
Parameter parameter = (Parameter) xo.getChild(i);
if (values == null) {
numCols = parameter.getDimension();
values = new double[numCols * numRows];
} else {
if (numCols != parameter.getDimension()) {
throw new XMLParseException(
"All parameters must have the same dimension to construct a rectangular matrix");
}
}
double[] newValues = parameter.getParameterValues();
System.arraycopy(newValues, 0, values, i * numCols, numCols);
}
String name = (xo.hasId() ? xo.getId() : MATRIX_PARAMETER);
return new NewMatrixParameter(name, values, numRows, numCols);
}
//************************************************************************
// AbstractXMLObjectParser implementation
//************************************************************************
public String getParserDescription() {
return "A matrix parameter constructed from its component parameters.";
}
public XMLSyntaxRule[] getSyntaxRules() {
return rules;
}
private final XMLSyntaxRule[] rules = {
new ElementRule(Parameter.class, 1, Integer.MAX_VALUE),
};
public Class getReturnType() {
return NewMatrixParameter.class;
}
};
}