From cca66b9ec4e494c1d919bff0f71a820d8afab1fa Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 20:24:48 +0200 Subject: Adding upstream version 1.2.2. Signed-off-by: Daniel Baumann --- src/3rdparty/adaptagrams/libvpsc/constraint.cpp | 218 ++++++++++++++++++++++++ 1 file changed, 218 insertions(+) create mode 100644 src/3rdparty/adaptagrams/libvpsc/constraint.cpp (limited to 'src/3rdparty/adaptagrams/libvpsc/constraint.cpp') diff --git a/src/3rdparty/adaptagrams/libvpsc/constraint.cpp b/src/3rdparty/adaptagrams/libvpsc/constraint.cpp new file mode 100644 index 0000000..96581c7 --- /dev/null +++ b/src/3rdparty/adaptagrams/libvpsc/constraint.cpp @@ -0,0 +1,218 @@ +/* + * vim: ts=4 sw=4 et tw=0 wm=0 + * + * libvpsc - A solver for the problem of Variable Placement with + * Separation Constraints. + * + * Copyright (C) 2005-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. + * + * Author(s): Tim Dwyer +*/ + + +#include +#include +#include +#include +#include +#include + + +#include "libvpsc/constraint.h" +#include "libvpsc/variable.h" + +namespace vpsc { +Constraint::Constraint(Variable *left, Variable *right, double gap, bool equality) +: left(left), + right(right), + gap(gap), + timeStamp(0), + active(false), + equality(equality), + unsatisfiable(false), + needsScaling(true), + creator(nullptr) +{ + // In hindsight I think it's probably better to build the constraint DAG + // (by creating variable in/out lists) when needed, rather than in advance + //left->out.push_back(this); + //right->in.push_back(this); +} +Constraint::~Constraint() { + // see constructor: the following is just way too slow. + // Better to create a + // new DAG on demand than maintain the lists dynamically. + //Constraints::iterator i; + //for(i=left->out.begin(); i!=left->out.end(); i++) { + //if(*i==this) break; + //} + //left->out.erase(i); + //for(i=right->in.begin(); i!=right->in.end(); i++) { + //if(*i==this) break; + //} + //right->in.erase(i); +} +std::ostream& operator <<(std::ostream &os, const Constraint &c) +{ + const char *type = c.equality ? "=" : "<="; + std::ostringstream lscale, rscale; + if (c.left->scale != 1) + { + lscale << c.left->scale << "*"; + } + if (c.right->scale != 1) + { + rscale << c.right->scale << "*"; + } + os << lscale.str() << *c.left << "+" << c.gap << type << + rscale.str() << *c.right; + if (c.left->block && c.right->block) + { + os << "(" << c.slack() << ")" << (c.active ? "-active" : "") << + "(lm=" << c.lm << ")"; + } + else + { + os << "(vars have no position)"; + } + return os; +} +#include "libvpsc/block.h" +bool CompareConstraints::operator() ( + Constraint *const &l, Constraint *const &r +) const { + double const sl = + l->left->block->timeStamp > l->timeStamp + ||l->left->block==l->right->block + ?-DBL_MAX:l->slack(); + double const sr = + r->left->block->timeStamp > r->timeStamp + ||r->left->block==r->right->block + ?-DBL_MAX:r->slack(); + if(sl==sr) { + // arbitrary choice based on id + if(l->left->id==r->left->id) { + if(l->right->idright->id) return true; + return false; + } + if(l->left->idleft->id) return true; + return false; + } + return sl < sr; +} + + +typedef std::list > VarOffsetMapList; + +class EqualityConstraintSet +{ + public: + EqualityConstraintSet(Variables vs) + { + for (size_t i = 0; i < vs.size(); ++i) + { + std::map varSet; + varSet[vs[i]] = 0; + variableGroups.push_back(varSet); + } + } + bool isRedundant(Variable *lhs, Variable *rhs, double sep) + { + VarOffsetMapList::iterator lhsSet = setForVar(lhs); + VarOffsetMapList::iterator rhsSet = setForVar(rhs); + COLA_ASSERT(lhsSet != variableGroups.end()); + COLA_ASSERT(rhsSet != variableGroups.end()); + if (lhsSet == rhsSet) + { + // Check if this is a redundant constraint. + if (fabs(((*lhsSet)[lhs] + sep) - (*rhsSet)[rhs]) < 0.0001) + { + // If so, return true. + return true; + } + } + return false; + } + void mergeSets(Variable *lhs, Variable *rhs, double sep) + { + VarOffsetMapList::iterator lhsSet = setForVar(lhs); + VarOffsetMapList::iterator rhsSet = setForVar(rhs); + if (lhsSet == rhsSet) + { + return; + } + + double rhsOldOffset = (*rhsSet)[rhs]; + double rhsNewOffset = (*lhsSet)[lhs] + sep; + double offset = rhsNewOffset - rhsOldOffset; + + // Update offsets + for (std::map::iterator it = rhsSet->begin(); + it != rhsSet->end(); ++it) + { + it->second += offset; + } + + // Merge rhsSet into lhsSet + lhsSet->insert(rhsSet->begin(), rhsSet->end()); + variableGroups.erase(rhsSet); + } + + private: + VarOffsetMapList::iterator setForVar(Variable *var) + { + for (VarOffsetMapList::iterator it = variableGroups.begin(); + it != variableGroups.end(); ++it) + { + if (it->find(var) != it->end()) + { + return it; + } + } + return variableGroups.end(); + } + + VarOffsetMapList variableGroups; +}; + +Constraints constraintsRemovingRedundantEqualities(const Variables& vars, + const Constraints& constraints) +{ + EqualityConstraintSet equalitySets(vars); + Constraints cs = Constraints(constraints.size()); + int csSize = 0; + + for (unsigned i = 0; i < constraints.size(); ++i) + { + Constraint *c = constraints[i]; + if (c->equality) + { + if (!equalitySets.isRedundant(c->left, c->right, c->gap)) + { + // Only add non-redundant equalities + equalitySets.mergeSets(c->left, c->right, c->gap); + cs[csSize++] = c; + } + } + else + { + // Add all non-equalities + cs[csSize++] = c; + } + } + cs.resize(csSize); + return cs; +} + + +} -- cgit v1.2.3