#include <assert.h>
#include <sstream>
#include "soplex/cring.h"
#include "soplex/spxdefines.h"
#ifdef SOPLEX_DEBUG
#include <stdio.h>
#endif
namespace soplex
{
#define MINSTABILITYRAT REAL(4e-2)
inline void SLUFactorRational::solveRight(VectorRational& x, const VectorRational& b) {
solveTime->start();
vec = b;
CLUFactorRational::solveRight(x.get_ptr(), vec.get_ptr());
solveCount++;
solveTime->stop();
}
inline void SLUFactorRational::solveRight(SSVectorRational& x, const SVectorRational& b) {
solveTime->start();
vec.assign(b);
x.clear();
CLUFactorRational::solveRight(x.altValues(), vec.get_ptr());
solveCount++;
solveTime->stop();
}
inline void SLUFactorRational::solveRight4update(SSVectorRational& x, const SVectorRational& b)
{
solveTime->start();
int m;
int n;
int f = 0;
x.clear();
ssvec = b;
n = ssvec.size();
if(l.updateType == ETA)
{
m = vSolveRight4update(x.altValues(), x.altIndexMem(),
ssvec.altValues(), ssvec.altIndexMem(), n, 0, 0, 0);
x.setSize(m);
x.unSetup();
eta.setup_and_assign(x);
}
else
{
forest.clear();
m = vSolveRight4update(x.altValues(), x.altIndexMem(),
ssvec.altValues(), ssvec.altIndexMem(), n,
forest.altValues(), &f, forest.altIndexMem());
forest.setSize(f);
forest.forceSetup();
x.setSize(m);
x.forceSetup();
}
usetup = true;
solveCount++;
solveTime->stop();
}
inline void SLUFactorRational::solve2right4update(
SSVectorRational& x,
VectorRational& y,
const SVectorRational& b,
SSVectorRational& rhs)
{
solveTime->start();
int m;
int n;
int f = 0;
int* sidx = ssvec.altIndexMem();
int rsize = rhs.size();
int* ridx = rhs.altIndexMem();
x.clear();
y.clear();
usetup = true;
ssvec = b;
if(l.updateType == ETA)
{
n = ssvec.size();
m = vSolveRight4update2(x.altValues(), x.altIndexMem(),
ssvec.get_ptr(), sidx, n, y.get_ptr(),
rhs.altValues(), ridx, rsize, 0, 0, 0);
x.setSize(m);
x.unSetup();
eta.setup_and_assign(x);
}
else
{
forest.clear();
n = ssvec.size();
m = vSolveRight4update2(x.altValues(), x.altIndexMem(),
ssvec.get_ptr(), sidx, n, y.get_ptr(),
rhs.altValues(), ridx, rsize,
forest.altValues(), &f, forest.altIndexMem());
x.setSize(m);
x.forceSetup();
forest.setSize(f);
forest.forceSetup();
}
solveCount++;
solveTime->stop();
}
inline void SLUFactorRational::solve3right4update(
SSVectorRational& x,
VectorRational& y,
VectorRational& y2,
const SVectorRational& b,
SSVectorRational& rhs,
SSVectorRational& rhs2)
{
solveTime->start();
int m;
int n;
int f;
int* sidx = ssvec.altIndexMem();
int rsize = rhs.size();
int* ridx = rhs.altIndexMem();
int rsize2 = rhs2.size();
int* ridx2 = rhs2.altIndexMem();
x.clear();
y.clear();
y2.clear();
usetup = true;
ssvec = b;
if(l.updateType == ETA)
{
n = ssvec.size();
m = vSolveRight4update3(x.altValues(), x.altIndexMem(), ssvec.get_ptr(), sidx, n,
y.get_ptr(), rhs.altValues(), ridx, rsize,
y2.get_ptr(), rhs2.altValues(), ridx2, rsize2,
0, 0, 0);
x.setSize(m);
x.unSetup();
eta.setup_and_assign(x);
}
else
{
forest.clear();
n = ssvec.size();
m = vSolveRight4update3(x.altValues(), x.altIndexMem(), ssvec.get_ptr(), sidx, n,
y.get_ptr(), rhs.altValues(), ridx, rsize,
y2.get_ptr(), rhs2.altValues(), ridx2, rsize2,
forest.altValues(), &f, forest.altIndexMem());
x.setSize(m);
x.forceSetup();
forest.setSize(f);
forest.forceSetup();
}
solveCount++;
solveTime->stop();
}
inline void SLUFactorRational::solveLeft(VectorRational& x, const VectorRational& b) {
solveTime->start();
vec = b;
x.clear();
CLUFactorRational::solveLeft(x.get_ptr(), vec.get_ptr());
solveCount++;
solveTime->stop();
}
inline void SLUFactorRational::solveLeft(SSVectorRational& x, const SVectorRational& b) {
solveTime->start();
ssvec.assign(b);
x.clear();
int sz = ssvec.size(); int n = vSolveLeft(x.altValues(), x.altIndexMem(),
ssvec.altValues(), ssvec.altIndexMem(), sz);
if(n > 0)
{
x.setSize(n);
x.forceSetup();
}
else
x.unSetup();
ssvec.setSize(0);
ssvec.forceSetup();
solveCount++;
solveTime->stop();
}
inline void SLUFactorRational::solveLeft(
SSVectorRational& x,
VectorRational& y,
const SVectorRational& rhs1,
SSVectorRational& rhs2) {
solveTime->start();
int n;
Rational* svec = ssvec.altValues();
int* sidx = ssvec.altIndexMem();
int rn = rhs2.size();
int* ridx = rhs2.altIndexMem();
x.clear();
y.clear();
ssvec.assign(rhs1);
n = ssvec.size(); n = vSolveLeft2(x.altValues(), x.altIndexMem(), svec, sidx, n,
y.get_ptr(), rhs2.altValues(), ridx, rn);
x.setSize(n);
if(n > 0)
x.forceSetup();
else
x.unSetup();
rhs2.setSize(0);
rhs2.forceSetup();
ssvec.setSize(0);
ssvec.forceSetup();
solveCount++;
solveTime->stop();
}
inline void SLUFactorRational::solveLeft(
SSVectorRational& x,
VectorRational& y,
VectorRational& z,
const SVectorRational& rhs1,
SSVectorRational& rhs2,
SSVectorRational& rhs3)
{
solveTime->start();
int n;
Rational* svec = ssvec.altValues();
int* sidx = ssvec.altIndexMem();
x.clear();
y.clear();
z.clear();
ssvec.assign(rhs1);
n = ssvec.size(); n = vSolveLeft3(x.altValues(), x.altIndexMem(), svec, sidx, n,
y.get_ptr(), rhs2.altValues(), rhs2.altIndexMem(), rhs2.size(),
z.get_ptr(), rhs3.altValues(), rhs3.altIndexMem(), rhs3.size());
x.setSize(n);
if(n > 0)
x.forceSetup();
else
x.unSetup();
ssvec.setSize(0);
ssvec.forceSetup();
solveCount++;
solveTime->stop();
}
inline Rational SLUFactorRational::stability() const
{
if(status() != OK)
return 0;
if(maxabs < initMaxabs)
return 1;
return initMaxabs / maxabs;
}
inline std::string SLUFactorRational::statistics() const
{
std::stringstream s;
s << "Factorizations : " << std::setw(10) << getFactorCount() << std::endl
<< " Time spent : " << std::setw(10) << std::fixed << std::setprecision(
2) << getFactorTime() << std::endl
<< "Solves : " << std::setw(10) << getSolveCount() << std::endl
<< " Time spent : " << std::setw(10) << getSolveTime() << std::endl;
return s.str();
}
inline void SLUFactorRational::changeEta(int idx, SSVectorRational& et)
{
int es = et.size(); update(idx, et.altValues(), et.altIndexMem(), es);
et.setSize(0);
et.forceSetup();
}
inline SLUFactorRational::Status SLUFactorRational::change(
int idx,
const SVectorRational& subst,
const SSVectorRational* e)
{
if(usetup)
{
if(l.updateType == FOREST_TOMLIN) {
int fsize = forest.size(); forestUpdate(idx, forest.altValues(), fsize, forest.altIndexMem());
forest.setSize(0);
forest.forceSetup();
}
else
{
assert(l.updateType == ETA);
changeEta(idx, eta);
}
}
else if(e != 0) {
l.updateType = ETA;
updateNoClear(idx, e->values(), e->indexMem(), e->size());
l.updateType = uptype;
}
else if(l.updateType == FOREST_TOMLIN) {
assert(0); forest = subst;
CLUFactorRational::solveLright(forest.altValues());
forestUpdate(idx, forest.altValues(), 0, nullptr);
forest.setSize(0);
forest.forceSetup();
}
else {
assert(l.updateType == ETA);
vec = subst;
eta.clear();
CLUFactorRational::solveRight(eta.altValues(), vec.get_ptr());
changeEta(idx, eta);
}
usetup = false;
MSG_DEBUG(std::cout << "DSLUFA01\tupdated\t\tstability = " << stability()
<< std::endl;)
return status();
}
inline void SLUFactorRational::clear()
{
rowMemMult = 5;
colMemMult = 5;
lMemMult = 1;
l.firstUpdate = 0;
l.firstUnused = 0;
thedim = 0;
usetup = false;
maxabs = 1;
initMaxabs = 1;
lastThreshold = minThreshold;
minStability = MINSTABILITYRAT;
stat = UNLOADED;
vec.clear();
eta.clear();
ssvec.clear();
forest.clear();
u.col.size = 100;
l.startSize = 100;
l.rval.reDim(0);
if(l.ridx)
spx_free(l.ridx);
if(l.rbeg)
spx_free(l.rbeg);
if(l.rorig)
spx_free(l.rorig);
if(l.rperm)
spx_free(l.rperm);
if(u.row.idx)
spx_free(u.row.idx);
if(u.col.idx)
spx_free(u.col.idx);
if(l.idx)
spx_free(l.idx);
if(l.start)
spx_free(l.start);
if(l.row)
spx_free(l.row);
try
{
u.row.val.reDim(100);
spx_alloc(u.row.idx, u.row.val.dim());
spx_alloc(u.col.idx, u.col.size);
l.val.reDim(100);
spx_alloc(l.idx, l.val.dim());
spx_alloc(l.start, l.startSize);
spx_alloc(l.row, l.startSize);
}
catch(const SPxMemoryException& x)
{
freeAll();
throw x;
}
}
inline void SLUFactorRational::assign(const SLUFactorRational& old)
{
unsigned int thediminc;
uptype = old.uptype;
minThreshold = old.minThreshold;
minStability = old.minStability;
lastThreshold = old.lastThreshold;
stat = old.stat;
thedim = old.thedim;
nzCnt = old.nzCnt;
initMaxabs = old.initMaxabs;
maxabs = old.maxabs;
rowMemMult = old.rowMemMult;
colMemMult = old.colMemMult;
lMemMult = old.lMemMult;
factorCount = old.factorCount;
factorTime = old.factorTime;
timeLimit = old.timeLimit;
spx_alloc(row.perm, thedim);
spx_alloc(row.orig, thedim);
spx_alloc(col.perm, thedim);
spx_alloc(col.orig, thedim);
memcpy(row.perm, old.row.perm, (unsigned int)thedim * sizeof(*row.perm));
memcpy(row.orig, old.row.orig, (unsigned int)thedim * sizeof(*row.orig));
memcpy(col.perm, old.col.perm, (unsigned int)thedim * sizeof(*col.perm));
memcpy(col.orig, old.col.orig, (unsigned int)thedim * sizeof(*col.orig));
diag = old.diag;
work = vec.get_ptr();
thediminc = (unsigned int)(thedim + 1);
u.row.used = old.u.row.used;
spx_alloc(u.row.elem, thedim);
spx_alloc(u.row.idx, u.row.val.dim());
spx_alloc(u.row.start, thediminc);
spx_alloc(u.row.len, thediminc);
spx_alloc(u.row.max, thediminc);
memcpy(u.row.elem, old.u.row.elem, (unsigned int)thedim * sizeof(*u.row.elem));
u.row.val = old.u.row.val;
memcpy(u.row.idx, old.u.row.idx, (unsigned int)u.row.val.dim() * sizeof(*u.row.idx));
memcpy(u.row.start, old.u.row.start, thediminc * sizeof(*u.row.start));
memcpy(u.row.len, old.u.row.len, thediminc * sizeof(*u.row.len));
memcpy(u.row.max, old.u.row.max, thediminc * sizeof(*u.row.max));
if(thedim > 0 && stat == OK)
{
u.row.list.idx = old.u.row.list.idx;
const Dring* oring = &old.u.row.list;
Dring* ring = &u.row.list;
while(oring->next != &old.u.row.list)
{
ring->next = &u.row.elem[oring->next->idx];
ring->next->prev = ring;
oring = oring->next;
ring = ring->next;
}
ring->next = &u.row.list;
ring->next->prev = ring;
}
u.col.size = old.u.col.size;
u.col.used = old.u.col.used;
spx_alloc(u.col.elem, thedim);
spx_alloc(u.col.idx, u.col.size);
spx_alloc(u.col.start, thediminc);
spx_alloc(u.col.len, thediminc);
spx_alloc(u.col.max, thediminc);
u.col.val = old.u.col.val;
memcpy(u.col.elem, old.u.col.elem, (unsigned int)thedim * sizeof(*u.col.elem));
memcpy(u.col.idx, old.u.col.idx, (unsigned int)u.col.size * sizeof(*u.col.idx));
memcpy(u.col.start, old.u.col.start, thediminc * sizeof(*u.col.start));
memcpy(u.col.len, old.u.col.len, thediminc * sizeof(*u.col.len));
memcpy(u.col.max, old.u.col.max, thediminc * sizeof(*u.col.max));
if(thedim > 0 && stat == OK)
{
u.col.list.idx = old.u.col.list.idx;
const Dring* oring = &old.u.col.list;
Dring* ring = &u.col.list;
while(oring->next != &old.u.col.list)
{
ring->next = &u.col.elem[oring->next->idx];
ring->next->prev = ring;
oring = oring->next;
ring = ring->next;
}
ring->next = &u.col.list;
ring->next->prev = ring;
}
l.startSize = old.l.startSize;
l.firstUpdate = old.l.firstUpdate;
l.firstUnused = old.l.firstUnused;
l.updateType = old.l.updateType;
l.val = old.l.val;
spx_alloc(l.idx, l.val.dim());
spx_alloc(l.start, l.startSize);
spx_alloc(l.row, l.startSize);
memcpy(l.idx, old.l.idx, (unsigned int)l.val.dim() * sizeof(*l.idx));
memcpy(l.start, old.l.start, (unsigned int)l.startSize * sizeof(*l.start));
memcpy(l.row, old.l.row, (unsigned int)l.startSize * sizeof(*l.row));
if(l.rval.dim() != 0)
{
assert(old.l.ridx != 0);
assert(old.l.rbeg != 0);
assert(old.l.rorig != 0);
assert(old.l.rperm != 0);
int memsize = l.start[l.firstUpdate];
l.rval = old.l.rval;
spx_alloc(l.ridx, memsize);
spx_alloc(l.rbeg, thediminc);
spx_alloc(l.rorig, thedim);
spx_alloc(l.rperm, thedim);
memcpy(l.ridx, old.l.ridx, (unsigned int)memsize * sizeof(*l.ridx));
memcpy(l.rbeg, old.l.rbeg, thediminc * sizeof(*l.rbeg));
memcpy(l.rorig, old.l.rorig, (unsigned int)thedim * sizeof(*l.rorig));
memcpy(l.rperm, old.l.rperm, (unsigned int)thedim * sizeof(*l.rperm));
}
else
{
assert(old.l.ridx == 0);
assert(old.l.rbeg == 0);
assert(old.l.rorig == 0);
assert(old.l.rperm == 0);
l.rval.reDim(0);
l.ridx = 0;
l.rbeg = 0;
l.rorig = 0;
l.rperm = 0;
}
assert(row.perm != 0);
assert(row.orig != 0);
assert(col.perm != 0);
assert(col.orig != 0);
assert(u.row.elem != 0);
assert(u.row.idx != 0);
assert(u.row.start != 0);
assert(u.row.len != 0);
assert(u.row.max != 0);
assert(u.col.elem != 0);
assert(u.col.idx != 0);
assert(u.col.start != 0);
assert(u.col.len != 0);
assert(u.col.max != 0);
assert(l.idx != 0);
assert(l.start != 0);
assert(l.row != 0);
}
inline void SLUFactorRational::freeAll()
{
if(row.perm)
spx_free(row.perm);
if(row.orig)
spx_free(row.orig);
if(col.perm)
spx_free(col.perm);
if(col.orig)
spx_free(col.orig);
if(u.row.elem)
spx_free(u.row.elem);
if(u.row.idx)
spx_free(u.row.idx);
if(u.row.start)
spx_free(u.row.start);
if(u.row.len)
spx_free(u.row.len);
if(u.row.max)
spx_free(u.row.max);
if(u.col.elem)
spx_free(u.col.elem);
if(u.col.idx)
spx_free(u.col.idx);
if(u.col.start)
spx_free(u.col.start);
if(u.col.len)
spx_free(u.col.len);
if(u.col.max)
spx_free(u.col.max);
if(l.idx)
spx_free(l.idx);
if(l.start)
spx_free(l.start);
if(l.row)
spx_free(l.row);
if(l.ridx)
spx_free(l.ridx);
if(l.rbeg)
spx_free(l.rbeg);
if(l.rorig)
spx_free(l.rorig);
if(l.rperm)
spx_free(l.rperm);
spx_free(solveTime);
spx_free(factorTime);
}
inline SLUFactorRational::~SLUFactorRational()
{
freeAll();
}
static Rational betterThreshold(Rational th)
{
assert(th < 1);
if(10 * th < 1)
th *= 10;
else if(10 * th < 8)
th = (th + 1) / 2;
else if(th < 0.999)
th = 0.99999;
assert(th < 1);
return th;
}
inline SLUFactorRational::Status SLUFactorRational::load(const SVectorRational* matrix[], int dm)
{
assert(dm >= 0);
assert(matrix != 0);
Rational lastStability = stability();
initDR(u.row.list);
initDR(u.col.list);
usetup = false;
l.updateType = uptype;
l.firstUpdate = 0;
l.firstUnused = 0;
if(dm != thedim)
{
clear();
thedim = dm;
vec.reDim(thedim);
ssvec.reDim(thedim);
eta.reDim(thedim);
forest.reDim(thedim);
work = vec.get_ptr();
spx_realloc(row.perm, thedim);
spx_realloc(row.orig, thedim);
spx_realloc(col.perm, thedim);
spx_realloc(col.orig, thedim);
diag.reDim(thedim);
spx_realloc(u.row.elem, thedim);
spx_realloc(u.row.len, thedim + 1);
spx_realloc(u.row.max, thedim + 1);
spx_realloc(u.row.start, thedim + 1);
spx_realloc(u.col.elem, thedim);
spx_realloc(u.col.len, thedim + 1);
spx_realloc(u.col.max, thedim + 1);
spx_realloc(u.col.start, thedim + 1);
l.startSize = thedim + MAXUPDATES;
spx_realloc(l.row, l.startSize);
spx_realloc(l.start, l.startSize);
}
else if(lastStability > 2.0 * MINSTABILITYRAT)
{
Rational last = minThreshold;
Rational better = betterThreshold(last);
while(better < lastThreshold)
{
last = better;
better = betterThreshold(last);
}
lastThreshold = last;
minStability = 2 * MINSTABILITYRAT;
}
u.row.list.idx = thedim;
u.row.start[thedim] = 0;
u.row.max[thedim] = 0;
u.row.len[thedim] = 0;
u.col.list.idx = thedim;
u.col.start[thedim] = 0;
u.col.max[thedim] = 0;
u.col.len[thedim] = 0;
stat = OK;
factor(matrix, lastThreshold);
MSG_DEBUG(std::cout << "DSLUFA02 threshold = " << lastThreshold
<< "\tstability = " << stability()
<< "\tMINSTABILITYRAT = " << MINSTABILITYRAT << std::endl;)
MSG_DEBUG(
int i;
FILE* fl = fopen("dump.lp", "w");
std::cout << "DSLUFA03 Basis:\n";
int j = 0;
for(i = 0; i < dim(); ++i)
j += matrix[i]->size();
for(i = 0; i < dim(); ++i)
{
for(j = 0; j < matrix[i]->size(); ++j)
fprintf(fl, "%8d %8d %s\n",
i + 1, matrix[i]->index(j) + 1, matrix[i]->value(j).str());
}
fclose(fl);
std::cout << "DSLUFA04 LU-Factors:" << std::endl;
dump();
std::cout << "DSLUFA05 threshold = " << lastThreshold
<< "\tstability = " << stability() << std::endl;
)
assert(isConsistent());
return Status(stat);
}
inline bool SLUFactorRational::isConsistent() const
{
#ifdef ENABLE_CONSISTENCY_CHECKS
return CLUFactorRational::isConsistent();
#else
return true;
#endif
}
inline void SLUFactorRational::dump() const
{
CLUFactorRational::dump();
}
}