1315 lines
36 KiB
C++
1315 lines
36 KiB
C++
/* -------------------------------------------------------------
|
|
|
|
This file is a component of SDPA
|
|
Copyright (C) 2004-2013 SDPA Project
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
|
|
------------------------------------------------------------- */
|
|
|
|
#include "sdpa_parts.h"
|
|
#include "sdpa_linear.h"
|
|
#include "sdpa_newton.h"
|
|
|
|
namespace sdpa {
|
|
|
|
ComputeTime::ComputeTime()
|
|
{
|
|
Predictor = 0.0;
|
|
Corrector = 0.0;
|
|
|
|
StepPredictor = 0.0;
|
|
StepCorrector = 0.0;
|
|
|
|
xMatTime = 0.0;
|
|
zMatTime = 0.0;
|
|
xMatzMatTime = 0.0;
|
|
invzMatTime = 0.0;
|
|
|
|
EigxMatTime = 0.0;
|
|
EigzMatTime = 0.0;
|
|
EigxMatzMatTime = 0.0;
|
|
|
|
makebMat = 0.0;
|
|
B_DIAG = 0.0;
|
|
B_F1 = 0.0;
|
|
B_F2 = 0.0;
|
|
B_F3 = 0.0;
|
|
B_PRE = 0.0;
|
|
|
|
makebMatgVec = 0.0;
|
|
makerMat = 0.0;
|
|
choleskybMat = 0.0;
|
|
|
|
solve = 0.0;
|
|
sumDz = 0.0;
|
|
makedX = 0.0;
|
|
symmetriseDx = 0.0;
|
|
makedXdZ = 0.0;
|
|
updateRes = 0.0;
|
|
|
|
MainLoop = 0.0;
|
|
FileRead = 0.0;
|
|
FileCheck = 0.0;
|
|
FileChange= 0.0;
|
|
TotalTime = 0.0;
|
|
}
|
|
|
|
ComputeTime::~ComputeTime()
|
|
{
|
|
// Nothing needs.
|
|
}
|
|
|
|
|
|
void ComputeTime::display(FILE* fpout)
|
|
{
|
|
if (fpout == NULL) {
|
|
return;
|
|
}
|
|
fprintf(fpout,"\n");
|
|
#if 0
|
|
if (TotalTime <= 0.0) {
|
|
return;
|
|
}
|
|
#endif
|
|
fprintf(fpout, " Time(sec) ");
|
|
fprintf(fpout," Ratio(%% : MainLoop) \n");
|
|
fprintf(fpout, " Predictor time = %f, %f\n",
|
|
Predictor, Predictor/MainLoop*100.0);
|
|
fprintf(fpout, " Corrector time = %f, %f\n",
|
|
Corrector, Corrector/MainLoop*100.0);
|
|
fprintf(fpout, " Make bMat time = %f, %f\n",
|
|
makebMat, makebMat/MainLoop*100.0);
|
|
fprintf(fpout, " Make bDia time = %f, %f\n",
|
|
B_DIAG,B_DIAG/MainLoop*100.0);
|
|
fprintf(fpout, " Make bF1 time = %f, %f\n",
|
|
B_F1,B_F1/MainLoop*100.0);
|
|
fprintf(fpout, " Make bF2 time = %f, %f\n",
|
|
B_F2,B_F2/MainLoop*100.0);
|
|
fprintf(fpout, " Make bF3 time = %f, %f\n",
|
|
B_F3,B_F3/MainLoop*100.0);
|
|
fprintf(fpout, " Make bPRE time = %f, %f\n",
|
|
B_PRE,B_PRE/MainLoop*100.0);
|
|
fprintf(fpout, " Make rMat time = %f, %f\n",
|
|
makerMat, makerMat/MainLoop*100.0);
|
|
fprintf(fpout, " Make bMatgVec = %f, %f\n",
|
|
makebMatgVec, makebMatgVec/MainLoop*100.0);
|
|
fprintf(fpout, " Cholesky bMat = %f, %f\n",
|
|
choleskybMat, choleskybMat/MainLoop*100.0);
|
|
fprintf(fpout, " Ste Pre time = %f, %f\n",
|
|
StepPredictor, StepPredictor/MainLoop*100.0);
|
|
fprintf(fpout, " Ste Cor time = %f, %f\n",
|
|
StepCorrector, StepCorrector/MainLoop*100.0);
|
|
fprintf(fpout, " solve = %f, %f\n",
|
|
solve, solve/MainLoop*100.0);
|
|
fprintf(fpout, " sumDz = %f, %f\n",
|
|
sumDz, sumDz/MainLoop*100.0);
|
|
fprintf(fpout, " makedX = %f, %f\n",
|
|
makedX, makedX/MainLoop*100.0);
|
|
fprintf(fpout, " symmetriseDx = %f, %f\n",
|
|
symmetriseDx, symmetriseDx/MainLoop*100.0);
|
|
fprintf(fpout, " makedXdZ = %f, %f\n",
|
|
makedXdZ, makedXdZ/MainLoop*100.0);
|
|
fprintf(fpout, " xMatTime = %f, %f\n",
|
|
xMatTime, xMatTime/MainLoop*100.0);
|
|
fprintf(fpout, " zMatTime = %f, %f\n",
|
|
zMatTime, zMatTime/MainLoop*100.0);
|
|
fprintf(fpout, " invzMatTime = %f, %f\n",
|
|
invzMatTime, invzMatTime/MainLoop*100.0);
|
|
fprintf(fpout, " xMatzMatTime = %f, %f\n",
|
|
xMatzMatTime, xMatzMatTime/MainLoop*100.0);
|
|
fprintf(fpout, " EigxMatTime = %f, %f\n",
|
|
EigxMatTime, EigxMatTime/MainLoop*100.0);
|
|
fprintf(fpout, " EigzMatTime = %f, %f\n",
|
|
EigzMatTime, EigzMatTime/MainLoop*100.0);
|
|
fprintf(fpout, " EigxMatzMatTime = %f, %f\n",
|
|
EigxMatzMatTime, EigxMatzMatTime/MainLoop*100.0);
|
|
fprintf(fpout, " updateRes = %f, %f\n",
|
|
updateRes, updateRes/MainLoop*100.0);
|
|
double total_eigen = EigxMatTime + EigzMatTime + EigxMatzMatTime;
|
|
fprintf(fpout, " EigTime = %f, %f\n",
|
|
total_eigen, total_eigen/MainLoop*100.0);
|
|
double sub_total_bMat = MainLoop - makebMat;
|
|
fprintf(fpout, " sub_total_bMat = %f, %f\n",
|
|
sub_total_bMat, sub_total_bMat/MainLoop*100.0);
|
|
fprintf(fpout, " Main Loop = %f, %f\n",
|
|
MainLoop, MainLoop/MainLoop*100.0);
|
|
fprintf(fpout, " File Check = %f, %f\n",
|
|
FileCheck, FileCheck/MainLoop*100.0);
|
|
fprintf(fpout, " File Change = %f, %f\n",
|
|
FileChange, FileChange/MainLoop*100.0);
|
|
fprintf(fpout, " File Read = %f, %f\n",
|
|
FileRead, FileRead/MainLoop*100.0);
|
|
fprintf(fpout, " Total = %f, %f\n",
|
|
TotalTime, TotalTime/MainLoop*100.0);
|
|
fprintf(fpout, "\n");
|
|
|
|
return;
|
|
}
|
|
|
|
//-------------------------------------------------------------
|
|
|
|
Parameter::Parameter()
|
|
{
|
|
// setDefaultParameter();
|
|
}
|
|
Parameter::Parameter(FILE* parameterFile)
|
|
{
|
|
readFile(parameterFile);
|
|
}
|
|
|
|
Parameter::~Parameter()
|
|
{
|
|
// Nothings needs.
|
|
}
|
|
|
|
void Parameter::setDefaultParameter(Parameter::parameterType type)
|
|
{
|
|
if (type == PARAMETER_STABLE_BUT_SLOW) {
|
|
maxIteration = 1000;
|
|
epsilonStar = 1.0e-7;
|
|
lambdaStar = 1.0e+4;
|
|
omegaStar = 2.0;
|
|
lowerBound = -1.0e+5;
|
|
upperBound = 1.0e+5;
|
|
betaStar = 0.1;
|
|
betaBar = 0.5;
|
|
gammaStar = 0.8;
|
|
epsilonDash = 1.0e-7;
|
|
}
|
|
else if (type == PARAMETER_UNSTABLE_BUT_FAST) {
|
|
maxIteration = 100;
|
|
epsilonStar = 1.0e-7;
|
|
lambdaStar = 1.0e+2;
|
|
omegaStar = 2.0;
|
|
lowerBound = -1.0e+5;
|
|
upperBound = 1.0e+5;
|
|
betaStar = 0.01;
|
|
betaBar = 0.02;
|
|
gammaStar = 0.95;
|
|
epsilonDash = 1.0e-7;
|
|
}
|
|
else {
|
|
maxIteration = 100;
|
|
epsilonStar = 1.0e-7;
|
|
lambdaStar = 1.0e+2;
|
|
omegaStar = 2.0;
|
|
lowerBound = -1.0e+5;
|
|
upperBound = 1.0e+5;
|
|
betaStar = 0.1;
|
|
betaBar = 0.3;
|
|
gammaStar = 0.9;
|
|
epsilonDash = 1.0e-7;
|
|
}
|
|
strcpy(xPrint,xPRINT_DEFAULT);
|
|
strcpy(XPrint,XPRINT_DEFAULT);
|
|
strcpy(YPrint,YPRINT_DEFAULT);
|
|
strcpy(infPrint,infPRINT_DEFAULT);
|
|
}
|
|
|
|
char Parameter::xPRINT_DEFAULT[PRINT_DEFAULT_LENGTH] = "%+8.3e";
|
|
char Parameter::XPRINT_DEFAULT[PRINT_DEFAULT_LENGTH] = "%+8.3e";
|
|
char Parameter::YPRINT_DEFAULT[PRINT_DEFAULT_LENGTH] = "%+8.3e";
|
|
char Parameter::infPRINT_DEFAULT[PRINT_DEFAULT_LENGTH] = "%+10.16e";
|
|
|
|
void Parameter::readFile(FILE* parameterFile)
|
|
{
|
|
fscanf(parameterFile,"%d%*[^\n]",&maxIteration);
|
|
fscanf(parameterFile,"%lf%*[^\n]",&epsilonStar);
|
|
fscanf(parameterFile,"%lf%*[^\n]",&lambdaStar);
|
|
fscanf(parameterFile,"%lf%*[^\n]",&omegaStar);
|
|
fscanf(parameterFile,"%lf%*[^\n]",&lowerBound);
|
|
fscanf(parameterFile,"%lf%*[^\n]",&upperBound);
|
|
fscanf(parameterFile,"%lf%*[^\n]",&betaStar);
|
|
fscanf(parameterFile,"%lf%*[^\n]",&betaBar);
|
|
fscanf(parameterFile,"%lf%*[^\n]",&gammaStar);
|
|
fscanf(parameterFile,"%lf%*[^\n]",&epsilonDash);
|
|
fscanf(parameterFile,"%s %*[^\n]",xPrint);
|
|
fscanf(parameterFile,"%s %*[^\n]",XPrint);
|
|
fscanf(parameterFile,"%s %*[^\n]",YPrint);
|
|
fscanf(parameterFile,"%s %*[^\n]",infPrint);
|
|
if (strcmp(xPrint,NO_P_FORMAT)!=0 && xPrint[0]!='%') {
|
|
rMessage("Strange xPrint[" << xPrint << "]"
|
|
" migh cause trouble when printing x");
|
|
}
|
|
if (strcmp(XPrint,NO_P_FORMAT)!=0 && XPrint[0]!='%') {
|
|
rMessage("Strange XPrint[" << XPrint << "]"
|
|
" migh cause trouble when printing X.");
|
|
}
|
|
if (strcmp(YPrint,NO_P_FORMAT)!=0 && YPrint[0]!='%') {
|
|
rMessage("Strange YPrint[" << YPrint << "]"
|
|
" migh cause trouble when printing Y.");
|
|
}
|
|
if (strcmp(infPrint,NO_P_FORMAT)!=0 && infPrint[0]!='%') {
|
|
rMessage("Strange infPrint[" << infPrint << "]"
|
|
" migh cause trouble when printing information.");
|
|
}
|
|
}
|
|
|
|
|
|
void Parameter::display(FILE* fpout, char* printFormat)
|
|
{
|
|
if (fpout == NULL) {
|
|
return;
|
|
}
|
|
if (strcmp(printFormat,NO_P_FORMAT) == 0) {
|
|
fprintf(fpout,"%s\n",NO_P_FORMAT);
|
|
return;
|
|
}
|
|
fprintf(fpout, "** Parameters **\n");
|
|
fprintf(fpout, "maxIteration = %d\n",maxIteration);
|
|
fprintf(fpout, "epsilonStar = ");
|
|
fprintf(fpout, printFormat, epsilonStar );
|
|
fprintf(fpout, "\n");
|
|
fprintf(fpout, "lambdaStar = ");
|
|
fprintf(fpout, printFormat, lambdaStar );
|
|
fprintf(fpout, "\n");
|
|
fprintf(fpout, "omegaStar = ");
|
|
fprintf(fpout, printFormat, omegaStar );
|
|
fprintf(fpout, "\n");
|
|
fprintf(fpout, "lowerBound = ");
|
|
fprintf(fpout, printFormat, lowerBound);
|
|
fprintf(fpout, "\n");
|
|
fprintf(fpout, "upperBound = ");
|
|
fprintf(fpout, printFormat, upperBound);
|
|
fprintf(fpout, "\n");
|
|
fprintf(fpout, "betaStar = ");
|
|
fprintf(fpout, printFormat, betaStar );
|
|
fprintf(fpout, "\n");
|
|
fprintf(fpout, "betaBar = ");
|
|
fprintf(fpout, printFormat, betaBar );
|
|
fprintf(fpout, "\n");
|
|
fprintf(fpout, "gammaStar = ");
|
|
fprintf(fpout, printFormat, gammaStar );
|
|
fprintf(fpout, "\n");
|
|
fprintf(fpout, "epsilonDash = ");
|
|
fprintf(fpout, printFormat, epsilonDash );
|
|
fprintf(fpout, "\n");
|
|
#if 1
|
|
fprintf(fpout, "xPrint = %s \n", xPrint );
|
|
fprintf(fpout, "XPrint = %s \n", XPrint );
|
|
fprintf(fpout, "YPrint = %s \n", YPrint );
|
|
fprintf(fpout, "infPrint = %s \n", infPrint );
|
|
#endif
|
|
return;
|
|
}
|
|
|
|
//----------------------------------------------------------
|
|
|
|
StepLength::StepLength()
|
|
{
|
|
primal = 0.0;
|
|
dual = 0.0;
|
|
|
|
}
|
|
|
|
StepLength::~StepLength()
|
|
{
|
|
finalize();
|
|
}
|
|
|
|
|
|
void StepLength::initialize(double alphaP, double alphaD)
|
|
{
|
|
primal = alphaP;
|
|
dual = alphaD;
|
|
}
|
|
|
|
void StepLength::finalize()
|
|
{
|
|
// Nothing needs.
|
|
}
|
|
|
|
double StepLength::minBlockVector(BlockVector& aVec)
|
|
{
|
|
int nBlock = aVec.nBlock;
|
|
double ret = aVec.ele[0].ele[0];
|
|
double tmp;
|
|
int size = aVec.ele[0].nDim;
|
|
for (int j=1; j<size; ++j) {
|
|
tmp = aVec.ele[0].ele[j];
|
|
if (tmp < ret) {
|
|
ret = tmp;
|
|
}
|
|
}
|
|
for (int k=1; k<nBlock; ++k) {
|
|
size = aVec.ele[k].nDim;
|
|
for (int j=0; j<size; ++j) {
|
|
tmp = aVec.ele[k].ele[j];
|
|
if (tmp < ret) {
|
|
ret = tmp;
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
void StepLength::computeStepLength(Solutions& currentPt,
|
|
ComputeTime& com)
|
|
{
|
|
double alphaBD = 100.0;
|
|
CholmodSpace& cholmodSpace = currentPt.cholmodSpace;
|
|
TimeStart(START1);
|
|
// rMessage("invCholeskyX=");
|
|
double minValue = 1.0e+50;
|
|
for (int l=0; l<cholmodSpace.LP_nBlock; ++l) {
|
|
double* LP_dX = cholmodSpace.LP_dX;
|
|
double* LP_invX = cholmodSpace.LP_invX;
|
|
double value = LP_dX[l]*LP_invX[l];
|
|
if (value < minValue) {
|
|
minValue = value;
|
|
}
|
|
} // end of 'for (int l)'
|
|
for (int l=0; l<cholmodSpace.SDP_nBlock; ++l) {
|
|
CliqueMatrix& clique_invCholeskyX
|
|
= cholmodSpace.SDP_block[l].clique_invCholeskyX;
|
|
CliqueMatrix& clique_dX = cholmodSpace.SDP_block[l].clique_dX;
|
|
for (int l2=0; l2<clique_dX.nBlock; ++l2) {
|
|
DenseMatrix& invCholeskyX = clique_invCholeskyX.ele[l2];
|
|
DenseMatrix& DxMat = clique_dX.ele[l2];
|
|
const int size = DxMat.nRow;
|
|
double value = 0.0; // dummy initialize
|
|
DenseMatrix DLS1;
|
|
DLS1.initialize(size,size);
|
|
Vector Two_BV1(3*size);
|
|
Vector BV1(size);
|
|
if (size > 64) { // Lanczos method
|
|
Vector BV2(size);
|
|
Vector BV3(size);
|
|
Vector BV4(size);
|
|
Vector BV5(size);
|
|
Vector BV6(size);
|
|
Vector BV7(size);
|
|
Vector BV8(size);
|
|
Vector BV9(size);
|
|
// In SDPA, DLS1 = invCholeskyX*Dx*invCholeskyX'
|
|
// In SDPA-C, DLS1 = invCholeskyX'*Dx*invCholeskyX
|
|
// The last 'T' means transpose of invCholeskyX
|
|
value = Lal::getMinEigen(invCholeskyX, DxMat, DLS1,
|
|
BV1, BV2, BV3, BV4, BV5, BV6,
|
|
BV7, BV8, BV9, Two_BV1,'T');
|
|
}
|
|
else { // QR method
|
|
// In SDPA, DLS1 = invCholeskyX*Dx*invCholeskyX'
|
|
// In SDPA-C, DLS1 = invCholeskyX'*Dx*invCholeskyX
|
|
DenseMatrix DLS2;
|
|
DLS2.initialize(size,size);
|
|
Lal::let(DLS2,'=',DxMat,'*',invCholeskyX);
|
|
Lal::let(DLS1,'=',invCholeskyX,'t',DLS2);
|
|
value = Lal::getMinEigenValue(DLS1, BV1, Two_BV1);
|
|
}
|
|
if (value < minValue) {
|
|
minValue = value;
|
|
}
|
|
#if 0
|
|
rMessage("value for " << l2 << " th clique of "
|
|
<< l << " th block = " << value);
|
|
#endif
|
|
} // end of 'for (int l2=0; l2<clique_xMat.nBlock; ++l2) '
|
|
}
|
|
double minxInvDxEigenValue = minValue;
|
|
// rMessage("minxInvDxEigenValue = " << minxInvDxEigenValue);
|
|
if (-minxInvDxEigenValue > 1.0 /alphaBD) {
|
|
primal = - 1.0/minxInvDxEigenValue;
|
|
// the limint of primal steplength
|
|
} else {
|
|
primal = alphaBD;
|
|
}
|
|
TimeEnd(END1);
|
|
com.EigxMatTime += TimeCal(START1,END1);
|
|
|
|
// calculate eigenvalues of Z^{-1} dZ
|
|
TimeStart(START2);
|
|
// rMessage("invCholeskyZ=");
|
|
// currentPt.invCholeskyZ.display();
|
|
// rMessage("Dz=");
|
|
// newton.DzMat.display();
|
|
|
|
minValue = 1.0e+50;
|
|
for (int l=0; l<cholmodSpace.LP_nBlock; ++l) {
|
|
double* LP_dZ = cholmodSpace.LP_dZ;
|
|
double* LP_invZ = cholmodSpace.LP_invZ;
|
|
double value = LP_dZ[l]*LP_invZ[l];
|
|
if (value < minValue) {
|
|
minValue = value;
|
|
}
|
|
} // end of 'for (int l)'
|
|
for (int l=0; l<cholmodSpace.SDP_nBlock; ++l) {
|
|
double value = Lal::getMinEigenValue(cholmodSpace.SDP_block[l]);
|
|
if (value < minValue) {
|
|
minValue = value;
|
|
}
|
|
}
|
|
double minzInvDzEigenValue = minValue;
|
|
// rMessage("minzInvDzEigenValue = " << minzInvDzEigenValue);
|
|
if (-minzInvDzEigenValue > 1.0 /alphaBD) {
|
|
dual = - 1.0/minzInvDzEigenValue;
|
|
// the limint of dual steplength
|
|
} else {
|
|
dual = alphaBD;
|
|
}
|
|
TimeEnd(END2);
|
|
com.EigzMatTime += TimeCal(START2,END2);
|
|
#if 0
|
|
rMessage("minxInvDxEigenValue = " << minxInvDxEigenValue);
|
|
rMessage("minzInvDzEigenValue = " << minzInvDzEigenValue);
|
|
#endif
|
|
}
|
|
|
|
|
|
void StepLength::MehrotraPredictor(InputData& inputData,
|
|
Solutions& currentPt,
|
|
Phase& phase,
|
|
Switch& reduction,
|
|
AverageComplementarity& mu,
|
|
RatioInitResCurrentRes& theta,
|
|
Parameter& param,
|
|
ComputeTime& com)
|
|
{
|
|
computeStepLength(currentPt, com);
|
|
|
|
// adjust steplength with param.gammaStar
|
|
// param.gammaStar = 0.9;
|
|
primal = param.gammaStar * primal;
|
|
dual = param.gammaStar * dual;
|
|
|
|
CholmodSpace& cholmodSpace = currentPt.cholmodSpace;
|
|
OrderingSpace& order = currentPt.order;
|
|
|
|
if (phase.value==SolveInfo::noINFO
|
|
|| phase.value==SolveInfo::dFEAS) {
|
|
// primal is infeasible
|
|
if (primal>1.0) {
|
|
primal = 1.0;
|
|
}
|
|
} else {
|
|
// when primal is feasible,
|
|
// check stepP1 is effective or not.
|
|
double incPrimalObj = 0.0;
|
|
// Lal::let(incPrimalObj,'=',C,'.',newton.DxMat);
|
|
CompSpace& C = inputData.C;
|
|
for (int l_index = 0; l_index< C.LP_sp_nBlock; ++l_index) {
|
|
const double Cvalue = C.LP_sp_block[l_index];
|
|
const int l = C.LP_sp_index[l_index];
|
|
const double dXvalue = cholmodSpace.LP_dX[l];
|
|
incPrimalObj += Cvalue*dXvalue;
|
|
}
|
|
|
|
for (int l_index = 0; l_index< C.SDP_sp_nBlock; ++l_index) {
|
|
double tmpret = 0.0;
|
|
const int l = C.SDP_sp_index[l_index];
|
|
Lal::getInnerProduct(tmpret, C.SDP_sp_block[l_index],
|
|
cholmodSpace.SDP_block[l].clique_dX,
|
|
order.SDP_block[l]);
|
|
incPrimalObj += tmpret;
|
|
}
|
|
|
|
if (incPrimalObj>0.0) {
|
|
#if 1
|
|
if (primal>dual) {
|
|
primal = dual;
|
|
}
|
|
#endif
|
|
if (primal>1.0) {
|
|
primal = 1.0;
|
|
}
|
|
}
|
|
}
|
|
if (phase.value==SolveInfo::noINFO
|
|
|| phase.value==SolveInfo::pFEAS) {
|
|
// dual is infeasible
|
|
if (dual>1.0) {
|
|
dual = 1.0;
|
|
}
|
|
} else {
|
|
// when dual is feasible
|
|
// check stepD1 is effective or not.
|
|
double incDualObj;
|
|
Lal::let(incDualObj,'=',inputData.b,'.',cholmodSpace.dyVec);
|
|
if(incDualObj<0.0) {
|
|
#if 1
|
|
if (dual>primal) {
|
|
dual = primal;
|
|
}
|
|
#endif
|
|
if (dual>1.0) {
|
|
dual = 1.0;
|
|
}
|
|
}
|
|
}
|
|
|
|
#if 1
|
|
// attain feasibility before mu reduction
|
|
if (reduction.switchType==Switch::CENTERING
|
|
&& (phase.value == SolveInfo::noINFO
|
|
|| phase.value == SolveInfo::pFEAS
|
|
|| phase.value == SolveInfo::dFEAS) ) {
|
|
double xMatvMat = 0.0;
|
|
// rAl::let(xMatvMat,'=',currentPt.xMat,'.',newton.DzMat);
|
|
for (int l = 0; l < cholmodSpace.LP_nBlock; ++l) {
|
|
xMatvMat += cholmodSpace.LP_X[l]*cholmodSpace.LP_dZ[l];
|
|
}
|
|
for (int l=0; l<cholmodSpace.SDP_nBlock; ++l) {
|
|
CliqueMatrix& X = cholmodSpace.SDP_block[l].clique_xMat;
|
|
cholmod_sparse* dZ = cholmodSpace.SDP_block[l].dZ;
|
|
double tmpret = 0.0; // dummy initialize
|
|
Lal::getInnerProduct(tmpret, dZ, X, currentPt.order.SDP_block[l],
|
|
cholmodSpace.SDP_block[l].Z_blockNumber,
|
|
cholmodSpace.SDP_block[l].Z_blockIndex);
|
|
xMatvMat += tmpret;
|
|
}
|
|
|
|
double uMatzMat = 0.0;
|
|
// rAl::let(uMatzMat,'=',newton.DxMat,'.',currentPt.zMat);
|
|
for (int l = 0; l < cholmodSpace.LP_nBlock; ++l) {
|
|
uMatzMat += cholmodSpace.LP_dX[l]*cholmodSpace.LP_Z[l];
|
|
}
|
|
for (int l=0; l<cholmodSpace.SDP_nBlock; ++l) {
|
|
CliqueMatrix& dX = cholmodSpace.SDP_block[l].clique_dX;
|
|
cholmod_sparse* Z = cholmodSpace.SDP_block[l].Z;
|
|
double tmpret = 0.0; // dummy initialize
|
|
Lal::getInnerProduct(tmpret, Z, dX, currentPt.order.SDP_block[l],
|
|
cholmodSpace.SDP_block[l].Z_blockNumber,
|
|
cholmodSpace.SDP_block[l].Z_blockIndex);
|
|
uMatzMat += tmpret;
|
|
}
|
|
|
|
double uMatvMat = 0.0;
|
|
// rAl::let(uMatvMat,'=',newton.DxMat,'.',newton.DzMat);
|
|
for (int l = 0; l < cholmodSpace.LP_nBlock; ++l) {
|
|
uMatvMat += cholmodSpace.LP_dX[l]*cholmodSpace.LP_dZ[l];
|
|
}
|
|
for (int l=0; l<cholmodSpace.SDP_nBlock; ++l) {
|
|
CliqueMatrix& dX = cholmodSpace.SDP_block[l].clique_dX;
|
|
cholmod_sparse* dZ = cholmodSpace.SDP_block[l].dZ;
|
|
double tmpret = 0.0; // dummy initialize
|
|
Lal::getInnerProduct(tmpret, dZ, dX, currentPt.order.SDP_block[l],
|
|
cholmodSpace.SDP_block[l].Z_blockNumber,
|
|
cholmodSpace.SDP_block[l].Z_blockIndex);
|
|
uMatvMat += tmpret;
|
|
}
|
|
|
|
int nDim = cholmodSpace.LP_nBlock;
|
|
for (int l=0; l<cholmodSpace.SDP_nBlock; ++l) {
|
|
nDim += cholmodSpace.SDP_block[l].nDim;
|
|
}
|
|
|
|
|
|
double thetaMax = max((1.0-primal)*theta.primal,
|
|
(1.0-dual )*theta.dual);
|
|
double muNew = mu.current
|
|
+ (primal*uMatzMat + dual*xMatvMat
|
|
+ primal*dual*uMatvMat) / nDim;
|
|
const double xi = 3.0; // this is one of implicit parameters
|
|
while (thetaMax*mu.initial > xi*muNew) {
|
|
double alphaMax = 0.95 * max(primal,dual);
|
|
primal = min(primal,alphaMax);
|
|
dual = min(dual ,alphaMax);
|
|
thetaMax = max((1.0-primal)*theta.primal,
|
|
(1.0-dual )*theta.dual);
|
|
muNew = mu.current + (primal*uMatzMat + dual*xMatvMat
|
|
+ primal*dual*uMatvMat) / nDim;
|
|
// if "too short step", then break down the algorithm.
|
|
if (primal < 1.0e-6 && dual < 1.0e-6) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void StepLength::Centering(Solutions& currentPt,
|
|
Parameter& param,
|
|
ComputeTime& com)
|
|
{
|
|
computeStepLength(currentPt, com);
|
|
|
|
// adjust steplength with param.gammaStar
|
|
// param.gammaStar = 0.5;
|
|
primal = param.gammaStar * primal;
|
|
dual = param.gammaStar * dual;
|
|
|
|
if (primal>1.0) {
|
|
primal = 1.0;
|
|
}
|
|
if (dual>1.0) {
|
|
dual = 1.0;
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
void StepLength::display(FILE* fpout)
|
|
{
|
|
if (fpout == NULL) {
|
|
return;
|
|
}
|
|
|
|
fprintf(fpout,"alpha.primal = %8.3e\n",primal);
|
|
fprintf(fpout,"alpha.dual = %8.3e\n",dual);
|
|
}
|
|
|
|
//-------------------------------------------------
|
|
DirectionParameter::DirectionParameter(double betaStar)
|
|
{
|
|
initialize(betaStar);
|
|
}
|
|
|
|
DirectionParameter::~DirectionParameter()
|
|
{
|
|
// Nothing needs.
|
|
}
|
|
|
|
void DirectionParameter::initialize(double betaStar)
|
|
{
|
|
value = betaStar;
|
|
}
|
|
|
|
void DirectionParameter::Predictor(Phase& phase,
|
|
Switch& reduction,
|
|
Parameter& param)
|
|
{
|
|
const double nu = 2.0;
|
|
if (phase.value == SolveInfo::pdFEAS) {
|
|
value = param.betaStar;
|
|
} else {
|
|
value = param.betaBar;
|
|
if (reduction.switchType==Switch::AFFINE) {
|
|
value = nu;
|
|
}
|
|
}
|
|
}
|
|
|
|
void DirectionParameter::Centering()
|
|
{
|
|
value = 1.0;
|
|
}
|
|
|
|
void DirectionParameter::
|
|
MehrotraCorrector(Phase& phase, StepLength& alpha,
|
|
Solutions& currentPt,
|
|
AverageComplementarity& mu, Parameter& param)
|
|
{
|
|
int nDim = currentPt.nDim;
|
|
CholmodSpace& cholmodSpace = currentPt.cholmodSpace;
|
|
|
|
// Lal::let(uMatzMat,'=',newton.DxMat,'.',currentPt.zMat);
|
|
// Lal::let(xMatvMat,'=',currentPt.xMat,'.',newton.DzMat);
|
|
// Lal::let(uMatvMat,'=',newton.DxMat,'.',newton.DzMat);
|
|
double uMatzMat = 0.0;
|
|
double xMatvMat = 0.0;
|
|
double uMatvMat = 0.0;
|
|
for (int l=0; l<cholmodSpace.LP_nBlock; ++l) {
|
|
uMatzMat += cholmodSpace.LP_dX[l] * cholmodSpace.LP_Z [l];
|
|
xMatvMat += cholmodSpace.LP_X [l] * cholmodSpace.LP_dZ[l];
|
|
uMatvMat += cholmodSpace.LP_dX[l] * cholmodSpace.LP_dZ[l];
|
|
}
|
|
for (int l=0; l<cholmodSpace.SDP_nBlock; ++l) {
|
|
OrderingMatrix& order = currentPt.order.SDP_block[l];
|
|
CholmodMatrix& cholmodMatrix = cholmodSpace.SDP_block[l];
|
|
CliqueMatrix& clique_xMat = cholmodMatrix.clique_xMat;
|
|
CliqueMatrix& clique_dX = cholmodMatrix.clique_dX;
|
|
cholmod_sparse* Z = cholmodMatrix.Z;
|
|
cholmod_sparse* dZ = cholmodMatrix.dZ;
|
|
int* Z_blockNumber = cholmodMatrix.Z_blockNumber;
|
|
int* Z_blockIndex = cholmodMatrix.Z_blockIndex;
|
|
double ip = 0.0; // dummy initialize
|
|
Lal::getInnerProduct(ip, Z, clique_dX, order, Z_blockNumber, Z_blockIndex);
|
|
uMatzMat += ip;
|
|
Lal::getInnerProduct(ip, dZ, clique_xMat, order,
|
|
Z_blockNumber, Z_blockIndex);
|
|
xMatvMat += ip;
|
|
Lal::getInnerProduct(ip, dZ, clique_dX, order, Z_blockNumber, Z_blockIndex);
|
|
uMatvMat += ip;
|
|
}
|
|
|
|
double primal = alpha.primal;
|
|
double dual = alpha.dual;
|
|
|
|
// primal = max(alpha.primal,1.0);
|
|
// dual = max(alpha.dual, 1.0);
|
|
|
|
double muTarget = mu.current
|
|
+ (primal*uMatzMat + dual*xMatvMat + primal*dual*uMatvMat) / nDim;
|
|
// rMessage("muTarget : " << muTarget);
|
|
// rMessage("muCurrent : " << mu.current);
|
|
value = muTarget/mu.current;
|
|
// rMessage("muValue : " << value);
|
|
if (value < 1.0) {
|
|
value = value*value;
|
|
}
|
|
if (phase.value==SolveInfo::pdFEAS) {
|
|
// rMessage("MehrotraCorrector : pdFEAS" << value);
|
|
if (value < param.betaStar) {
|
|
value = param.betaStar;
|
|
}
|
|
if (value > 1.0) {
|
|
value = 1.0;
|
|
}
|
|
} else {
|
|
if (value < param.betaBar) {
|
|
value = param.betaBar;
|
|
}
|
|
}
|
|
// rMessage("MehrotraCorrector : " << value);
|
|
}
|
|
|
|
void DirectionParameter::display(FILE* fpout)
|
|
{
|
|
if (fpout == NULL) {
|
|
return;
|
|
}
|
|
fprintf(fpout,"beta.value = %8.3e\n",value);
|
|
}
|
|
|
|
//---------------------------------------------------
|
|
|
|
Switch::Switch(SwitchType switchType)
|
|
{
|
|
initialize(switchType);
|
|
}
|
|
|
|
Switch::~Switch()
|
|
{
|
|
// Nothing needs.
|
|
}
|
|
|
|
void Switch::initialize(SwitchType switchType)
|
|
{
|
|
this->switchType = switchType;
|
|
}
|
|
|
|
void Switch::MehrotraPredictor(Phase& phase)
|
|
{
|
|
if (phase.value==SolveInfo::noINFO
|
|
|| phase.value==SolveInfo::pFEAS
|
|
|| phase.value==SolveInfo::dFEAS) {
|
|
// At least one of primal or dual is infeasible.
|
|
switchType = CENTERING;
|
|
} else {
|
|
switchType = AFFINE;
|
|
}
|
|
}
|
|
|
|
void Switch::display(FILE* fpout)
|
|
{
|
|
if (fpout == NULL) {
|
|
return;
|
|
}
|
|
|
|
if (switchType == CENTERING) {
|
|
fprintf(fpout,"reduction.switchType == CENTERING\n");
|
|
} else {
|
|
fprintf(fpout,"reduction.switchType == AFFINE\n");
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------
|
|
|
|
AverageComplementarity::AverageComplementarity(double lambdaStar)
|
|
{
|
|
initialize(lambdaStar);
|
|
}
|
|
|
|
AverageComplementarity::~AverageComplementarity()
|
|
{
|
|
// Nothing needs.
|
|
}
|
|
|
|
void AverageComplementarity::initialize(double lambdaStar)
|
|
{
|
|
initial = lambdaStar*lambdaStar;
|
|
current = initial;
|
|
// rMessage("initial average = " << initial);
|
|
}
|
|
|
|
void AverageComplementarity::update(Solutions& currentPt)
|
|
{
|
|
CholmodSpace& cholmodSpace = currentPt.cholmodSpace;
|
|
int nDim = cholmodSpace.LP_nBlock;
|
|
current = 0.0;
|
|
for (int l=0; l<cholmodSpace.LP_nBlock; ++l) {
|
|
current += cholmodSpace.LP_Z[l]*cholmodSpace.LP_X[l];
|
|
}
|
|
for (int l=0; l<cholmodSpace.SDP_nBlock; ++l) {
|
|
nDim += cholmodSpace.SDP_block[l].nDim;
|
|
cholmod_sparse* Z = cholmodSpace.SDP_block[l].Z;
|
|
CliqueMatrix& X = cholmodSpace.SDP_block[l].clique_xMat;
|
|
double tmpret = 0.0; // dummy initialize
|
|
Lal::getInnerProduct(tmpret, Z, X, currentPt.order.SDP_block[l],
|
|
cholmodSpace.SDP_block[l].Z_blockNumber,
|
|
cholmodSpace.SDP_block[l].Z_blockIndex);
|
|
current += tmpret;
|
|
}
|
|
current /= nDim;
|
|
}
|
|
|
|
void AverageComplementarity::display(FILE* fpout)
|
|
{
|
|
if (fpout == NULL) {
|
|
return;
|
|
}
|
|
|
|
fprintf(fpout,"mu0 = %8.3e\n",initial);
|
|
fprintf(fpout,"mu = %8.3e\n",current);
|
|
}
|
|
|
|
//--------------------------------------------------
|
|
|
|
|
|
RatioInitResCurrentRes::RatioInitResCurrentRes()
|
|
{
|
|
primal = 0.0;
|
|
dual = 0.0;
|
|
}
|
|
|
|
RatioInitResCurrentRes::~RatioInitResCurrentRes()
|
|
{
|
|
// Nothing needs.
|
|
}
|
|
|
|
void RatioInitResCurrentRes::initialize(Parameter& param,
|
|
Residuals& currentRes)
|
|
{
|
|
double accuracy = param.epsilonDash;
|
|
if (currentRes.normPrimal < accuracy) {
|
|
primal = 0.0;
|
|
} else {
|
|
primal = 1.0;
|
|
}
|
|
if (currentRes.normDual < accuracy) {
|
|
dual = 0.0;
|
|
} else {
|
|
dual = 1.0;
|
|
}
|
|
}
|
|
|
|
void RatioInitResCurrentRes::update(Switch& reduction,
|
|
StepLength& alpha)
|
|
{
|
|
if (reduction.switchType==Switch::CENTERING) {
|
|
// At least one of primal or dual is infeasible
|
|
primal = fabs((1.0-alpha.primal)*primal);
|
|
dual = fabs((1.0-alpha.dual )*dual );
|
|
}
|
|
}
|
|
|
|
void RatioInitResCurrentRes::update_exact(Residuals& currentRes,
|
|
Parameter& param)
|
|
{
|
|
if (currentRes.initNormPrimal
|
|
> param.epsilonDash * 1.0e-2) {
|
|
primal = currentRes.normPrimal / currentRes.initNormPrimal;
|
|
}
|
|
else {
|
|
primal = 0.0;
|
|
}
|
|
if (currentRes.initNormDual
|
|
> param.epsilonDash * 1.0e-2) {
|
|
dual = currentRes.normDual / currentRes.initNormDual;
|
|
}
|
|
else {
|
|
dual = 0.0;
|
|
}
|
|
}
|
|
|
|
void RatioInitResCurrentRes::display(FILE* fpout)
|
|
{
|
|
if (fpout == NULL) {
|
|
return;
|
|
}
|
|
|
|
fprintf(fpout,"theta.primal = %8.3e\n",primal);
|
|
fprintf(fpout,"theta.dual = %8.3e\n",dual);
|
|
}
|
|
|
|
//---------------------------------------------------
|
|
|
|
SolveInfo::SolveInfo()
|
|
{
|
|
rho = 0.0;
|
|
etaPrimal = 0.0;
|
|
etaDual = 0.0;
|
|
objValPrimal = 0.0;
|
|
objValDual = 0.0;
|
|
}
|
|
|
|
SolveInfo::SolveInfo(InputData& inputData, Solutions& currentPt,
|
|
double mu0, double omegaStar)
|
|
{
|
|
initialize(inputData,currentPt,mu0,omegaStar);
|
|
}
|
|
|
|
SolveInfo::~SolveInfo()
|
|
{
|
|
// Nothing needs.
|
|
}
|
|
|
|
void SolveInfo::initialize(InputData& inputData, Solutions& currentPt,
|
|
double mu0, double omegaStar)
|
|
{
|
|
int nDim = currentPt.nDim;
|
|
Vector& b = inputData.b;
|
|
CompSpace& C = inputData.C;
|
|
CholmodSpace& cholmodSpace = currentPt.cholmodSpace;
|
|
|
|
rho = 1.0;
|
|
etaPrimal = omegaStar * nDim * mu0;
|
|
etaDual = omegaStar * nDim * mu0;
|
|
cholmodSpace.getInnerProductAX(objValPrimal, C, currentPt.order);
|
|
#if 0
|
|
C.display();
|
|
cholmodSpace.display();
|
|
rMessage("objValPrimal = " << objValPrimal);
|
|
#endif
|
|
Lal::let(objValDual,'=',b,'.',cholmodSpace.yVec);
|
|
}
|
|
|
|
void SolveInfo::update(InputData& inputData,
|
|
Solutions& currentPt,
|
|
Residuals& currentRes,
|
|
AverageComplementarity& mu,
|
|
RatioInitResCurrentRes& theta,
|
|
Parameter& param)
|
|
{
|
|
CholmodSpace& cholmodSpace = currentPt.cholmodSpace;
|
|
|
|
// Lal::let(objValPrimal,'=',C,'.',currentPt.xMat);
|
|
objValPrimal = 0.0;
|
|
cholmodSpace.getInnerProductAX(objValPrimal, inputData.C, currentPt.order);
|
|
Lal::let(objValDual,'=',inputData.b,'.',cholmodSpace.yVec);
|
|
|
|
int nDim = cholmodSpace.LP_nBlock;
|
|
for (int l=0; l<cholmodSpace.SDP_nBlock; ++l) {
|
|
nDim += cholmodSpace.SDP_block[l].nDim;
|
|
}
|
|
|
|
double primal = theta.primal;
|
|
double dual = theta.dual;
|
|
double omega = param.omegaStar;
|
|
double lambda = param.lambdaStar;
|
|
rho = 0.0;
|
|
double x0z0 = nDim*mu.initial;
|
|
double xMatzMat = nDim*mu.current;
|
|
|
|
// Lal::let(x0zMat,'=',initPt_xMat,'.',currentPt.zMat);
|
|
double x0zMat = 0.0;
|
|
for (int l=0; l<cholmodSpace.LP_nBlock; ++l) {
|
|
x0zMat += cholmodSpace.LP_Z[l];
|
|
}
|
|
for (int l=0; l<cholmodSpace.SDP_nBlock; ++l) {
|
|
cholmod_sparse* Z = cholmodSpace.SDP_block[l].Z;
|
|
const int ncol = (int) Z->ncol;
|
|
for (int j=0; j < ncol; ++j) {
|
|
const int diag_row = ((int*)Z->p)[j];
|
|
x0zMat += ((double*)Z->x)[diag_row];
|
|
}
|
|
}
|
|
x0zMat *= lambda;
|
|
|
|
// Lal::let(xMatz0,'=',currentPt.xMat,'.',initPt_zMat);
|
|
double xMatz0 = 0.0;
|
|
for (int l=0; l<cholmodSpace.LP_nBlock; ++l) {
|
|
xMatz0 += cholmodSpace.LP_X[l];
|
|
}
|
|
for (int l=0; l<cholmodSpace.SDP_nBlock; ++l) {
|
|
CliqueMatrix& clique_xMat = cholmodSpace.SDP_block[l].clique_xMat;
|
|
OrderingMatrix& order = currentPt.order.SDP_block[l];
|
|
int size = cholmodSpace.SDP_block[l].nDim;
|
|
for (int j=0; j<size; ++j) {
|
|
for (int index1 = 0; index1 < order.dXtNonzeros[j]; ++index1) {
|
|
int i = order.dXtIndex[j][index1];
|
|
if (i==j) {
|
|
int block = order.dXtClique[j][index1];
|
|
int position = order.dXtBlock[j][index1];
|
|
xMatz0 += clique_xMat.ele[block].de_ele[position];
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
xMatz0 *= lambda;
|
|
|
|
double accuracy = param.epsilonDash;
|
|
|
|
if (currentRes.normPrimal <= accuracy) {
|
|
// rMessage("primal accuracy");
|
|
if (xMatz0 < etaPrimal) {
|
|
etaPrimal = xMatz0;
|
|
}
|
|
}
|
|
if (currentRes.normDual <= accuracy) {
|
|
// rMessage("dual accuracy");
|
|
if (x0zMat < etaDual) {
|
|
etaDual = x0zMat;
|
|
}
|
|
}
|
|
|
|
// primal is infeasible and dual is feasible
|
|
if (currentRes.normPrimal > accuracy
|
|
&& currentRes.normDual <= accuracy) {
|
|
rho = primal*x0zMat
|
|
/ ((primal+(1.0-primal)*omega)*etaDual + xMatzMat);
|
|
}
|
|
|
|
// primal is feasible and dual is infeasible
|
|
if (currentRes.normPrimal <= accuracy
|
|
&& currentRes.normDual > accuracy) {
|
|
rho = dual*xMatz0
|
|
/ ((dual+(1.0-dual)*omega)* etaPrimal + xMatzMat);
|
|
}
|
|
|
|
// primal and dual are infeasible
|
|
if (currentRes.normPrimal > accuracy
|
|
&& currentRes.normDual > accuracy) {
|
|
rho = (dual*xMatz0+primal*x0zMat)
|
|
/ ((primal*dual
|
|
+ omega *(primal*(1.0-dual) + (1.0-primal)*dual))* x0z0
|
|
+ xMatzMat);
|
|
}
|
|
// rMessage("eta Primal = " << etaPrimal);
|
|
// rMessage("eta Dual = " << etaDual);
|
|
}
|
|
|
|
// 2007/09/13 kazuhide nakata
|
|
// print information of ObjVal, residual, gap, complementarity
|
|
// b^T y + R \bullet X = value, norm(r), norm(Z)
|
|
// C \bullet X + r^T y = value, norm(R), norm(X)
|
|
// gap gap, mu * nDim
|
|
void SolveInfo::check(InputData& inputData,
|
|
Solutions& currentPt,
|
|
Residuals& currentRes,
|
|
AverageComplementarity& mu,
|
|
RatioInitResCurrentRes& theta,
|
|
Parameter& param)
|
|
{
|
|
rMessage("This function is not implemented in SDPA-C");
|
|
#if 0
|
|
double tmp,tmp1p,tmp1d,tmp2p,tmp2d,tmp3p,tmp3d,tmp4,tmp5p,tmp5d;
|
|
|
|
Lal::let(tmp,'=',inputData.b,'.',currentPt.yVec);
|
|
tmp1p = - tmp;
|
|
printf("Primal: %9.1e",tmp1p);
|
|
Lal::let(tmp,'=',currentRes.dualMat,'.',currentPt.xMat);
|
|
tmp2p = -tmp;
|
|
printf(" + %9.1e",tmp2p);
|
|
tmp3p = tmp1p + tmp2p;
|
|
printf(" = %9.1e",tmp3p);
|
|
printf(", residual:%-9.1e",currentRes.normDualMat);
|
|
tmp5p = currentRes.computeMaxNorm(currentPt.zMat);
|
|
printf(" norm:%-9.1e\n",tmp5p);
|
|
|
|
Lal::let(tmp,'=',inputData.C,'.',currentPt.xMat);
|
|
tmp1d = - tmp;
|
|
printf("Dual: %9.1e",tmp1d);
|
|
Lal::let(tmp,'=',currentRes.primalVec,'.',currentPt.yVec);
|
|
tmp2d = -tmp;
|
|
printf(" + %9.1e",tmp2d);
|
|
tmp3d = tmp1d + tmp2d;
|
|
printf(" = %9.1e",tmp3d);
|
|
printf(", residual:%-9.1e", currentRes.normPrimalVec);
|
|
tmp5d = currentRes.computeMaxNorm(currentPt.xMat);
|
|
printf(" norm:%-9.1e\n",tmp5d);
|
|
|
|
tmp4 = tmp1p - tmp1d;
|
|
printf("P-D: %9.1e",tmp4);
|
|
tmp4 = tmp3p - tmp3d;
|
|
printf(" %9.1e",tmp4);
|
|
tmp4 = mu.current * currentPt.nDim;
|
|
printf(", mu * n:%-9.1e\n",tmp4);
|
|
|
|
#endif
|
|
}
|
|
|
|
|
|
void SolveInfo::display(FILE* fpout)
|
|
{
|
|
if (fpout == NULL) {
|
|
return;
|
|
}
|
|
|
|
fprintf(fpout,"rSolveInfo.rho = %8.3e\n",rho);
|
|
fprintf(fpout,"rSolveInfo.etaPrimal = %8.3e\n",etaPrimal);
|
|
fprintf(fpout,"rSolveInfo.etaDual = %8.3e\n",etaDual);
|
|
fprintf(fpout,"rSolveInfo.objValPrimal = %8.3e\n",objValPrimal);
|
|
fprintf(fpout,"rSolveInfo.objValDual = %8.3e\n",objValDual);
|
|
}
|
|
|
|
// ----------------------------------------------------
|
|
|
|
Phase::Phase()
|
|
{
|
|
nDim = 0;
|
|
value = SolveInfo::noINFO;
|
|
}
|
|
|
|
Phase::~Phase()
|
|
{
|
|
// Nothing needs.
|
|
}
|
|
|
|
bool Phase::initialize(Residuals& currentRes,
|
|
SolveInfo& solveInfo,
|
|
Parameter& param, int nDim)
|
|
{
|
|
this->nDim = nDim;
|
|
return updateCheck(currentRes, solveInfo, param);
|
|
}
|
|
|
|
bool Phase::updateCheck(Residuals& currentRes,
|
|
SolveInfo& solveInfo,
|
|
Parameter& param)
|
|
{
|
|
const double NONZERO = 1.0e-6;
|
|
double accuracy = param.epsilonDash;
|
|
value = SolveInfo::noINFO;
|
|
|
|
if (currentRes.normPrimal <= accuracy) {
|
|
if (currentRes.normDual <= accuracy) {
|
|
value = SolveInfo::pdFEAS;
|
|
} else {
|
|
value = SolveInfo::pFEAS;
|
|
}
|
|
}
|
|
if (value==SolveInfo::noINFO
|
|
&& currentRes.normDual <= accuracy) {
|
|
value = SolveInfo::dFEAS;
|
|
}
|
|
if (value==SolveInfo::pdFEAS) {
|
|
double mean = (fabs(solveInfo.objValPrimal)+
|
|
fabs(solveInfo.objValDual)) / 2.0;
|
|
double PDgap = fabs(solveInfo.objValPrimal - solveInfo.objValDual);
|
|
|
|
double dominator;
|
|
if (mean < 1.0) {
|
|
dominator = 1.0;
|
|
} else {
|
|
dominator = mean;
|
|
}
|
|
#if 0
|
|
rMessage("PDgap = " << PDgap);
|
|
rMessage("dominator = " << dominator);
|
|
rMessage("PDgap/dominator = " << PDgap/dominator);
|
|
#endif
|
|
if (PDgap/dominator <= param.epsilonStar) {
|
|
value = SolveInfo::pdOPT;
|
|
return false;
|
|
}
|
|
}
|
|
if (value == SolveInfo::noINFO
|
|
&& solveInfo.rho > 1.0+NONZERO) {
|
|
rMessage("pdINF criteria");
|
|
value = SolveInfo::pdINF;
|
|
return false;
|
|
}
|
|
if (value == SolveInfo::pFEAS) {
|
|
#if REVERSE_PRIMAL_DUAL
|
|
if (solveInfo.objValPrimal<=-param.upperBound) {
|
|
rMessage("pUNBD criteria");
|
|
value = SolveInfo::pUNBD;
|
|
return false;
|
|
}
|
|
#else
|
|
if (solveInfo.objValPrimal<=param.lowerBound) {
|
|
rMessage("pdINF criteria");
|
|
value = SolveInfo::pUNBD;
|
|
return false;
|
|
}
|
|
#endif
|
|
if (solveInfo.rho > 1.0+NONZERO) {
|
|
rMessage("pFEAS_dINF criteria");
|
|
value = SolveInfo::pFEAS_dINF;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
if (value == SolveInfo::dFEAS) {
|
|
#if REVERSE_PRIMAL_DUAL
|
|
if (solveInfo.objValDual>=-param.lowerBound) {
|
|
rMessage("dUNBD criteria");
|
|
value = SolveInfo::dUNBD;
|
|
return false;
|
|
}
|
|
#else
|
|
if (solveInfo.objValDual>=param.upperBound) {
|
|
rMessage("dUNBD criteria");
|
|
value = SolveInfo::dUNBD;
|
|
return false;
|
|
}
|
|
#endif
|
|
if (solveInfo.rho > 1.0+NONZERO) {
|
|
rMessage("pINF_dFEAD criteria");
|
|
value = SolveInfo::pINF_dFEAS;
|
|
return false;
|
|
}
|
|
}
|
|
#if 0
|
|
rMessage("phase =");
|
|
display();
|
|
#endif
|
|
return true;
|
|
}
|
|
|
|
void Phase::reverse()
|
|
{
|
|
#if REVERSE_PRIMAL_DUAL
|
|
switch (value) {
|
|
case SolveInfo::noINFO : ; break;
|
|
case SolveInfo::pFEAS : value = SolveInfo::dFEAS ; break;
|
|
case SolveInfo::dFEAS : value = SolveInfo::pFEAS ; break;
|
|
case SolveInfo::pdFEAS : ; break;
|
|
case SolveInfo::pdINF : ; break;
|
|
case SolveInfo::pFEAS_dINF: value = SolveInfo::pINF_dFEAS; break;
|
|
case SolveInfo::pINF_dFEAS: value = SolveInfo::pFEAS_dINF; break;
|
|
case SolveInfo::pdOPT : ; break;
|
|
case SolveInfo::pUNBD : value = SolveInfo::dUNBD ; break;
|
|
case SolveInfo::dUNBD : value = SolveInfo::pUNBD ; break;
|
|
default: break;
|
|
}
|
|
#else
|
|
// do nothing
|
|
#endif
|
|
}
|
|
|
|
|
|
void Phase::display(FILE* fpout)
|
|
{
|
|
if (fpout == NULL) {
|
|
return;
|
|
}
|
|
char* str;
|
|
switch (value) {
|
|
case SolveInfo::noINFO : str = (char *)"noINFO "; break;
|
|
case SolveInfo::pFEAS : str = (char *)"pFEAS "; break;
|
|
case SolveInfo::dFEAS : str = (char *)"dFEAS "; break;
|
|
case SolveInfo::pdFEAS : str = (char *)"pdFEAS "; break;
|
|
case SolveInfo::pdINF : str = (char *)"pdINF "; break;
|
|
case SolveInfo::pFEAS_dINF: str = (char *)"pFEAS_dINF"; break;
|
|
case SolveInfo::pINF_dFEAS: str = (char *)"pINF_dFEAS"; break;
|
|
case SolveInfo::pdOPT : str = (char *)"pdOPT "; break;
|
|
case SolveInfo::pUNBD : str = (char *)"pUNBD "; break;
|
|
case SolveInfo::dUNBD : str = (char *)"dUNBD "; break;
|
|
default:
|
|
str = (char *)"phase error";
|
|
rMessage("rPhase:: phase error");
|
|
break;
|
|
}
|
|
fprintf(fpout,"phase.value = %s\n",str);
|
|
}
|
|
|
|
} // end of namespace 'sdpa'
|
|
|