package jaea.optimization.sampling;
import jaea.optimization.tools.Matrix;
import jaea.optimization.tools.Permutation;
import jaea.optimization.tools.Utils;
/**
* Create Morris Sampling matrix. Each row differs from prev. row in one column
* @author Le Minh Nghia, NTU-Singapore
*
*/
public class MorrisSampling {
/**
*
* @param elements Number of samples required (+1)
* @param p Number of features as well as Number of division in each dimension [0 - 1]
* @param runs Number of experiment runs
* @return Sampling matrix
*/
public double [][] getMorrisData(int elements, int p,
int runs)
{
double [][] res = new double[runs*(elements +1)][elements];
for (int i = 0; i <runs; i++)
{
double [][] oneRun = getMorrisMatrix(elements,p);
int row = oneRun.length;
int col = oneRun[0].length;;
for (int r = 0; r < row; r++)
for (int c =0; c < col; c++)
res[i*row + r][c] = oneRun[r][c];
}
return res;
}
/**
* Get Morris Matrix for each run
* @param elements Number of samples required (+1)
* @param p Number of features as well as Number of division in each dimension [0 - 1]
* @return Sampling matrix
*/
public double [][] getMorrisMatrix(int elements, int p)
{
Permutation permGen = new Permutation();
Matrix BI =
new Matrix(elements + 1, elements, Matrix.M_ZEROS);
/* Get initial matrix B */
for(int a = 1; a < elements +1; a++)
for (int b = 0; b < a ; b++)
{
BI.getMat()[a][b] = 1;
}
/* Get matrix J, (k+1)xk of 1's */
Matrix Jstar =
new Matrix(elements + 1, elements, Matrix.M_ONES);
/* Get matrix D*, k-dim diagonal matrix with
* diagonal elements = 1 or -1 with equal prob
* */
Matrix D =
new Matrix(elements, elements, Matrix.M_DIAG);
int [] perm = permGen.getPerm(elements);
for (int c = 0; c < elements; c++)
if (perm[c] % 2 == 1)
D.getMat()[c][c] = -1;
/* Get matrix P*, kxk random permutation matrix
* with column 00..1..0
* */
Matrix P =
new Matrix(elements, elements, Matrix.M_ZEROS);
int [] rr = permGen.getPerm(elements);
for (int e = 0; e < elements; e++)
P.getMat()[e][rr[e]-1]=1;
/* Get the range of x value, 0 to 1-delta */
Matrix xi = new Matrix(1, elements);
double delta = (1.0 * p)/(2*(p-1));
int mm = (int)Math.floor((1-delta)*(p-1));
double [] xvalue = new double[mm + 1];
for (int m = 0; m <= mm; m++)
xvalue[m] = m * 1.0/(p-1);
for (int m = 0; m < elements; m++)
{
// get index: 0:(mm+1)
int index = Utils.getRandom(mm+1);
xi.getMat()[0][m] = xvalue[index];
}
/* Transform and get the orient matrix B*,
* one elementary effect per input
* BO = (term1 + term2)* P
*/
Matrix J1 =
new Matrix(elements + 1,1,Matrix.M_ONES);
Matrix term1 = Matrix.multiply(J1, xi);
Matrix temp = Matrix.multiply(
Matrix.substract(Matrix.multiply(BI, 2),
Jstar), D);
Matrix term2 = Matrix.multiply(
Matrix.add(temp, Jstar),
delta/2);
Matrix BO = Matrix.multiply(
Matrix.add(term1, term2), P);
return BO.getMat();
}
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
MorrisSampling ms = new MorrisSampling();
Matrix res = new Matrix(ms.getMorrisData(5, 4, 1));
System.out.println(res.toString());
}
}