// Optimization function for hypersphere and lower-diagonal algorithm private static Matrix hypersphereOptimize(Matrix targetMatrix, Matrix currentRoot, bool lowerDiagonal) { int i, j, k, size = targetMatrix.rows(); Matrix result = new Matrix(currentRoot); Vector variance = new Vector(size); for (i = 0; i < size; i++) { variance[i] = Math.Sqrt(targetMatrix[i, i]); } if (lowerDiagonal) { Matrix approxMatrix = result * Matrix.transpose(result); result = MatrixUtilities.CholeskyDecomposition(approxMatrix, true); for (i = 0; i < size; i++) { for (j = 0; j < size; j++) { result[i, j] /= Math.Sqrt(approxMatrix[i, i]); } } } else { for (i = 0; i < size; i++) { for (j = 0; j < size; j++) { result[i, j] /= variance[i]; } } } ConjugateGradient optimize = new ConjugateGradient(); EndCriteria endCriteria = new EndCriteria(100, 10, 1e-8, 1e-8, 1e-8); HypersphereCostFunction costFunction = new HypersphereCostFunction(targetMatrix, variance, lowerDiagonal); NoConstraint constraint = new NoConstraint(); // hypersphere vector optimization if (lowerDiagonal) { Vector theta = new Vector(size * (size - 1) / 2); const double eps = 1e-16; for (i = 1; i < size; i++) { for (j = 0; j < i; j++) { theta[i * (i - 1) / 2 + j] = result[i, j]; if (theta[i * (i - 1) / 2 + j] > 1 - eps) { theta[i * (i - 1) / 2 + j] = 1 - eps; } if (theta[i * (i - 1) / 2 + j] < -1 + eps) { theta[i * (i - 1) / 2 + j] = -1 + eps; } for (k = 0; k < j; k++) { theta[i * (i - 1) / 2 + j] /= Math.Sin(theta[i * (i - 1) / 2 + k]); if (theta[i * (i - 1) / 2 + j] > 1 - eps) { theta[i * (i - 1) / 2 + j] = 1 - eps; } if (theta[i * (i - 1) / 2 + j] < -1 + eps) { theta[i * (i - 1) / 2 + j] = -1 + eps; } } theta[i * (i - 1) / 2 + j] = Math.Acos(theta[i * (i - 1) / 2 + j]); if (j == i - 1) { if (result[i, i] < 0) { theta[i * (i - 1) / 2 + j] = -theta[i * (i - 1) / 2 + j]; } } } } Problem p = new Problem(costFunction, constraint, theta); optimize.minimize(p, endCriteria); theta = p.currentValue(); result.fill(1); for (i = 0; i < size; i++) { for (k = 0; k < size; k++) { if (k > i) { result[i, k] = 0; } else { for (j = 0; j <= k; j++) { if (j == k && k != i) { result[i, k] *= Math.Cos(theta[i * (i - 1) / 2 + j]); } else if (j != i) { result[i, k] *= Math.Sin(theta[i * (i - 1) / 2 + j]); } } } } } } else { Vector theta = new Vector(size * (size - 1)); const double eps = 1e-16; for (i = 0; i < size; i++) { for (j = 0; j < size - 1; j++) { theta[j * size + i] = result[i, j]; if (theta[j * size + i] > 1 - eps) { theta[j * size + i] = 1 - eps; } if (theta[j * size + i] < -1 + eps) { theta[j * size + i] = -1 + eps; } for (k = 0; k < j; k++) { theta[j * size + i] /= Math.Sin(theta[k * size + i]); if (theta[j * size + i] > 1 - eps) { theta[j * size + i] = 1 - eps; } if (theta[j * size + i] < -1 + eps) { theta[j * size + i] = -1 + eps; } } theta[j * size + i] = Math.Acos(theta[j * size + i]); if (j == size - 2) { if (result[i, j + 1] < 0) { theta[j * size + i] = -theta[j * size + i]; } } } } Problem p = new Problem(costFunction, constraint, theta); optimize.minimize(p, endCriteria); theta = p.currentValue(); result.fill(1); for (i = 0; i < size; i++) { for (k = 0; k < size; k++) { for (j = 0; j <= k; j++) { if (j == k && k != size - 1) { result[i, k] *= Math.Cos(theta[j * size + i]); } else if (j != size - 1) { result[i, k] *= Math.Sin(theta[j * size + i]); } } } } } for (i = 0; i < size; i++) { for (j = 0; j < size; j++) { result[i, j] *= variance[i]; } } return(result); }
// Optimization function for hypersphere and lower-diagonal algorithm private static Matrix hypersphereOptimize(Matrix targetMatrix, Matrix currentRoot, bool lowerDiagonal) { int i,j,k,size = targetMatrix.rows(); Matrix result = new Matrix(currentRoot); Vector variance = new Vector(size); for (i=0; i<size; i++){ variance[i]=Math.Sqrt(targetMatrix[i,i]); } if (lowerDiagonal) { Matrix approxMatrix = result*Matrix.transpose(result); result = MatrixUtilities.CholeskyDecomposition(approxMatrix, true); for (i=0; i<size; i++) { for (j=0; j<size; j++) { result[i,j]/=Math.Sqrt(approxMatrix[i,i]); } } } else { for (i=0; i<size; i++) { for (j=0; j<size; j++) { result[i,j]/=variance[i]; } } } ConjugateGradient optimize = new ConjugateGradient(); EndCriteria endCriteria = new EndCriteria(100, 10, 1e-8, 1e-8, 1e-8); HypersphereCostFunction costFunction = new HypersphereCostFunction(targetMatrix, variance, lowerDiagonal); NoConstraint constraint = new NoConstraint(); // hypersphere vector optimization if (lowerDiagonal) { Vector theta = new Vector(size * (size-1)/2); const double eps=1e-16; for (i=1; i<size; i++) { for (j=0; j<i; j++) { theta[i*(i-1)/2+j]=result[i,j]; if (theta[i*(i-1)/2+j]>1-eps) theta[i*(i-1)/2+j]=1-eps; if (theta[i*(i-1)/2+j]<-1+eps) theta[i*(i-1)/2+j]=-1+eps; for (k=0; k<j; k++) { theta[i*(i-1)/2+j] /= Math.Sin(theta[i*(i-1)/2+k]); if (theta[i*(i-1)/2+j]>1-eps) theta[i*(i-1)/2+j]=1-eps; if (theta[i*(i-1)/2+j]<-1+eps) theta[i*(i-1)/2+j]=-1+eps; } theta[i*(i-1)/2+j] = Math.Acos(theta[i*(i-1)/2+j]); if (j==i-1) { if (result[i,i]<0) theta[i*(i-1)/2+j]=-theta[i*(i-1)/2+j]; } } } Problem p = new Problem(costFunction, constraint, theta); optimize.minimize(p, endCriteria); theta = p.currentValue(); result.fill(1); for (i=0; i<size; i++) { for (k=0; k<size; k++) { if (k>i) { result[i,k]=0; } else { for (j=0; j<=k; j++) { if (j == k && k!=i) result[i,k] *= Math.Cos(theta[i*(i-1)/2+j]); else if (j!=i) result[i,k] *= Math.Sin(theta[i*(i-1)/2+j]); } } } } } else { Vector theta = new Vector(size * (size-1)); const double eps=1e-16; for (i=0; i<size; i++) { for (j=0; j<size-1; j++) { theta[j*size+i]=result[i,j]; if (theta[j*size+i]>1-eps) theta[j*size+i]=1-eps; if (theta[j*size+i]<-1+eps) theta[j*size+i]=-1+eps; for (k=0;k<j;k++) { theta[j*size+i] /= Math.Sin(theta[k*size+i]); if (theta[j*size+i]>1-eps) theta[j*size+i]=1-eps; if (theta[j*size+i]<-1+eps) theta[j*size+i]=-1+eps; } theta[j*size+i] = Math.Acos(theta[j*size+i]); if (j==size-2) { if (result[i,j+1]<0) theta[j*size+i]=-theta[j*size+i]; } } } Problem p = new Problem(costFunction, constraint, theta); optimize.minimize(p, endCriteria); theta=p.currentValue(); result.fill(1); for (i = 0; i < size; i++) { for (k=0; k<size; k++) { for (j=0; j<=k; j++) { if (j == k && k!=size-1) result[i,k] *= Math.Cos(theta[j*size+i]); else if (j!=size-1) result[i,k] *= Math.Sin(theta[j*size+i]); } } } } for (i=0; i<size; i++) { for (j=0; j<size; j++) { result[i,j]*=variance[i]; } } return result; }