Vsolution.java
/*
* Created on 2011/02/03
* Copyright (C) 2011 Koga Laboratory. All rights reserved.
*
*/
package org.mklab.sdpj.iocenter;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.List;
import org.mklab.cga.round.FPURoundModeSelector;
import org.mklab.gap.Guarantor;
import org.mklab.gap.MPFloatComplexIntervalMatrix;
import org.mklab.gap.MPFloatIntervalMatrix;
import org.mklab.gap.MPFloatIntervalNumber;
import org.mklab.gap.eigen.MPFloatRumpMethod;
import org.mklab.mpf.ap.MPFloat;
import org.mklab.mpf.ap.MPFloatMatrix;
import org.mklab.mpf.ap.MPFloatRoundModeSelector;
import org.mklab.nfc.matrix.ComplexNumericalMatrix;
import org.mklab.nfc.matrix.RealNumericalMatrix;
import org.mklab.nfc.scalar.ComplexNumericalScalar;
import org.mklab.nfc.scalar.RealNumericalScalar;
import org.mklab.nfc.util.RoundModeManager;
import org.mklab.sdpj.algorithm.Solution;
import org.mklab.sdpj.datastructure.Vector;
import org.mklab.sdpj.problem.Problem;
import org.mklab.sdpj.tool.Tools;
/**
* The <tt>Class Vsolution</tt>, which is designed, is to verify SDP solution. If you saved your SDP solutions and want to know how accuracy these solution, you can use <tt>Class Vsolution</tt> to
* verify. Before introducing how to use it, you must to know something rules, which can help you to use <tt>Class Vsolution</tt> correctly. The rules is introduced as follows:
*
* <ul>
*
* <li>The SDP solution based on GMP "one data" and "one '\n' " are written per line by binary format with using functions from GMP. The float number written format is
* <code>(±0.d<sub>1</sub>d<sub>2</sub>...d<sub>n</sub>)<sub>β</sub> × β <sup>E</sup></code>, where β is radix and <code>E</code> is exponent in decimal.</li>
*
* <li>The SDP solution based on double Before writing the data into file, you must to write string "SDPJ" into the file firstly. Reason is that we need use that to judge your data saved by small
* endians or big endians in your machine. Then, write the data. Follow the rule as: "one data" and "one '\n' " are written per line by binary format with using functions from c library.</li>
*
* </ul>
*
*
* For more easier to know the rule of saving data. Here, introduce a simple example based on double as below: Example (1):
*
* <ul> <li><code>FILE* writeFile; </code></li> <li> <code>char* sdpj = "SDPJ"; //this string must to be written</code> </li> <li><code>fwrite(sdpj, sizeof(char), 4, writeFile);</code></li>
* <li><code>fwrite(&data, sizeof(data), 1, writeFile);</code></li> <li><code>fprintf(writeFile,"\n");</code></li> <li><code>fwrite(&data, sizeof(data), 1, writeFile);</code></li>
* <li><code>fprintf(writeFile,"\n");</code></li> </ul>
*
* For users can use <tt>Class Vsolution</tt> correctly and flexibly, introduce a simple example usage as follows: * Example (2):
*
* <ul> <li><code>final String outputFileName = "hinf2.vsdpj";</code></li>
*
* <li><code>final String problemFileName = "hinf2.dat-s";</code></li>
*
* <li><code>final String resultFileName = "hinf2.result";</code></li>
*
* <li><code>final int precision = 77;</code></li>
*
* <li><code>final RS unit = new MFPloat(1);</code></li>
*
* <li><code>final int radix = 16;</code></li> </ul>
*
* If The SDP solution based on GMP, you must to define a radix.
*
* <ul> <li> <code>Vsolution verifier = new {link #Vsolution(NumericalScalar, String, String, int)};</code> </li>
*
* <li> If The SDP solution based on double. <code>Vsolution verifier = new {link #Vsolution(NumericalScalar, String, String)};</code> </li>
* <li><code>verifier.{@link #setOutputFile(String)};</code></li> <li><code>verifier.{@link #setPrecision(int)};</code></li> <li><code>verifier.{@link #run()};</code></li> </ul> where it is an example
* usage of <code>Vsolution</code> based on setting functions. You should try these usage by yourself<br> and I think you can use <code>Vsolution</code> flexibly for verifying your SDP solutions.
*
* @author wu
* @version 0.6.3 (β), 2011/02/03
* @param <RS> type of real scalar
* @param <RM> type of real matrix
* @param <CS> type of complex scalar
* @param <CM> type of complex Matrix
*/
public class Vsolution<RS extends RealNumericalScalar<RS, RM, CS, CM>, RM extends RealNumericalMatrix<RS, RM, CS, CM>, CS extends ComplexNumericalScalar<RS, RM, CS, CM>, CM extends ComplexNumericalMatrix<RS, RM, CS, CM>> {
/**
* Size of matrix
*/
private int dimension;
/**
* The number of matrix
*/
private int m;
/**
* Constant vector <code>c</code>
*/
private RS[] c;
/**
* Variable vector <code>x</code>
*/
private RS[] x;
/**
* Array of constant matrices <code>F</code>
*/
private List<RS[][]> F;
/**
* Variable matrix <code>X</code>
*/
private RS[][] X;
/**
* Variable matrix <code>Y</code>
*/
private RS[][] Y;
/**
* The constant <code>unit</code> based on a general data type
*/
private RS unit;
/**
* If matrix is sparse, <code>true</code>;else,<code>false</code>
*/
private boolean isSparse;
/**
* The number <code>nBlock</code> of block of matrices
*/
private int nBlock;
/**
* An array of <code>int</code>, which saves the information of block of matrices
*/
private int[] blockStruct;
/**
* The file name of a SDP problem data saved
*/
private String problemFileName;
/**
* The file name of a SDP solution data saved
*/
private String solutionFileName;
/**
* The name of file in which the verifying result should be saved
*/
private String outputFileName;
/**
* Show the verifying result to the monitor
*/
private PrintStream display;
/**
* Save the verifying result to disk
*/
private PrintStream save;
/**
* If the saved data follows the big endians, true; else, false.
*/
private boolean isBigEndians;
/**
* If you saved the data by the example method, you can set parameter <code>isExampleFormat</code> by <code>true</code>; else,<code>false</code>.
*/
private boolean isExampleFormat;
/**
* Confirm the parameter <code>isExampleFormat</code> whether it is set or not.
*/
private String Format;
/**
* Save the elapsed time of verifying solution.
*/
private double elapsedTime;
/**
* If you want not to show the elapsed time, True; else, false.
*/
private boolean notShowElapsedTime;
/** */
private SolverIO<RS,RM,CS,CM> io;
/** information of SDP problem */
private Problem<RS,RM,CS,CM> problem;
/** save initial Class <code>currentPt</code> information */
private Solution<RS,RM,CS,CM> initialCurrentPt;
/** solution of dual problem */
private RS dualValue;
/** solution of primal problem */
private RS primalValue;
/** if use an external data computed by vsdpj, true; else, false */
public static boolean isExternal = false;
// /**
// * 新しく生成された<code>SolutionWithVerifier</code>オブジェクトを初期化します。<br> Create an empty instance
// */
// public Vsolution() {
// //do nothing;
// }
/**
* 新しく生成された<code>SolutionWithVerifier</code>オブジェクトを初期化します。<br> Create an instance with initializing a data type <code>unit</code>.
*
* @param unit The general data type
*/
public Vsolution(RS unit) {
this.unit = unit;
MPFloat.setDefaultPrecisionDigits(64);
//this.setDataType(unit);
}
// /**
// * 新しく生成された<code>Vsolution</code>オブジェクトを初期化します。<br> Create an instance with initializing a file name for saving data
// *
// * @param outputFileName The outputting file name
// */
// public Vsolution(String outputFileName) {
// this.setOutputFile(outputFileName);
// }
// /**
// * 新しく生成された<code>SolutionWithVerifier</code>オブジェクトを初期化します。<br> Create an instance with initializing a data type <code>unit</code> and an initial file <code>initialFile</code>.
// *
// * @param unit The general data type
// * @param initialFile The initial file
// * @throws IOException If an I/O error occurs
// */
// public Vsolution(RS unit, String initialFile) throws IOException {
// this.unit = unit;
// MPFloat.setDefaultPrecisionDigits(64);
// //this.setDataType(unit);
// this.setInitialFile(initialFile);
// }
// /**
// * 新しく生成された<code>SolutionWithVerifier</code>オブジェクトを初期化します。<br> Create an instance with initializing a data type <code>unit</code>, an initial file <code>initialFile</code> and a solution file
// * <code>solutionFile</code> you want to verify, which must be saved in binary format based on double precision.
// *
// * @param unit The unit based on a general data type
// * @param initialFile The name of an initial file
// * @param solutionFile The name of a solution file
// * @throws IOException If an I/O error occurs
// */
// public Vsolution(RS unit, String initialFile, String solutionFile) throws IOException {
// this.unit = unit;
// MPFloat.setDefaultPrecisionDigits(64);
// //this.setDataType(unit);
// this.setInitialFile(initialFile);
// this.setSolutionFile(solutionFile);
// this.initializeVsdpj();
// }
/**
* @throws IOException If an I/O error occurs
*/
private void initializeVsdpj() throws IOException {
if (isExternal == true) {
this.io = new SolverIO<>(null, System.out, this.unit);
this.io.setMatrixData(new ArrayList<String>(1));
this.io.setIsDataSparse(true);
this.problem = this.io.readFile(this.problemFileName);
this.initialCurrentPt = this.problem.getCurrentPt();
this.getCertificateOfOptimality();
}
}
// /**
// * 新しく生成された<code>SolutionWithVerifier</code>オブジェクトを初期化します。<br> Create an instance with initializing a data type <code>unit</code>, an initial file <code>initialFile</code> ,a solution file
// * <code>solutionFile</code> and the data saved based on radix <code>base</code> you want to verify, which must be saved in binary format based on double precision.
// *
// * @param unit The unit one based on a data type, where must be <code>MPFloat</code> now
// * @param initialFile The initial problem setting
// * @param solutionFile The result of SDP problem solved you want to verify
// * @param base The radix of data
// * @throws IOException If an I/O error occurs
// */
// public Vsolution(RS unit, String initialFile, String solutionFile, int base) throws IOException {
// this.unit = unit;
// MPFloat.setDefaultPrecisionDigits(64);
// //this.setDataType(unit);
// this.setInitialFile(initialFile);
// this.setSolutionFile(solutionFile, base);
// this.initializeVsdpj();
// }
/**
* Set a outputting file name
*
* @param outputFileName The outputting file name
*/
public void setOutputFile(String outputFileName) {
this.outputFileName = outputFileName;
}
/**
* Set a initial data which is a SDP problem
*
* @param initialFile The path of an initial data saved
* @throws IOException If an I/O error occurs
*/
public void setInitialFile(String initialFile) throws IOException {
this.problemFileName = initialFile;
this.readInitialData(initialFile);
this.x = this.unit.createArray(this.c.length);
this.x = getInitialVectorX(this.x);
this.X = this.unit.createArray(this.dimension, this.dimension);
this.X = getInitialArray(this.X);
this.Y = this.unit.createArray(this.dimension, this.dimension);
this.Y = getInitialArray(this.Y);
}
/**
* Set a SDP problem result based on double which should be verified.
*
* @param solutionFile The SDP problem result should be verified
* @throws IOException If an I/O error occurs
*/
public void setSolutionFile(String solutionFile) throws IOException {
this.solutionFileName = solutionFile;
this.readDataBasedOnDouble(solutionFile);
}
/**
* Set the name of file, and do not read nothing.
*
* @param fileName The name of file
*/
public void setSolutionFileName(String fileName) {
this.solutionFileName = fileName;
}
/**
* Set a SDP problem result based on GMP which should be verified.
*
* @param solutionFile The SDP problem result should be verified
* @param base The SDP result based on radix
* @throws IOException If an I/O error occurs
*/
public void setSolutionFile(String solutionFile, int base) throws IOException {
this.solutionFileName = solutionFile;
this.readDataBasedOnGMP(solutionFile, base);
}
// /**
// * Set a general data type
// *
// * @param unit The unit based on a general data type
// */
// public void setDataType(RS unit) {
// Tools.setUnitNumber(unit);
// MPFloat.setDefaultPrecisionDigits(64);
// }
/**
* Set a general data type
*
* @param unit The unit based on a general data type
* @param precision Set the efficient digits
*/
public void setDataType(RS unit, int precision) {
this.unit = unit;
//Tools.setUnitNumber(unit);
MPFloat.setDefaultPrecisionDigits(precision);
}
// /**
// * If you know your machine how to save your data in binary very well,
// * I advise you set this parameter;else, I advise this parameter is set by default.
// *
// * @param isBigEndians
// * If the saved data is big endians,true; else,false.
// */
// public void setDataFormat(boolean isBigEndians) {
// this.isBigEndians = isBigEndians;
// }
/**
* If you save the data by following the example, our advisement is you should set this parameter <code>isExampleFormat</code>, true; else, false. If you want not to set this parameter, the
* parameter will be set by default.
*
* @param isExampleFormat If the saved data follows the {@link org.mklab.sdpj.iocenter.Vsolution Example} , true; else, false.
*/
public void setDataRule(boolean isExampleFormat) {
if (isExampleFormat == true) {
this.Format = "TRUE"; //$NON-NLS-1$
} else {
this.Format = "FALSE"; //$NON-NLS-1$
}
this.isExampleFormat = isExampleFormat;
}
/**
* Set the numerical arithmetic precision
*
* @param precision The numerical arithmetic precision
*/
public void setPrecision(int precision) {
MPFloat.setDefaultPrecisionDigits(precision);
}
/**
* Set the size of matrix, and initialize the matrices by default.
*
* @param dimension The size of matrix
*/
public void setDimension(int dimension) {
this.dimension = dimension;
this.X = this.unit.createArray(this.dimension, this.dimension);
this.X = this.getInitialArray(this.X);
this.Y = this.unit.createArray(this.dimension, this.dimension);
this.Y = this.getInitialArray(this.Y);
//this.F = new NumericalScalar[this.m + 1][this.dimension][this.dimension];
this.F = new ArrayList<>(this.m + 1);
for (int i = 0; i <= this.m; i++) {
this.F.add(getInitialF());
}
}
/**
* @return cell-array of F
*/
public List<RS[][]> getF() {
return this.F;
}
/**
* @return matrix of Y
*/
public RS[][] getY() {
return this.Y;
}
/**
* @return matrix of X
*/
public RS[][] getX() {
return this.X;
}
/**
* @return vector of c
*/
public RS[] getC() {
return this.c;
}
/**
* @return vector of x
*/
public RS[] getVecX() {
return this.x;
}
/**
* @return dimension of vector
*/
public int getM() {
return this.m;
}
/**
* @return the dimension of matrix
*/
public int getDimension() {
return this.dimension;
}
/**
* Set the value of m
*
* @param m The number of matrix
*/
public void setM(int m) {
this.m = m;
this.c = this.unit.createArray(this.m);
this.c = this.getInitialVectorX(this.c);
this.x = this.unit.createArray(this.m);
this.x = this.getInitialVectorX(this.x);
}
/**
* Set the vector c
*
* @param c The vector c
*/
public void setConstantVector(RS[] c) {
this.c = c;
}
/**
* Set the vector x
*
* @param x The vector x
*/
public void setVectorX(RS[] x) {
this.x = x;
}
/**
* Set the matrix F(i)
*
* @param Fi The matrix F(i) of index i
* @param i Index of array
*/
public void setF(RS[][] Fi, int i) {
this.F.set(i, Fi);
}
/**
* Set the matrix X
*
* @param X The 2 dimension array
*/
public void setMatX(RS[][] X) {
this.X = X;
}
/**
* Set the matrix Y
*
* @param Y The 2 dimension array
*/
public void setMatY(RS[][] Y) {
this.Y = Y;
}
/**
* Set the file name only
*
* @param problemFileName The name of SDP problem file
*/
public void setProblemFileName(String problemFileName) {
this.problemFileName = problemFileName;
}
/**
* Set the elapsed time whether should be shown or not.
*
* @param notShowTime If not show time, true; else, false.
*/
public void setNotShowElapsedTime(boolean notShowTime) {
this.notShowElapsedTime = notShowTime;
}
/**
* Get the elapsed time of verifying solution
*
* @return The time of verifying solution
*/
public double getElapsedTime() {
return this.elapsedTime;
}
/**
* Initialize the parameters <code>display</code> and <code>save</code>, and if the parameter <code>outputFileName</code> is <code>null</code>, which will be defined by default.
*
* @throws FileNotFoundException If the file can not be found, an error occurs
*/
private void initializeParameter() throws FileNotFoundException {
this.display = System.out;
if (this.outputFileName == null) {
this.outputFileName = Tools.getFileName(this.problemFileName) + ".vsolution"; //$NON-NLS-1$
}
this.save = new PrintStream(new FileOutputStream(new File(this.outputFileName)));
}
/**
* @return name of sdp problem
*/
public String getProblemName() {
return this.problemFileName;
}
/**
* Run function for verifying result of SDP solver.
*
* @throws FileNotFoundException If the file can not be found, an error occurs
*/
public void run() throws FileNotFoundException {
final double D10E9 = Math.pow(10, 9);
final double StartTime = System.nanoTime();
this.initializeParameter();
this.printHead();
this.getCertificateOfOptimality();
this.getCertificateOfFeasibilityOfPrimal();
this.getCertificateOfFeasibilityOfDual();
this.printLine();
final double EndTime = System.nanoTime();
this.elapsedTime = (EndTime - StartTime) / D10E9;
if (this.notShowElapsedTime == false) {
this.display.printf("The elapsed time of verifying this SDP solution is : %.3f seconds\n\n\n", Double.valueOf(this.elapsedTime)); //$NON-NLS-1$
}
this.save.printf("The elapsed time of verifying this SDP solution is : %.3f seconds\n\n", Double.valueOf(this.elapsedTime)); //$NON-NLS-1$
}
/**
* Print a head message
*/
private void printHead() {
StringBuffer buff = new StringBuffer();
buff.append("\nVSOLUTION start at " + new java.util.Date() + "\n"); //$NON-NLS-1$ //$NON-NLS-2$
buff.append("VSOLUTION is based on the datatype : MPFloat\n"); //$NON-NLS-1$
buff.append("VSOLUTION approximate significant digits : " + MPFloat.getDefaultNumberOfPrecisionDigits() + "\n"); //$NON-NLS-1$ //$NON-NLS-2$
buff.append("Initial Problem is : " + this.problemFileName + "\n"); //$NON-NLS-1$ //$NON-NLS-2$
buff.append("Verified solution is : " + this.solutionFileName + "\n"); //$NON-NLS-1$ //$NON-NLS-2$
buff.append("The VSOLUTION report is saved at : " + this.outputFileName + "\n"); //$NON-NLS-1$ //$NON-NLS-2$
Tools.message(new String(buff), this.save);
Tools.message(new String(buff), this.display);
this.printHeadLine();
}
/**
* Print lines.
*/
private void printLine() {
this.display.println("------------------------------------------------------------------------------------"); //$NON-NLS-1$
this.save.println("------------------------------------------------------------------------------------"); //$NON-NLS-1$
}
/**
* Print headline.
*/
private void printHeadLine() {
StringBuffer buff = new StringBuffer();
buff.append("The detail report is shown as follows : \n"); //$NON-NLS-1$
Tools.message(new String(buff), this.display);
Tools.message(new String(buff), this.save);
this.display.println("------------------------Certification report for optimality-------------------------"); //$NON-NLS-1$
this.save.println("------------------------Certification report for optimality-------------------------"); //$NON-NLS-1$
}
/**
* Get a initial array based on 2 dimensions.
*
* @param array Initialize a two-dimension array
* @return a two-dimension array
*/
private RS[][] getInitialArray(RS[][] array) {
for (int row = 0; row < array.length; row++) {
for (int col = 0; col < array.length; col++) {
array[row][col] = this.unit.createZero();
}
}
return array;
}
/**
* Get a initial vector X
*
* @param x2 Initialize a vector
* @return An initial vector
*/
private RS[] getInitialVectorX(RS[] x2) {
for (int i = 0; i < x2.length; i++) {
x2[i] = this.unit.createZero();
}
return x2;
}
// /**
// * Read result of SDP solver
// * @param fileName Result file
// * @throws IOException I/O exception
// */
// private void readSolutionOfSDP(String fileName) throws IOException {
// BufferedReader reader = new BufferedReader(new FileReader(new File(fileName)));
// String name = ""; //$NON-NLS-1$
// name = reader.readLine();
// while(!name.contains("xVec")){ //$NON-NLS-1$
// name = reader.readLine();
// }
// StringBuffer br2 = new StringBuffer(reader.readLine());
// for(int i = 0; i < this.x.length; i++){
// RS value = this.unit.valueOf(IO.readOtherStringRealNumber(br2));
// this.x[i] = value;
// }
// name = reader.readLine();
// while(!name.contains("xMat")){ //$NON-NLS-1$
// name = reader.readLine();
// }
// reader.readLine();
//
// int shift = 0;
// for(int block = 0; block < this.nBlock; block++) {
// if(block != 0){
// shift += this.blockStruct[block - 1];
// }
// for(int row = 0; row < this.blockStruct[block]; row++){
// br2 = new StringBuffer(reader.readLine());
// for(int col = 0; col < this.blockStruct[block]; col++){
// RS value = this.unit.valueOf(IO.readOtherStringRealNumber(br2));
// this.X[row + shift][col + shift] = value;
// }
// }
// }
// name = reader.readLine();
// while(!name.contains("yMat")){ //$NON-NLS-1$
// name = reader.readLine();
// }
// reader.readLine();
//
// shift = 0;
// for(int block = 0; block < this.nBlock; block++) {
// if(block != 0){
// shift += this.blockStruct[block - 1];
// }
// for(int row = 0; row < this.blockStruct[block]; row++){
// br2 = new StringBuffer(reader.readLine());
// for(int col = 0; col < this.blockStruct[block]; col++){
// RS value = this.unit.valueOf(IO.readOtherStringRealNumber(br2));
// this.Y[row + shift][col + shift] = value;
// }
// }
// }
// }
/**
* Read a initial file
*
* @param fileName An initial file
* @throws IOException If an I/O error occurs
*/
private void readInitialData(String fileName) throws IOException {
try (BufferedReader reader = new BufferedReader(new FileReader(new File(fileName)))) {
this.m = readM(reader); //read m
this.dimension = readDimension(reader); //read the dimension of matrix
Vector<RS,RM,CS,CM> b = Vector.<RS,RM,CS,CM> read(reader, this.m, this.unit);
this.c = b.getElements(); //read vector c
this.F = readF(reader, fileName);
}
}
/**
* Read the constant matrices F
*
* @param reader The object <code>BufferedReader</code> read an initial file
* @param fileName The initial file
* @return The constant matrices F
* @throws IOException If an I/O error occurs
*/
private List<RS[][]> readF(BufferedReader reader, String fileName) throws IOException {
this.isSparse = false;
if (fileName.charAt(fileName.length() - 1) == 's' && fileName.charAt(fileName.length() - 2) == '-') {
this.isSparse = true;
}
List<RS[][]>tempF = new ArrayList<>(this.m + 1);
for (int i = 0; i <= this.m; i++) {
tempF.add(getInitialF());
}
if (tempF == null) {
System.err.println("Matrix F is null, which is in the method readInitialData of class Vsolution."); //$NON-NLS-1$
System.exit(1);
}
if (this.isSparse) {
String line;
int oldM = 0;
int oldL = 1;
int shift = 0;
while ((line = reader.readLine()) != null) {
StringBuffer br2 = new StringBuffer(line);
int mIndex = IO.readOtherStringInteger(br2);
int l = IO.readOtherStringInteger(br2);
int i = IO.readOtherStringInteger(br2);
int j = IO.readOtherStringInteger(br2);
RS value = this.unit.valueOf(IO.readOtherStringRealNumber(br2));
if (oldM != mIndex) {
oldM = mIndex;
shift = 0;
oldL = 1;
}
if (l - 2 >= 0 && oldL != l) {
if (l - oldL == 1) {
shift += Math.abs(this.blockStruct[l - 2]);
} else {
for (int gap = 0; gap < l - oldL; gap++) {
shift += Math.abs(this.blockStruct[oldL + gap - 1]);
}
}
}
if (oldL != l) {
oldL = l;
}
tempF.get(mIndex)[i + shift - 1][j + shift - 1] = value;
tempF.get(mIndex)[j + shift - 1][i + shift - 1] = tempF.get(mIndex)[i + shift - 1][j + shift - 1];
}
} else { // read the data of dense matrix.
for (int i = 0; i <= this.m; i++) {
StringBuffer br2 = new StringBuffer(reader.readLine()); //define the data of dense matrix, which must be one matrix by one line.
for (int block = 0; block < this.nBlock; block++) { //if you want to know detail it, please refer to file, "example.dat"
for (int row = 0; row < this.blockStruct[block]; row++) {
for (int col = 0; col < this.blockStruct[block]; col++) {
RS value = this.unit.valueOf(IO.readOtherStringRealNumber(br2));
tempF.get(i)[row][col] = value;
}
}
}
}
}
return tempF;
}
/**
* Get a initial matrices F
* @return f
*/
private RS[][] getInitialF() {
RS[][] f = this.unit.createArray(this.dimension, this.dimension);
for (int row = 0; row < this.dimension; row++) {
for (int col = 0; col < this.dimension; col++) {
f[row][col] = this.unit.createZero();
}
}
return f;
}
/**
* Read the dimension of matrix.
*
* @param reader The object <code>BufferedReader</code> reads the file
* @return Size of matrix
* @throws IOException If an I/O error occurs
*/
private int readDimension(BufferedReader reader) throws IOException {
this.nBlock = IO.readInteger(reader.readLine());
this.blockStruct = IO.readBlockStruct(reader, this.nBlock);
int tempDimension = 0;
for (int i = 0; i < this.nBlock; ++i) {
tempDimension += Math.abs(this.blockStruct[i]);
}
return tempDimension;
}
/**
* Read the integer number, which is the size of array F.
*
* @param reader The object <code>BufferedReader</code> reads the file
* @return The number of matrices
* @throws IOException If an I/O error occurs
*/
private int readM(BufferedReader reader) throws IOException {
String size;
do {
size = reader.readLine();
if (size.charAt(0) == '*' || size.charAt(0) == '"') {
continue;
}
break;
} while (true);
size = size.replaceAll("(\\p{Space}*)", ""); //$NON-NLS-1$ //$NON-NLS-2$
return IO.readInteger(size);
}
/**
* Verify a accuracy optimal solutions of the SDP problem based on reliable computing.
*/
private void getCertificateOfOptimality() {
RoundModeManager manager = RoundModeManager.getManager();
manager.add(new FPURoundModeSelector());
manager.add(new MPFloatRoundModeSelector());
MPFloat[] cc = (MPFloat[])this.c;
MPFloatMatrix tempC = cc[0].createGrid(cc);
MPFloatIntervalMatrix intervalC = new MPFloatIntervalMatrix(tempC);
MPFloat[] xx = (MPFloat[])this.x;
MPFloatMatrix tempxVec = xx[0].createGrid(xx);
MPFloatIntervalMatrix intervalxVec = new MPFloatIntervalMatrix(tempxVec.unaryMinus()); //must to be minus
MPFloatIntervalNumber primalOptimalValue = (intervalC.multiply(intervalxVec.transpose())).trace();
this.primalValue = (RS)primalOptimalValue.getMiddle();
if (isExternal == false) {
this.display.printf("primalOptimalValue = %s, Radius = %s\n", this.primalValue.abs().toString("%4.16e"), primalOptimalValue.getRadius().toString("%4.16e")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
this.save.printf("primalOptimalValue = %s, Radius = %s\n", this.primalValue.abs().toString("%4.16e"), primalOptimalValue.getRadius().toString("%4.16e")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
MPFloat[][] ff = (MPFloat[][])this.F.get(0);
MPFloatMatrix tempF = ff[0][0].createGrid(ff);
MPFloatIntervalMatrix intervalF = new MPFloatIntervalMatrix(tempF.unaryMinus()); //must to be minus
MPFloat[][] yy = (MPFloat[][])this.Y;
MPFloatMatrix tempY = yy[0][0].createGrid(yy);
MPFloatIntervalMatrix intervalY = new MPFloatIntervalMatrix(tempY);
MPFloatIntervalNumber dualOptimalValue = (intervalF.multiply(intervalY)).trace();
this.dualValue = (RS)dualOptimalValue.getMiddle();
if (isExternal == false) {
this.display.printf("dualOptimalValue = %s, Radius = %s\n", this.dualValue.abs().toString("%4.16e"), dualOptimalValue.getRadius().toString("%4.16e")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
this.save.printf("dualOptimalValue = %s, Radius = %s\n", this.dualValue.abs().toString("%4.16e"), dualOptimalValue.getRadius().toString("%4.16e")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
MPFloat[][] xx2 = (MPFloat[][])this.X;
MPFloatMatrix tempX = xx2[0][0].createGrid(xx2);
MPFloatIntervalMatrix intervalX = new MPFloatIntervalMatrix(tempX);
MPFloatIntervalNumber muValue = (intervalX.multiply(intervalY)).trace();
MPFloat mu = muValue.getMiddle();
MPFloatIntervalNumber optimality = primalOptimalValue.subtract(dualOptimalValue);
MPFloat gap = optimality.getMiddle();
MPFloat mean = (MPFloat)(this.primalValue.abs().add(this.dualValue.abs())).divide(2);
if (!mean.isZero()) {
gap = gap.divide(mean);
}
MPFloat radiusOfOptimal = optimality.getRadius();
MPFloat radiusOfMu = muValue.getMiddle();
this.display.printf("Relative Gap = %s, Radius = %s\n", gap.abs().toString("%4.16e"), optimality.getRadius().toString("%4.16e")); //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
this.save.printf("Relative Gap = %s, Radius = %s\n", gap.abs().toString("%4.16e"), optimality.getRadius().toString("%4.16e")); //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
MPFloat optimal = gap;
this.display.printf("Mu = %s, Radius = %s\n", mu.divide(this.dimension).toString("%4.16e"), muValue.getRadius().toString("%4.16e")); //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
this.save.printf("Mu = %s, Radius = %s\n", mu.divide(this.dimension).toString("%4.16e"), muValue.getRadius().toString("%4.16e")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
if (!mean.isZero()) {
mu = mu.divide(mean);
}
if (mu.abs().isGreaterThan(gap.abs())) {
optimal = mu;
optimality = muValue;
}
this.display.printf("Optimality = %s, Radius = %s\n", optimal.abs().toString("%4.16e"), optimality.getRadius().toString("%4.16e")); //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
this.save.printf("Optimality = %s, Radius = %s\n", optimal.abs().toString("%4.16e"), optimality.getRadius().toString("%4.16e")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
}
/**
* Verify a feasible error and radius of primal constraint condition based on reliable computing.
*/
private void getCertificateOfFeasibilityOfPrimal() {
MPFloatMatrix tempX = (MPFloatMatrix)this.X[0][0].createGrid(this.X);
MPFloatIntervalMatrix intervalX = new MPFloatIntervalMatrix(tempX.unaryMinus());
MPFloat[][] f0 = (MPFloat[][])this.F.get(0);
MPFloatMatrix cMat = f0[0][0].createGrid(f0);
MPFloatIntervalMatrix intervalC = new MPFloatIntervalMatrix(cMat.unaryMinus()); //minus
MPFloatIntervalMatrix primalConstraintCondition = intervalX.add(intervalC);
MPFloatIntervalMatrix primalCondition = new MPFloatIntervalMatrix(cMat.unaryMinus());
for (int i = 1; i <= this.m; ++i) {
MPFloat[][] fi = (MPFloat[][])this.F.get(i);
MPFloatMatrix tempA = fi[0][0].createGrid(fi);
tempA = tempA.multiply((MPFloat)this.x[i - 1]); //minus
MPFloatIntervalMatrix intervalA = new MPFloatIntervalMatrix(tempA.unaryMinus());
primalConstraintCondition = primalConstraintCondition.subtract(intervalA);
primalCondition = primalCondition.add(intervalA);
}
MPFloat primalFeasibleError = primalConstraintCondition.getSupremum().absElementWise().max();
this.display.printf("primalFeasibleError = %s (No Radius Information)\n", primalFeasibleError.abs().toString("%4.16e")); //$NON-NLS-1$ //$NON-NLS-2$
this.save.printf("primalFeasibleError = %s (No Radius Information)\n", primalFeasibleError.abs().toString("%4.16e")); //$NON-NLS-1$ //$NON-NLS-2$
MPFloatRumpMethod verifier = new MPFloatRumpMethod(tempX);
Guarantor<MPFloatRumpMethod> guarantor = new Guarantor<>(verifier);
int digit = MPFloat.getDefaultNumberOfPrecisionDigits();
guarantor.solveWithEffectiveDigits(digit);
MPFloatRumpMethod guaranteedVerifier = guarantor.getGuranteedVerifier();
MPFloatComplexIntervalMatrix ans = guaranteedVerifier.getEigenValue();
MPFloat minimumEigenValue = ans.getRealPart().getInfimum().min();
this.display.printf("minEigenValue(X) = %s (No Radius Information)\n", minimumEigenValue.toString("%4.16e")); //$NON-NLS-1$ //$NON-NLS-2$
this.save.printf("minEigenValue(X) = %s (No Radius Information)\n", minimumEigenValue.toString("%4.16e")); //$NON-NLS-1$ //$NON-NLS-2$
MPFloatMatrix primalConstraint = primalCondition.getMiddle();
MPFloatRumpMethod verifier2 = new MPFloatRumpMethod(primalConstraint.unaryMinus());
Guarantor<MPFloatRumpMethod> guarantor2 = new Guarantor<>(verifier2);
guarantor2.solveWithEffectiveDigits(digit);
MPFloatRumpMethod guaranteedVerifier2 = guarantor2.getGuranteedVerifier();
MPFloatComplexIntervalMatrix ans2 = guaranteedVerifier2.getEigenValue();
MPFloat minimumEigenValue2 = ans2.getRealPart().getInfimum().min();
this.display.printf("minEigenValue(equation) = %s (No Radius Information)\n", minimumEigenValue2.toString("%4.16e")); //$NON-NLS-1$ //$NON-NLS-2$
this.save.printf("minEigenValue(equation) = %s (No Radius Information)\n", minimumEigenValue2.toString("%4.16e")); //$NON-NLS-1$ //$NON-NLS-2$
}
/**
* Verify a feasible error and radius of dual constraint condition based on reliable computing.
*/
private void getCertificateOfFeasibilityOfDual() {
int size = this.c.length;//b.getDimension();
final MPFloat[] data = new MPFloat[size];
for (int row = 0; row < size; row++) {
data[row] = new MPFloat(0);
}
MPFloat[][] yy = (MPFloat[][])this.Y;
MPFloatMatrix tempY = yy[0][0].createGrid(yy);
MPFloatIntervalMatrix intervalY = new MPFloatIntervalMatrix(tempY);
for (int i = 1; i <= this.m; ++i) {
MPFloat[][] fi = (MPFloat[][])this.F.get(i);
MPFloatMatrix A = fi[0][0].createGrid(fi);
MPFloatIntervalMatrix intervalA = new MPFloatIntervalMatrix(A);
MPFloatIntervalNumber intervalC = (intervalA.multiply(intervalY)).trace();
data[i - 1] = intervalC.getMiddle();
}
MPFloat[] cc = (MPFloat[])this.c;
MPFloatMatrix tempB = cc[0].createGrid(cc);
MPFloatIntervalMatrix intervalB = new MPFloatIntervalMatrix(tempB);
MPFloatMatrix tempData = data[0].createGrid(data);
MPFloatIntervalMatrix intervalData = new MPFloatIntervalMatrix(tempData);
MPFloatIntervalMatrix dualConstraintCondition = intervalData.subtract(intervalB);
MPFloat dualFeasibleError = dualConstraintCondition.getInfimum().absElementWise().max();
this.display.printf("dualFeasibleError = %s (No Radius Information)\n", dualFeasibleError.abs().toString("%4.16e")); //$NON-NLS-1$ //$NON-NLS-2$
this.save.printf("dualFeasibleError = %s (No Radius Information)\n", dualFeasibleError.abs().toString("%4.16e")); //$NON-NLS-1$ //$NON-NLS-2$
MPFloatRumpMethod verifier = new MPFloatRumpMethod(intervalY);
Guarantor<MPFloatRumpMethod> guarantor = new Guarantor<>(verifier);
int digit = MPFloat.getDefaultNumberOfPrecisionDigits();
guarantor.solveWithEffectiveDigits(digit);
MPFloatRumpMethod guaranteedVerifier = guarantor.getGuranteedVerifier();
MPFloatComplexIntervalMatrix ans = guaranteedVerifier.getEigenValue();
MPFloat minimumEigenValue = ans.getRealPart().getInfimum().min();
this.display.printf("minEigenValue(Y) = %s (No Radius Information)\n", minimumEigenValue.toString("%4.16e")); //$NON-NLS-1$ //$NON-NLS-2$
this.save.printf("minEigenValue(Y) = %s (No Radius Information)\n", minimumEigenValue.toString("%4.16e")); //$NON-NLS-1$ //$NON-NLS-2$
}
/**
* Read the result file based on GMP, which should be verified. The GMP format is <code>(±0.d<sub>1</sub> d<sub>2</sub>...d<sub>n</sub>)<sub>β</sub> × β<sup>E</sup></code> , where
* β is radix and <code>E</code> is exponent in decimal.
*
* @param FileName The file you want to verify
* @param Base The radix of data
* @throws IOException If an I/O error occurs
* @throws NumberFormatException If an format of number error occurs
*/
private void readDataBasedOnGMP(String FileName, int Base) throws NumberFormatException, IOException {
try (BufferedReader reader = new BufferedReader(new FileReader(new File(FileName)))) {
final int Dimensions = Integer.parseInt(reader.readLine(), Base);
for (int i = 0; i < Dimensions; i++) {
this.x[i] = this.readDataBasedOnRadix(Base, reader);
}
final int NUMBER_OF_MATRICES = 2;
for (int interationNumber = 0; interationNumber < NUMBER_OF_MATRICES; interationNumber++) {
final int Block = Integer.parseInt(reader.readLine(), Base);
int shift = 0;
for (int block = 0; block < Block; block++) {
//Read row and column of matrix
final int size = Integer.parseInt(reader.readLine(), Base);
for (int row = 0; row < size; row++) {
for (int col = 0; col < size; col++) {
switch (interationNumber) {
case 0:
this.X[row + shift][col + shift] = this.readDataBasedOnRadix(Base, reader);
break;
case 1:
this.Y[row + shift][col + shift] = this.readDataBasedOnRadix(Base, reader);
break;
}
}
}
shift += size;
}
}
}
}
/**
* Read the result file based on GMP, which should be verified. Then, change a float-number from the data based on radix and return it.
*
* @param Base The radix of data
* @param reader The bufferedReader object
* @return The number based on radix you specified
* @throws IOException If an I/O error occurs
*/
private RS readDataBasedOnRadix(int Base, BufferedReader reader) throws IOException {
String Data = reader.readLine();
RS number = this.unit.createZero();
RS base = this.unit.create(Base).multiply(1.0);
RS element;
int Index = 1;
int negative = 1; // '1' represent the number is positive, and '2' is negative.
if (Data.charAt(Index) == '.') {
element = this.unit.create(Integer.parseInt(Data.substring(Index - 1, Index), Base));
number = number.add(element);
Index = Index + 1;
} else {
element = this.unit.create(Integer.parseInt(Data.substring(Index, Index + 1), Base));
number = number.add(element);
Index = Index + 2;
negative = negative + 1;
}
char exponentMark = 'e'; //The criterion of GMP floating number
if (Base > 10) {
exponentMark = '@';
}
while (Data.charAt(Index) != exponentMark) {
element = this.unit.create(Integer.parseInt(Data.substring(Index, Index + 1), Base));
element = element.divide(base.power(Index - negative));
number = number.add(element);
Index = Index + 1;
}
int exponent = Integer.parseInt(Data.substring(Index + 1), 10);
number = number.multiply(base.power(exponent));
if (negative == 2) {
number = number.unaryMinus();
}
return number;
}
/**
* Read the result file based on double, which should be verified. Before writing data into file, you must to write string "SDPJ" into the file firstly. Reason is that we need use that to judge your
* data saved by small endians or big endians in your machine.
*
* @param FileName The SDP problem file, which should be verified
* @throws IOException If an I/O error occurs
*/
private void readDataBasedOnDouble(String FileName) throws IOException {
final int SDPJ = 0X5344504a; // 0X5344504a means "SDPJ"
try (BufferedInputStream reader = new BufferedInputStream(new FileInputStream(new File(FileName)))) {
if (this.Format == null) {
this.isExampleFormat = isExampleFormat(reader, FileName, SDPJ);
} else {
this.isBigEndians = isBigEndians(SDPJ, reader);
}
final int dimensions = this.getIntegerFromBinary(reader);
for (int i = 0; i < dimensions; i++) {
this.x[i] = this.getDoubleFromBinary(reader);
}
final int NUMBER_OF_MATRICES = 2;
for (int interationNumber = 0; interationNumber < NUMBER_OF_MATRICES; interationNumber++) {
final int Block = this.getIntegerFromBinary(reader);
int shift = 0;
for (int block = 0; block < Block; block++) {
//Read row and column of matrix
final int size = this.getIntegerFromBinary(reader);
for (int row = 0; row < size; row++) {
for (int col = 0; col < size; col++) {
switch (interationNumber) {
case 0:
this.X[row + shift][col + shift] = this.getDoubleFromBinary(reader);
break;
case 1:
this.Y[row + shift][col + shift] = this.getDoubleFromBinary(reader);
break;
}
}
}
shift += size;
}
}
}
}
/**
* get a matrix from a binary file written base on double.
*
* @param FileName name of binary file.
* @return a matrix
* @throws IOException If an I/O error occurs
*/
public RS[][] getMatrixBasedOnDoubleBinary(String FileName) throws IOException {
final int SDPJ = 0X5344504a; // 0X5344504a means "SDPJ"
try (BufferedInputStream reader = new BufferedInputStream(new FileInputStream(new File(FileName)))) {
if (this.Format == null) {
this.isExampleFormat = isExampleFormat(reader, FileName, SDPJ);
} else {
this.isBigEndians = isBigEndians(SDPJ, reader);
}
final int matrixSize = this.getIntegerFromBinary(reader);
RS[][] matrix = this.unit.createArray(matrixSize, matrixSize);
for (int row = 0; row < matrixSize; row++) {
for (int col = 0; col < matrixSize; col++) {
matrix[row][col] = this.getDoubleFromBinary(reader);
}
}
return matrix;
}
}
/**
* Judge the saved data whether it is the big endians or not. If it is big endians, true; else, false.
*
* @param SDPJ The head information "SDPJ" mark
* @param reader The bufferedReader object
* @return If the saved data is big endians, true; else, false
* @throws IOException If an I/O error occurs
*/
private boolean isBigEndians(final int SDPJ, BufferedInputStream reader) throws IOException {
byte buf[] = new byte[4];
reader.read(buf);
final int sdpj = buf[0] << 24 | buf[1] << 16 | buf[2] << 8 | buf[3];
if ((sdpj & 0XFFFFFFFF) != SDPJ) {
return false;
}
return true;
}
/**
* Judge whether saved file data follows the example format or not. If following that,true;else, false.
*
* @param reader The bufferedReader object
* @param FileName The data file
* @param sdpj It is constant integer, "SDPJ"
* @return If the saved data follows the example rule,true; else, false
* @throws IOException If an I/O error occurs
*/
private boolean isExampleFormat(BufferedInputStream reader, String FileName, int sdpj) throws IOException {
try (BufferedInputStream testDataFormat = new BufferedInputStream(new FileInputStream(new File(FileName)))) {
byte[] testBuf = new byte[4];
testDataFormat.read(testBuf);//Head of file, 4 bytes should be cut
this.isBigEndians = isBigEndians(sdpj, reader);
testBuf = new byte[5];
testDataFormat.read(testBuf);
if (testBuf[4] != 10) {
return false;
}
final int dimensionOfvector = Integer.parseInt(this.getStringBits(5, true, testBuf), 2);
testBuf = new byte[9 * dimensionOfvector];
testDataFormat.read(testBuf);
for (int i = 1; i <= dimensionOfvector; i++) {
if (testBuf[i * 9 - 1] != 10) {
testDataFormat.close();
return false;
}
}
final int NUMBER_OF_MATRICES = 2;
for (int interationNumber = 0; interationNumber < NUMBER_OF_MATRICES; interationNumber++) {
testBuf = new byte[5];
testDataFormat.read(testBuf);
if (testBuf[4] != 10) {
testDataFormat.close();
return false;
}
final int numBlock = Integer.parseInt(this.getStringBits(5, true, testBuf), 2);
for (int b = 0; b < numBlock; b++) {
testBuf = new byte[5];
testDataFormat.read(testBuf);
if (testBuf[4] != 10) {
testDataFormat.close();
return false;
}
final int size = Integer.parseInt(this.getStringBits(5, true, testBuf), 2);
testBuf = new byte[9 * size * size];
testDataFormat.read(testBuf);
for (int i = 1; i <= size * size; i++) {
if (testBuf[i * 9 - 1] != 10) {
testDataFormat.close();
return false;
}
}
}
}
}
return true;
}
/**
* Get a float number from a string of bits.
*
* @param reader The object <code>BufferedInputStream</code> reads the SDP result file
* @return a float number (double)
* @throws IOException If an I/O error occurs
*/
private RS getDoubleFromBinary(BufferedInputStream reader) throws IOException {
final int size;
if (this.isExampleFormat == true) {
size = 9;
} else {
size = 8;
}
final double data = this.getDoublePrecisionValue(this.getStringBits(reader, size));
// System.err.println("Machine Epsilon is = " + this.unit.getMachineEpsilon());
if (this.unit.getMachineEpsilon().isLessThan(Math.abs(data))) {
return this.unit.create(data);
} else {
return this.unit.createZero();
}
}
/**
* Get a integer from a string of bits.
*
* @param reader The object <code>BufferedInputStream</code> reads the SDP result file
* @return An integer
* @throws IOException If an I/O error occurs
*/
private int getIntegerFromBinary(BufferedInputStream reader) throws IOException {
final int size;
if (this.isExampleFormat == true) {
size = 5;
} else {
size = 4;
}
return Integer.parseInt(this.getStringBits(reader, size), 2);
}
/**
* Get a string of bits from inputting file
*
* @param reader The object <code>BufferedInputStream</code> reads the SDP result file
* @param size The size of array
* @return A string of bits
* @throws IOException If an I/O error occurs
*/
private String getStringBits(BufferedInputStream reader, final int size) throws IOException {
byte buf[] = new byte[size];
reader.read(buf);
return this.getStringBits(size, this.isExampleFormat, buf);
}
/**
* Get a String of the array of byte
*
* @param size The length of array
* @param exampleFormat If the saved data follows the example rule,true; else, false.
* @param buf The byte array
* @return The String of bits
*/
private String getStringBits(final int size, boolean exampleFormat, byte[] buf) {
String data = ""; //$NON-NLS-1$
byte[] bufCopy = buf;
if (this.isBigEndians == false) {
bufCopy = getBigEndians(bufCopy);
}
int index = 0;
byte byteData;
while (index != size) { //10 means '\n'
if ((byteData = buf[index]) == 10 && exampleFormat == true && index == size - 1) {
break;
}
String bit = this.getStringBitsFromByte(byteData);
data = bit + data;
index++;
}
return data;
}
/**
* Get the data by the big endians or change the data to the big endians.
*
* @param buf The array of bits based on the small endians
* @return The array of bits based on the big endians
*/
private byte[] getBigEndians(byte[] buf) {
final int length = buf.length - 1;
final int shift;
if (this.isExampleFormat == true) {
shift = 1;
} else {
shift = 0;
}
for (int i = 0; i < (length + 1) / 2; i++) {
byte tempByte = buf[i];
buf[i] = buf[length - shift - i];
buf[length - shift - i] = tempByte;
}
return buf;
}
/**
* Get a string of bits from byte data.
*
* @param byteData The byte data
* @return The string of bits
*/
private String getStringBitsFromByte(byte byteData) {
String bit = Integer.toBinaryString(byteData);
if (bit.length() < 8) {
final StringBuilder sb = new StringBuilder(bit);
while (sb.length() < 8) {
sb.insert(0, "0"); //$NON-NLS-1$
}
bit = sb.toString();
}
if (bit.length() > 8) {
String subBit = bit.substring(24);
bit = subBit;
}
return bit;
}
/**
* Get a float number from a string of bits.
*
* @param value The string of bits
* @return The float number
*/
private double getDoublePrecisionValue(String value) {
final String doublePrecisionBitString = fillBits(value);
final char[] doublePrecisionBit = doublePrecisionBitString.toCharArray();
final int signBitIndex = 0;
final int exponentBitBegin = 1;
final int exponentBitEnd = 11;
final int fractionBitBegin = 12;
final int bitLength = 64;
final int bias64Bit = 1023;
int exponentValue = 0;
int sign = 1;
double doublePrecisionValue = 0;
sign = getSignSectionValue(doublePrecisionBit, signBitIndex);
exponentValue = getExponentSectionValue(doublePrecisionBit, exponentBitBegin, exponentBitEnd);
exponentValue -= bias64Bit;
doublePrecisionValue = getDoublePrecisionValue(doublePrecisionBit, exponentValue, sign, fractionBitBegin, bitLength);
return doublePrecisionValue;
}
/**
* Get a float number.
*
* @param doublePrecisionBit The array of <code>char</code>
* @param exponentValue The exponent value
* @param sign The sign of the number
* @param fractionBitBegin The start point of mantissa
* @param bitLength The length of bits
* @return A float number
*/
private double getDoublePrecisionValue(final char[] doublePrecisionBit, int exponentValue, int sign, int fractionBitBegin, int bitLength) {
double doublePrecisionValue = 1.0;
for (int i = fractionBitBegin; i < bitLength; i++) {
if (doublePrecisionBit[i] == '1') {
doublePrecisionValue += Math.pow(0.5, i - fractionBitBegin + 1);
}
}
doublePrecisionValue *= sign * Math.pow(2, exponentValue);
return doublePrecisionValue;
}
/**
* Get the sign of the float number.
*
* @param doublePrecisionBit The array of <code>char</code>
* @param signBitIndex The index of sign bit
* @return If positive,1;else, -1.
*/
private int getSignSectionValue(final char[] doublePrecisionBit, final int signBitIndex) {
int sign = 1;
if (doublePrecisionBit[signBitIndex] == '1') {
sign = -1;
}
return sign;
}
/**
* Get the exponent of the float number.
*
* @param doublePrecisionBit The array of <code>char</code>
* @param exponentBitBegin The start point of exponent bits
* @param exponentBitEnd The end point of exponent bits
* @return The exponent value
*/
private int getExponentSectionValue(final char[] doublePrecisionBit, final int exponentBitBegin, final int exponentBitEnd) {
int exponentValue = 0;
for (int i = exponentBitBegin; i <= exponentBitEnd; i++) {
if (doublePrecisionBit[i] == '1') {
exponentValue += Math.pow(2, exponentBitEnd - i);
}
}
return exponentValue;
}
/**
* Fill bits into the string of bits, if the length of string bits is less than 64 (<64).
*
* @param doublePrecisionBitString The string of bits
* @return The string of bits filled, whose length is 64.
*/
private String fillBits(String doublePrecisionBitString) {
final StringBuilder sb = new StringBuilder(doublePrecisionBitString);
while (sb.length() < 64) {
sb.insert(0, "0"); //$NON-NLS-1$
}
return sb.toString();
}
/**
* @param io ioを設定します。
*/
public void setIo(SolverIO<RS,RM,CS,CM> io) {
this.io = io;
}
/**
* @return ioを返します。
*/
public SolverIO<RS,RM,CS,CM> getIo() {
return this.io;
}
/**
* @param problem problemを設定します。
*/
public void setProblem(Problem<RS,RM,CS,CM> problem) {
this.problem = problem;
}
/**
* @return problemを返します。
*/
public Problem<RS,RM,CS,CM> getProblem() {
return this.problem;
}
/**
* @param initialCurrentPt initialCurrentPtを設定します。
*/
public void setInitialCurrentPt(Solution<RS,RM,CS,CM> initialCurrentPt) {
this.initialCurrentPt = initialCurrentPt.createClone();
}
/**
* @return initialCurrentPtを返します。
*/
public Solution<RS,RM,CS,CM> getInitialCurrentPt() {
return this.initialCurrentPt;
}
/**
* @param dualValue dualValueを設定します。
*/
public void setDualValue(RS dualValue) {
this.dualValue = dualValue;
}
/**
* @return dualValueを返します。
*/
public RS getDualValue() {
return this.dualValue;
}
/**
* @param primalValue primalValueを設定します。
*/
public void setPrimalValue(RS primalValue) {
this.primalValue = primalValue;
}
/**
* @return primalValueを返します。
*/
public RS getPrimalValue() {
return this.primalValue;
}
/**
* @param blockStruct blockStructを設定します。
*/
public void setBlockStruct(int[] blockStruct) {
this.blockStruct = blockStruct;
}
/**
* @return blockStruct
*/
public int[] getBlockStruct() {
return this.blockStruct;
}
}