From ab5f8ff5869021958f4ae8b838c3d707a2e85eaa Mon Sep 17 00:00:00 2001 From: Marc Jeanmougin Date: Sun, 29 Apr 2018 16:25:32 +0200 Subject: Put adaptagrams into its own folder --- src/libcola/gradient_projection.cpp | 483 ------------------------------------ 1 file changed, 483 deletions(-) delete mode 100644 src/libcola/gradient_projection.cpp (limited to 'src/libcola/gradient_projection.cpp') diff --git a/src/libcola/gradient_projection.cpp b/src/libcola/gradient_projection.cpp deleted file mode 100644 index 50b8d27d7..000000000 --- a/src/libcola/gradient_projection.cpp +++ /dev/null @@ -1,483 +0,0 @@ -/* - * vim: ts=4 sw=4 et tw=0 wm=0 - * - * libcola - A library providing force-directed network layout using the - * stress-majorization method subject to separation constraints. - * - * Copyright (C) 2006-2008 Monash University - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * See the file LICENSE.LGPL distributed with the library. - * - * This library 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. - * -*/ - -/********************************************************** - * - * Solve a quadratic function f(X) = X' A X + b X - * subject to a set of separation constraints cs - * - **********************************************************/ - -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "libcola/cluster.h" -#include "libcola/gradient_projection.h" -#include "libcola/straightener.h" -#include "libcola/commondefs.h" -//#define CHECK_CONVERGENCE_BY_COST 1 - - -using namespace std; -using namespace vpsc; -namespace cola { -GradientProjection::GradientProjection( - const Dim k, - std::valarray *denseQ, - const double tol, - const unsigned max_iterations, - CompoundConstraints const *ccs, - UnsatisfiableConstraintInfos *unsatisfiableConstraints, - NonOverlapConstraintsMode nonOverlapConstraints, - RootCluster* clusterHierarchy, - vpsc::Rectangles* rs, - const bool scaling, - SolveWithMosek solveWithMosek) - : k(k), - denseSize(static_cast((floor(sqrt(static_cast(denseQ->size())))))), - denseQ(denseQ), - rs(rs), - ccs(ccs), - unsatisfiableConstraints(unsatisfiableConstraints), - nonOverlapConstraints(nonOverlapConstraints), - clusterHierarchy(clusterHierarchy), - tolerance(tol), - max_iterations(max_iterations), - sparseQ(NULL), - solveWithMosek(solveWithMosek), - scaling(scaling) -{ - printf("GP Instance: scaling=%d, mosek=%d\n",scaling,solveWithMosek); - for(unsigned i=0;iscale=1./sqrt(fabs((*denseQ)[i*denseSize+i])); - // XXX: Scale can sometimes be set to infinity here when - // there are nodes not connected to any other node. - // Thus we just set the scale for such a variable to 1. - if (!isFinite(vars[i]->scale)) - { - vars[i]->scale = 1; - } - } - // the following computes S'QS for Q=denseQ - // and S is diagonal matrix of scale factors - for(unsigned i=0;iscale - *vars[j]->scale; - } - } - this->denseQ = &scaledDenseQ; - } - //dumpSquareMatrix(*this->denseQ); - //dumpSquareMatrix(scaledDenseQ); - - if(ccs) { - for(CompoundConstraints::const_iterator c=ccs->begin(); - c!=ccs->end();++c) { - (*c)->generateVariables(k, vars); - OrthogonalEdgeConstraint* e=dynamic_cast(*c); - if(e) { - orthogonalEdges.push_back(e); - } - } - for(CompoundConstraints::const_iterator c=ccs->begin(); - c!=ccs->end();++c) { - (*c)->generateSeparationConstraints(k, vars, gcs, *rs); - } - } - /* - if(clusterHierarchy) { - clusterHierarchy->createVars(k,*rs,vars); - } - */ - numStaticVars=vars.size(); - //solver=setupVPSC(); -} -static inline double dotProd(valarray const & a, valarray const & b) { - double p = 0; - for (unsigned i=0; i const &b, - valarray const &x) const { - // computes cost = 2 b x - x A x - double cost = 2. * dotProd(b,x); - valarray Ax(x.size()); - for (unsigned i=0; i r(x.size()); - sparseQ->rightMultiply(x,r); - Ax+=r; - } - return cost - dotProd(x,Ax); -} - -double GradientProjection::computeSteepestDescentVector( - valarray const &b, - valarray const &x, - valarray &g) const { - // find steepest descent direction - // g = 2 ( b - A x ) - // where: A = denseQ + sparseQ - // g = 2 ( b - denseQ x) - 2 sparseQ x - // - // except the 2s don't matter because we compute - // the optimal stepsize anyway - COLA_ASSERT(x.size()==b.size() && b.size()==g.size()); - g = b; - for (unsigned i=0; i r(x.size()); - sparseQ->rightMultiply(x,r); - g-=r; - } - return computeStepSize(g,g); -} -// compute optimal step size along descent vector d relative to -// a gradient related vector g -// stepsize = ( g' d ) / ( d' A d ) -double GradientProjection::computeStepSize( - valarray const & g, valarray const & d) const { - COLA_ASSERT(g.size()==d.size()); - valarray Ad; - if(sparseQ) { - Ad.resize(g.size()); - sparseQ->rightMultiply(d,Ad); - } - double const numerator = dotProd(g, d); - double denominator = 0; - for (unsigned i=0; i & result) { - bool activeConstraints = false; - switch(solveWithMosek) { - case Off: - activeConstraints = solver->satisfy(); - for (unsigned i=0;ifinalPosition; - } - break; - case Inner: -#ifdef MOSEK_AVAILABLE - float *ba=new float[vars.size()]; - float *coords=new float[vars.size()]; - for(unsigned i=0;idesiredPosition; - } - mosek_quad_solve_sep(menv,ba,coords); - for(unsigned i=0;i const &linearCoefficients, - valarray &x) { - COLA_ASSERT(linearCoefficients.size()==x.size()); - COLA_ASSERT(x.size()==denseSize); - COLA_ASSERT(numStaticVars>=denseSize); - COLA_ASSERT(sparseQ==NULL || - (sparseQ!=NULL && (vars.size()==sparseQ->rowSize())) ); - - if(max_iterations==0) return 0; - - bool converged=false; - - solver = setupVPSC(); -#ifdef MOSEK_AVAILABLE - if(solveWithMosek==Outer) { - float* ba=new float[vars.size()]; - float* xa=new float[vars.size()]; - for(unsigned i=0;i b(n); - result.resize(n); - - // load desired positions into vars, note that we keep desired positions - // already calculated for dummy vars - for (unsigned i=0;iscale; - result[i]/=vars[i]->scale; - } - if(!vars[i]->fixedDesiredPosition) vars[i]->desiredPosition=result[i]; - } - runSolver(result); - - valarray g(n); /* gradient */ - valarray previous(n); /* stored positions */ - valarray d(n); /* actual descent vector */ - -#ifdef CHECK_CONVERGENCE_BY_COST - double previousCost = DBL_MAX; -#endif - unsigned counter=0; - double stepSize; - for (; counterweight; - result[i]+=step; - //printf(" after unconstrained step: x[%d]=%f\n",i,result[i]); - stepSize+=step*step; - COLA_ASSERT(!isNaN(result[i])); - COLA_ASSERT(isFinite(result[i])); - if(!vars[i]->fixedDesiredPosition) vars[i]->desiredPosition=result[i]; - } - - //project to constraint boundary - bool constrainedOptimum = false; - constrainedOptimum=runSolver(result); - stepSize=0; - for (unsigned i=0;i1! - if(constrainedOptimum) { - // The following step limits the step-size in the feasible - // direction - d = result - previous; - const double beta = 0.5*computeStepSize(g, d); - // beta > 1.0 takes us back outside the feasible region - // beta < 0 clearly not useful and may happen due to numerical imp. - //printf("beta=%f\n",beta); - if(beta>0&&beta<0.99999) { - stepSize=0; - for (unsigned i=0; icost); - if(fabs(previousCost - cost) < tolerance) { - converged = true; - } - previousCost = cost; - //} -#else - if(stepSizescale; - } - } - destroyVPSC(solver); - return counter; -} -// Setup an instance of the Variable Placement with Separation Constraints -// for one iteration. -// Generate transient local constraints --- such as non-overlap constraints -// --- that are only relevant to one iteration, and merge these with the -// global constraint list (including alignment constraints, -// dir-edge constraints, containment constraints, etc). -IncSolver* GradientProjection::setupVPSC() { - if(nonOverlapConstraints!=None) { - if(clusterHierarchy) { - //printf("Setup up cluster constraints, dim=%d--------------\n",k); - //clusterHierarchy->generateNonOverlapConstraints(k,nonOverlapConstraints,*rs,vars,lcs); - } else { - for(vector::iterator i=orthogonalEdges.begin();i!=orthogonalEdges.end();i++) { - OrthogonalEdgeConstraint* e=*i; - e->generateTopologyConstraints(k,*rs,vars,lcs); - } - if(k==HORIZONTAL) { - // Make rectangles a little bit wider when processing horizontally so that any overlap - // resolved horizontally is strictly non-overlapping when processing vertically - Rectangle::setXBorder(0.0001); - // use rs->size() rather than n because some of the variables may - // be dummy vars with no corresponding rectangle - generateXConstraints(*rs,vars,lcs,nonOverlapConstraints==Both?true:false); - Rectangle::setXBorder(0); - } else { - generateYConstraints(*rs,vars,lcs); - } - } - } - cs=gcs; - cs.insert(cs.end(),lcs.begin(),lcs.end()); - switch(solveWithMosek) { - case Off: - break; -#ifdef MOSEK_AVAILABLE - case Inner: - menv = mosek_init_sep_ls(vars.size(),cs); - break; - case Outer: - unsigned n = vars.size(); - float* lap = new float[n*(n+1)/2]; - unsigned k=0; - for(unsigned i=0;ibegin(); - c!=ccs->end();++c) { - (*c)->updatePosition(vpsc::XDIM); - (*c)->updatePosition(vpsc::YDIM); - } - } - if(unsatisfiableConstraints) { - unsatisfiableConstraints->clear(); - for(Constraints::iterator i=cs.begin();i!=cs.end();i++) { - Constraint* c=*i; - if(c->unsatisfiable) { - UnsatisfiableConstraintInfo *ci = new UnsatisfiableConstraintInfo(c); - unsatisfiableConstraints->push_back(ci); - } - } - } - if(clusterHierarchy) { - clusterHierarchy->computeBoundary(*rs); - } - if(sparseQ) { - for(unsigned i=numStaticVars;i::iterator i=lcs.begin();i!=lcs.end();i++) { - delete *i; - } - lcs.clear(); - delete vpsc; -#ifdef MOSEK_AVAILABLE - if(solveWithMosek!=Off) mosek_delete(menv); -#endif -} -void GradientProjection::straighten( - cola::SparseMatrix const * Q, - vector const & cs, - vector const & snodes) -{ - COLA_ASSERT(Q->rowSize()==snodes.size()); - COLA_ASSERT(vars.size()==numStaticVars); - sparseQ = Q; - for(unsigned i=numStaticVars;ipos[k],1); - COLA_ASSERT(v->desiredPosition==snodes[i]->pos[k]); - vars.push_back(v); - } - COLA_ASSERT(lcs.size()==0); - for(vector::const_iterator i=cs.begin();i!=cs.end();i++) { - (*i)->generateSeparationConstraints(k, vars, lcs, *rs); - } -} -} // namespace cola -- cgit v1.2.3