From 0d1488b956da3425e57c3ce1831d92e8771263cb Mon Sep 17 00:00:00 2001 From: Slorup Date: Fri, 21 Oct 2022 11:48:19 +0200 Subject: [PATCH 01/32] A few fixes --- include/dbm/partition.h | 16 +++++++++++++ include/dbm/pfed.h | 43 +++++++++++++++++++++++++++++----- src/pfed.cpp | 51 ++++++++++++++++++++++++++++++++++++----- 3 files changed, 98 insertions(+), 12 deletions(-) diff --git a/include/dbm/partition.h b/include/dbm/partition.h index 774f996..5e17bc9 100644 --- a/include/dbm/partition.h +++ b/include/dbm/partition.h @@ -15,6 +15,7 @@ #define INCLUDE_DBM_PARTITION_H #include "dbm/fed.h" +#include "dbm/pfed.h" #include "base/intutils.h" /** @@ -114,6 +115,18 @@ namespace dbm return isPtr() ? fedTable->getAll() : fed_t(edim()); } + pfed_t get(uint32_t id) const + { + assert(fedTable); + return isPtr() ? fedTable->get(id) : pfed_t(edim()); + } + + pfed_t getAll() const + { + assert(fedTable); + return isPtr() ? fedTable->getAll() : pfed_t(edim()); + } + /// @return the dimension of the federations. cindex_t getDimension() const { @@ -244,6 +257,9 @@ namespace dbm fed_t get(uint32_t id) const; fed_t getAll() const { return all; } + pfed_t get(uint32_t id) const; + pfed_t getAll() const { return all; } + /// Add a federation to the subset 'id' of the partition. /// @return true if this table must be resized. bool add(uintptr_t id, fed_t& fed); diff --git a/include/dbm/pfed.h b/include/dbm/pfed.h index 930c8d2..d2a3256 100644 --- a/include/dbm/pfed.h +++ b/include/dbm/pfed.h @@ -11,6 +11,7 @@ #define DBM_PFED_H #include "Valuation.h" +#include "fed.h" #include "dbm/priced.h" @@ -132,6 +133,9 @@ namespace dbm /** @see dbm_t::readFromMinDBM() */ static pdbm_t readFromMinDBM(cindex_t dimension, const int32_t*); + + /// @return true if it is empty. + bool isEmpty() const; }; inline pdbm_t::pdbm_t(): pdbm(nullptr), dim(0) {} @@ -352,19 +356,19 @@ namespace dbm bool containsWeakly(const IntValuation& v) const; /** Delay with the current delay rate. */ - void up(); + pfed_t& up(); /** Delay with rate \a rate. */ - void up(int32_t rate); + pfed_t& up(int32_t rate); /** Set x(clock) to \a value. */ - void updateValue(cindex_t clock, uint32_t value); + pfed_t& updateValue(cindex_t clock, uint32_t value); /** * Set x(clock) to \a value. x(zero) must be on a zero-cycle with * x(clock). */ - void updateValueZero(cindex_t clock, int32_t value, cindex_t zero); + pfed_t& updateValueZero(cindex_t clock, int32_t value, cindex_t zero); void extrapolateMaxBounds(int32_t* max); void diagonalExtrapolateMaxBounds(int32_t* max); @@ -452,13 +456,13 @@ namespace dbm pfed_t operator-(const pfed_t& b) const; /** Not implemented. */ - void down(); + pfed_t& down(); /** Not implemented. */ int32_t getUpperMinimumCost(cindex_t) const; /** Not implemented. */ - void relaxUp(); + pfed_t& relaxUp(); /** Not implemented. */ void getValuation(double* cval, size_t dim, bool* freeC = nullptr) const; @@ -481,6 +485,33 @@ namespace dbm /** Not implemented. */ pfed_t& convexHull(); + + /** Not implemented + * @return the max upper bound (raw) of a clock. + */ + raw_t getMaxUpper(cindex_t) const; + + /** Not implemented + * @return the max lower bound (raw) of a clock. + */ + raw_t getMaxLower(cindex_t) const; + + /// Not implemented + std::string toString(const ClockAccessor&, bool full = false) const; + + /// Not implemented + pfed_t& upStop(const uint32_t* stopped); + + /// Not implemented + void updateClock(cindex_t x, cindex_t y); + + /// Not implemented + pfed_t& append(pfed_t& arg); + + /// Not implemented + pfed_t& steal(pfed_t& arg); + + /** * Relation between two priced federations: SUBSET is returned * if all zones of this federation are contained in some zone diff --git a/src/pfed.cpp b/src/pfed.cpp index 6862c4c..8d8829c 100644 --- a/src/pfed.cpp +++ b/src/pfed.cpp @@ -219,9 +219,12 @@ namespace dbm return relation(b); } - void pfed_t::up() { for_each(beginMutable(), endMutable(), bind(pdbm_up, _1, ptr->dim)); } + pfed_t& pfed_t::up() { + for_each(beginMutable(), endMutable(), bind(pdbm_up, _1, ptr->dim)); + return *this; + } - void pfed_t::up(int32_t rate) + pfed_t& pfed_t::up(int32_t rate) { assert(rate >= 0); @@ -274,14 +277,16 @@ namespace dbm pdbm_upZero(*zone, dim, rate, facets[count - 1]); } } + return *this; } - void pfed_t::updateValueZero(cindex_t clock, int32_t value, cindex_t zero) + pfed_t& pfed_t::updateValueZero(cindex_t clock, int32_t value, cindex_t zero) { for_each(beginMutable(), endMutable(), bind(pdbm_updateValueZero, _1, ptr->dim, clock, value, zero)); + return *this; } - void pfed_t::updateValue(cindex_t clock, uint32_t value) + pfed_t& pfed_t::updateValue(cindex_t clock, uint32_t value) { uint32_t dim = ptr->dim; @@ -326,6 +331,7 @@ namespace dbm pdbm_updateValueZero(*zone, dim, clock, value, facets[count - 1]); } } + return *this; } void pfed_t::extrapolateMaxBounds(int32_t* max) @@ -429,14 +435,14 @@ namespace dbm pfed_t& pfed_t::operator+=(const pfed_t&) { throw std::logic_error("pfed_t::operator += not implemented"); } - void pfed_t::down() { throw std::logic_error("pfed_t::down not implemented"); } + pfed_t& pfed_t::down() { throw std::logic_error("pfed_t::down not implemented"); } int32_t pfed_t::getUpperMinimumCost(cindex_t) const { throw std::logic_error("pfed_t::getUpperMinimumCost not implemented"); } - void pfed_t::relaxUp() { throw std::logic_error("pfed_t::relaxUp not implemented"); } + pfed_t& pfed_t::relaxUp() { throw std::logic_error("pfed_t::relaxUp not implemented"); } void pfed_t::getValuation(double*, size_t, bool* freeC) const { @@ -468,4 +474,37 @@ namespace dbm } return o; } + + raw_t pfed_t::getMaxUpper(cindex_t clock) const + { + throw std::logic_error("pfed_t::getMaxUpper not implemented"); + } + + raw_t pfed_t::getMaxLower(cindex_t clock) const + { + throw std::logic_error("pfed_t::getMaxLower not implemented"); + } + + std::string pfed_t::toString(const ClockAccessor& access, bool full) const{ + throw std::logic_error("pfed_t::getMaxLower not implemented"); + } + + void pfed_t::updateClock(cindex_t x, cindex_t y){ + throw std::logic_error("pfed_t::updateClock not implemented"); + } + + pfed_t& pfed_t::upStop(const uint32_t* stopped){ + throw std::logic_error("pfed_t::upStop not implemented"); + } + + pfed_t& pfed_t::append(pfed_t& arg){ + throw std::logic_error("pfed_t::append not implemented"); + } + + pfed_t& pfed_t::steal(pfed_t& arg){ + throw std::logic_error("pfed_t::steal not implemented"); + } + + inline bool pdbm_t::isEmpty() const { throw std::logic_error("pdbm_t::isEmpty not implemented"); } + } // namespace dbm From f0325195fe2706502bfc77bf92650b9720ff796f Mon Sep 17 00:00:00 2001 From: Slorup Date: Fri, 21 Oct 2022 11:55:31 +0200 Subject: [PATCH 02/32] small --- include/dbm/partition.h | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/include/dbm/partition.h b/include/dbm/partition.h index 5e17bc9..ae9e813 100644 --- a/include/dbm/partition.h +++ b/include/dbm/partition.h @@ -115,18 +115,6 @@ namespace dbm return isPtr() ? fedTable->getAll() : fed_t(edim()); } - pfed_t get(uint32_t id) const - { - assert(fedTable); - return isPtr() ? fedTable->get(id) : pfed_t(edim()); - } - - pfed_t getAll() const - { - assert(fedTable); - return isPtr() ? fedTable->getAll() : pfed_t(edim()); - } - /// @return the dimension of the federations. cindex_t getDimension() const { @@ -257,9 +245,6 @@ namespace dbm fed_t get(uint32_t id) const; fed_t getAll() const { return all; } - pfed_t get(uint32_t id) const; - pfed_t getAll() const { return all; } - /// Add a federation to the subset 'id' of the partition. /// @return true if this table must be resized. bool add(uintptr_t id, fed_t& fed); From 7fcc5ae3e78484f5dea791a4bd2534e26332354e Mon Sep 17 00:00:00 2001 From: Slorup Date: Fri, 21 Oct 2022 12:11:46 +0200 Subject: [PATCH 03/32] Few more fixes --- include/dbm/pfed.h | 13 ++++++++++--- src/pfed.cpp | 8 ++++++++ 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/include/dbm/pfed.h b/include/dbm/pfed.h index d2a3256..771b7f3 100644 --- a/include/dbm/pfed.h +++ b/include/dbm/pfed.h @@ -37,7 +37,7 @@ namespace dbm * priced DBM is stored in the wrapper. However, the bulk of the * pdbm_X() functions are not made available as methods. */ - class pdbm_t + class pdbm_t : dbm_t { protected: PDBM pdbm; @@ -216,7 +216,7 @@ namespace dbm * Priced federations implement copy-on-write using reference * counting. */ - class pfed_t + class pfed_t : fed_t { public: typedef std::list::const_iterator const_iterator; @@ -341,7 +341,7 @@ namespace dbm bool isUnbounded() const; /** Contains a hash of the federation. */ - uint32_t hash(uint32_t seed) const; + uint32_t hash(uint32_t seed = 0) const; /** Returns true iff the federation contains \v. */ bool contains(const DoubleValuation& v) const; @@ -511,6 +511,13 @@ namespace dbm /// Not implemented pfed_t& steal(pfed_t& arg); + /// Not implemented + pfed_t& toLowerBounds() const; + + /// Not implemented + pfed_t& toUpperBounds() const; + + /** * Relation between two priced federations: SUBSET is returned diff --git a/src/pfed.cpp b/src/pfed.cpp index 8d8829c..448fe3e 100644 --- a/src/pfed.cpp +++ b/src/pfed.cpp @@ -505,6 +505,14 @@ namespace dbm throw std::logic_error("pfed_t::steal not implemented"); } + pfed_t& pfed_t::toLowerBounds() const { + throw std::logic_error("pfed_t::toLowerBounds not implemented"); + } + + pfed_t& pfed_t::toUpperBounds() const { + throw std::logic_error("pfed_t::toUpperBounds not implemented"); + } + inline bool pdbm_t::isEmpty() const { throw std::logic_error("pdbm_t::isEmpty not implemented"); } } // namespace dbm From e5aa83dd0073d2ba1f78d71286867a7d86ff3618 Mon Sep 17 00:00:00 2001 From: Slorup Date: Fri, 28 Oct 2022 10:27:01 +0200 Subject: [PATCH 04/32] Messy const_iterator - probably doesn't work, just to avoid errors for now --- include/dbm/pfed.h | 24 +++++++++++++++++++++--- src/pfed.cpp | 1 + 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/include/dbm/pfed.h b/include/dbm/pfed.h index 771b7f3..98ac776 100644 --- a/include/dbm/pfed.h +++ b/include/dbm/pfed.h @@ -18,8 +18,21 @@ #include #include + + namespace dbm { + class pdbm_t; + + class cst_iterator : public std::_List_const_iterator{ + + public: + cst_iterator(); + cst_iterator(iterator iterator); + bool null(); + const raw_t* operator()() const; + }; + /** * Small C++ wrapper for the PDBM priced DBM type. * @@ -37,7 +50,7 @@ namespace dbm * priced DBM is stored in the wrapper. However, the bulk of the * pdbm_X() functions are not made available as methods. */ - class pdbm_t : dbm_t + class pdbm_t { protected: PDBM pdbm; @@ -216,10 +229,10 @@ namespace dbm * Priced federations implement copy-on-write using reference * counting. */ - class pfed_t : fed_t + class pfed_t { public: - typedef std::list::const_iterator const_iterator; + typedef cst_iterator const_iterator; typedef std::list::iterator iterator; @@ -672,6 +685,11 @@ namespace dbm inline bool pfed_t::satisfies(const constraint_t& c) const { return satisfies(c.i, c.j, c.value); } std::ostream& operator<<(std::ostream&, const pfed_t&); + + bool cst_iterator::null() { return _M_node == NULL; } + const raw_t* cst_iterator::operator()() const { return reinterpret_cast(_M_node); } + cst_iterator::cst_iterator(std::_List_const_iterator::iterator iterator) {} + cst_iterator::cst_iterator() = default; } // namespace dbm #endif /* DBM_PFED_H */ diff --git a/src/pfed.cpp b/src/pfed.cpp index 448fe3e..5be5506 100644 --- a/src/pfed.cpp +++ b/src/pfed.cpp @@ -515,4 +515,5 @@ namespace dbm inline bool pdbm_t::isEmpty() const { throw std::logic_error("pdbm_t::isEmpty not implemented"); } + } // namespace dbm From 7b6d358ea07550e5ed35ae93e952edbab9041906 Mon Sep 17 00:00:00 2001 From: Slorup Date: Mon, 31 Oct 2022 11:09:08 +0100 Subject: [PATCH 05/32] Hack for iterator errors and added lots of 'not implemented' functions --- include/dbm/pfed.h | 88 ++++++++++++++++++++++++++++++++++++++++--- src/pfed.cpp | 93 +++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 174 insertions(+), 7 deletions(-) diff --git a/include/dbm/pfed.h b/include/dbm/pfed.h index 98ac776..cd7a471 100644 --- a/include/dbm/pfed.h +++ b/include/dbm/pfed.h @@ -33,6 +33,13 @@ namespace dbm const raw_t* operator()() const; }; + class iterato : public std::list::iterator { + + public: + iterato(_List_iterator iterator); + void remove(); + }; + /** * Small C++ wrapper for the PDBM priced DBM type. * @@ -149,6 +156,12 @@ namespace dbm /// @return true if it is empty. bool isEmpty() const; + + /// @return dimension + cindex_t pdim() const; + + bool contains(const int32_t* point, cindex_t dim) const; + bool contains(const double* point, cindex_t dim) const; }; inline pdbm_t::pdbm_t(): pdbm(nullptr), dim(0) {} @@ -234,7 +247,7 @@ namespace dbm public: typedef cst_iterator const_iterator; - typedef std::list::iterator iterator; + typedef iterato iterator; protected: struct pfed_s @@ -261,15 +274,17 @@ namespace dbm /** Copy-on-write: Creates an unshared copy of the federation. */ void cow(); + public: + /** Allocate empty priced federation of dimension 0. */ + pfed_t(); + /** * Adds \a pdbm to the federation. The reference count on pdbm * is incremented by one. */ void add(const PDBM pdbm, cindex_t dim); - public: - /** Allocate empty priced federation of dimension 0. */ - pfed_t(); + void add(pdbm_t pdbm); /** Allocate empty priced federation of dimension \a dim. */ explicit pfed_t(cindex_t dim); @@ -362,6 +377,12 @@ namespace dbm /** Returns true iff the federation contains \v. */ bool contains(const IntValuation& v) const; + /// Not implemented + bool contains(const int32_t* point, cindex_t dim) const; + bool contains(const double* point, cindex_t dim) const; + + pfed_t& predt(const pfed_t& bad, const raw_t* restrict = NULL); + /** * Returns true iff the federation contains \v, ignoring * strictness of constraints. @@ -459,6 +480,9 @@ namespace dbm /** Not implemented. */ pfed_t& operator&=(const pfed_t&); + /** Not implemented. */ + pfed_t& operator&=(const pdbm_t&); + /** Not implemented. */ bool intersects(const pfed_t&) const; @@ -498,7 +522,6 @@ namespace dbm /** Not implemented. */ pfed_t& convexHull(); - /** Not implemented * @return the max upper bound (raw) of a clock. */ @@ -530,6 +553,52 @@ namespace dbm /// Not implemented pfed_t& toUpperBounds() const; + /// Not implemented + bool isConstrainedBy(cindex_t, cindex_t, raw_t) const; + + /// Not implemented + bool getDelay(const double* point, cindex_t dim, double* min, double* max, double* minVal = NULL, + bool* minStrict = NULL, double* maxVal = NULL, bool* maxStrict = NULL, + const uint32_t* stopped = NULL) const; + + /// Not implemented + pfed_t& mergeReduce(size_t skip = 0, int level = 0); + + /// Not implemented + bool le(const pfed_t& arg) const; + + /// Not implemented + bool lt(const pfed_t& arg) const; + + /// Not implemented + bool gt(const pfed_t& arg) const; + + /// Not implemented + bool ge(const pfed_t& arg) const; + + /// Not implemented + bool eq(const pfed_t& arg) const; + + + /// Not implemented + pfed_t& unionWith(pfed_t& arg); + + /// Not implemented + int32_t maxOnZero(cindex_t clock); + + /// Not implemented + pfed_t& downStop(const uint32_t* stopped); + + /// Not implemented + bool hasZero() const; + + /// Not implemented + void swap(pfed_t&); + + /// Not implemented + void intern(); + + void nil(); /** @@ -686,10 +755,17 @@ namespace dbm std::ostream& operator<<(std::ostream&, const pfed_t&); - bool cst_iterator::null() { return _M_node == NULL; } + //bool cst_iterator::null() { return _M_node == NULL; } + bool cst_iterator::null() { throw std::logic_error("cst_iterator::null not implemented"); } const raw_t* cst_iterator::operator()() const { return reinterpret_cast(_M_node); } cst_iterator::cst_iterator(std::_List_const_iterator::iterator iterator) {} cst_iterator::cst_iterator() = default; + + iterato::iterato(std::_List_iterator iterator) {} + void iterato::remove() { throw std::logic_error("iterato::remove not implemented"); } + + pfed_t operator|(const pfed_t& a, const pfed_t& b); + } // namespace dbm #endif /* DBM_PFED_H */ diff --git a/src/pfed.cpp b/src/pfed.cpp index 5be5506..0280491 100644 --- a/src/pfed.cpp +++ b/src/pfed.cpp @@ -377,6 +377,10 @@ namespace dbm ptr->zones.push_front(pdbm_t(pdbm, dim)); } + void pfed_t::add(pdbm_t pdbm){ + add(pdbm.operator PDBM(), pdbm.pdim()); + } + void pfed_t::setZero() { PDBM pdbm = nullptr; @@ -423,10 +427,14 @@ namespace dbm return *this; } + inline pfed_t operator|(const pfed_t& a, const pfed_t& b) { return pfed_t(a) |= b; } + bool pfed_t::intersects(const pfed_t&) const { throw std::logic_error("pfed_t::intersects not implemented"); } pfed_t& pfed_t::operator&=(const pfed_t&) { throw std::logic_error("pfed_t::operator &= not implemented"); } + pfed_t& pfed_t::operator&=(const pdbm_t&) { throw std::logic_error("pfed_t::operator &= not implemented"); } + pfed_t pfed_t::operator&(const pfed_t&) const { throw std::logic_error("pfed_t::operator & not implemented"); } pfed_t pfed_t::operator-(const pfed_t&) const { throw std::logic_error("pfed_t::operator - not implemented"); } @@ -513,7 +521,90 @@ namespace dbm throw std::logic_error("pfed_t::toUpperBounds not implemented"); } - inline bool pdbm_t::isEmpty() const { throw std::logic_error("pdbm_t::isEmpty not implemented"); } + bool pfed_t::isConstrainedBy(cindex_t, cindex_t, raw_t) const { + throw std::logic_error("pfed_t::isConstrainedBy not implemented"); + } + bool pfed_t::getDelay(const double* point, cindex_t dim, double* min, double* max, double* minVal, bool* minStrict, + double* maxVal, bool* maxStrict, const uint32_t* stopped) const + { + throw std::logic_error("pfed_t::getDelay not implemented"); + } + + inline bool pdbm_t::isEmpty() const { + throw std::logic_error("pdbm_t::isEmpty not implemented"); + } + + inline pfed_t& pfed_t::mergeReduce(size_t skip, int expensiveTry){ + throw std::logic_error("pfed_t::mergeReduce not implemented"); + } + + inline bool pfed_t::le(const pfed_t& arg) const { + throw std::logic_error("pfed_t::le not implemented"); + } + + inline bool pfed_t::lt(const pfed_t& arg) const { + throw std::logic_error("pfed_t::lt not implemented"); + } + + inline bool pfed_t::gt(const pfed_t& arg) const { + throw std::logic_error("pfed_t::gt not implemented"); + } + + inline bool pfed_t::ge(const pfed_t& arg) const { + throw std::logic_error("pfed_t::ge not implemented"); + } + + inline bool pfed_t::eq(const pfed_t& arg) const { + throw std::logic_error("pfed_t::eq not implemented"); + } + + pfed_t& pfed_t::unionWith(pfed_t& arg){ + throw std::logic_error("pfed_t::unionWith not implemented"); + } + + int32_t pfed_t::maxOnZero(cindex_t x){ + throw std::logic_error("pfed_t::maxOnZero not implemented"); + } + + pfed_t& pfed_t::downStop(const uint32_t* stopped){ + throw std::logic_error("pfed_t::downStop not implemented"); + } + + bool pdbm_t::contains(const int32_t* point, cindex_t dim) const{ + throw std::logic_error("pfed_t::contains not implemented"); + } + + bool pdbm_t::contains(const double* point, cindex_t dim) const{ + throw std::logic_error("pfed_t::contains not implemented"); + } + + bool pfed_t::hasZero() const{ + throw std::logic_error("pfed_t::hasZero not implemented"); + } + + inline void pfed_t::swap(pfed_t& arg){ + throw std::logic_error("pfed_t::swap not implemented"); + } + + bool pfed_t::contains(const int32_t* point, cindex_t dim) const{ + throw std::logic_error("pfed_t::contains not implemented"); + } + + bool pfed_t::contains(const double * point, cindex_t dim) const{ + throw std::logic_error("pfed_t::contains not implemented"); + } + + pfed_t& pfed_t::predt(const pfed_t& bad, const raw_t* restrict){ + throw std::logic_error("pfed_t::predt not implemented"); + } + + void pfed_t::intern(){ + throw std::logic_error("pfed_t::intern not implemented"); + } + + inline void pfed_t::nil() { setDimension(1); } + cindex_t pdbm_t::pdim() const { return dim; } + } // namespace dbm From d81529d9b51348d4e64ce211886efe0321c4dfbd Mon Sep 17 00:00:00 2001 From: Slorup Date: Tue, 1 Nov 2022 10:40:42 +0100 Subject: [PATCH 06/32] Fixed linker errors - It now compiles with latest UPPAAL! --- include/dbm/pfed.h | 81 ++++++++++++++++++++++++++++++---------------- src/pfed.cpp | 54 ++++++++++++++++--------------- 2 files changed, 81 insertions(+), 54 deletions(-) diff --git a/include/dbm/pfed.h b/include/dbm/pfed.h index cd7a471..4ac574a 100644 --- a/include/dbm/pfed.h +++ b/include/dbm/pfed.h @@ -24,22 +24,6 @@ namespace dbm { class pdbm_t; - class cst_iterator : public std::_List_const_iterator{ - - public: - cst_iterator(); - cst_iterator(iterator iterator); - bool null(); - const raw_t* operator()() const; - }; - - class iterato : public std::list::iterator { - - public: - iterato(_List_iterator iterator); - void remove(); - }; - /** * Small C++ wrapper for the PDBM priced DBM type. * @@ -245,9 +229,27 @@ namespace dbm class pfed_t { public: - typedef cst_iterator const_iterator; +// typedef cst_iterator const_iterator; +// typedef iterato iterator; + +// typedef std::_List_const_iterator const_iterator; +// typedef std::list::iterator iterator; - typedef iterato iterator; + class const_iterator : public std::_List_const_iterator{ + + public: + const_iterator(); + const_iterator(iterator iterator); + bool null(); + const raw_t* operator()() const; + }; + + class iterator : public std::list::iterator { + + public: + iterator(_List_iterator iterator); + void remove(); + }; protected: struct pfed_s @@ -411,6 +413,8 @@ namespace dbm void incrementCost(int32_t value); int32_t getCostOfValuation(const IntValuation& valuation) const; + + void relax(); void freeClock(cindex_t clock); @@ -600,7 +604,6 @@ namespace dbm void nil(); - /** * Relation between two priced federations: SUBSET is returned * if all zones of this federation are contained in some zone @@ -702,6 +705,8 @@ namespace dbm } } + + inline pfed_t::iterator pfed_t::beginMutable() { prepare(); @@ -718,6 +723,35 @@ namespace dbm inline pfed_t::const_iterator pfed_t::end() const { return ptr->zones.end(); } + + inline bool pfed_t::const_iterator::null() { throw std::logic_error("const_iterator::null() not implemented"); } + + inline const raw_t* pfed_t::const_iterator::operator()() const { throw std::logic_error("const_iterator::operator()() not implemented"); } + + inline pfed_t::const_iterator::const_iterator() { throw std::logic_error("const_iterator constructor not implemented"); } + inline pfed_t::const_iterator::const_iterator(std::_List_const_iterator::iterator iterator) { throw std::logic_error("const_iterator constructor not implemented"); } + + inline void pfed_t::iterator::remove() { throw std::logic_error("iterator::remove() not implemented"); } + inline pfed_t::iterator::iterator(std::_List_iterator iterator) {throw std::logic_error("iterator constructor not implemented");} + + inline pfed_t::iterator pfed_t::erase(iterator i) { + assert(ptr->count <= 1); + return ptr->zones.erase(i); + } + + // //bool cst_iterator::null() { return _M_node == NULL; } +// bool pfed_t::const_iterator::null() { throw std::logic_error("cst_iterator::null not implemented"); } +// +// const raw_t* pfed_t::const_iterator::operator()() const { return reinterpret_cast(_M_node); } +// +// pfed_t::const_iterator::cst_iterator(std::_List_const_iterator::iterator iterator) {} +// +// pfed_t::const_iterator::cst_iterator() = default; +// +// pfed_t::iterator::iterato(std::_List_iterator iterator) {} +// +// void pfed_t::iterator::remove() { throw std::logic_error("iterato::remove not implemented"); } + inline cindex_t pfed_t::getDimension() const { return ptr->dim; } inline size_t pfed_t::size() const { return ptr->zones.size(); } @@ -755,15 +789,6 @@ namespace dbm std::ostream& operator<<(std::ostream&, const pfed_t&); - //bool cst_iterator::null() { return _M_node == NULL; } - bool cst_iterator::null() { throw std::logic_error("cst_iterator::null not implemented"); } - const raw_t* cst_iterator::operator()() const { return reinterpret_cast(_M_node); } - cst_iterator::cst_iterator(std::_List_const_iterator::iterator iterator) {} - cst_iterator::cst_iterator() = default; - - iterato::iterato(std::_List_iterator iterator) {} - void iterato::remove() { throw std::logic_error("iterato::remove not implemented"); } - pfed_t operator|(const pfed_t& a, const pfed_t& b); } // namespace dbm diff --git a/src/pfed.cpp b/src/pfed.cpp index 0280491..1f450e5 100644 --- a/src/pfed.cpp +++ b/src/pfed.cpp @@ -70,12 +70,6 @@ namespace dbm add(pdbm, dim); } - pfed_t::iterator pfed_t::erase(iterator i) - { - assert(ptr->count <= 1); - return ptr->zones.erase(i); - } - #define for_each__(Z) for (iterator Z = beginMutable(), Z_ = endMutable(); Z != Z_; zone++) #define for_each_(Z) for (iterator Z = beginMutable(), Z_ = endMutable(); Z != Z_;) #define for_each_const(Z) for (const_iterator Z = begin(), Z_ = end(); Z != Z_; zone++) @@ -395,6 +389,11 @@ namespace dbm *this = pfed_t(pdbm, ptr->dim); } + void pfed_t::nil() + { + setDimension(1); + } + void pfed_t::setEmpty() { *this = pfed_t(ptr->dim); } void pfed_t::freeUp(cindex_t i) { for_each(beginMutable(), endMutable(), bind(pdbm_freeUp, _1, ptr->dim, i)); } @@ -427,7 +426,7 @@ namespace dbm return *this; } - inline pfed_t operator|(const pfed_t& a, const pfed_t& b) { return pfed_t(a) |= b; } + pfed_t operator|(const pfed_t& a, const pfed_t& b) { return pfed_t(a) |= b; } bool pfed_t::intersects(const pfed_t&) const { throw std::logic_error("pfed_t::intersects not implemented"); } @@ -474,12 +473,17 @@ namespace dbm std::ostream& operator<<(std::ostream& o, const pfed_t& f) { - pfed_t::const_iterator first = f.begin(); - pfed_t::const_iterator last = f.end(); - while (first != last) { - pdbm_print(o, *first, f.getDimension()); - first++; + + for (pfed_t::const_iterator first = f.begin(), end = f.end(); first != end; first++){ + } + +// pfed_t::const_iterator first = f.begin(); +// pfed_t::const_iterator last = f.end(); +// while (first != last) { +// pdbm_print(o, *first, f.getDimension()); +// first++; +// } return o; } @@ -530,31 +534,27 @@ namespace dbm throw std::logic_error("pfed_t::getDelay not implemented"); } - inline bool pdbm_t::isEmpty() const { + bool pdbm_t::isEmpty() const { throw std::logic_error("pdbm_t::isEmpty not implemented"); } - inline pfed_t& pfed_t::mergeReduce(size_t skip, int expensiveTry){ - throw std::logic_error("pfed_t::mergeReduce not implemented"); - } - - inline bool pfed_t::le(const pfed_t& arg) const { + bool pfed_t::le(const pfed_t& arg) const { throw std::logic_error("pfed_t::le not implemented"); } - inline bool pfed_t::lt(const pfed_t& arg) const { + bool pfed_t::lt(const pfed_t& arg) const { throw std::logic_error("pfed_t::lt not implemented"); } - inline bool pfed_t::gt(const pfed_t& arg) const { + bool pfed_t::gt(const pfed_t& arg) const { throw std::logic_error("pfed_t::gt not implemented"); } - inline bool pfed_t::ge(const pfed_t& arg) const { + bool pfed_t::ge(const pfed_t& arg) const { throw std::logic_error("pfed_t::ge not implemented"); } - inline bool pfed_t::eq(const pfed_t& arg) const { + bool pfed_t::eq(const pfed_t& arg) const { throw std::logic_error("pfed_t::eq not implemented"); } @@ -582,7 +582,7 @@ namespace dbm throw std::logic_error("pfed_t::hasZero not implemented"); } - inline void pfed_t::swap(pfed_t& arg){ + void pfed_t::swap(pfed_t& arg){ throw std::logic_error("pfed_t::swap not implemented"); } @@ -602,9 +602,11 @@ namespace dbm throw std::logic_error("pfed_t::intern not implemented"); } - - inline void pfed_t::nil() { setDimension(1); } + pfed_t& pfed_t::mergeReduce(size_t skip, int expensiveTry){ + throw std::logic_error("pfed_t::mergeReduce not implemented"); + } cindex_t pdbm_t::pdim() const { return dim; } - + + } // namespace dbm From 34743459847112417e4f21a50f184b5f12738d08 Mon Sep 17 00:00:00 2001 From: Ragusaen Date: Fri, 4 Nov 2022 10:21:02 +0100 Subject: [PATCH 07/32] Fixed iterators --- include/dbm/pfed.h | 336 ++++++++++++++++++++++++++++++++++++++------- src/pfed.cpp | 42 ++---- 2 files changed, 299 insertions(+), 79 deletions(-) diff --git a/include/dbm/pfed.h b/include/dbm/pfed.h index 4ac574a..34be9e4 100644 --- a/include/dbm/pfed.h +++ b/include/dbm/pfed.h @@ -229,26 +229,108 @@ namespace dbm class pfed_t { public: -// typedef cst_iterator const_iterator; -// typedef iterato iterator; +// +// typedef std::list::const_iterator const_list_iterator; +// typedef std::list::iterator list_iterator; + + /// Mutable iterator -> iterate though dbm_t + class iterator + { + public: + iterator(); + /// Initialize the iterator of a federation. + /// @param _pfed: federation. + explicit iterator(pfed_t* _pfed); + + iterator& end(); + + /// Dereference to dbm_t, @pre !null() + pdbm_t& operator*() const; + + /// Dereference to dbm_t*, @pre !null() + pdbm_t* operator->() const; + + /// Mutable access to the matrix as for fed_t, @pre !null() + raw_t* operator()() const; + raw_t operator()(cindex_t i, cindex_t j) const; + + /// Increment iterator, @pre !null() + iterator& operator++(); -// typedef std::_List_const_iterator const_iterator; -// typedef std::list::iterator iterator; + // Post increment iterator + const iterator operator++(int); - class const_iterator : public std::_List_const_iterator{ + /// Test if there are DBMs left on the list. + bool null() const; + /// @return true if there is another DBM after, @pre !null() + bool hasNext() const; + + /// Equality test of the internal fdbm_t* + bool operator==(const iterator& arg) const; + bool operator!=(const iterator& arg) const; + + /// Remove (and deallocate) current dbm_t. + void remove(); + + /// Remove (and deallocate) current empty dbm_t. + void removeEmpty(); + + /// Extract the current DBM from the list. + /// The result->getNext() points to the rest of the list. + pfed_t::iterator extract(); + + /// Insert a DBM in the list at the current position. + void insert(pdbm_t& pdbm); + + private: + std::list* zones; /// list of DBMs + std::list::iterator it; + pfed_t* pfed; /// to update the size + }; + + /// Const iterator -> iterate though dbm_t + class const_iterator + { public: const_iterator(); - const_iterator(iterator iterator); - bool null(); + + /// Constructor: @param fed: federation. + explicit const_iterator(const pfed_t* pfed); + + // Move iterator to end + const_iterator& end(); + + /// Dereference to dbm_t + const pdbm_t& operator*() const; + + /// Dereference to dbm_t*, @pre !null() + const pdbm_t* operator->() const; + + /// Access to the matrix as for fed_t const raw_t* operator()() const; - }; + raw_t operator()(cindex_t i, cindex_t j) const; - class iterator : public std::list::iterator { + /// Increment iterator, @pre !null() + const_iterator& operator++(); - public: - iterator(_List_iterator iterator); - void remove(); + /// Post increment iterator + const const_iterator operator++(int); + + /// Test if there are DBMs left on the list. + bool null() const; + + /// @return true if there is another DBM after, @pre !null() + bool hasNext() const; + + /// Equality test of the internal fdbm_t* + bool operator==(const const_iterator& arg) const; + bool operator!=(const const_iterator& arg) const; + + private: + const std::list* zones; /// list of DBMs + std::list::const_iterator it; + const pfed_t* pfed; /// to update the size }; protected: @@ -277,8 +359,10 @@ namespace dbm void cow(); public: - /** Allocate empty priced federation of dimension 0. */ - pfed_t(); + /// Initialize a pfed_t to empty federation of a given dimension. + /// @param dim: dimension of the federation. + /// @post isEmpty() + explicit pfed_t(cindex_t dim = 1); /** * Adds \a pdbm to the federation. The reference count on pdbm @@ -288,9 +372,6 @@ namespace dbm void add(pdbm_t pdbm); - /** Allocate empty priced federation of dimension \a dim. */ - explicit pfed_t(cindex_t dim); - /** * Allocate a priced federation of dimension \a dim initialised to * \a pdbm. @@ -461,7 +542,7 @@ namespace dbm * Erases a DBM from the federation and returns an iterator to * the successor element. */ - iterator erase(iterator); + iterator erase(iterator& iter); /** Assignment operator. */ pfed_t& operator=(const pfed_t&); @@ -710,47 +791,18 @@ namespace dbm inline pfed_t::iterator pfed_t::beginMutable() { prepare(); - return ptr->zones.begin(); + return iterator(this); } inline pfed_t::iterator pfed_t::endMutable() { prepare(); - return ptr->zones.end(); + return iterator(this).end(); } - inline pfed_t::const_iterator pfed_t::begin() const { return ptr->zones.begin(); } - - inline pfed_t::const_iterator pfed_t::end() const { return ptr->zones.end(); } + inline pfed_t::const_iterator pfed_t::begin() const { return const_iterator(this); } - - inline bool pfed_t::const_iterator::null() { throw std::logic_error("const_iterator::null() not implemented"); } - - inline const raw_t* pfed_t::const_iterator::operator()() const { throw std::logic_error("const_iterator::operator()() not implemented"); } - - inline pfed_t::const_iterator::const_iterator() { throw std::logic_error("const_iterator constructor not implemented"); } - inline pfed_t::const_iterator::const_iterator(std::_List_const_iterator::iterator iterator) { throw std::logic_error("const_iterator constructor not implemented"); } - - inline void pfed_t::iterator::remove() { throw std::logic_error("iterator::remove() not implemented"); } - inline pfed_t::iterator::iterator(std::_List_iterator iterator) {throw std::logic_error("iterator constructor not implemented");} - - inline pfed_t::iterator pfed_t::erase(iterator i) { - assert(ptr->count <= 1); - return ptr->zones.erase(i); - } - - // //bool cst_iterator::null() { return _M_node == NULL; } -// bool pfed_t::const_iterator::null() { throw std::logic_error("cst_iterator::null not implemented"); } -// -// const raw_t* pfed_t::const_iterator::operator()() const { return reinterpret_cast(_M_node); } -// -// pfed_t::const_iterator::cst_iterator(std::_List_const_iterator::iterator iterator) {} -// -// pfed_t::const_iterator::cst_iterator() = default; -// -// pfed_t::iterator::iterato(std::_List_iterator iterator) {} -// -// void pfed_t::iterator::remove() { throw std::logic_error("iterato::remove not implemented"); } + inline pfed_t::const_iterator pfed_t::end() const { return const_iterator(this).end(); } inline cindex_t pfed_t::getDimension() const { return ptr->dim; } @@ -791,6 +843,188 @@ namespace dbm pfed_t operator|(const pfed_t& a, const pfed_t& b); + /*********************************************** + * Inlined implementations of pfed_t::iterator * + ***********************************************/ + + inline pfed_t::iterator::iterator(pfed_t* _pfed): zones(&_pfed->ptr->zones), it(_pfed->ptr->zones.begin()), pfed(_pfed) { + assert(_pfed); + } + + inline pfed_t::iterator::iterator(): zones(nullptr), pfed(nullptr) {} + + inline pdbm_t& pfed_t::iterator::operator*() const + { + assert(pfed && zones); + return *it; + } + + inline pdbm_t* pfed_t::iterator::operator->() const + { + assert(pfed && zones); + return &*it; + } + + inline raw_t* pfed_t::iterator::operator()() const + { + assert(pfed && zones); + return it->getDBM(); + } + + inline raw_t pfed_t::iterator::operator()(cindex_t i, cindex_t j) const + { + assert(pfed && zones); + return (*it)(i, j); + } + + inline pfed_t::iterator& pfed_t::iterator::operator++() + { + assert(pfed && zones); + ++it; + return *this; + } + + inline const pfed_t::iterator pfed_t::iterator::operator++(int) + { + assert(pfed && zones); + auto before = iterator(*this); + ++it; + return before; + } + + inline bool pfed_t::iterator::null() const + { + return pfed != nullptr && zones != nullptr && it != zones->end(); + } + + inline bool pfed_t::iterator::hasNext() const + { + assert(pfed && zones); + return it != zones->end(); + } + + inline bool pfed_t::iterator::operator==(const iterator& arg) const + { + assert(pfed && zones); + return it == arg.it; + } + + inline bool pfed_t::iterator::operator!=(const iterator& arg) const { return !(*this == arg); } + + inline void pfed_t::iterator::remove() + { + assert(pfed && zones); + zones->erase(it); + } + + inline void pfed_t::iterator::removeEmpty() + { + // assert(fdbm && *fdbm); + // *fdbm = (*fdbm)->removeEmptyAndNext(); + // ifed->decSize(); + throw std::logic_error("pfed_t::iterator::removeEmpty not implemented"); + } + + inline pfed_t::iterator pfed_t::iterator::extract() + { + // assert(fdbm && *fdbm); + // fpdbm_t* current = *fdbm; + // *fdbm = current->getNext(); + // ifed->decSize(); + // return current; + throw std::logic_error("pfed_t::iterator::extract not implemented"); + } + + inline void pfed_t::iterator::insert(pdbm_t& pdbm) + { + assert(pfed->getDimension() == pdbm.getDimension()); + pfed->prepare(); + it = zones->insert(it, pdbm); + } + + inline pfed_t::iterator& pfed_t::iterator::end() { + assert(pfed && zones); + it = zones->end(); + return *this; + } + + inline pfed_t::iterator pfed_t::erase(iterator& iter) + { + iter.remove(); + return iter; + } + + /***************************************************** + * Inlined implementations of pfed_t::const_iterator * + *****************************************************/ + + inline pfed_t::const_iterator::const_iterator(const pfed_t* _pfed) : zones(&_pfed->ptr->zones), it(_pfed->ptr->zones.begin()), pfed(_pfed) { + assert(_pfed && zones); + } + + inline pfed_t::const_iterator::const_iterator(): zones(nullptr), pfed(nullptr) {} + + inline const pdbm_t& pfed_t::const_iterator::operator*() const + { + assert(pfed && zones); + return *it; + } + + inline const pdbm_t* pfed_t::const_iterator::operator->() const + { + assert(pfed && zones); + return &*it; + } + + inline const raw_t* pfed_t::const_iterator::operator()() const + { + assert(pfed && zones); + return it->const_dbm(); + } + + inline raw_t pfed_t::const_iterator::operator()(cindex_t i, cindex_t j) const + { + assert(pfed && zones); + return (*it)(i, j); + } + + inline pfed_t::const_iterator& pfed_t::const_iterator::operator++() + { + assert(pfed && zones); + ++it; + return *this; + } + + inline const pfed_t::const_iterator pfed_t::const_iterator::operator++(int) + { + assert(pfed && zones); + auto before = const_iterator(*this); + ++it; + return before; + } + + inline bool pfed_t::const_iterator::null() const + { + return zones != nullptr && it != zones->end(); + } + + inline bool pfed_t::const_iterator::hasNext() const + { + assert(pfed && zones); + return it != zones->end(); + } + + inline bool pfed_t::const_iterator::operator==(const const_iterator& arg) const { return it == arg.it; } + + inline bool pfed_t::const_iterator::operator!=(const const_iterator& arg) const { return !(*this == arg); } + + inline pfed_t::const_iterator& pfed_t::const_iterator::end() + { + assert(pfed && zones); + it = zones->end(); + return *this; + } + } // namespace dbm #endif /* DBM_PFED_H */ diff --git a/src/pfed.cpp b/src/pfed.cpp index 1f450e5..b406191 100644 --- a/src/pfed.cpp +++ b/src/pfed.cpp @@ -45,14 +45,6 @@ namespace dbm ptr->count = 1; } - pfed_t::pfed_t() - { - ptr = alloc.allocate(1); - alloc.construct(ptr, pfed_s()); - ptr->dim = 0; - ptr->count = 1; - } - pfed_t::pfed_t(cindex_t dim) { ptr = alloc.allocate(1); @@ -124,10 +116,10 @@ namespace dbm bool pfed_t::satisfies(cindex_t i, cindex_t j, raw_t constraint) const { - return find_if(begin(), end(), bind(pdbm_satisfies, _1, ptr->dim, i, j, constraint)) != end(); + return find_if(ptr->zones.begin(), ptr->zones.end(), bind(pdbm_satisfies, _1, ptr->dim, i, j, constraint)) != ptr->zones.end(); } - bool pfed_t::isUnbounded() const { return find_if(begin(), end(), bind(pdbm_isUnbounded, _1, ptr->dim)) != end(); } + bool pfed_t::isUnbounded() const { return find_if(ptr->zones.begin(), ptr->zones.end(), bind(pdbm_isUnbounded, _1, ptr->dim)) != ptr->zones.end(); } uint32_t pfed_t::hash(uint32_t seed) const { @@ -139,17 +131,17 @@ namespace dbm bool pfed_t::contains(const IntValuation& valuation) const { - return find_if(begin(), end(), bind(pdbm_containsInt, _1, ptr->dim, valuation())) != end(); + return find_if(ptr->zones.begin(), ptr->zones.end(), bind(pdbm_containsInt, _1, ptr->dim, valuation())) != ptr->zones.end(); } bool pfed_t::contains(const DoubleValuation& valuation) const { - return find_if(begin(), end(), bind(pdbm_containsDouble, _1, ptr->dim, valuation())) != end(); + return find_if(ptr->zones.begin(), ptr->zones.end(), bind(pdbm_containsDouble, _1, ptr->dim, valuation())) != ptr->zones.end(); } bool pfed_t::containsWeakly(const IntValuation& valuation) const { - return find_if(begin(), end(), bind(pdbm_containsIntWeakly, _1, ptr->dim, valuation())) != end(); + return find_if(ptr->zones.begin(), ptr->zones.end(), bind(pdbm_containsIntWeakly, _1, ptr->dim, valuation())) != ptr->zones.end(); } relation_t pfed_t::relation(const pfed_t& b) const @@ -410,12 +402,12 @@ namespace dbm return *this; } - pfed_t& pfed_t::operator|=(const pfed_t& fed) + pfed_t& pfed_t::operator|=(const pfed_t& pfed) { // REVISIT: Eliminate included zones. - assert(fed.ptr->dim == ptr->dim); + assert(pfed.ptr->dim == ptr->dim); prepare(); - ptr->zones.insert(ptr->zones.begin(), fed.begin(), fed.end()); + ptr->zones.insert(ptr->zones.begin(), pfed.ptr->zones.begin(), pfed.ptr->zones.end()); return *this; } @@ -473,17 +465,12 @@ namespace dbm std::ostream& operator<<(std::ostream& o, const pfed_t& f) { - - for (pfed_t::const_iterator first = f.begin(), end = f.end(); first != end; first++){ - + pfed_t::const_iterator first = f.begin(); + pfed_t::const_iterator last = f.end(); + while (first != last) { + pdbm_print(o, *first, f.getDimension()); + ++first; } - -// pfed_t::const_iterator first = f.begin(); -// pfed_t::const_iterator last = f.end(); -// while (first != last) { -// pdbm_print(o, *first, f.getDimension()); -// first++; -// } return o; } @@ -607,6 +594,5 @@ namespace dbm } cindex_t pdbm_t::pdim() const { return dim; } - - } // namespace dbm + From 6ed33e482935ce7ee002739073d8f59944806877 Mon Sep 17 00:00:00 2001 From: Ragusaen Date: Fri, 4 Nov 2022 16:02:44 +0100 Subject: [PATCH 08/32] Fixed gigantic delay bug --- include/dbm/pfed.h | 11 +++++++++-- src/pfed.cpp | 27 ++++++++++++++++++++++++--- 2 files changed, 33 insertions(+), 5 deletions(-) diff --git a/include/dbm/pfed.h b/include/dbm/pfed.h index 34be9e4..bc790ff 100644 --- a/include/dbm/pfed.h +++ b/include/dbm/pfed.h @@ -138,6 +138,13 @@ namespace dbm /** @see dbm_t::readFromMinDBM() */ static pdbm_t readFromMinDBM(cindex_t dimension, const int32_t*); + + /// @return string representation of the + /// constraints of this PDBM. A clock + /// is always positive, so "true" simply means + /// all clocks positive. + std::string toString(const ClockAccessor&, bool full = false) const; + /// @return true if it is empty. bool isEmpty() const; @@ -894,7 +901,7 @@ namespace dbm inline bool pfed_t::iterator::null() const { - return pfed != nullptr && zones != nullptr && it != zones->end(); + return pfed == nullptr || zones == nullptr || it == zones->end(); } inline bool pfed_t::iterator::hasNext() const @@ -1005,7 +1012,7 @@ namespace dbm inline bool pfed_t::const_iterator::null() const { - return zones != nullptr && it != zones->end(); + return pfed == nullptr || zones == nullptr || it == zones->end(); } inline bool pfed_t::const_iterator::hasNext() const diff --git a/src/pfed.cpp b/src/pfed.cpp index b406191..6f9b91f 100644 --- a/src/pfed.cpp +++ b/src/pfed.cpp @@ -223,6 +223,8 @@ namespace dbm cindex_t x; int32_t oldrate = pdbm_getSlopeOfDelayTrajectory(*zone, dim); + pdbm_print(std::cout, zone->operator PDBM(), dim); + if (rate == oldrate) { /* This is a simple case which does not require splits. */ @@ -259,8 +261,8 @@ namespace dbm pdbm_constrainToFacet(ptr->zones.front(), dim, facets[j], 0); pdbm_upZero(ptr->zones.front(), dim, rate, facets[j]); } - pdbm_constrainToFacet(*zone, dim, facets[count - 1], 0); - pdbm_upZero(*zone, dim, rate, facets[count - 1]); +// pdbm_constrainToFacet(*zone, dim, facets[count - 1], 0); +// pdbm_upZero(*zone, dim, rate, facets[count - 1]); } } return *this; @@ -485,7 +487,19 @@ namespace dbm } std::string pfed_t::toString(const ClockAccessor& access, bool full) const{ - throw std::logic_error("pfed_t::getMaxLower not implemented"); + if (isEmpty()) { + return "false"; + } + std::string str; + bool isFirst = true; + for (const_iterator i = begin(); !i.null(); ++i) { + if (!isFirst) { + str += " || "; + } + str += i->toString(access, full); + isFirst = false; + } + return str; } void pfed_t::updateClock(cindex_t x, cindex_t y){ @@ -565,6 +579,13 @@ namespace dbm throw std::logic_error("pfed_t::contains not implemented"); } + std::string pdbm_t::toString(const ClockAccessor&, bool full) const + { + std::stringstream ss; + pdbm_print(ss, *this, dim); + return ss.str(); + } + bool pfed_t::hasZero() const{ throw std::logic_error("pfed_t::hasZero not implemented"); } From ce9dda7b947090c94fe2fd4eb7fd2393ed3707c6 Mon Sep 17 00:00:00 2001 From: Ragusaen Date: Tue, 29 Nov 2022 16:05:03 +0100 Subject: [PATCH 09/32] ??? --- include/dbm/fed.h | 3 ++ include/dbm/inline_fed.h | 6 +++ include/dbm/pfed.h | 19 ++++++--- src/fed.cpp | 16 ++++++++ src/pfed.cpp | 88 +++++++++++++++++++++++++++++++++------- 5 files changed, 113 insertions(+), 19 deletions(-) diff --git a/include/dbm/fed.h b/include/dbm/fed.h index ac2d7aa..9f9313c 100644 --- a/include/dbm/fed.h +++ b/include/dbm/fed.h @@ -955,6 +955,9 @@ namespace dbm fed_t& unionWith(fed_t& arg); fed_t& unionWithC(fed_t arg); // dummy wrapper + // Performs unionWith operation and returns whether the fed changed + bool unionWithChanged(const fed_t& arg); + /// Simply add (list concatenation) DBMs to this federation. /// @pre same dimension. diff --git a/include/dbm/inline_fed.h b/include/dbm/inline_fed.h index d164c71..5004393 100644 --- a/include/dbm/inline_fed.h +++ b/include/dbm/inline_fed.h @@ -512,6 +512,12 @@ namespace dbm return *this; } + bool unionWithChanged(dbmlist_t& arg) { + removeIncluded(arg); + append(arg); + return arg.size() > 0; + } + /// Simple reduction by inclusion check of DBMs. void reduce(cindex_t dim); diff --git a/include/dbm/pfed.h b/include/dbm/pfed.h index bc790ff..0bd39ee 100644 --- a/include/dbm/pfed.h +++ b/include/dbm/pfed.h @@ -290,6 +290,8 @@ namespace dbm /// Insert a DBM in the list at the current position. void insert(pdbm_t& pdbm); + const std::list::iterator& getInternalIterator() { return it; }; + private: std::list* zones; /// list of DBMs std::list::iterator it; @@ -318,6 +320,8 @@ namespace dbm const raw_t* operator()() const; raw_t operator()(cindex_t i, cindex_t j) const; + // New iterator at end + /// Increment iterator, @pre !null() const_iterator& operator++(); @@ -334,6 +338,8 @@ namespace dbm bool operator==(const const_iterator& arg) const; bool operator!=(const const_iterator& arg) const; + const std::list::const_iterator& getInternalIterator() { return it; }; + private: const std::list* zones; /// list of DBMs std::list::const_iterator it; @@ -624,7 +630,9 @@ namespace dbm */ raw_t getMaxLower(cindex_t) const; - /// Not implemented + /* + * Prints string + */ std::string toString(const ClockAccessor&, bool full = false) const; /// Not implemented @@ -672,8 +680,10 @@ namespace dbm bool eq(const pfed_t& arg) const; - /// Not implemented - pfed_t& unionWith(pfed_t& arg); + /* + * Non-exact union. Keeps all zones that are not subseteq of another zone. Returns true if the zones changed. + */ + bool unionWith(pfed_t& arg); /// Not implemented int32_t maxOnZero(cindex_t clock); @@ -921,7 +931,7 @@ namespace dbm inline void pfed_t::iterator::remove() { assert(pfed && zones); - zones->erase(it); + it = zones->erase(it); } inline void pfed_t::iterator::removeEmpty() @@ -1031,7 +1041,6 @@ namespace dbm it = zones->end(); return *this; } - } // namespace dbm #endif /* DBM_PFED_H */ diff --git a/src/fed.cpp b/src/fed.cpp index 271ce2a..7239644 100644 --- a/src/fed.cpp +++ b/src/fed.cpp @@ -1374,6 +1374,22 @@ namespace dbm return *this; } + bool fed_t::unionWithChanged(const fed_t& arg) { + assert(getDimension() == arg.getDimension()); + assert(isOK()); + assert(arg.isOK()); + + if (!arg.isEmpty()) { + setMutable(); + auto copy = fed_t(arg); + copy.setMutable(); + bool changed = ifed()->unionWithChanged(*copy.ifed()); + copy.ifed()->reset(); + return changed; + } + return false; + } + fed_t& fed_t::append(fed_t& arg) { assert(getDimension() == arg.getDimension()); diff --git a/src/pfed.cpp b/src/pfed.cpp index 6f9b91f..5f34fd4 100644 --- a/src/pfed.cpp +++ b/src/pfed.cpp @@ -223,7 +223,7 @@ namespace dbm cindex_t x; int32_t oldrate = pdbm_getSlopeOfDelayTrajectory(*zone, dim); - pdbm_print(std::cout, zone->operator PDBM(), dim); +// pdbm_print(std::cout, zone->operator PDBM(), dim); if (rate == oldrate) { /* This is a simple case which does not require splits. @@ -487,19 +487,54 @@ namespace dbm } std::string pfed_t::toString(const ClockAccessor& access, bool full) const{ - if (isEmpty()) { - return "false"; - } - std::string str; - bool isFirst = true; - for (const_iterator i = begin(); !i.null(); ++i) { - if (!isFirst) { - str += " || "; + bool dbmprinted = false; + bool brackets = size() > 1; + uint32_t size = getDimension(); + std::stringstream out; + for (auto z = begin(); z != end(); ++z) { + bool oneprinted = false; + if (dbmprinted) { + out << " or "; + } + if (brackets) { + out << "("; + } + for (uint32_t i = 0; i < size; i++) { + for (uint32_t j = 0; j < size; j++) { + raw_t raw = z(i, j); + bool strict = dbm_rawIsStrict(raw); + int32_t bound = dbm_raw2bound(raw); + if (raw < dbm_LS_INFINITY) { + if (i != 0u) { + if (i != j) { + out << (oneprinted ? ", " : "") << access.getClockName(i); + if (j > 0) { + out << "-" << access.getClockName(j); + } + out << (strict ? "<" : "<=") << bound; + oneprinted = true; + } + } else if ((j != 0u) && ((bound != 0) || strict)) { + // print for i==0,j!=0,bound!=0 + out << (oneprinted ? ", " : "") << access.getClockName(j) << (strict ? ">" : ">=") + << -bound; + oneprinted = true; + } + } + } + } + oneprinted = false; + out << " :"; + for (uint32_t i = 1; i < size; ++i) { + out << (oneprinted? ",": "") << " r(" << access.getClockName(i) << ") = " << pdbm_getRate(z->operator PDBM(), size, i); + oneprinted = true; } - str += i->toString(access, full); - isFirst = false; + if (brackets) { + out << ")"; + } + dbmprinted = true; } - return str; + return out.str(); } void pfed_t::updateClock(cindex_t x, cindex_t y){ @@ -559,8 +594,33 @@ namespace dbm throw std::logic_error("pfed_t::eq not implemented"); } - pfed_t& pfed_t::unionWith(pfed_t& arg){ - throw std::logic_error("pfed_t::unionWith not implemented"); + bool pfed_t::unionWith(pfed_t& other) { + assert(ptr->dim == other.ptr->dim); + bool changed = false; + + for (auto ot = other.beginMutable(); ot != other.endMutable(); ++ot) { + bool maybe_insert = true; + bool definitely_insert = false; + for (auto it = beginMutable(); it != endMutable();) { + switch (pdbm_relation(*ot, *it, ptr->dim)) { + case base_SUPERSET: + it.remove(); + definitely_insert = true; + break; + case base_SUBSET: + case base_EQUAL: + maybe_insert = false; + case base_DIFFERENT: + ++it; + break; + } + } + if (definitely_insert || maybe_insert) { + add(*ot); + changed = true; + } + } + return changed; } int32_t pfed_t::maxOnZero(cindex_t x){ From 0f6fbb2f3c44a47c59261621be20f47a2569742c Mon Sep 17 00:00:00 2001 From: Slorup Date: Mon, 13 Mar 2023 13:56:10 +0100 Subject: [PATCH 10/32] Added pfed equals operator and resize function --- include/dbm/pfed.h | 14 ++++++++++++++ src/pfed.cpp | 4 ++++ 2 files changed, 18 insertions(+) diff --git a/include/dbm/pfed.h b/include/dbm/pfed.h index 0bd39ee..4abd984 100644 --- a/include/dbm/pfed.h +++ b/include/dbm/pfed.h @@ -584,6 +584,9 @@ namespace dbm /** Not implemented. */ bool intersects(const pfed_t&) const; + /** Equals Operator */ + bool operator==(const pfed_t&) const; + /** Not implemented. */ pfed_t operator&(const pfed_t& b) const; @@ -593,6 +596,17 @@ namespace dbm /** Not implemented. */ pfed_t& down(); + /** Resize all the DBMs of this federation, @see dbm_t. + * @see dbm_shrinkExpand in dbm.h. + * @param bitSrc,bitDst,bitSize: bit strings of (int) size bitSize + * that mark the source and destination active clocks. + * @param table: redirection table to write. + * @pre bitSrc & bitDst are uint32_t[bitSize] and + * table is a uint32_t[32*bitSize] + * @post the indirection table is written. + */ + void resize(const uint32_t* bitSrc, const uint32_t* bitDst, size_t bitSize, cindex_t* table); + /** Not implemented. */ int32_t getUpperMinimumCost(cindex_t) const; diff --git a/src/pfed.cpp b/src/pfed.cpp index 5f34fd4..e35ab32 100644 --- a/src/pfed.cpp +++ b/src/pfed.cpp @@ -438,6 +438,10 @@ namespace dbm pfed_t& pfed_t::down() { throw std::logic_error("pfed_t::down not implemented"); } + void pfed_t::resize(const uint32_t* bitSrc, const uint32_t* bitDst, size_t bitSize, cindex_t* table) { throw std::logic_error("pfed_t::resize not implemented"); } + + bool pfed_t::operator==(const pfed_t& arg) const { return relation(arg) == base_EQUAL; } + int32_t pfed_t::getUpperMinimumCost(cindex_t) const { throw std::logic_error("pfed_t::getUpperMinimumCost not implemented"); From e6175a6e326cf70ad5ec4b0d778710d876e9e953 Mon Sep 17 00:00:00 2001 From: Slorup Date: Mon, 13 Mar 2023 15:15:41 +0100 Subject: [PATCH 11/32] Changed cost of priced zone functions to be int instead of uint --- include/dbm/priced.h | 2 +- src/priced.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/dbm/priced.h b/include/dbm/priced.h index 40d0b5d..7cff551 100644 --- a/include/dbm/priced.h +++ b/include/dbm/priced.h @@ -591,7 +591,7 @@ const int32_t* pdbm_getRates(const PDBM pdbm, cindex_t dim); * @param pdbm is a closed priced DBM of dimension \a dim. * @param dim is the dimension of \a pdbm. */ -uint32_t pdbm_getCostAtOffset(const PDBM pdbm, cindex_t dim); +int32_t pdbm_getCostAtOffset(const PDBM pdbm, cindex_t dim); /** * Sets the cost at the offset point. diff --git a/src/priced.cpp b/src/priced.cpp index 0fabd9d..67161c4 100644 --- a/src/priced.cpp +++ b/src/priced.cpp @@ -970,7 +970,7 @@ int32_t pdbm_getRate(const PDBM pdbm, cindex_t dim, cindex_t clock) return pdbm_rates(pdbm)[clock]; } -uint32_t pdbm_getCostAtOffset(const PDBM pdbm, cindex_t dim) +int32_t pdbm_getCostAtOffset(const PDBM pdbm, cindex_t dim) { assert(pdbm && dim); From 2eabfd08656e3b2a93d40c19f9057e0f9b7a15aa Mon Sep 17 00:00:00 2001 From: Slorup Date: Tue, 14 Mar 2023 09:39:41 +0100 Subject: [PATCH 12/32] Add strict/nonstrict cost comparison function to priced --- include/dbm/priced.h | 12 +++++++++ src/priced.cpp | 59 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 71 insertions(+) diff --git a/include/dbm/priced.h b/include/dbm/priced.h index 7cff551..bfc58f9 100644 --- a/include/dbm/priced.h +++ b/include/dbm/priced.h @@ -245,6 +245,18 @@ bool pdbm_constrainToFacet(PDBM& pdbm, cindex_t dim, cindex_t i, cindex_t j); */ relation_t pdbm_relation(const PDBM pdbm1, const PDBM pdbm2, cindex_t dim); +/* + * Compares the costs of two identical DBMs. + * If the zones are not identical, it returns {base_DIFFERENT, false} + * + * @see relation_t + * @param pdbm1 is a closed priced DBM of dimension \a dim. + * @param pdbm2 is a closed priced DBM of dimension \a dim. + * @param dim is the dimension of \a pdbm1 and \a pdbm2. + * @return The cost relation between pdbm1 and pdbm2 and if the relation is strict. + */ +std::pair pdbm_compare_cost_identical_pdbms(const PDBM pdbm1, const PDBM pdbm2, cindex_t dim); + /** * Relation between 2 priced dbms where one is in compressed. Notice * that in constract to dbm_relationWithMinDBM, \a buffer may not be diff --git a/src/priced.cpp b/src/priced.cpp index 67161c4..0c64c21 100644 --- a/src/priced.cpp +++ b/src/priced.cpp @@ -335,6 +335,21 @@ inline static bool leq(const int32_t* first, const int32_t* last, const int32_t* return std::equal(first, last, rate, std::less_equal()); } +/** + * Given two planes, returns true if the slope of the first is less + * than to the slope of the other. + * + * @param first is a pointer to the first coefficient of the first plane. + * @param last is a pointer to the last coefficient of the first plane. + * @param rate is a pointer to the first coefficient of the second plane. + */ +inline static bool less(const int32_t* first, const int32_t* last, const int32_t* rate) +{ + assert(first && last && rate); + + return std::equal(first, last, rate, std::less()); +} + /** * Given a zone and two hyperplanes over that zone, returns the * infimum of the difference of the two planes. @@ -358,6 +373,50 @@ static int32_t infOfDiff(const raw_t* dbm, uint32_t dim, int32_t cost1, const in return pdbm_infimum(dbm, dim, cost, rates); } +std::pair pdbm_compare_cost_identical_pdbms(const PDBM pdbm1, const PDBM pdbm2, cindex_t dim) +{ + assert(pdbm1 && pdbm2 && dim); + + raw_t* dbm1 = pdbm_matrix(pdbm1); + raw_t* dbm2 = pdbm_matrix(pdbm2); + int32_t* rates1 = pdbm_rates(pdbm1); + int32_t* rates2 = pdbm_rates(pdbm2); + uint32_t cost1 = pdbm_cost(pdbm1); + uint32_t cost2 = pdbm_cost(pdbm2); + + /* Function should only be called for identical dbms. + * In case they are not, return costs are different. */ + if (dbm_relation(dbm1, dbm2, dim) != base_EQUAL) { + return {base_DIFFERENT, false}; + } + + /* Both have the same size. We need to compare the planes to + * see which one is cheaper. + */ + int32_t c = infOfDiff(dbm1, dim, cost2, rates2, cost1, rates1); + if (c > 0) { + /* Early return to avoid unnecessary computation of the + * second subtraction. + */ + return {base_SUPERSET, true}; + } + + int32_t d = infOfDiff(dbm1, dim, cost1, rates1, cost2, rates2); + if (d > 0) { + return {base_SUBSET, true}; + } + if (c == 0 && d == 0) { + return {base_EQUAL, false}; + } + if (c >= 0) { + return {base_SUPERSET, false}; + } + if (d >= 0) { + return {base_SUBSET, false}; + } + return {base_DIFFERENT, false}; +} + relation_t pdbm_relation(const PDBM pdbm1, const PDBM pdbm2, cindex_t dim) { assert(pdbm1 && pdbm2 && dim); From d3d28d4822d9398538343ff084b8893e2079932d Mon Sep 17 00:00:00 2001 From: Slorup Date: Tue, 14 Mar 2023 11:16:48 +0100 Subject: [PATCH 13/32] Changed priced DBMs to support doubles for cost, rate and cache. Needs to update double comparisons with epsilons. --- include/dbm/pfed.h | 10 +- include/dbm/priced.h | 22 +-- src/infimum.cpp | 49 +++--- src/infimum.h | 4 +- src/pfed.cpp | 25 +-- src/priced.cpp | 392 ++++++++++++++++++++++--------------------- 6 files changed, 256 insertions(+), 246 deletions(-) diff --git a/include/dbm/pfed.h b/include/dbm/pfed.h index 4abd984..3b15263 100644 --- a/include/dbm/pfed.h +++ b/include/dbm/pfed.h @@ -442,7 +442,7 @@ namespace dbm bool constrain(const constraint_t& c); /** Returns the infimum of the federation. */ - int32_t getInfimum() const; + double getInfimum() const; /** * Check if the federation satisfies a given constraint. @@ -489,7 +489,7 @@ namespace dbm pfed_t& up(); /** Delay with rate \a rate. */ - pfed_t& up(int32_t rate); + pfed_t& up(double rate); /** Set x(clock) to \a value. */ pfed_t& updateValue(cindex_t clock, uint32_t value); @@ -504,9 +504,9 @@ namespace dbm void diagonalExtrapolateMaxBounds(int32_t* max); void diagonalExtrapolateLUBounds(int32_t* lower, int32_t* upper); - void incrementCost(int32_t value); + void incrementCost(double value); - int32_t getCostOfValuation(const IntValuation& valuation) const; + double getCostOfValuation(const IntValuation& valuation) const; void relax(); @@ -740,7 +740,7 @@ namespace dbm * Returns the infimum of the federation given a partial * valuation. */ - int32_t getInfimumValuation(IntValuation& valuation, const bool* free = nullptr) const; + double getInfimumValuation(IntValuation& valuation, const bool* free = nullptr) const; /** Returns the number of zones in the federation. */ size_t size() const; diff --git a/include/dbm/priced.h b/include/dbm/priced.h index bfc58f9..43f39f2 100644 --- a/include/dbm/priced.h +++ b/include/dbm/priced.h @@ -279,7 +279,7 @@ relation_t pdbm_relationWithMinDBM(const PDBM pdbm, cindex_t dim, const mingraph * @param dim is the dimension of \a pdbm. * @return The infimum cost of \a pdbm. */ -int32_t pdbm_getInfimum(const PDBM pdbm, cindex_t dim); +double pdbm_getInfimum(const PDBM pdbm, cindex_t dim); /** * Generates a valuation which has the infimum cost of the priced DBM. @@ -303,7 +303,7 @@ int32_t pdbm_getInfimum(const PDBM pdbm, cindex_t dim); * @throw out_of_range if no valuation with the given constraints can * be found. */ -int32_t pdbm_getInfimumValuation(const PDBM pdbm, cindex_t dim, int32_t* valuation, const bool* free); +double pdbm_getInfimumValuation(const PDBM pdbm, cindex_t dim, int32_t* valuation, const bool* free); /** * Check if a priced DBM satisfies a given constraint. @@ -399,7 +399,7 @@ void pdbm_up(PDBM& pdbm, cindex_t dim); * reference clock. * @post The priced DBM is closed. */ -void pdbm_upZero(PDBM& pdbm, cindex_t dim, int32_t rate, cindex_t zero); +void pdbm_upZero(PDBM& pdbm, cindex_t dim, double rate, cindex_t zero); /** * Updates \a clock to \a value. This is only legitimate if the @@ -470,7 +470,7 @@ void pdbm_diagonalExtrapolateLUBounds(PDBM& pdbm, cindex_t dim, int32_t* lower, * @post The priced DBM is closed. * @pre value >= 0 */ -void pdbm_incrementCost(PDBM& pdbm, cindex_t dim, int32_t value); +void pdbm_incrementCost(PDBM& pdbm, cindex_t dim, double value); /** * Compute the closure of a priced DBM. This function is only relevant @@ -583,7 +583,7 @@ bool pdbm_findNextZeroCycle(const PDBM pdbm, cindex_t dim, cindex_t x, cindex_t* * @param pdbm is a closed priced DBM of dimension \a dim. * @param dim is the dimension of \a pdbm. */ -int32_t pdbm_getSlopeOfDelayTrajectory(const PDBM pdbm, cindex_t dim); +double pdbm_getSlopeOfDelayTrajectory(const PDBM pdbm, cindex_t dim); /** * Returns the rate (coefficient of the hyperplane) of \a clock. @@ -593,9 +593,9 @@ int32_t pdbm_getSlopeOfDelayTrajectory(const PDBM pdbm, cindex_t dim); * @param clock is the clock for which to return the coefficient. * @return the rate of \a clock. */ -int32_t pdbm_getRate(const PDBM pdbm, cindex_t dim, cindex_t clock); +double pdbm_getRate(const PDBM pdbm, cindex_t dim, cindex_t clock); -const int32_t* pdbm_getRates(const PDBM pdbm, cindex_t dim); +const double* pdbm_getRates(const PDBM pdbm, cindex_t dim); /** * Returns the cost of the offset point. @@ -603,7 +603,7 @@ const int32_t* pdbm_getRates(const PDBM pdbm, cindex_t dim); * @param pdbm is a closed priced DBM of dimension \a dim. * @param dim is the dimension of \a pdbm. */ -int32_t pdbm_getCostAtOffset(const PDBM pdbm, cindex_t dim); +double pdbm_getCostAtOffset(const PDBM pdbm, cindex_t dim); /** * Sets the cost at the offset point. @@ -617,7 +617,7 @@ int32_t pdbm_getCostAtOffset(const PDBM pdbm, cindex_t dim); * @param dim is the dimension of \a pdbm. * @param value is the new cost of the offset point. */ -void pdbm_setCostAtOffset(PDBM& pdbm, cindex_t dim, uint32_t value); +void pdbm_setCostAtOffset(PDBM& pdbm, cindex_t dim, double value); /** * Returns true if the DBM is valid. Useful for debugging. @@ -686,7 +686,7 @@ uint32_t pdbm_getUpperFacets(PDBM& pdbm, cindex_t dim, cindex_t* facets); * @pre pdbm_containsInt(pdbm, dim, valuation) * @return The cost of \a valuation in \a pdbm. */ -int32_t pdbm_getCostOfValuation(const PDBM pdbm, cindex_t dim, const int32_t* valuation); +double pdbm_getCostOfValuation(const PDBM pdbm, cindex_t dim, const int32_t* valuation); /** * Makes all strong constraints of a priced DBM weak. @@ -715,7 +715,7 @@ void pdbm_getOffset(const PDBM pdbm, cindex_t dim, int32_t* valuation); * @param clock is the index of a clock for which to set the coefficient. * @param rate is the coefficient. */ -void pdbm_setRate(PDBM& pdbm, cindex_t dim, cindex_t clock, int32_t rate); +void pdbm_setRate(PDBM& pdbm, cindex_t dim, cindex_t clock, double rate); /** * Returns the inner matrix of a priced DBM. The matrix can be diff --git a/src/infimum.cpp b/src/infimum.cpp index 6e73506..903f582 100644 --- a/src/infimum.cpp +++ b/src/infimum.cpp @@ -40,8 +40,8 @@ struct Node uint32_t depth; /**< Depth from root (Always node0). */ Node* thread; /**< Next according to the preorder. */ bool inbound; /**< Is the arc pointing to me or away. */ - int32_t flow; /**< Flow for the current solution. */ - int32_t potential; /**< Node potential for spanning tree solution. */ + double flow; /**< Flow for the current solution. */ + double potential; /**< Node potential for spanning tree solution. */ }; /* @@ -61,14 +61,14 @@ static void printSimpleNodeInfo(Node* nodes, uint32_t i) << ", inbound: " << inbound(i) << ", flow: " << flow(i) << ", potential: " << potential(i); } -static void printNodeInfo(Node* nodes, const int32_t* rates, uint32_t i) +static void printNodeInfo(Node* nodes, const double* rates, uint32_t i) { printSimpleNodeInfo(nodes, i); std::cerr << ", s/d: " << b(i) << " "; std::cerr << std::endl; } -static void printAllNodeInfo(Node* nodes, const int32_t* rates, uint32_t dim) +static void printAllNodeInfo(Node* nodes, const double* rates, uint32_t dim) { std::cerr << "Nodes:" << std::endl; for (uint32_t i = 0; i < dim; i++) { @@ -87,11 +87,11 @@ static void printSimpleAllNodeInfo(Node *nodes, uint32_t dim) } */ -static bool checkTreeIntegrity(const raw_t* dbm, const int32_t* rates, Node* nodes, uint32_t dim) +static bool checkTreeIntegrity(const raw_t* dbm, const double* rates, Node* nodes, uint32_t dim) { bool treeOK = true; // Check that all nodes get their flow - int32_t sum[dim], total = 0; + double sum[dim], total = 0; uint32_t i; sum[0] = 0; @@ -203,7 +203,7 @@ static bool checkTreeIntegrity(const raw_t* dbm, const int32_t* rates, Node* nod static inline bool nodeHasNoChildren(Node* node) { return (node->thread->depth > node->depth); } -static void printSolution(int32_t* valuation, const int32_t* rates, uint32_t dim) +static void printSolution(int32_t* valuation, const double* rates, uint32_t dim) { for (uint32_t i = 0; i < dim; i++) { std::cerr << "Val " << i << ": " << valuation[i] << " (rate: " << rates[i] << ")" << std::endl; @@ -249,7 +249,7 @@ static void printAllRates(const int32_t *rates, uint32_t dim) * The initial solution includes computing the intial node potentials. * */ -static void findInitialSpanningTreeSolution(const raw_t* dbm, uint32_t dim, const int32_t* rates, Node* nodes) +static void findInitialSpanningTreeSolution(const raw_t* dbm, uint32_t dim, const double* rates, Node* nodes) { Node* last = nodes + dim; Node* node = nodes; @@ -288,7 +288,7 @@ static void findInitialSpanningTreeSolution(const raw_t* dbm, uint32_t dim, cons * Pre: leave should be on the path from arcs[enter].{i,j} to the root. */ -static void updatePotentials(Node* leave, int32_t change) +static void updatePotentials(Node* leave, double change) { /* Update the entire subtree rooted at leave with a change * corresponding the reduced cost of the entering arc. This is @@ -362,8 +362,7 @@ static inline bool isPredecessorOf(Node* n, Node* m) { return n == findNthPredec * I.e., pred, depth, and thread. * */ -static void updateNonRootSubtree(Node* rootNode, Node* nonRootNode, Node* leave, bool sourceInRootSubtree, - uint32_t flow) +static void updateNonRootSubtree(Node* rootNode, Node* nonRootNode, Node* leave, bool sourceInRootSubtree, double flow) { /* * Update thread information NOT COMPLETELY SURE ABOUT CORRECTNESS @@ -427,7 +426,7 @@ static void updateNonRootSubtree(Node* rootNode, Node* nonRootNode, Node* leave, */ Node *tmppred1, *tmppred2, *newi; - int32_t tmpflow1, tmpflow2; + double tmpflow1, tmpflow2; bool tmpinbound1, tmpinbound2; tmppred1 = rootNode; tmpflow1 = flow; @@ -475,7 +474,7 @@ static void updateNonRootSubtree(Node* rootNode, Node* nonRootNode, Node* leave, * and subtract flow from arcs in the opposite direction * of (k,l). */ -static void updateFlowInCycle(Node* k, Node* l, Node* root, int32_t flowToAugment) +static void updateFlowInCycle(Node* k, Node* l, Node* root, double flowToAugment) { if (flowToAugment > 0) { while (k != root) { @@ -495,10 +494,10 @@ static void updateFlowInCycle(Node* k, Node* l, Node* root, int32_t flowToAugmen * Update the spanning tree so the node information is updated * including flow and node potentials. */ -static void updateSpanningTree(Node* k, Node* l, Node* leave, Node* root, int32_t costEnter) +static void updateSpanningTree(Node* k, Node* l, Node* leave, Node* root, double costEnter) { - int32_t reducedCostEnter = costEnter - k->potential + l->potential; - int32_t flowToAugment = leave->flow; + double reducedCostEnter = costEnter - k->potential + l->potential; + double flowToAugment = leave->flow; updateFlowInCycle(k, l, root, flowToAugment); if (!isPredecessorOf(leave, k)) { updatePotentials(leave, -reducedCostEnter); @@ -598,7 +597,7 @@ static Node* discoverCycleRoot(Node* k, Node* l) */ static Node* findLeavingArc(Node* k, Node* l, Node* root) { - int32_t smallestFlow = INT_MAX; + double smallestFlow = INT_MAX; /* * Node with the lowest depth of the leaving arc. */ @@ -645,16 +644,16 @@ static Node* findLeavingArc(Node* k, Node* l, Node* root) * If it is not a transshipment node, we need to follow the * thread to update the potentials. We do it by computing */ -static void testAndRemoveArtificialArcs(const raw_t* dbm, const int32_t* rates, Node* nodes, uint32_t dim) +static void testAndRemoveArtificialArcs(const raw_t* dbm, const double* rates, Node* nodes, uint32_t dim) { for (uint32_t i = 1; i < dim; i++) { if (potential(i) == dbm_INFINITY && pred(i) == 0 && flow(i) == 0) { inbound(i) = true; Node* tmp = nodes[i].thread; - int32_t rateSum = b(i); + double rateSum = b(i); - int32_t minPotential = dbm_INFINITY + constraintValue(0, i); + double minPotential = dbm_INFINITY + constraintValue(0, i); /* * Find the highest potential we can decrease i with and @@ -688,7 +687,7 @@ static void testAndRemoveArtificialArcs(const raw_t* dbm, const int32_t* rates, * Returns true if and only if all elements in [first, last) are * non-negative. */ -static bool allPositive(const int32_t* first, const int32_t* last) +static bool allPositive(const double* first, const double* last) { while (first != last) { if (*first < 0) { @@ -704,7 +703,7 @@ static bool allPositive(const int32_t* first, const int32_t* last) * network flow problem. I.e. the cost of the offset and the costless * moves to the offset is not taken into account. */ -static void infimumNetSimplex(const raw_t* dbm, uint32_t dim, const int32_t* rates, Node* nodes) +static void infimumNetSimplex(const raw_t* dbm, uint32_t dim, const double* rates, Node* nodes) { /* Find and store the minimal set of arcs. The netsimplex * algorithm is polynomial in the number of arcs. @@ -766,7 +765,7 @@ static void infimumNetSimplex(const raw_t* dbm, uint32_t dim, const int32_t* rat * the infimum-achieving point in the zone. * */ -int32_t pdbm_infimum(const raw_t* dbm, uint32_t dim, uint32_t offsetCost, const int32_t* rates) +double pdbm_infimum(const raw_t* dbm, uint32_t dim, double offsetCost, const double* rates) { if (allPositive(rates, rates + dim)) { return offsetCost; @@ -775,7 +774,7 @@ int32_t pdbm_infimum(const raw_t* dbm, uint32_t dim, uint32_t offsetCost, const Node nodes[dim]; infimumNetSimplex(dbm, dim, rates, nodes); - int32_t solution = offsetCost; + double solution = offsetCost; for (uint32_t i = 0; i < dim; i++) { ASSERT(potential(i) >= 0, std::cerr << "Node: " << i << std::endl; printAllNodeInfo(nodes, rates, dim); printClockLowerBounds(dbm, dim)); @@ -792,7 +791,7 @@ int32_t pdbm_infimum(const raw_t* dbm, uint32_t dim, uint32_t offsetCost, const return solution; } -void pdbm_infimum(const raw_t* dbm, uint32_t dim, uint32_t offsetCost, const int32_t* rates, int32_t* valuation) +void pdbm_infimum(const raw_t* dbm, uint32_t dim, double offsetCost, const double* rates, int32_t* valuation) { if (allPositive(rates, rates + dim)) { valuation[0] = 0; diff --git a/src/infimum.h b/src/infimum.h index 126e720..1f47ca6 100644 --- a/src/infimum.h +++ b/src/infimum.h @@ -12,7 +12,7 @@ #include "dbm/constraints.h" -int32_t pdbm_infimum(const raw_t* dbm, uint32_t dim, uint32_t offsetCost, const int32_t* rates); -void pdbm_infimum(const raw_t* dbm, uint32_t dim, uint32_t offsetCost, const int32_t* rates, int32_t* valuation); +double pdbm_infimum(const raw_t* dbm, uint32_t dim, double offsetCost, const double* rates); +void pdbm_infimum(const raw_t* dbm, uint32_t dim, double offsetCost, const double* rates, int32_t* valuation); #endif diff --git a/src/pfed.cpp b/src/pfed.cpp index e35ab32..47b0a36 100644 --- a/src/pfed.cpp +++ b/src/pfed.cpp @@ -13,6 +13,7 @@ #include // std::bind #include #include +#include using std::bind; using std::for_each; @@ -86,26 +87,26 @@ namespace dbm return !isEmpty(); } - static int32_t min(int32_t a, int32_t b) { return a < b ? a : b; } + static double min(double a, double b) { return a < b ? a : b; } - int32_t pfed_t::getInfimum() const + double pfed_t::getInfimum() const { /* The binary operator used in the following accumulation is * lambda inf zone.min(inf, pdbm_getInfimum(zone, ptr->dim)); */ - return accumulate(begin(), end(), INT_MAX, bind(min, _1, bind(pdbm_getInfimum, _2, ptr->dim))); + return accumulate(begin(), end(), DBL_MAX, bind(min, _1, bind(pdbm_getInfimum, _2, ptr->dim))); } - int32_t pfed_t::getInfimumValuation(IntValuation& valuation, const bool* free) const + double pfed_t::getInfimumValuation(IntValuation& valuation, const bool* free) const { uint32_t dim = ptr->dim; - int32_t infimum = INT_MAX; + double infimum = INT_MAX; int32_t copy[dim]; for_each_const(zone) { std::copy(valuation.begin(), valuation.end(), copy); - int32_t inf = pdbm_getInfimumValuation(*zone, dim, copy, free); + double inf = pdbm_getInfimumValuation(*zone, dim, copy, free); if (inf < infimum) { infimum = inf; std::copy(copy, copy + dim, valuation.begin()); @@ -210,7 +211,7 @@ namespace dbm return *this; } - pfed_t& pfed_t::up(int32_t rate) + pfed_t& pfed_t::up(double rate) { assert(rate >= 0); @@ -221,7 +222,7 @@ namespace dbm for_each__(zone) { cindex_t x; - int32_t oldrate = pdbm_getSlopeOfDelayTrajectory(*zone, dim); + double oldrate = pdbm_getSlopeOfDelayTrajectory(*zone, dim); // pdbm_print(std::cout, zone->operator PDBM(), dim); @@ -283,7 +284,7 @@ namespace dbm for_each__(zone) { cindex_t k; - int32_t rate = pdbm_getRate(*zone, dim, clock); + double rate = pdbm_getRate(*zone, dim, clock); if (rate == 0) { pdbm_updateValue(*zone, dim, clock, value); @@ -337,17 +338,17 @@ namespace dbm for_each(beginMutable(), endMutable(), bind(pdbm_diagonalExtrapolateLUBounds, _1, ptr->dim, lower, upper)); } - void pfed_t::incrementCost(int32_t value) + void pfed_t::incrementCost(double value) { for_each(beginMutable(), endMutable(), bind(pdbm_incrementCost, _1, ptr->dim, value)); } - int32_t pfed_t::getCostOfValuation(const IntValuation& valuation) const + double pfed_t::getCostOfValuation(const IntValuation& valuation) const { /* The binary operator used in the following accumulation is * lambda x y . min(x, pdbm_getCostOfValuation(y, dim, val)) */ - return accumulate(begin(), end(), INT_MAX, + return accumulate(begin(), end(), DBL_MAX, bind(min, _1, bind(pdbm_getCostOfValuation, _2, ptr->dim, valuation()))); } diff --git a/src/priced.cpp b/src/priced.cpp index 0c64c21..64cb173 100644 --- a/src/priced.cpp +++ b/src/priced.cpp @@ -21,15 +21,24 @@ #include #include #include +#include struct PDBM_s { uint32_t count; - uint32_t cost; - uint32_t infimum; + double cost; + double infimum; + std::vector rates; int32_t data[]; }; +double epsilon = DBL_EPSILON;//TODO: Change epsilon + +bool are_same(double a, double b) +{ + return std::abs(a - b) < epsilon; +} + /** Convenient macro for accessing DBM entries. */ #define DBM(I, J) dbm[(I)*dim + (J)] @@ -37,10 +46,10 @@ struct PDBM_s #define pdbm_cost(pdbm) ((pdbm)->cost) /** Returns the vectors of coefficients. */ -#define pdbm_rates(pdbm) ((pdbm)->data) +#define pdbm_rates(pdbm) ((pdbm)->rates.data()) /** Returns the matrix. */ -#define pdbm_matrix(pdbm) ((pdbm)->data + dim) +#define pdbm_matrix(pdbm) ((pdbm)->data) /** Returns the cache infimum. */ #define pdbm_cache(pdbm) ((pdbm)->infimum) @@ -132,7 +141,7 @@ static void pdbm_blank(PDBM& pdbm, cindex_t dim) size_t pdbm_size(cindex_t dim) { assert(dim); - return sizeof(struct PDBM_s) + (dim * dim + dim) * sizeof(int32_t); + return sizeof(struct PDBM_s) + (dim * dim) * sizeof(int32_t) + dim * sizeof(double); } PDBM pdbm_reserve(cindex_t dim, void* p) @@ -238,8 +247,8 @@ bool pdbm_constrain1(PDBM& pdbm, cindex_t dim, cindex_t i, cindex_t j, raw_t con /* Compute the cost at the origin. */ - uint32_t cost = pdbm_cost(pdbm); - int32_t* rates = pdbm_rates(pdbm); + double cost = pdbm_cost(pdbm); + double* rates = pdbm_rates(pdbm); for (uint32_t k = 1; k < dim; k++) { cost += rates[k] * dbm_raw2bound(DBM(0, k)); } @@ -273,8 +282,8 @@ bool pdbm_constrainN(PDBM& pdbm, cindex_t dim, const constraint_t* constraints, pdbm_prepare(pdbm, dim); dbm = pdbm_matrix(pdbm); - uint32_t cost = pdbm_cost(pdbm); - int32_t* rates = pdbm_rates(pdbm); + double cost = pdbm_cost(pdbm); + double* rates = pdbm_rates(pdbm); for (uint32_t k = 1; k < dim; k++) { cost += rates[k] * dbm_raw2bound(DBM(0, k)); @@ -306,7 +315,7 @@ bool pdbm_constrainN(PDBM& pdbm, cindex_t dim, const constraint_t* constraints, * we want to find the cost. * @param dim is the dimension of \a dbm1 and \a dbm2. */ -static int32_t costAtOtherOffset(const raw_t* dbm1, const int32_t* rates1, uint32_t cost1, const raw_t* dbm2, +static double costAtOtherOffset(const raw_t* dbm1, const double* rates1, double cost1, const raw_t* dbm2, cindex_t dim) { assert(dbm1 && dbm2 && rates1 && dim); @@ -328,11 +337,11 @@ static int32_t costAtOtherOffset(const raw_t* dbm1, const int32_t* rates1, uint3 * @param last is a pointer to the last coefficient of the first plane. * @param rate is a pointer to the first coefficient of the second plane. */ -inline static bool leq(const int32_t* first, const int32_t* last, const int32_t* rate) +inline static bool leq(const double* first, const double* last, const double* rate) { assert(first && last && rate); - return std::equal(first, last, rate, std::less_equal()); + return std::equal(first, last, rate, std::less_equal<>()); } /** @@ -343,11 +352,11 @@ inline static bool leq(const int32_t* first, const int32_t* last, const int32_t* * @param last is a pointer to the last coefficient of the first plane. * @param rate is a pointer to the first coefficient of the second plane. */ -inline static bool less(const int32_t* first, const int32_t* last, const int32_t* rate) +inline static bool less(const double* first, const double* last, const double* rate) { assert(first && last && rate); - return std::equal(first, last, rate, std::less()); + return std::equal(first, last, rate, std::less<>()); } /** @@ -361,14 +370,14 @@ inline static bool less(const int32_t* first, const int32_t* last, const int32_t * @param cost2 The cost at the offset for the second plane. * @param rate2 The rates of the second plane. */ -static int32_t infOfDiff(const raw_t* dbm, uint32_t dim, int32_t cost1, const int32_t* rate1, int32_t cost2, - const int32_t* rate2) +static double infOfDiff(const raw_t* dbm, uint32_t dim, double cost1, const double* rate1, double cost2, + const double* rate2) { assert(dbm && dim && rate1 && rate2); - int32_t cost = cost1 - cost2; - int32_t rates[dim]; - std::transform(rate1, rate1 + dim, rate2, rates, std::minus()); + double cost = cost1 - cost2; + double rates[dim]; + std::transform(rate1, rate1 + dim, rate2, rates, std::minus<>()); return pdbm_infimum(dbm, dim, cost, rates); } @@ -379,10 +388,10 @@ std::pair pdbm_compare_cost_identical_pdbms(const PDBM pdbm1, raw_t* dbm1 = pdbm_matrix(pdbm1); raw_t* dbm2 = pdbm_matrix(pdbm2); - int32_t* rates1 = pdbm_rates(pdbm1); - int32_t* rates2 = pdbm_rates(pdbm2); - uint32_t cost1 = pdbm_cost(pdbm1); - uint32_t cost2 = pdbm_cost(pdbm2); + double* rates1 = pdbm_rates(pdbm1); + double* rates2 = pdbm_rates(pdbm2); + double cost1 = pdbm_cost(pdbm1); + double cost2 = pdbm_cost(pdbm2); /* Function should only be called for identical dbms. * In case they are not, return costs are different. */ @@ -393,21 +402,18 @@ std::pair pdbm_compare_cost_identical_pdbms(const PDBM pdbm1, /* Both have the same size. We need to compare the planes to * see which one is cheaper. */ - int32_t c = infOfDiff(dbm1, dim, cost2, rates2, cost1, rates1); + double c = infOfDiff(dbm1, dim, cost2, rates2, cost1, rates1); if (c > 0) { - /* Early return to avoid unnecessary computation of the - * second subtraction. - */ return {base_SUPERSET, true}; } - int32_t d = infOfDiff(dbm1, dim, cost1, rates1, cost2, rates2); - if (d > 0) { - return {base_SUBSET, true}; - } + double d = infOfDiff(dbm1, dim, cost1, rates1, cost2, rates2); if (c == 0 && d == 0) { return {base_EQUAL, false}; } + if (d > 0) { + return {base_SUBSET, true}; + } if (c >= 0) { return {base_SUPERSET, false}; } @@ -423,12 +429,13 @@ relation_t pdbm_relation(const PDBM pdbm1, const PDBM pdbm2, cindex_t dim) raw_t* dbm1 = pdbm_matrix(pdbm1); raw_t* dbm2 = pdbm_matrix(pdbm2); - int32_t* rates1 = pdbm_rates(pdbm1); - int32_t* rates2 = pdbm_rates(pdbm2); - uint32_t cost1 = pdbm_cost(pdbm1); - uint32_t cost2 = pdbm_cost(pdbm2); + double* rates1 = pdbm_rates(pdbm1); + double* rates2 = pdbm_rates(pdbm2); + double cost1 = pdbm_cost(pdbm1); + double cost2 = pdbm_cost(pdbm2); - int32_t c, d; + bool a, b; + double c, d; switch (dbm_relation(dbm1, dbm2, dim)) { case base_SUPERSET: @@ -466,14 +473,14 @@ relation_t pdbm_relation(const PDBM pdbm1, const PDBM pdbm2, cindex_t dim) /* Do sound and cheap comparison first. */ - c = cost1 <= cost2 && leq(rates1, rates1 + dim, rates2); - d = cost2 <= cost1 && leq(rates2, rates2 + dim, rates1); + a = cost1 <= cost2 && leq(rates1, rates1 + dim, rates2); + b = cost2 <= cost1 && leq(rates2, rates2 + dim, rates1); - if (c & d) { + if (a && b) { return base_EQUAL; - } else if (c) { + } else if (a) { return base_SUPERSET; - } else if (d) { + } else if (b) { return base_SUBSET; } @@ -512,137 +519,139 @@ relation_t pdbm_relation(const PDBM pdbm1, const PDBM pdbm2, cindex_t dim) relation_t pdbm_relationWithMinDBM(const PDBM pdbm1, cindex_t dim, const mingraph_t pdbm2, raw_t* dbm2) { - assert(pdbm1 && pdbm2 && dim && dbm2); - - raw_t* dbm1 = pdbm_matrix(pdbm1); - uint32_t cost1 = pdbm_cost(pdbm1); - int32_t* rates1 = pdbm_rates(pdbm1); - - int32_t c, d; - - /* We know how the cost and the rates are encoded in a mingraph: - * see writeToMinDBMWithOffset and readFromMinDBM. - */ - uint32_t cost2 = pdbm2[0]; - const int32_t* rates2 = pdbm2 + 2; - - /* dbm_relationWithMinDBM will in some cases unpack pdbm2 into - * dbm2. In order to detect whether this has happened, we set the - * first entry of dbm2 to -1. If dbm_relationWithMinDBM did indeed - * unpack pdbm2, this entry will have a different value - * afterwards. - */ - dbm2[0] = -1; - - switch (dbm_relationWithMinDBM(dbm1, dim, pdbm2 + dim + 2, dbm2)) { - case base_SUPERSET: - /* pdbm2 is smaller. Check whether it is also the most - * expensive: This is the case when the difference between - * pdbm2 and pdbm1 is always non-negative (the infimum is not - * smaller than 0). - */ - if (dbm2[0] == -1) { - dbm_readFromMinDBM(dbm2, pdbm2 + dim + 2); - } - cost1 = costAtOtherOffset(dbm1, rates1, cost1, dbm2, dim); - if (cost1 <= cost2 && - (leq(rates1, rates1 + dim, rates2) || infOfDiff(dbm2, dim, cost2, rates2, cost1, rates1) >= 0)) { - return base_SUPERSET; - } else { - return base_DIFFERENT; - } - - case base_SUBSET: - /* pdbm2 is bigger. Check whether it is also the cheapest: - * This is the case when the difference between pdbm1 and - * pdbm2 is always non-negative (the infimum is not smaller - * than 0). - */ - if (dbm2[0] == -1) { - dbm_readFromMinDBM(dbm2, pdbm2 + dim + 2); - } - cost2 = costAtOtherOffset(dbm2, rates2, cost2, dbm1, dim); - if (cost2 <= cost1 && - (leq(rates2, rates2 + dim, rates1) || infOfDiff(dbm1, dim, cost1, rates1, cost2, rates2) >= 0)) { - return base_SUBSET; - } else { - return base_DIFFERENT; - } - - case base_EQUAL: - /* Both have the same size. We need to compare the planes to - * see which one is cheaper. - */ - - /* Do sound and cheap comparison first. - */ - c = cost1 <= cost2 && leq(rates1, rates1 + dim, rates2); - d = cost2 <= cost1 && leq(rates2, rates2 + dim, rates1); - - if (c & d) { - return base_EQUAL; - } else if (c) { - return base_SUPERSET; - } else if (d) { - return base_SUBSET; - } - - /* The planes are incomparable, so we need to do the - * subtraction. Notice that priced zones are not canonical, - * so the two zones can in fact be equal even though the rates - * are different. Therefore we must also check for the - * situation where both infima are zero. - * - * Notice that dbm1 equals dbm2, hence we do not need to - * unpacked dbm2. - */ - c = infOfDiff(dbm1, dim, cost2, rates2, cost1, rates1); - if (c > 0) { - /* Early return to avoid unnecessary computation of the - * second subtraction. - */ - return base_SUPERSET; - } - - d = infOfDiff(dbm1, dim, cost1, rates1, cost2, rates2); - if (c == 0 && d == 0) { - return base_EQUAL; - } - if (c >= 0) { - return base_SUPERSET; - } - if (d >= 0) { - return base_SUBSET; - } - return base_DIFFERENT; - - default: return base_DIFFERENT; - } -} - -int32_t pdbm_getInfimum(const PDBM pdbm, cindex_t dim) + throw std::logic_error("pdbm_relationWithMinDBM not implemented!"); + +// assert(pdbm1 && pdbm2 && dim && dbm2); +// +// raw_t* dbm1 = pdbm_matrix(pdbm1); +// double cost1 = pdbm_cost(pdbm1); +// double* rates1 = pdbm_rates(pdbm1); +// +// double c, d; +// +// /* We know how the cost and the rates are encoded in a mingraph: +// * see writeToMinDBMWithOffset and readFromMinDBM. +// */ +// double cost2 = pdbm2[0]; +// const double* rates2 = pdbm2 + 2; +// +// /* dbm_relationWithMinDBM will in some cases unpack pdbm2 into +// * dbm2. In order to detect whether this has happened, we set the +// * first entry of dbm2 to -1. If dbm_relationWithMinDBM did indeed +// * unpack pdbm2, this entry will have a different value +// * afterwards. +// */ +// dbm2[0] = -1; +// +// switch (dbm_relationWithMinDBM(dbm1, dim, pdbm2 + dim + 2, dbm2)) { +// case base_SUPERSET: +// /* pdbm2 is smaller. Check whether it is also the most +// * expensive: This is the case when the difference between +// * pdbm2 and pdbm1 is always non-negative (the infimum is not +// * smaller than 0). +// */ +// if (dbm2[0] == -1) { +// dbm_readFromMinDBM(dbm2, pdbm2 + dim + 2); +// } +// cost1 = costAtOtherOffset(dbm1, rates1, cost1, dbm2, dim); +// if (cost1 <= cost2 && +// (leq(rates1, rates1 + dim, rates2) || infOfDiff(dbm2, dim, cost2, rates2, cost1, rates1) >= 0)) { +// return base_SUPERSET; +// } else { +// return base_DIFFERENT; +// } +// +// case base_SUBSET: +// /* pdbm2 is bigger. Check whether it is also the cheapest: +// * This is the case when the difference between pdbm1 and +// * pdbm2 is always non-negative (the infimum is not smaller +// * than 0). +// */ +// if (dbm2[0] == -1) { +// dbm_readFromMinDBM(dbm2, pdbm2 + dim + 2); +// } +// cost2 = costAtOtherOffset(dbm2, rates2, cost2, dbm1, dim); +// if (cost2 <= cost1 && +// (leq(rates2, rates2 + dim, rates1) || infOfDiff(dbm1, dim, cost1, rates1, cost2, rates2) >= 0)) { +// return base_SUBSET; +// } else { +// return base_DIFFERENT; +// } +// +// case base_EQUAL: +// /* Both have the same size. We need to compare the planes to +// * see which one is cheaper. +// */ +// +// /* Do sound and cheap comparison first. +// */ +// c = cost1 <= cost2 && leq(rates1, rates1 + dim, rates2); +// d = cost2 <= cost1 && leq(rates2, rates2 + dim, rates1); +// +// if (c & d) { +// return base_EQUAL; +// } else if (c) { +// return base_SUPERSET; +// } else if (d) { +// return base_SUBSET; +// } +// +// /* The planes are incomparable, so we need to do the +// * subtraction. Notice that priced zones are not canonical, +// * so the two zones can in fact be equal even though the rates +// * are different. Therefore we must also check for the +// * situation where both infima are zero. +// * +// * Notice that dbm1 equals dbm2, hence we do not need to +// * unpacked dbm2. +// */ +// c = infOfDiff(dbm1, dim, cost2, rates2, cost1, rates1); +// if (c > 0) { +// /* Early return to avoid unnecessary computation of the +// * second subtraction. +// */ +// return base_SUPERSET; +// } +// +// d = infOfDiff(dbm1, dim, cost1, rates1, cost2, rates2); +// if (c == 0 && d == 0) { +// return base_EQUAL; +// } +// if (c >= 0) { +// return base_SUPERSET; +// } +// if (d >= 0) { +// return base_SUBSET; +// } +// return base_DIFFERENT; +// +// default: return base_DIFFERENT; +// } +} + +double pdbm_getInfimum(const PDBM pdbm, cindex_t dim) { assert(pdbm && dim); assert(dbm_isValid(pdbm_matrix(pdbm), dim)); - uint32_t cache = pdbm_cache(pdbm); + double cache = pdbm_cache(pdbm); if (cache == INVALID) { pdbm_cache((PDBM)pdbm) = cache = pdbm_infimum(pdbm_matrix(pdbm), dim, pdbm_cost(pdbm), pdbm_rates(pdbm)); } return cache; } -int32_t pdbm_getInfimumValuation(const PDBM pdbm, cindex_t dim, int32_t* valuation, const bool* free) +double pdbm_getInfimumValuation(const PDBM pdbm, cindex_t dim, int32_t* valuation, const bool* free) { assert(pdbm && dim && valuation); assert(pdbm_isValid(pdbm, dim)); raw_t copy[dim * dim]; raw_t* dbm = pdbm_matrix(pdbm); - int32_t* rates = pdbm_rates(pdbm); + double* rates = pdbm_rates(pdbm); /* Compute the cost of the origin. */ - int32_t cost = pdbm_cost(pdbm); + double cost = pdbm_cost(pdbm); for (uint32_t i = 1; i < dim; i++) { cost -= rates[i] * -dbm_raw2bound(DBM(0, i)); } @@ -745,7 +754,7 @@ void pdbm_up(PDBM& pdbm, cindex_t dim) assertx(pdbm_isValid(pdbm, dim)); } -void pdbm_upZero(PDBM& pdbm, cindex_t dim, int32_t rate, cindex_t zero) +void pdbm_upZero(PDBM& pdbm, cindex_t dim, double rate, cindex_t zero) { assert(pdbm && dim && zero > 0 && zero < dim); assert(pdbm_areOnZeroCycle(pdbm, dim, 0, zero)); @@ -753,7 +762,7 @@ void pdbm_upZero(PDBM& pdbm, cindex_t dim, int32_t rate, cindex_t zero) pdbm_prepare(pdbm, dim); raw_t* dbm = pdbm_matrix(pdbm); - int32_t* rates = pdbm_rates(pdbm); + double* rates = pdbm_rates(pdbm); dbm_up(dbm, dim); rates[zero] = 0; @@ -781,7 +790,7 @@ void pdbm_updateValueZero(PDBM& pdbm, cindex_t dim, cindex_t clock, uint32_t val pdbm_prepare(pdbm, dim); - int32_t* rates = pdbm_rates(pdbm); + double* rates = pdbm_rates(pdbm); if (zero) { rates[zero] += rates[clock]; @@ -840,7 +849,7 @@ void pdbm_extrapolateMaxBounds(PDBM& pdbm, cindex_t dim, int32_t* max) { assert(pdbm && dim); - int32_t* rates = pdbm_rates(pdbm); + double* rates = pdbm_rates(pdbm); for (uint32_t i = 1; i < dim; i++) { if (rates[i] != 0) { @@ -863,7 +872,7 @@ void pdbm_diagonalExtrapolateMaxBounds(PDBM& pdbm, cindex_t dim, int32_t* max) { assert(pdbm && dim); - int32_t* rates = pdbm_rates(pdbm); + double* rates = pdbm_rates(pdbm); /* If possible, transfer the cost rate of inactive clocks to other * clocks (clocks which are on a zero cycle with the inactive @@ -907,7 +916,7 @@ void pdbm_diagonalExtrapolateLUBounds(PDBM& pdbm, cindex_t dim, int32_t* lower, { assert(pdbm && dim); - int32_t* rates = pdbm_rates(pdbm); + double* rates = pdbm_rates(pdbm); for (uint32_t i = 1; i < dim; i++) { // if (rates[i] < 0) @@ -928,7 +937,7 @@ void pdbm_diagonalExtrapolateLUBounds(PDBM& pdbm, cindex_t dim, int32_t* lower, dbm_diagonalExtrapolateLUBounds(pdbm_matrix(pdbm), dim, lower, upper); } -void pdbm_incrementCost(PDBM& pdbm, cindex_t dim, int32_t value) +void pdbm_incrementCost(PDBM& pdbm, cindex_t dim, double value) { assert(pdbm && dim && value >= 0); @@ -961,15 +970,16 @@ size_t pdbm_analyzeForMinDBM(const PDBM pdbm, cindex_t dim, uint32_t* bitMatrix) int32_t* pdbm_writeToMinDBMWithOffset(const PDBM pdbm, cindex_t dim, bool minimizeGraph, bool tryConstraints16, allocator_t allocator, uint32_t offset) { - assert(pdbm && dim); - - int32_t* graph = dbm_writeToMinDBMWithOffset(pdbm_matrix(pdbm), dim, minimizeGraph, tryConstraints16, allocator, - offset + dim + 2); - graph[offset] = pdbm_cost(pdbm); - graph[offset + 1] = pdbm_cache(pdbm); - auto* r = pdbm_rates(pdbm); - std::copy(r, r + dim, graph + offset + 2); - return graph; + throw std::logic_error("pdbm_writeToMinDBMWithOffset not implemented"); +// assert(pdbm && dim); +// +// int32_t* graph = dbm_writeToMinDBMWithOffset(pdbm_matrix(pdbm), dim, minimizeGraph, tryConstraints16, allocator, +// offset + dim + 2); +// graph[offset] = pdbm_cost(pdbm); +// graph[offset + 1] = pdbm_cache(pdbm); +// auto* r = pdbm_rates(pdbm); +// std::copy(r, r + dim, graph + offset + 2); +// return graph; } void pdbm_readFromMinDBM(PDBM& dst, cindex_t dim, mingraph_t src) @@ -1010,33 +1020,33 @@ bool pdbm_findZeroCycle(const PDBM pdbm, cindex_t dim, cindex_t x, cindex_t* out return pdbm_findNextZeroCycle(pdbm, dim, x, out); } -int32_t pdbm_getSlopeOfDelayTrajectory(const PDBM pdbm, cindex_t dim) +double pdbm_getSlopeOfDelayTrajectory(const PDBM pdbm, cindex_t dim) { assert(pdbm && dim); - int32_t* rates = pdbm_rates(pdbm); - int32_t sum = 0; + double* rates = pdbm_rates(pdbm); + double sum = 0; for (uint32_t i = 1; i < dim; i++) { sum += rates[i]; } return sum; } -int32_t pdbm_getRate(const PDBM pdbm, cindex_t dim, cindex_t clock) +double pdbm_getRate(const PDBM pdbm, cindex_t dim, cindex_t clock) { assert(pdbm && dim && clock > 0 && clock < dim); return pdbm_rates(pdbm)[clock]; } -int32_t pdbm_getCostAtOffset(const PDBM pdbm, cindex_t dim) +double pdbm_getCostAtOffset(const PDBM pdbm, cindex_t dim) { assert(pdbm && dim); return pdbm_cost(pdbm); } -void pdbm_setCostAtOffset(PDBM& pdbm, cindex_t dim, uint32_t value) +void pdbm_setCostAtOffset(PDBM& pdbm, cindex_t dim, double value) { assert(pdbm && dim); @@ -1199,13 +1209,13 @@ uint32_t pdbm_getUpperFacets(PDBM& pdbm, cindex_t dim, cindex_t* facets) return cnt; } -int32_t pdbm_getCostOfValuation(const PDBM pdbm, cindex_t dim, const int32_t* valuation) +double pdbm_getCostOfValuation(const PDBM pdbm, cindex_t dim, const int32_t* valuation) { assert(pdbm && dim && valuation); assert(pdbm_containsInt(pdbm, dim, valuation)); raw_t* dbm = pdbm_matrix(pdbm); - int32_t cost = pdbm_cost(pdbm); + double cost = pdbm_cost(pdbm); for (uint32_t i = 1; i < dim; i++) { cost += (valuation[i] - -dbm_raw2bound(DBM(0, i))) * pdbm_rates(pdbm)[i]; } @@ -1238,10 +1248,10 @@ bool pdbm_isValid(const PDBM pdbm, cindex_t dim) } raw_t* dbm = pdbm_matrix(pdbm); - int32_t* rates = pdbm_rates(pdbm); - uint32_t cost = pdbm_cost(pdbm); - int32_t cache = pdbm_cache(pdbm); - int32_t inf = pdbm_infimum(dbm, dim, cost, rates); + double* rates = pdbm_rates(pdbm); + double cost = pdbm_cost(pdbm); + double cache = pdbm_cache(pdbm); + double inf = pdbm_infimum(dbm, dim, cost, rates); return (cache == INVALID || cache == inf) && dbm_isValid(dbm, dim) && rates[0] == 0 && (!pdbm_isUnbounded(pdbm, dim) || pdbm_getSlopeOfDelayTrajectory(pdbm, dim) >= 0); @@ -1268,7 +1278,7 @@ void pdbm_getOffset(const PDBM pdbm, cindex_t dim, int32_t* valuation) } } -void pdbm_setRate(PDBM& pdbm, cindex_t dim, cindex_t clock, int32_t rate) +void pdbm_setRate(PDBM& pdbm, cindex_t dim, cindex_t clock, double rate) { assert(pdbm && dim && clock > 0 && clock < dim); @@ -1298,7 +1308,7 @@ const raw_t* pdbm_getMatrix(const PDBM pdbm, cindex_t dim) return pdbm_matrix(pdbm); } -const int32_t* pdbm_getRates(const PDBM pdbm, cindex_t dim) +const double* pdbm_getRates(const PDBM pdbm, cindex_t dim) { assert(pdbm && dim); return pdbm_rates(pdbm); @@ -1313,19 +1323,19 @@ bool pdbm_constrainToFacet(PDBM& pdbm, cindex_t dim, cindex_t i, cindex_t j) void pdbm_print(FILE* f, const PDBM pdbm, cindex_t dim) { - int32_t infimum = pdbm_getInfimum(pdbm, dim); + double infimum = pdbm_getInfimum(pdbm, dim); dbm_print(f, pdbm_matrix(pdbm), dim); fprintf(f, "Rates:"); for (cindex_t i = 1; i < dim; i++) { - fprintf(f, " %d", pdbm_getRate(pdbm, dim, i)); + fprintf(f, " %f", pdbm_getRate(pdbm, dim, i)); } fprintf(f, "\n"); - fprintf(f, "Offset: %d Infimum: %d\n", pdbm_cost(pdbm), infimum); + fprintf(f, "Offset: %f Infimum: %f\n", pdbm_cost(pdbm), infimum); } void pdbm_print(std::ostream& o, const PDBM pdbm, cindex_t dim) { - int32_t infimum = pdbm_getInfimum(pdbm, dim); + double infimum = pdbm_getInfimum(pdbm, dim); dbm_cppPrint(o, pdbm_matrix(pdbm), dim); o << "Rates:"; for (cindex_t i = 1; i < dim; i++) { @@ -1352,7 +1362,7 @@ void pdbm_freeDown(PDBM& pdbm, cindex_t dim, cindex_t index) /* Move offset point. */ - int32_t rate = pdbm_rates(pdbm)[index]; + double rate = pdbm_rates(pdbm)[index]; int32_t bound = -dbm_raw2bound(DBM(0, index)); pdbm_cost(pdbm) -= bound * rate; @@ -1363,7 +1373,7 @@ void pdbm_freeDown(PDBM& pdbm, cindex_t dim, cindex_t index) void pdbm_normalise(PDBM pdbm, cindex_t dim) { - int32_t* rates = pdbm_rates(pdbm); + double* rates = pdbm_rates(pdbm); cindex_t next[dim]; cindex_t i; @@ -1389,7 +1399,7 @@ void pdbm_normalise(PDBM pdbm, cindex_t dim) bool pdbm_hasNormalForm(PDBM pdbm, cindex_t dim) { - int32_t* rates = pdbm_rates(pdbm); + double* rates = pdbm_rates(pdbm); cindex_t next[dim]; cindex_t i; From c269e6f38de42bfb75a61cfb5ba28fe47c655395 Mon Sep 17 00:00:00 2001 From: Ragusaen Date: Wed, 15 Mar 2023 09:08:04 +0100 Subject: [PATCH 14/32] fixed some bugs with negative costs --- CMakeLists.txt | 3 +++ include/dbm/pfed.h | 5 ++++- src/pfed.cpp | 7 +++---- src/priced.cpp | 8 +++++--- 4 files changed, 15 insertions(+), 8 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 13d46a1..c131b24 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -25,6 +25,9 @@ if(STATIC) set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-Bstatic,--whole-archive -lwinpthread -Wl,--no-whole-archive") endif(STATIC) + +set(CMAKE_BUILD_TYPE Debug) + target_include_directories(UDBM PRIVATE # where the library itself will look for its internal headers diff --git a/include/dbm/pfed.h b/include/dbm/pfed.h index 4abd984..6701505 100644 --- a/include/dbm/pfed.h +++ b/include/dbm/pfed.h @@ -697,7 +697,10 @@ namespace dbm /* * Non-exact union. Keeps all zones that are not subseteq of another zone. Returns true if the zones changed. */ - bool unionWith(pfed_t& arg); + bool unionWith(const pfed_t& arg); + + // Performs unionWith operation and returns whether the fed changed + bool unionWithChanged(const pfed_t& arg) { return unionWith(pfed_t(arg)); }; /// Not implemented int32_t maxOnZero(cindex_t clock); diff --git a/src/pfed.cpp b/src/pfed.cpp index e35ab32..52c1746 100644 --- a/src/pfed.cpp +++ b/src/pfed.cpp @@ -212,8 +212,6 @@ namespace dbm pfed_t& pfed_t::up(int32_t rate) { - assert(rate >= 0); - uint32_t dim = ptr->dim; prepare(); @@ -598,11 +596,11 @@ namespace dbm throw std::logic_error("pfed_t::eq not implemented"); } - bool pfed_t::unionWith(pfed_t& other) { + bool pfed_t::unionWith(const pfed_t& other) { assert(ptr->dim == other.ptr->dim); bool changed = false; - for (auto ot = other.beginMutable(); ot != other.endMutable(); ++ot) { + for (auto ot = other.begin(); ot != other.end(); ++ot) { bool maybe_insert = true; bool definitely_insert = false; for (auto it = beginMutable(); it != endMutable();) { @@ -627,6 +625,7 @@ namespace dbm return changed; } + int32_t pfed_t::maxOnZero(cindex_t x){ throw std::logic_error("pfed_t::maxOnZero not implemented"); } diff --git a/src/priced.cpp b/src/priced.cpp index 0c64c21..7e2b4c7 100644 --- a/src/priced.cpp +++ b/src/priced.cpp @@ -930,11 +930,13 @@ void pdbm_diagonalExtrapolateLUBounds(PDBM& pdbm, cindex_t dim, int32_t* lower, void pdbm_incrementCost(PDBM& pdbm, cindex_t dim, int32_t value) { - assert(pdbm && dim && value >= 0); + assert(pdbm && dim); pdbm_prepare(pdbm, dim); pdbm_cost(pdbm) += value; - pdbm_cache(pdbm) += value; + if (pdbm_cache(pdbm) != INVALID && pdbm_cache(pdbm) != -dbm_INFINITY) { + pdbm_cache(pdbm) += value; + } assertx(pdbm_isValid(pdbm, dim)); } @@ -1244,7 +1246,7 @@ bool pdbm_isValid(const PDBM pdbm, cindex_t dim) int32_t inf = pdbm_infimum(dbm, dim, cost, rates); return (cache == INVALID || cache == inf) && dbm_isValid(dbm, dim) && rates[0] == 0 && - (!pdbm_isUnbounded(pdbm, dim) || pdbm_getSlopeOfDelayTrajectory(pdbm, dim) >= 0); + (!(pdbm_isUnbounded(pdbm, dim) && pdbm_getSlopeOfDelayTrajectory(pdbm, dim) < 0) || inf == -dbm_INFINITY); } void pdbm_freeClock(PDBM& pdbm, cindex_t dim, cindex_t clock) From 1824e1239641e6051627c70fda3e7103eb5c3e27 Mon Sep 17 00:00:00 2001 From: Ragusaen Date: Wed, 15 Mar 2023 10:30:16 +0100 Subject: [PATCH 15/32] add offsetcost function --- include/dbm/pfed.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/include/dbm/pfed.h b/include/dbm/pfed.h index 6701505..55b1814 100644 --- a/include/dbm/pfed.h +++ b/include/dbm/pfed.h @@ -97,6 +97,11 @@ namespace dbm */ operator PDBM() const { return pdbm; } + /** + * Returns the cost of the offset point in the pdbm. + */ + int32_t getOffsetCost() const { return pdbm_getCostAtOffset(pdbm, dim); }; + /** * Returns a hash value for the priced DBM. */ From 540096e3f4f2741188f4d54c2f747e1dc982f7a8 Mon Sep 17 00:00:00 2001 From: Slorup Date: Wed, 15 Mar 2023 10:31:21 +0100 Subject: [PATCH 16/32] Fixed bugs with double changes --- CMakeLists.txt | 2 ++ src/infimum.cpp | 5 +++-- src/priced.cpp | 41 ++++++++++++++++++++++++----------------- 3 files changed, 29 insertions(+), 19 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 13d46a1..930ac86 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,6 +6,8 @@ include(GNUInstallDirs) option(TESTING OFF) option(STATIC OFF) +set(CMAKE_BUILD_TYPE Debug) + cmake_policy(SET CMP0048 NEW) # project() command manages VERSION variables set(CMAKE_CXX_STANDARD 17) set(UDBM_PACKAGE_STRING "${PACKAGE_NAME} ${PACKAGE_VERSION}") diff --git a/src/infimum.cpp b/src/infimum.cpp index 903f582..2e7406f 100644 --- a/src/infimum.cpp +++ b/src/infimum.cpp @@ -8,6 +8,7 @@ #include #include +#include /* * constraintValue(i,j) @@ -597,7 +598,7 @@ static Node* discoverCycleRoot(Node* k, Node* l) */ static Node* findLeavingArc(Node* k, Node* l, Node* root) { - double smallestFlow = INT_MAX; + double smallestFlow = std::numeric_limits::infinity(); /* * Node with the lowest depth of the leaving arc. */ @@ -630,7 +631,7 @@ static Node* findLeavingArc(Node* k, Node* l, Node* root) } l = l->pred; } - ASSERT(smallestFlow != INT_MAX, std::cerr << "No oppositely directed arcs" << std::endl); + ASSERT(smallestFlow != std::numeric_limits::infinity(), std::cerr << "No oppositely directed arcs" << std::endl); return smallestFlowNode; } diff --git a/src/priced.cpp b/src/priced.cpp index 64cb173..93b88c8 100644 --- a/src/priced.cpp +++ b/src/priced.cpp @@ -28,7 +28,7 @@ struct PDBM_s uint32_t count; double cost; double infimum; - std::vector rates; + double* rates; int32_t data[]; }; @@ -46,7 +46,7 @@ bool are_same(double a, double b) #define pdbm_cost(pdbm) ((pdbm)->cost) /** Returns the vectors of coefficients. */ -#define pdbm_rates(pdbm) ((pdbm)->rates.data()) +#define pdbm_rates(pdbm) ((pdbm)->rates) /** Returns the matrix. */ #define pdbm_matrix(pdbm) ((pdbm)->data) @@ -141,7 +141,8 @@ static void pdbm_blank(PDBM& pdbm, cindex_t dim) size_t pdbm_size(cindex_t dim) { assert(dim); - return sizeof(struct PDBM_s) + (dim * dim) * sizeof(int32_t) + dim * sizeof(double); + return sizeof(struct PDBM_s) + (dim * dim) * sizeof(int32_t); + //return sizeof(struct PDBM_s) + (dim * dim) * sizeof(int32_t) + dim * sizeof(double); } PDBM pdbm_reserve(cindex_t dim, void* p) @@ -151,7 +152,9 @@ PDBM pdbm_reserve(cindex_t dim, void* p) PDBM pdbm = (PDBM)p; pdbm_count(pdbm) = 0; pdbm_cache(pdbm) = INVALID; - pdbm_rates(pdbm)[0] = 0; + pdbm_rates(pdbm) = (double*)malloc(sizeof(double) * dim); + std::fill(pdbm_rates(pdbm), pdbm_rates(pdbm) + dim, 0.0); + return pdbm; } @@ -165,6 +168,7 @@ void pdbm_deallocate(PDBM& pdbm) { assert(pdbm == nullptr || pdbm_count(pdbm) == 0); + free(pdbm->rates); free(pdbm); /* Setting the pointer to NULL protects against accidental use of @@ -182,6 +186,8 @@ PDBM pdbm_copy(PDBM dst, const PDBM src, cindex_t dim) } memcpy(dst, src, pdbm_size(dim)); + dst->rates = (double*)malloc(sizeof(double) * dim); + std::copy(src->rates, src->rates + dim, dst->rates); pdbm_count(dst) = 0; return dst; @@ -195,8 +201,8 @@ void pdbm_init(PDBM& pdbm, cindex_t dim) dbm_init(pdbm_matrix(pdbm), dim); pdbm_cost(pdbm) = 0; pdbm_cache(pdbm) = 0; - auto* r = pdbm_rates(pdbm); - std::fill(r, r + dim, 0); + double* r = pdbm_rates(pdbm); + std::fill(r, r + dim, 0.0); assertx(pdbm_isValid(pdbm, dim)); } @@ -209,8 +215,8 @@ void pdbm_zero(PDBM& pdbm, cindex_t dim) dbm_zero(pdbm_matrix(pdbm), dim); pdbm_cost(pdbm) = 0; pdbm_cache(pdbm) = 0; - auto* r = pdbm_rates(pdbm); - std::fill(r, r + dim, 0); + double* r = pdbm_rates(pdbm); + std::fill(r, r + dim, 0.0); assertx(pdbm_isValid(pdbm, dim)); } @@ -984,15 +990,16 @@ int32_t* pdbm_writeToMinDBMWithOffset(const PDBM pdbm, cindex_t dim, bool minimi void pdbm_readFromMinDBM(PDBM& dst, cindex_t dim, mingraph_t src) { - assert(dst && dim); - - pdbm_blank(dst, dim); - pdbm_cost(dst) = src[0]; - pdbm_cache(dst) = src[1]; - std::copy(src + 2, src + 2 + dim, pdbm_rates(dst)); - dbm_readFromMinDBM(pdbm_matrix(dst), src + dim + 2); - - assertx(pdbm_isValid(dst, dim)); + throw std::logic_error("pdbm_readFromMinDBM not implemented"); +// assert(dst && dim); +// +// pdbm_blank(dst, dim); +// pdbm_cost(dst) = src[0]; +// pdbm_cache(dst) = src[1]; +// std::copy(src + 2, src + 2 + dim, pdbm_rates(dst)); +// dbm_readFromMinDBM(pdbm_matrix(dst), src + dim + 2); +// +// assertx(pdbm_isValid(dst, dim)); } bool pdbm_findNextZeroCycle(const PDBM pdbm, cindex_t dim, cindex_t x, cindex_t* out) From 382842a269200f9304600094d533056846172b47 Mon Sep 17 00:00:00 2001 From: Slorup Date: Wed, 15 Mar 2023 10:36:43 +0100 Subject: [PATCH 17/32] smol --- include/dbm/pfed.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/dbm/pfed.h b/include/dbm/pfed.h index 45364be..5ce8918 100644 --- a/include/dbm/pfed.h +++ b/include/dbm/pfed.h @@ -100,7 +100,7 @@ namespace dbm /** * Returns the cost of the offset point in the pdbm. */ - int32_t getOffsetCost() const { return pdbm_getCostAtOffset(pdbm, dim); }; + [[nodiscard]] double getOffsetCost() const { return pdbm_getCostAtOffset(pdbm, dim); }; /** * Returns a hash value for the priced DBM. From d66ca6b1106a86f9944095b46484882a45185d66 Mon Sep 17 00:00:00 2001 From: Ragusaen Date: Fri, 17 Mar 2023 14:42:20 +0100 Subject: [PATCH 18/32] bug fixes --- CMakeLists.txt | 2 ++ getlibs.sh | 7 ++++++ include/dbm/pfed.h | 19 +++++++++++++++ include/dbm/priced.h | 9 ++++++++ src/infimum.cpp | 31 ++++++++++++++----------- src/infimum.h | 5 ++++ src/pfed.cpp | 17 +++++++++++++- src/priced.cpp | 55 ++++++++++++++++++++++---------------------- 8 files changed, 103 insertions(+), 42 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 25fbd24..67d3510 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -19,6 +19,8 @@ set(CMAKE_PREFIX_PATH "${CMAKE_PREFIX_PATH};${CMAKE_CURRENT_SOURCE_DIR}/libs") find_package(xxHash 0.8.0 CONFIG REQUIRED) find_package(UUtils 1.1.1 REQUIRED COMPONENTS base hash debug) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/libs) + add_library(UDBM src/DBMAllocator.cpp src/dbm.c src/fed_dbm.cpp src/mingraph.c src/mingraph_read.c src/partition.cpp src/print.cpp src/gen.c src/mingraph_cache.cpp src/mingraph_relation.c src/pfed.cpp src/fed.cpp src/infimum.cpp src/mingraph_equal.c src/mingraph_write.c src/priced.cpp) target_link_libraries(UDBM UUtils::base UUtils::udebug UUtils::hash) diff --git a/getlibs.sh b/getlibs.sh index 85b0684..02111bf 100755 --- a/getlibs.sh +++ b/getlibs.sh @@ -35,3 +35,10 @@ cd build cmake $CMAKE_ARGS -DCMAKE_INSTALL_PREFIX="$SOURCE_DIR/libs/UUtils" .. cmake --build . --config Release cmake --install . --config Release + +cd $SOURCE_DIR/libs/sources; +wget -nc https://boostorg.jfrog.io/artifactory/main/release/1.81.0/source/boost_1_81_0.tar.gz +tar -xvf boost_1_81_0.tar.gz +mkdir -p "$SOURCE_DIR/libs/sources/boost_1_81_0/build" +cd "$SOURCE_DIR/libs/sources/boost_1_81_0/build" +cp -r "$SOURCE_DIR/libs/sources/boost_1_81_0/boost" "$SOURCE_DIR/libs/" diff --git a/include/dbm/pfed.h b/include/dbm/pfed.h index 5ce8918..76aecfc 100644 --- a/include/dbm/pfed.h +++ b/include/dbm/pfed.h @@ -102,6 +102,8 @@ namespace dbm */ [[nodiscard]] double getOffsetCost() const { return pdbm_getCostAtOffset(pdbm, dim); }; + bool constrain(cindex_t i, cindex_t j, raw_t c); + /** * Returns a hash value for the priced DBM. */ @@ -124,6 +126,11 @@ namespace dbm /** @see dbm_t::getDBM() */ raw_t* getDBM(); + /** Converts the pdbm_t to a dbm_t, discarding the cost information */ + dbm_t to_dbm() const { return dbm_t(const_dbm(), dim); }; + + static pdbm_t from_dbm(const dbm_t& dbm) { return pdbm_t(pdbm_from_dbm(dbm.const_dbm(), dbm.getDimension()), dbm.getDimension()); }; + /** @see dbm_t::analyseForMinDBM() */ size_t analyzeForMinDBM(uint32_t* bitMatrix) const; @@ -134,6 +141,15 @@ namespace dbm /** @see pdbm_relationWithMinDBM() */ relation_t relation(const int32_t*, raw_t*) const; + /* + * Compares the cost of this pdbm with the cost of the other pdbm, where their zones are identical. + * Returns a pair of the relation between the two costs and a strictness. + */ + [[nodiscard]] std::pair compare_to_identical(const pdbm_t& other) const { + auto [rel, is_strict] = pdbm_compare_cost_identical_pdbms(pdbm, other.pdbm, dim); + return std::make_pair(rel, is_strict ? strictness_t::dbm_STRICT : strictness_t::dbm_WEAK); + }; + /** @see dbm_t::freeClock() */ pdbm_t& freeClock(cindex_t clock); @@ -484,6 +500,9 @@ namespace dbm pfed_t& predt(const pfed_t& bad, const raw_t* restrict = NULL); + + [[nodiscard]] fed_t to_fed() const; + /** * Returns true iff the federation contains \v, ignoring * strictness of constraints. diff --git a/include/dbm/priced.h b/include/dbm/priced.h index 43f39f2..0d4c46f 100644 --- a/include/dbm/priced.h +++ b/include/dbm/priced.h @@ -65,6 +65,13 @@ * DBMs allocated in this manner must not be reference counted. */ +#include + +/** + * The type used to represent cost in the pdbm + */ +typedef boost::rational CostType; + /** * Data type for priced dbm. */ @@ -800,6 +807,8 @@ bool pdbm_hasNormalForm(PDBM pdbm, cindex_t dim); */ void pdbm_normalise(PDBM pdbm, cindex_t dim); +PDBM pdbm_from_dbm(const int32_t* dbm, cindex_t dim); + /////////////////////////////////////////////////////////////////////////// #endif /* INCLUDE_DBM_PRICED_H */ diff --git a/src/infimum.cpp b/src/infimum.cpp index 2e7406f..24b8c28 100644 --- a/src/infimum.cpp +++ b/src/infimum.cpp @@ -42,7 +42,7 @@ struct Node Node* thread; /**< Next according to the preorder. */ bool inbound; /**< Is the arc pointing to me or away. */ double flow; /**< Flow for the current solution. */ - double potential; /**< Node potential for spanning tree solution. */ + int32_t potential; /**< Node potential for spanning tree solution. */ }; /* @@ -111,7 +111,7 @@ static bool checkTreeIntegrity(const raw_t* dbm, const double* rates, Node* node } } for (i = 0; i < dim; i++) { - if (sum[i] != 0) { + if (!are_same(sum[i], 0.0)) { treeOK = false; std::cerr << "sum[" << i << "] is corrupted: " << sum[i] << ", should be: " << (i == 0 ? total : b(i)) << std::endl; @@ -258,7 +258,7 @@ static void findInitialSpanningTreeSolution(const raw_t* dbm, uint32_t dim, cons node->depth = 0; node->thread = nodes + 1; node->inbound = 0; - node->flow = -1; + node->flow = -1.0; node->potential = 0; for (node++; node != last; node++) { @@ -289,7 +289,7 @@ static void findInitialSpanningTreeSolution(const raw_t* dbm, uint32_t dim, cons * Pre: leave should be on the path from arcs[enter].{i,j} to the root. */ -static void updatePotentials(Node* leave, double change) +static void updatePotentials(Node* leave, int32_t change) { /* Update the entire subtree rooted at leave with a change * corresponding the reduced cost of the entering arc. This is @@ -480,7 +480,7 @@ static void updateFlowInCycle(Node* k, Node* l, Node* root, double flowToAugment if (flowToAugment > 0) { while (k != root) { k->flow += k->inbound ? flowToAugment : -flowToAugment; - ASSERT(k->flow >= 0, std::cerr << "flow(" << k << "): " << k->flow << std::endl); + ASSERT(k->flow + epsilon >= 0.0, std::cerr << "flow(" << k << "): " << k->flow << std::endl); k = k->pred; } while (l != root) { @@ -495,9 +495,9 @@ static void updateFlowInCycle(Node* k, Node* l, Node* root, double flowToAugment * Update the spanning tree so the node information is updated * including flow and node potentials. */ -static void updateSpanningTree(Node* k, Node* l, Node* leave, Node* root, double costEnter) +static void updateSpanningTree(Node* k, Node* l, Node* leave, Node* root, int32_t costEnter) { - double reducedCostEnter = costEnter - k->potential + l->potential; + int32_t reducedCostEnter = costEnter - k->potential + l->potential; double flowToAugment = leave->flow; updateFlowInCycle(k, l, root, flowToAugment); if (!isPredecessorOf(leave, k)) { @@ -623,7 +623,7 @@ static Node* findLeavingArc(Node* k, Node* l, Node* root) while (l != root) { if (l->inbound) // If inbound then opposite of (i,j) { - if (l->flow <= smallestFlow) // <= since we need the last along (i,j) + if (l->flow <= smallestFlow + epsilon) // <= since we need the last along (i,j) { smallestFlow = l->flow; smallestFlowNode = l; @@ -648,13 +648,13 @@ static Node* findLeavingArc(Node* k, Node* l, Node* root) static void testAndRemoveArtificialArcs(const raw_t* dbm, const double* rates, Node* nodes, uint32_t dim) { for (uint32_t i = 1; i < dim; i++) { - if (potential(i) == dbm_INFINITY && pred(i) == 0 && flow(i) == 0) { + if (potential(i) == dbm_INFINITY && pred(i) == 0 && are_same(flow(i), 0)) { inbound(i) = true; Node* tmp = nodes[i].thread; double rateSum = b(i); - double minPotential = dbm_INFINITY + constraintValue(0, i); + int32_t minPotential = dbm_INFINITY + constraintValue(0, i); /* * Find the highest potential we can decrease i with and @@ -666,7 +666,7 @@ static void testAndRemoveArtificialArcs(const raw_t* dbm, const double* rates, N minPotential = tmp->potential; tmp = tmp->thread; } - assert(rateSum == 0); + assert(are_same(rateSum, 0)); /* * Update all potentials in the thread by subtracting @@ -783,8 +783,8 @@ double pdbm_infimum(const raw_t* dbm, uint32_t dim, double offsetCost, const dou * Check if best solution has positive flow on artificial arc * if so, return minus infinity as the solution is unbounded. */ - if (potential(i) == dbm_INFINITY && pred(i) == 0 && flow(i) > 0) { - return -dbm_INFINITY; + if (potential(i) == dbm_INFINITY && pred(i) == 0 && flow(i) + epsilon > 0.0) { + return -std::numeric_limits::infinity(); } solution += rates[i] * (potential(i) + constraintValue(0, i)); } @@ -815,7 +815,7 @@ void pdbm_infimum(const raw_t* dbm, uint32_t dim, double offsetCost, const doubl * if so, infimum is not well defined as it is minus infinity * and we throw an exception. */ - if (potential(i) == dbm_INFINITY && pred(i) == 0 && flow(i) > 0) { + if (potential(i) == dbm_INFINITY && pred(i) == 0 && flow(i) + epsilon > 0.0) { throw std::domain_error("Infimum is downward unbound, thus, no well-defined infimum valuation."); } @@ -823,3 +823,6 @@ void pdbm_infimum(const raw_t* dbm, uint32_t dim, double offsetCost, const doubl } } } + + +bool are_same(double a, double b) { return std::abs(a - b) < epsilon; } diff --git a/src/infimum.h b/src/infimum.h index 1f47ca6..ef2bad8 100644 --- a/src/infimum.h +++ b/src/infimum.h @@ -12,6 +12,11 @@ #include "dbm/constraints.h" +#include + +const double epsilon = 0.000001; +bool are_same(double a, double b); + double pdbm_infimum(const raw_t* dbm, uint32_t dim, double offsetCost, const double* rates); void pdbm_infimum(const raw_t* dbm, uint32_t dim, double offsetCost, const double* rates, int32_t* valuation); diff --git a/src/pfed.cpp b/src/pfed.cpp index e23d317..3a3d5d3 100644 --- a/src/pfed.cpp +++ b/src/pfed.cpp @@ -403,6 +403,14 @@ namespace dbm return *this; } + fed_t pfed_t::to_fed() const { + fed_t fed; + for (const pdbm_t& pdbm : *this) { + fed.add(pdbm.to_dbm()); + } + return fed; + } + pfed_t& pfed_t::operator|=(const pfed_t& pfed) { // REVISIT: Eliminate included zones. @@ -573,8 +581,15 @@ namespace dbm throw std::logic_error("pfed_t::getDelay not implemented"); } + bool pdbm_t::constrain(cindex_t i, cindex_t j, raw_t c) { + if (!isEmpty()) { + return pdbm_constrain1(pdbm, dim, i, j, c); + } + return false; + } + bool pdbm_t::isEmpty() const { - throw std::logic_error("pdbm_t::isEmpty not implemented"); + return pdbm_isEmpty(pdbm, dim); } bool pfed_t::le(const pfed_t& arg) const { diff --git a/src/priced.cpp b/src/priced.cpp index 225943b..207ca66 100644 --- a/src/priced.cpp +++ b/src/priced.cpp @@ -21,7 +21,7 @@ #include #include #include -#include +#include struct PDBM_s { @@ -32,13 +32,6 @@ struct PDBM_s int32_t data[]; }; -double epsilon = DBL_EPSILON;//TODO: Change epsilon - -bool are_same(double a, double b) -{ - return std::abs(a - b) < epsilon; -} - /** Convenient macro for accessing DBM entries. */ #define DBM(I, J) dbm[(I)*dim + (J)] @@ -58,7 +51,7 @@ bool are_same(double a, double b) #define pdbm_count(pdbm) ((pdbm)->count) /** Constant to mark the cached infimum as void. */ -#define INVALID INT_MAX +#define INVALID std::numeric_limits::infinity() #ifndef NDEBUG /** @@ -409,21 +402,21 @@ std::pair pdbm_compare_cost_identical_pdbms(const PDBM pdbm1, * see which one is cheaper. */ double c = infOfDiff(dbm1, dim, cost2, rates2, cost1, rates1); - if (c > 0) { + if (c - epsilon > 0.0) { return {base_SUPERSET, true}; } double d = infOfDiff(dbm1, dim, cost1, rates1, cost2, rates2); - if (c == 0 && d == 0) { + if (are_same(c, 0.0) && are_same(d, 0.0)) { return {base_EQUAL, false}; } - if (d > 0) { + if (d - epsilon > 0.0) { return {base_SUBSET, true}; } - if (c >= 0) { + if (c + epsilon >= 0) { return {base_SUPERSET, false}; } - if (d >= 0) { + if (d + epsilon >= 0) { return {base_SUBSET, false}; } return {base_DIFFERENT, false}; @@ -500,7 +493,7 @@ relation_t pdbm_relation(const PDBM pdbm1, const PDBM pdbm2, cindex_t dim) * unpack dbm2. */ c = infOfDiff(dbm1, dim, cost2, rates2, cost1, rates1); - if (c > 0) { + if (c - epsilon > 0.0) { /* Early return to avoid unnecessary computation of the * second subtraction. */ @@ -508,13 +501,13 @@ relation_t pdbm_relation(const PDBM pdbm1, const PDBM pdbm2, cindex_t dim) } d = infOfDiff(dbm1, dim, cost1, rates1, cost2, rates2); - if (c == 0 && d == 0) { + if (are_same(c, 0.0) && are_same(d, 0.0)) { return base_EQUAL; } - if (c >= 0) { + if (c + epsilon >= 0) { return base_SUPERSET; } - if (d >= 0) { + if (d + epsilon >= 0) { return base_SUBSET; } return base_DIFFERENT; @@ -697,7 +690,7 @@ bool pdbm_satisfies(const PDBM pdbm, cindex_t dim, cindex_t i, cindex_t j, raw_t bool pdbm_isEmpty(const PDBM pdbm, cindex_t dim) { - assert(pdbm && dim); + assert(dim); return pdbm == nullptr || dbm_isEmpty(pdbm_matrix(pdbm), dim); } @@ -773,6 +766,7 @@ void pdbm_upZero(PDBM& pdbm, cindex_t dim, double rate, cindex_t zero) dbm_up(dbm, dim); rates[zero] = 0; rates[zero] = rate - pdbm_getSlopeOfDelayTrajectory(pdbm, dim); + pdbm->infimum = INVALID; assertx(pdbm_isValid(pdbm, dim)); } @@ -908,11 +902,11 @@ void pdbm_diagonalExtrapolateMaxBounds(PDBM& pdbm, cindex_t dim, int32_t* max) } /* It is only safe to extrapolate clocks with a zero cost rate. */ - for (cindex_t i = 1; i < dim; i++) { - if (rates[i] != 0) { - max[i] = dbm_INFINITY; - } - } +// for (cindex_t i = 1; i < dim; i++) { +// if (rates[i] != 0) { +// max[i] = dbm_INFINITY; +// } +// } pdbm_prepare(pdbm, dim); dbm_diagonalExtrapolateMaxBounds(pdbm_matrix(pdbm), dim, max); @@ -949,7 +943,7 @@ void pdbm_incrementCost(PDBM& pdbm, cindex_t dim, double value) pdbm_prepare(pdbm, dim); pdbm_cost(pdbm) += value; - if (pdbm_cache(pdbm) != INVALID && pdbm_cache(pdbm) != -dbm_INFINITY) { + if (pdbm_cache(pdbm) != INVALID && pdbm_cache(pdbm) != -std::numeric_limits::infinity()) { pdbm_cache(pdbm) += value; } @@ -1262,8 +1256,8 @@ bool pdbm_isValid(const PDBM pdbm, cindex_t dim) double cache = pdbm_cache(pdbm); double inf = pdbm_infimum(dbm, dim, cost, rates); - return (cache == INVALID || cache == inf) && dbm_isValid(dbm, dim) && rates[0] == 0 && - (!(pdbm_isUnbounded(pdbm, dim) && pdbm_getSlopeOfDelayTrajectory(pdbm, dim) < 0) || inf == -dbm_INFINITY); + return (cache == INVALID || cache == inf) && dbm_isValid(dbm, dim) && rates[0] == 0.0 && + (!(pdbm_isUnbounded(pdbm, dim) && pdbm_getSlopeOfDelayTrajectory(pdbm, dim) < 0) || inf == -std::numeric_limits::infinity()); } void pdbm_freeClock(PDBM& pdbm, cindex_t dim, cindex_t clock) @@ -1436,3 +1430,10 @@ bool pdbm_hasNormalForm(PDBM pdbm, cindex_t dim) return true; } + + +PDBM pdbm_from_dbm(const int32_t* dbm, cindex_t dim) { + PDBM pdbm = pdbm_allocate(dim); + memcpy(pdbm->data, dbm, dim * dim * sizeof(int32_t)); + return pdbm; +} \ No newline at end of file From 6b72e92733955766a78e80f5b0cd20e5dc313981 Mon Sep 17 00:00:00 2001 From: Ragusaen Date: Fri, 24 Mar 2023 10:09:27 +0100 Subject: [PATCH 19/32] changed double cost to rational cost type --- include/dbm/cost_type.h | 16 ++++ include/dbm/pfed.h | 18 ++-- include/dbm/priced.h | 30 +++---- src/infimum.cpp | 61 +++++++------- src/infimum.h | 7 +- src/pfed.cpp | 35 ++++---- src/priced.cpp | 176 +++++++++++++++++++++------------------- 7 files changed, 180 insertions(+), 163 deletions(-) create mode 100644 include/dbm/cost_type.h diff --git a/include/dbm/cost_type.h b/include/dbm/cost_type.h new file mode 100644 index 0000000..766b1c0 --- /dev/null +++ b/include/dbm/cost_type.h @@ -0,0 +1,16 @@ +// +// Created by ragusa on 3/17/23. +// + +#ifndef UDBM_COST_TYPE_H +#define UDBM_COST_TYPE_H + +#include + +/** + * The type used to represent cost in the pdbm + */ +typedef boost::rational CostType; +const CostType INFINITE_COST = (CostType)INT_MAX; + +#endif // UDBM_COST_TYPE_H diff --git a/include/dbm/pfed.h b/include/dbm/pfed.h index 76aecfc..fd02453 100644 --- a/include/dbm/pfed.h +++ b/include/dbm/pfed.h @@ -14,8 +14,10 @@ #include "fed.h" #include "dbm/priced.h" +#include "dbm/cost_type.h" #include + #include @@ -100,7 +102,11 @@ namespace dbm /** * Returns the cost of the offset point in the pdbm. */ - [[nodiscard]] double getOffsetCost() const { return pdbm_getCostAtOffset(pdbm, dim); }; + [[nodiscard]] CostType getOffsetCost() const { return pdbm_getCostAtOffset(pdbm, dim); }; + + [[nodiscard]] CostType getInfimum() const { return pdbm_getInfimum(pdbm, dim); }; + + [[nodiscard]] const CostType* getRates() const { return pdbm_getRates(pdbm, dim); }; bool constrain(cindex_t i, cindex_t j, raw_t c); @@ -463,7 +469,7 @@ namespace dbm bool constrain(const constraint_t& c); /** Returns the infimum of the federation. */ - double getInfimum() const; + CostType getInfimum() const; /** * Check if the federation satisfies a given constraint. @@ -513,7 +519,7 @@ namespace dbm pfed_t& up(); /** Delay with rate \a rate. */ - pfed_t& up(double rate); + pfed_t& up(CostType rate); /** Set x(clock) to \a value. */ pfed_t& updateValue(cindex_t clock, uint32_t value); @@ -528,9 +534,9 @@ namespace dbm void diagonalExtrapolateMaxBounds(int32_t* max); void diagonalExtrapolateLUBounds(int32_t* lower, int32_t* upper); - void incrementCost(double value); + void incrementCost(CostType value); - double getCostOfValuation(const IntValuation& valuation) const; + CostType getCostOfValuation(const IntValuation& valuation) const; void relax(); @@ -767,7 +773,7 @@ namespace dbm * Returns the infimum of the federation given a partial * valuation. */ - double getInfimumValuation(IntValuation& valuation, const bool* free = nullptr) const; + CostType getInfimumValuation(IntValuation& valuation, const bool* free = nullptr) const; /** Returns the number of zones in the federation. */ size_t size() const; diff --git a/include/dbm/priced.h b/include/dbm/priced.h index 0d4c46f..2912461 100644 --- a/include/dbm/priced.h +++ b/include/dbm/priced.h @@ -15,6 +15,7 @@ #include "dbm/dbm.h" #include "dbm/mingraph.h" #include "base/inttypes.h" +#include "dbm/cost_type.h" #include #include @@ -65,13 +66,6 @@ * DBMs allocated in this manner must not be reference counted. */ -#include - -/** - * The type used to represent cost in the pdbm - */ -typedef boost::rational CostType; - /** * Data type for priced dbm. */ @@ -286,7 +280,7 @@ relation_t pdbm_relationWithMinDBM(const PDBM pdbm, cindex_t dim, const mingraph * @param dim is the dimension of \a pdbm. * @return The infimum cost of \a pdbm. */ -double pdbm_getInfimum(const PDBM pdbm, cindex_t dim); +CostType pdbm_getInfimum(const PDBM pdbm, cindex_t dim); /** * Generates a valuation which has the infimum cost of the priced DBM. @@ -310,7 +304,7 @@ double pdbm_getInfimum(const PDBM pdbm, cindex_t dim); * @throw out_of_range if no valuation with the given constraints can * be found. */ -double pdbm_getInfimumValuation(const PDBM pdbm, cindex_t dim, int32_t* valuation, const bool* free); +CostType pdbm_getInfimumValuation(const PDBM pdbm, cindex_t dim, int32_t* valuation, const bool* free); /** * Check if a priced DBM satisfies a given constraint. @@ -406,7 +400,7 @@ void pdbm_up(PDBM& pdbm, cindex_t dim); * reference clock. * @post The priced DBM is closed. */ -void pdbm_upZero(PDBM& pdbm, cindex_t dim, double rate, cindex_t zero); +void pdbm_upZero(PDBM& pdbm, cindex_t dim, CostType rate, cindex_t zero); /** * Updates \a clock to \a value. This is only legitimate if the @@ -477,7 +471,7 @@ void pdbm_diagonalExtrapolateLUBounds(PDBM& pdbm, cindex_t dim, int32_t* lower, * @post The priced DBM is closed. * @pre value >= 0 */ -void pdbm_incrementCost(PDBM& pdbm, cindex_t dim, double value); +void pdbm_incrementCost(PDBM& pdbm, cindex_t dim, CostType value); /** * Compute the closure of a priced DBM. This function is only relevant @@ -590,7 +584,7 @@ bool pdbm_findNextZeroCycle(const PDBM pdbm, cindex_t dim, cindex_t x, cindex_t* * @param pdbm is a closed priced DBM of dimension \a dim. * @param dim is the dimension of \a pdbm. */ -double pdbm_getSlopeOfDelayTrajectory(const PDBM pdbm, cindex_t dim); +CostType pdbm_getSlopeOfDelayTrajectory(const PDBM pdbm, cindex_t dim); /** * Returns the rate (coefficient of the hyperplane) of \a clock. @@ -600,9 +594,9 @@ double pdbm_getSlopeOfDelayTrajectory(const PDBM pdbm, cindex_t dim); * @param clock is the clock for which to return the coefficient. * @return the rate of \a clock. */ -double pdbm_getRate(const PDBM pdbm, cindex_t dim, cindex_t clock); +CostType pdbm_getRate(const PDBM pdbm, cindex_t dim, cindex_t clock); -const double* pdbm_getRates(const PDBM pdbm, cindex_t dim); +const CostType* pdbm_getRates(const PDBM pdbm, cindex_t dim); /** * Returns the cost of the offset point. @@ -610,7 +604,7 @@ const double* pdbm_getRates(const PDBM pdbm, cindex_t dim); * @param pdbm is a closed priced DBM of dimension \a dim. * @param dim is the dimension of \a pdbm. */ -double pdbm_getCostAtOffset(const PDBM pdbm, cindex_t dim); +CostType pdbm_getCostAtOffset(const PDBM pdbm, cindex_t dim); /** * Sets the cost at the offset point. @@ -624,7 +618,7 @@ double pdbm_getCostAtOffset(const PDBM pdbm, cindex_t dim); * @param dim is the dimension of \a pdbm. * @param value is the new cost of the offset point. */ -void pdbm_setCostAtOffset(PDBM& pdbm, cindex_t dim, double value); +void pdbm_setCostAtOffset(PDBM& pdbm, cindex_t dim, CostType value); /** * Returns true if the DBM is valid. Useful for debugging. @@ -693,7 +687,7 @@ uint32_t pdbm_getUpperFacets(PDBM& pdbm, cindex_t dim, cindex_t* facets); * @pre pdbm_containsInt(pdbm, dim, valuation) * @return The cost of \a valuation in \a pdbm. */ -double pdbm_getCostOfValuation(const PDBM pdbm, cindex_t dim, const int32_t* valuation); +CostType pdbm_getCostOfValuation(const PDBM pdbm, cindex_t dim, const int32_t* valuation); /** * Makes all strong constraints of a priced DBM weak. @@ -722,7 +716,7 @@ void pdbm_getOffset(const PDBM pdbm, cindex_t dim, int32_t* valuation); * @param clock is the index of a clock for which to set the coefficient. * @param rate is the coefficient. */ -void pdbm_setRate(PDBM& pdbm, cindex_t dim, cindex_t clock, double rate); +void pdbm_setRate(PDBM& pdbm, cindex_t dim, cindex_t clock, CostType rate); /** * Returns the inner matrix of a priced DBM. The matrix can be diff --git a/src/infimum.cpp b/src/infimum.cpp index 24b8c28..0eeeb26 100644 --- a/src/infimum.cpp +++ b/src/infimum.cpp @@ -41,7 +41,7 @@ struct Node uint32_t depth; /**< Depth from root (Always node0). */ Node* thread; /**< Next according to the preorder. */ bool inbound; /**< Is the arc pointing to me or away. */ - double flow; /**< Flow for the current solution. */ + CostType flow; /**< Flow for the current solution. */ int32_t potential; /**< Node potential for spanning tree solution. */ }; @@ -62,14 +62,14 @@ static void printSimpleNodeInfo(Node* nodes, uint32_t i) << ", inbound: " << inbound(i) << ", flow: " << flow(i) << ", potential: " << potential(i); } -static void printNodeInfo(Node* nodes, const double* rates, uint32_t i) +static void printNodeInfo(Node* nodes, const CostType* rates, uint32_t i) { printSimpleNodeInfo(nodes, i); std::cerr << ", s/d: " << b(i) << " "; std::cerr << std::endl; } -static void printAllNodeInfo(Node* nodes, const double* rates, uint32_t dim) +static void printAllNodeInfo(Node* nodes, const CostType* rates, uint32_t dim) { std::cerr << "Nodes:" << std::endl; for (uint32_t i = 0; i < dim; i++) { @@ -88,11 +88,11 @@ static void printSimpleAllNodeInfo(Node *nodes, uint32_t dim) } */ -static bool checkTreeIntegrity(const raw_t* dbm, const double* rates, Node* nodes, uint32_t dim) +static bool checkTreeIntegrity(const raw_t* dbm, const CostType* rates, Node* nodes, uint32_t dim) { bool treeOK = true; // Check that all nodes get their flow - double sum[dim], total = 0; + CostType sum[dim], total = 0; uint32_t i; sum[0] = 0; @@ -111,7 +111,7 @@ static bool checkTreeIntegrity(const raw_t* dbm, const double* rates, Node* node } } for (i = 0; i < dim; i++) { - if (!are_same(sum[i], 0.0)) { + if (sum[i] != 0) { treeOK = false; std::cerr << "sum[" << i << "] is corrupted: " << sum[i] << ", should be: " << (i == 0 ? total : b(i)) << std::endl; @@ -204,7 +204,7 @@ static bool checkTreeIntegrity(const raw_t* dbm, const double* rates, Node* node static inline bool nodeHasNoChildren(Node* node) { return (node->thread->depth > node->depth); } -static void printSolution(int32_t* valuation, const double* rates, uint32_t dim) +static void printSolution(int32_t* valuation, const CostType* rates, uint32_t dim) { for (uint32_t i = 0; i < dim; i++) { std::cerr << "Val " << i << ": " << valuation[i] << " (rate: " << rates[i] << ")" << std::endl; @@ -250,7 +250,7 @@ static void printAllRates(const int32_t *rates, uint32_t dim) * The initial solution includes computing the intial node potentials. * */ -static void findInitialSpanningTreeSolution(const raw_t* dbm, uint32_t dim, const double* rates, Node* nodes) +static void findInitialSpanningTreeSolution(const raw_t* dbm, uint32_t dim, const CostType* rates, Node* nodes) { Node* last = nodes + dim; Node* node = nodes; @@ -258,7 +258,7 @@ static void findInitialSpanningTreeSolution(const raw_t* dbm, uint32_t dim, cons node->depth = 0; node->thread = nodes + 1; node->inbound = 0; - node->flow = -1.0; + node->flow = -1; node->potential = 0; for (node++; node != last; node++) { @@ -363,7 +363,7 @@ static inline bool isPredecessorOf(Node* n, Node* m) { return n == findNthPredec * I.e., pred, depth, and thread. * */ -static void updateNonRootSubtree(Node* rootNode, Node* nonRootNode, Node* leave, bool sourceInRootSubtree, double flow) +static void updateNonRootSubtree(Node* rootNode, Node* nonRootNode, Node* leave, bool sourceInRootSubtree, CostType flow) { /* * Update thread information NOT COMPLETELY SURE ABOUT CORRECTNESS @@ -427,7 +427,7 @@ static void updateNonRootSubtree(Node* rootNode, Node* nonRootNode, Node* leave, */ Node *tmppred1, *tmppred2, *newi; - double tmpflow1, tmpflow2; + CostType tmpflow1, tmpflow2; bool tmpinbound1, tmpinbound2; tmppred1 = rootNode; tmpflow1 = flow; @@ -475,12 +475,12 @@ static void updateNonRootSubtree(Node* rootNode, Node* nonRootNode, Node* leave, * and subtract flow from arcs in the opposite direction * of (k,l). */ -static void updateFlowInCycle(Node* k, Node* l, Node* root, double flowToAugment) +static void updateFlowInCycle(Node* k, Node* l, Node* root, CostType flowToAugment) { if (flowToAugment > 0) { while (k != root) { k->flow += k->inbound ? flowToAugment : -flowToAugment; - ASSERT(k->flow + epsilon >= 0.0, std::cerr << "flow(" << k << "): " << k->flow << std::endl); + ASSERT(k->flow >= 0, std::cerr << "flow(" << k << "): " << k->flow << std::endl); k = k->pred; } while (l != root) { @@ -498,7 +498,7 @@ static void updateFlowInCycle(Node* k, Node* l, Node* root, double flowToAugment static void updateSpanningTree(Node* k, Node* l, Node* leave, Node* root, int32_t costEnter) { int32_t reducedCostEnter = costEnter - k->potential + l->potential; - double flowToAugment = leave->flow; + CostType flowToAugment = leave->flow; updateFlowInCycle(k, l, root, flowToAugment); if (!isPredecessorOf(leave, k)) { updatePotentials(leave, -reducedCostEnter); @@ -598,7 +598,7 @@ static Node* discoverCycleRoot(Node* k, Node* l) */ static Node* findLeavingArc(Node* k, Node* l, Node* root) { - double smallestFlow = std::numeric_limits::infinity(); + CostType smallestFlow = INFINITE_COST; /* * Node with the lowest depth of the leaving arc. */ @@ -623,7 +623,7 @@ static Node* findLeavingArc(Node* k, Node* l, Node* root) while (l != root) { if (l->inbound) // If inbound then opposite of (i,j) { - if (l->flow <= smallestFlow + epsilon) // <= since we need the last along (i,j) + if (l->flow <= smallestFlow) // <= since we need the last along (i,j) { smallestFlow = l->flow; smallestFlowNode = l; @@ -631,7 +631,7 @@ static Node* findLeavingArc(Node* k, Node* l, Node* root) } l = l->pred; } - ASSERT(smallestFlow != std::numeric_limits::infinity(), std::cerr << "No oppositely directed arcs" << std::endl); + ASSERT(smallestFlow != INFINITE_COST, std::cerr << "No oppositely directed arcs" << std::endl); return smallestFlowNode; } @@ -645,14 +645,14 @@ static Node* findLeavingArc(Node* k, Node* l, Node* root) * If it is not a transshipment node, we need to follow the * thread to update the potentials. We do it by computing */ -static void testAndRemoveArtificialArcs(const raw_t* dbm, const double* rates, Node* nodes, uint32_t dim) +static void testAndRemoveArtificialArcs(const raw_t* dbm, const CostType* rates, Node* nodes, uint32_t dim) { for (uint32_t i = 1; i < dim; i++) { - if (potential(i) == dbm_INFINITY && pred(i) == 0 && are_same(flow(i), 0)) { + if (potential(i) == dbm_INFINITY && pred(i) == 0 && flow(i) == 0) { inbound(i) = true; Node* tmp = nodes[i].thread; - double rateSum = b(i); + CostType rateSum = b(i); int32_t minPotential = dbm_INFINITY + constraintValue(0, i); @@ -666,7 +666,7 @@ static void testAndRemoveArtificialArcs(const raw_t* dbm, const double* rates, N minPotential = tmp->potential; tmp = tmp->thread; } - assert(are_same(rateSum, 0)); + assert(rateSum == 0); /* * Update all potentials in the thread by subtracting @@ -688,7 +688,7 @@ static void testAndRemoveArtificialArcs(const raw_t* dbm, const double* rates, N * Returns true if and only if all elements in [first, last) are * non-negative. */ -static bool allPositive(const double* first, const double* last) +static bool allPositive(const CostType* first, const CostType* last) { while (first != last) { if (*first < 0) { @@ -704,7 +704,7 @@ static bool allPositive(const double* first, const double* last) * network flow problem. I.e. the cost of the offset and the costless * moves to the offset is not taken into account. */ -static void infimumNetSimplex(const raw_t* dbm, uint32_t dim, const double* rates, Node* nodes) +static void infimumNetSimplex(const raw_t* dbm, uint32_t dim, const CostType* rates, Node* nodes) { /* Find and store the minimal set of arcs. The netsimplex * algorithm is polynomial in the number of arcs. @@ -766,7 +766,7 @@ static void infimumNetSimplex(const raw_t* dbm, uint32_t dim, const double* rate * the infimum-achieving point in the zone. * */ -double pdbm_infimum(const raw_t* dbm, uint32_t dim, double offsetCost, const double* rates) +CostType pdbm_infimum(const raw_t* dbm, uint32_t dim, CostType offsetCost, const CostType* rates) { if (allPositive(rates, rates + dim)) { return offsetCost; @@ -775,7 +775,7 @@ double pdbm_infimum(const raw_t* dbm, uint32_t dim, double offsetCost, const dou Node nodes[dim]; infimumNetSimplex(dbm, dim, rates, nodes); - double solution = offsetCost; + CostType solution = offsetCost; for (uint32_t i = 0; i < dim; i++) { ASSERT(potential(i) >= 0, std::cerr << "Node: " << i << std::endl; printAllNodeInfo(nodes, rates, dim); printClockLowerBounds(dbm, dim)); @@ -783,8 +783,8 @@ double pdbm_infimum(const raw_t* dbm, uint32_t dim, double offsetCost, const dou * Check if best solution has positive flow on artificial arc * if so, return minus infinity as the solution is unbounded. */ - if (potential(i) == dbm_INFINITY && pred(i) == 0 && flow(i) + epsilon > 0.0) { - return -std::numeric_limits::infinity(); + if (potential(i) == dbm_INFINITY && pred(i) == 0 && flow(i) > 0) { + return -INFINITE_COST; } solution += rates[i] * (potential(i) + constraintValue(0, i)); } @@ -792,7 +792,7 @@ double pdbm_infimum(const raw_t* dbm, uint32_t dim, double offsetCost, const dou return solution; } -void pdbm_infimum(const raw_t* dbm, uint32_t dim, double offsetCost, const double* rates, int32_t* valuation) +void pdbm_infimum(const raw_t* dbm, uint32_t dim, CostType offsetCost, const CostType* rates, int32_t* valuation) { if (allPositive(rates, rates + dim)) { valuation[0] = 0; @@ -815,7 +815,7 @@ void pdbm_infimum(const raw_t* dbm, uint32_t dim, double offsetCost, const doubl * if so, infimum is not well defined as it is minus infinity * and we throw an exception. */ - if (potential(i) == dbm_INFINITY && pred(i) == 0 && flow(i) + epsilon > 0.0) { + if (potential(i) == dbm_INFINITY && pred(i) == 0 && flow(i) > 0) { throw std::domain_error("Infimum is downward unbound, thus, no well-defined infimum valuation."); } @@ -823,6 +823,3 @@ void pdbm_infimum(const raw_t* dbm, uint32_t dim, double offsetCost, const doubl } } } - - -bool are_same(double a, double b) { return std::abs(a - b) < epsilon; } diff --git a/src/infimum.h b/src/infimum.h index ef2bad8..876b9c2 100644 --- a/src/infimum.h +++ b/src/infimum.h @@ -13,11 +13,10 @@ #include "dbm/constraints.h" #include +#include "dbm/cost_type.h" -const double epsilon = 0.000001; -bool are_same(double a, double b); -double pdbm_infimum(const raw_t* dbm, uint32_t dim, double offsetCost, const double* rates); -void pdbm_infimum(const raw_t* dbm, uint32_t dim, double offsetCost, const double* rates, int32_t* valuation); +CostType pdbm_infimum(const raw_t* dbm, uint32_t dim, CostType offsetCost, const CostType* rates); +void pdbm_infimum(const raw_t* dbm, uint32_t dim, CostType offsetCost, const CostType* rates, int32_t* valuation); #endif diff --git a/src/pfed.cpp b/src/pfed.cpp index 3a3d5d3..a2b7078 100644 --- a/src/pfed.cpp +++ b/src/pfed.cpp @@ -87,26 +87,27 @@ namespace dbm return !isEmpty(); } - static double min(double a, double b) { return a < b ? a : b; } + static CostType min(CostType a, CostType b) { return a < b ? a : b; } - double pfed_t::getInfimum() const + CostType pfed_t::getInfimum() const { - /* The binary operator used in the following accumulation is - * lambda inf zone.min(inf, pdbm_getInfimum(zone, ptr->dim)); - */ - return accumulate(begin(), end(), DBL_MAX, bind(min, _1, bind(pdbm_getInfimum, _2, ptr->dim))); + CostType inf = INFINITE_COST; + for (const auto& zone : *this) { + inf = min(inf, pdbm_getInfimum(zone, ptr->dim)); + } + return inf; } - double pfed_t::getInfimumValuation(IntValuation& valuation, const bool* free) const + CostType pfed_t::getInfimumValuation(IntValuation& valuation, const bool* free) const { uint32_t dim = ptr->dim; - double infimum = INT_MAX; + CostType infimum = INFINITE_COST; int32_t copy[dim]; for_each_const(zone) { std::copy(valuation.begin(), valuation.end(), copy); - double inf = pdbm_getInfimumValuation(*zone, dim, copy, free); + CostType inf = pdbm_getInfimumValuation(*zone, dim, copy, free); if (inf < infimum) { infimum = inf; std::copy(copy, copy + dim, valuation.begin()); @@ -211,7 +212,7 @@ namespace dbm return *this; } - pfed_t& pfed_t::up(double rate) + pfed_t& pfed_t::up(CostType rate) { uint32_t dim = ptr->dim; @@ -220,7 +221,7 @@ namespace dbm for_each__(zone) { cindex_t x; - double oldrate = pdbm_getSlopeOfDelayTrajectory(*zone, dim); + CostType oldrate = pdbm_getSlopeOfDelayTrajectory(*zone, dim); // pdbm_print(std::cout, zone->operator PDBM(), dim); @@ -282,7 +283,7 @@ namespace dbm for_each__(zone) { cindex_t k; - double rate = pdbm_getRate(*zone, dim, clock); + CostType rate = pdbm_getRate(*zone, dim, clock); if (rate == 0) { pdbm_updateValue(*zone, dim, clock, value); @@ -336,18 +337,14 @@ namespace dbm for_each(beginMutable(), endMutable(), bind(pdbm_diagonalExtrapolateLUBounds, _1, ptr->dim, lower, upper)); } - void pfed_t::incrementCost(double value) + void pfed_t::incrementCost(CostType value) { for_each(beginMutable(), endMutable(), bind(pdbm_incrementCost, _1, ptr->dim, value)); } - double pfed_t::getCostOfValuation(const IntValuation& valuation) const + CostType pfed_t::getCostOfValuation(const IntValuation& valuation) const { - /* The binary operator used in the following accumulation is - * lambda x y . min(x, pdbm_getCostOfValuation(y, dim, val)) - */ - return accumulate(begin(), end(), DBL_MAX, - bind(min, _1, bind(pdbm_getCostOfValuation, _2, ptr->dim, valuation()))); + throw std::logic_error("pfed_t::getCostOfValuation not implemented"); } void pfed_t::relax() { for_each(beginMutable(), endMutable(), bind(pdbm_relax, _1, ptr->dim)); } diff --git a/src/priced.cpp b/src/priced.cpp index 207ca66..d72ed25 100644 --- a/src/priced.cpp +++ b/src/priced.cpp @@ -26,9 +26,9 @@ struct PDBM_s { uint32_t count; - double cost; - double infimum; - double* rates; + CostType cost; + CostType infimum; + CostType* rates; int32_t data[]; }; @@ -51,7 +51,7 @@ struct PDBM_s #define pdbm_count(pdbm) ((pdbm)->count) /** Constant to mark the cached infimum as void. */ -#define INVALID std::numeric_limits::infinity() +#define INVALID std::numeric_limits::infinity() #ifndef NDEBUG /** @@ -135,7 +135,7 @@ size_t pdbm_size(cindex_t dim) { assert(dim); return sizeof(struct PDBM_s) + (dim * dim) * sizeof(int32_t); - //return sizeof(struct PDBM_s) + (dim * dim) * sizeof(int32_t) + dim * sizeof(double); + //return sizeof(struct PDBM_s) + (dim * dim) * sizeof(int32_t) + dim * sizeof(CostType); } PDBM pdbm_reserve(cindex_t dim, void* p) @@ -145,8 +145,8 @@ PDBM pdbm_reserve(cindex_t dim, void* p) PDBM pdbm = (PDBM)p; pdbm_count(pdbm) = 0; pdbm_cache(pdbm) = INVALID; - pdbm_rates(pdbm) = (double*)malloc(sizeof(double) * dim); - std::fill(pdbm_rates(pdbm), pdbm_rates(pdbm) + dim, 0.0); + pdbm_rates(pdbm) = (CostType*)malloc(sizeof(CostType) * dim); + std::fill(pdbm_rates(pdbm), pdbm_rates(pdbm) + dim, 0); return pdbm; } @@ -179,7 +179,7 @@ PDBM pdbm_copy(PDBM dst, const PDBM src, cindex_t dim) } memcpy(dst, src, pdbm_size(dim)); - dst->rates = (double*)malloc(sizeof(double) * dim); + dst->rates = (CostType*)malloc(sizeof(CostType) * dim); std::copy(src->rates, src->rates + dim, dst->rates); pdbm_count(dst) = 0; @@ -194,8 +194,8 @@ void pdbm_init(PDBM& pdbm, cindex_t dim) dbm_init(pdbm_matrix(pdbm), dim); pdbm_cost(pdbm) = 0; pdbm_cache(pdbm) = 0; - double* r = pdbm_rates(pdbm); - std::fill(r, r + dim, 0.0); + CostType* r = pdbm_rates(pdbm); + std::fill(r, r + dim, 0); assertx(pdbm_isValid(pdbm, dim)); } @@ -208,8 +208,8 @@ void pdbm_zero(PDBM& pdbm, cindex_t dim) dbm_zero(pdbm_matrix(pdbm), dim); pdbm_cost(pdbm) = 0; pdbm_cache(pdbm) = 0; - double* r = pdbm_rates(pdbm); - std::fill(r, r + dim, 0.0); + CostType* r = pdbm_rates(pdbm); + std::fill(r, r + dim, 0); assertx(pdbm_isValid(pdbm, dim)); } @@ -246,8 +246,8 @@ bool pdbm_constrain1(PDBM& pdbm, cindex_t dim, cindex_t i, cindex_t j, raw_t con /* Compute the cost at the origin. */ - double cost = pdbm_cost(pdbm); - double* rates = pdbm_rates(pdbm); + CostType cost = pdbm_cost(pdbm); + CostType* rates = pdbm_rates(pdbm); for (uint32_t k = 1; k < dim; k++) { cost += rates[k] * dbm_raw2bound(DBM(0, k)); } @@ -281,8 +281,8 @@ bool pdbm_constrainN(PDBM& pdbm, cindex_t dim, const constraint_t* constraints, pdbm_prepare(pdbm, dim); dbm = pdbm_matrix(pdbm); - double cost = pdbm_cost(pdbm); - double* rates = pdbm_rates(pdbm); + CostType cost = pdbm_cost(pdbm); + CostType* rates = pdbm_rates(pdbm); for (uint32_t k = 1; k < dim; k++) { cost += rates[k] * dbm_raw2bound(DBM(0, k)); @@ -314,7 +314,7 @@ bool pdbm_constrainN(PDBM& pdbm, cindex_t dim, const constraint_t* constraints, * we want to find the cost. * @param dim is the dimension of \a dbm1 and \a dbm2. */ -static double costAtOtherOffset(const raw_t* dbm1, const double* rates1, double cost1, const raw_t* dbm2, +static CostType costAtOtherOffset(const raw_t* dbm1, const CostType* rates1, CostType cost1, const raw_t* dbm2, cindex_t dim) { assert(dbm1 && dbm2 && rates1 && dim); @@ -336,7 +336,7 @@ static double costAtOtherOffset(const raw_t* dbm1, const double* rates1, double * @param last is a pointer to the last coefficient of the first plane. * @param rate is a pointer to the first coefficient of the second plane. */ -inline static bool leq(const double* first, const double* last, const double* rate) +inline static bool leq(const CostType* first, const CostType* last, const CostType* rate) { assert(first && last && rate); @@ -351,7 +351,7 @@ inline static bool leq(const double* first, const double* last, const double* ra * @param last is a pointer to the last coefficient of the first plane. * @param rate is a pointer to the first coefficient of the second plane. */ -inline static bool less(const double* first, const double* last, const double* rate) +inline static bool less(const CostType* first, const CostType* last, const CostType* rate) { assert(first && last && rate); @@ -369,13 +369,13 @@ inline static bool less(const double* first, const double* last, const double* r * @param cost2 The cost at the offset for the second plane. * @param rate2 The rates of the second plane. */ -static double infOfDiff(const raw_t* dbm, uint32_t dim, double cost1, const double* rate1, double cost2, - const double* rate2) +static CostType infOfDiff(const raw_t* dbm, uint32_t dim, CostType cost1, const CostType* rate1, CostType cost2, + const CostType* rate2) { assert(dbm && dim && rate1 && rate2); - double cost = cost1 - cost2; - double rates[dim]; + CostType cost = cost1 - cost2; + CostType rates[dim]; std::transform(rate1, rate1 + dim, rate2, rates, std::minus<>()); return pdbm_infimum(dbm, dim, cost, rates); @@ -387,10 +387,10 @@ std::pair pdbm_compare_cost_identical_pdbms(const PDBM pdbm1, raw_t* dbm1 = pdbm_matrix(pdbm1); raw_t* dbm2 = pdbm_matrix(pdbm2); - double* rates1 = pdbm_rates(pdbm1); - double* rates2 = pdbm_rates(pdbm2); - double cost1 = pdbm_cost(pdbm1); - double cost2 = pdbm_cost(pdbm2); + CostType* rates1 = pdbm_rates(pdbm1); + CostType* rates2 = pdbm_rates(pdbm2); + CostType cost1 = pdbm_cost(pdbm1); + CostType cost2 = pdbm_cost(pdbm2); /* Function should only be called for identical dbms. * In case they are not, return costs are different. */ @@ -401,22 +401,22 @@ std::pair pdbm_compare_cost_identical_pdbms(const PDBM pdbm1, /* Both have the same size. We need to compare the planes to * see which one is cheaper. */ - double c = infOfDiff(dbm1, dim, cost2, rates2, cost1, rates1); - if (c - epsilon > 0.0) { + CostType c = infOfDiff(dbm1, dim, cost2, rates2, cost1, rates1); + if (c > 0) { return {base_SUPERSET, true}; } - double d = infOfDiff(dbm1, dim, cost1, rates1, cost2, rates2); - if (are_same(c, 0.0) && are_same(d, 0.0)) { + CostType d = infOfDiff(dbm1, dim, cost1, rates1, cost2, rates2); + if (c == 0 && d == 0) { return {base_EQUAL, false}; } - if (d - epsilon > 0.0) { + if (d > 0) { return {base_SUBSET, true}; } - if (c + epsilon >= 0) { + if (c >= 0) { return {base_SUPERSET, false}; } - if (d + epsilon >= 0) { + if (d >= 0) { return {base_SUBSET, false}; } return {base_DIFFERENT, false}; @@ -428,13 +428,13 @@ relation_t pdbm_relation(const PDBM pdbm1, const PDBM pdbm2, cindex_t dim) raw_t* dbm1 = pdbm_matrix(pdbm1); raw_t* dbm2 = pdbm_matrix(pdbm2); - double* rates1 = pdbm_rates(pdbm1); - double* rates2 = pdbm_rates(pdbm2); - double cost1 = pdbm_cost(pdbm1); - double cost2 = pdbm_cost(pdbm2); + CostType* rates1 = pdbm_rates(pdbm1); + CostType* rates2 = pdbm_rates(pdbm2); + CostType cost1 = pdbm_cost(pdbm1); + CostType cost2 = pdbm_cost(pdbm2); bool a, b; - double c, d; + CostType c, d; switch (dbm_relation(dbm1, dbm2, dim)) { case base_SUPERSET: @@ -493,7 +493,7 @@ relation_t pdbm_relation(const PDBM pdbm1, const PDBM pdbm2, cindex_t dim) * unpack dbm2. */ c = infOfDiff(dbm1, dim, cost2, rates2, cost1, rates1); - if (c - epsilon > 0.0) { + if (c > 0) { /* Early return to avoid unnecessary computation of the * second subtraction. */ @@ -501,13 +501,13 @@ relation_t pdbm_relation(const PDBM pdbm1, const PDBM pdbm2, cindex_t dim) } d = infOfDiff(dbm1, dim, cost1, rates1, cost2, rates2); - if (are_same(c, 0.0) && are_same(d, 0.0)) { + if (c == 0 && d == 0) { return base_EQUAL; } - if (c + epsilon >= 0) { + if (c >= 0) { return base_SUPERSET; } - if (d + epsilon >= 0) { + if (d >= 0) { return base_SUBSET; } return base_DIFFERENT; @@ -523,16 +523,16 @@ relation_t pdbm_relationWithMinDBM(const PDBM pdbm1, cindex_t dim, const mingrap // assert(pdbm1 && pdbm2 && dim && dbm2); // // raw_t* dbm1 = pdbm_matrix(pdbm1); -// double cost1 = pdbm_cost(pdbm1); -// double* rates1 = pdbm_rates(pdbm1); +// CostType cost1 = pdbm_cost(pdbm1); +// CostType* rates1 = pdbm_rates(pdbm1); // -// double c, d; +// CostType c, d; // // /* We know how the cost and the rates are encoded in a mingraph: // * see writeToMinDBMWithOffset and readFromMinDBM. // */ -// double cost2 = pdbm2[0]; -// const double* rates2 = pdbm2 + 2; +// CostType cost2 = pdbm2[0]; +// const CostType* rates2 = pdbm2 + 2; // // /* dbm_relationWithMinDBM will in some cases unpack pdbm2 into // * dbm2. In order to detect whether this has happened, we set the @@ -628,29 +628,29 @@ relation_t pdbm_relationWithMinDBM(const PDBM pdbm1, cindex_t dim, const mingrap // } } -double pdbm_getInfimum(const PDBM pdbm, cindex_t dim) +CostType pdbm_getInfimum(const PDBM pdbm, cindex_t dim) { assert(pdbm && dim); assert(dbm_isValid(pdbm_matrix(pdbm), dim)); - double cache = pdbm_cache(pdbm); + CostType cache = pdbm_cache(pdbm); if (cache == INVALID) { pdbm_cache((PDBM)pdbm) = cache = pdbm_infimum(pdbm_matrix(pdbm), dim, pdbm_cost(pdbm), pdbm_rates(pdbm)); } return cache; } -double pdbm_getInfimumValuation(const PDBM pdbm, cindex_t dim, int32_t* valuation, const bool* free) +CostType pdbm_getInfimumValuation(const PDBM pdbm, cindex_t dim, int32_t* valuation, const bool* free) { assert(pdbm && dim && valuation); assert(pdbm_isValid(pdbm, dim)); raw_t copy[dim * dim]; raw_t* dbm = pdbm_matrix(pdbm); - double* rates = pdbm_rates(pdbm); + CostType* rates = pdbm_rates(pdbm); /* Compute the cost of the origin. */ - double cost = pdbm_cost(pdbm); + CostType cost = pdbm_cost(pdbm); for (uint32_t i = 1; i < dim; i++) { cost -= rates[i] * -dbm_raw2bound(DBM(0, i)); } @@ -749,11 +749,14 @@ void pdbm_up(PDBM& pdbm, cindex_t dim) pdbm_prepare(pdbm, dim); dbm_up(pdbm_matrix(pdbm), dim); + if (pdbm_getSlopeOfDelayTrajectory(pdbm, dim) < 0) { + pdbm->infimum = INVALID; + } assertx(pdbm_isValid(pdbm, dim)); } -void pdbm_upZero(PDBM& pdbm, cindex_t dim, double rate, cindex_t zero) +void pdbm_upZero(PDBM& pdbm, cindex_t dim, CostType rate, cindex_t zero) { assert(pdbm && dim && zero > 0 && zero < dim); assert(pdbm_areOnZeroCycle(pdbm, dim, 0, zero)); @@ -761,7 +764,7 @@ void pdbm_upZero(PDBM& pdbm, cindex_t dim, double rate, cindex_t zero) pdbm_prepare(pdbm, dim); raw_t* dbm = pdbm_matrix(pdbm); - double* rates = pdbm_rates(pdbm); + CostType* rates = pdbm_rates(pdbm); dbm_up(dbm, dim); rates[zero] = 0; @@ -790,7 +793,7 @@ void pdbm_updateValueZero(PDBM& pdbm, cindex_t dim, cindex_t clock, uint32_t val pdbm_prepare(pdbm, dim); - double* rates = pdbm_rates(pdbm); + CostType* rates = pdbm_rates(pdbm); if (zero) { rates[zero] += rates[clock]; @@ -849,7 +852,7 @@ void pdbm_extrapolateMaxBounds(PDBM& pdbm, cindex_t dim, int32_t* max) { assert(pdbm && dim); - double* rates = pdbm_rates(pdbm); + CostType* rates = pdbm_rates(pdbm); for (uint32_t i = 1; i < dim; i++) { if (rates[i] != 0) { @@ -872,7 +875,7 @@ void pdbm_diagonalExtrapolateMaxBounds(PDBM& pdbm, cindex_t dim, int32_t* max) { assert(pdbm && dim); - double* rates = pdbm_rates(pdbm); + CostType* rates = pdbm_rates(pdbm); /* If possible, transfer the cost rate of inactive clocks to other * clocks (clocks which are on a zero cycle with the inactive @@ -916,7 +919,7 @@ void pdbm_diagonalExtrapolateLUBounds(PDBM& pdbm, cindex_t dim, int32_t* lower, { assert(pdbm && dim); - double* rates = pdbm_rates(pdbm); + CostType* rates = pdbm_rates(pdbm); for (uint32_t i = 1; i < dim; i++) { // if (rates[i] < 0) @@ -937,13 +940,13 @@ void pdbm_diagonalExtrapolateLUBounds(PDBM& pdbm, cindex_t dim, int32_t* lower, dbm_diagonalExtrapolateLUBounds(pdbm_matrix(pdbm), dim, lower, upper); } -void pdbm_incrementCost(PDBM& pdbm, cindex_t dim, double value) +void pdbm_incrementCost(PDBM& pdbm, cindex_t dim, CostType value) { assert(pdbm && dim); pdbm_prepare(pdbm, dim); pdbm_cost(pdbm) += value; - if (pdbm_cache(pdbm) != INVALID && pdbm_cache(pdbm) != -std::numeric_limits::infinity()) { + if (pdbm_cache(pdbm) != INVALID && pdbm_cache(pdbm) != -std::numeric_limits::infinity()) { pdbm_cache(pdbm) += value; } @@ -1023,33 +1026,33 @@ bool pdbm_findZeroCycle(const PDBM pdbm, cindex_t dim, cindex_t x, cindex_t* out return pdbm_findNextZeroCycle(pdbm, dim, x, out); } -double pdbm_getSlopeOfDelayTrajectory(const PDBM pdbm, cindex_t dim) +CostType pdbm_getSlopeOfDelayTrajectory(const PDBM pdbm, cindex_t dim) { assert(pdbm && dim); - double* rates = pdbm_rates(pdbm); - double sum = 0; + CostType* rates = pdbm_rates(pdbm); + CostType sum = 0; for (uint32_t i = 1; i < dim; i++) { sum += rates[i]; } return sum; } -double pdbm_getRate(const PDBM pdbm, cindex_t dim, cindex_t clock) +CostType pdbm_getRate(const PDBM pdbm, cindex_t dim, cindex_t clock) { assert(pdbm && dim && clock > 0 && clock < dim); return pdbm_rates(pdbm)[clock]; } -double pdbm_getCostAtOffset(const PDBM pdbm, cindex_t dim) +CostType pdbm_getCostAtOffset(const PDBM pdbm, cindex_t dim) { assert(pdbm && dim); return pdbm_cost(pdbm); } -void pdbm_setCostAtOffset(PDBM& pdbm, cindex_t dim, double value) +void pdbm_setCostAtOffset(PDBM& pdbm, cindex_t dim, CostType value) { assert(pdbm && dim); @@ -1212,13 +1215,13 @@ uint32_t pdbm_getUpperFacets(PDBM& pdbm, cindex_t dim, cindex_t* facets) return cnt; } -double pdbm_getCostOfValuation(const PDBM pdbm, cindex_t dim, const int32_t* valuation) +CostType pdbm_getCostOfValuation(const PDBM pdbm, cindex_t dim, const int32_t* valuation) { assert(pdbm && dim && valuation); assert(pdbm_containsInt(pdbm, dim, valuation)); raw_t* dbm = pdbm_matrix(pdbm); - double cost = pdbm_cost(pdbm); + CostType cost = pdbm_cost(pdbm); for (uint32_t i = 1; i < dim; i++) { cost += (valuation[i] - -dbm_raw2bound(DBM(0, i))) * pdbm_rates(pdbm)[i]; } @@ -1251,13 +1254,19 @@ bool pdbm_isValid(const PDBM pdbm, cindex_t dim) } raw_t* dbm = pdbm_matrix(pdbm); - double* rates = pdbm_rates(pdbm); - double cost = pdbm_cost(pdbm); - double cache = pdbm_cache(pdbm); - double inf = pdbm_infimum(dbm, dim, cost, rates); + CostType* rates = pdbm_rates(pdbm); + CostType cost = pdbm_cost(pdbm); + CostType cache = pdbm_cache(pdbm); + CostType inf = pdbm_infimum(dbm, dim, cost, rates); + +// std::cout << "inf: " << inf << std::endl; +// std::cout << "(cache == INVALID || cache == inf): " << (cache == INVALID || cache == inf) << std::endl; +// std::cout << "dbm_isValid(dbm, dim): " << dbm_isValid(dbm, dim) << std::endl; +// std::cout << " rates[0] == 0: " << (rates[0] == 0) << std::endl; +// std::cout << "(!(pdbm_isUnbounded(pdbm, dim) && pdbm_getSlopeOfDelayTrajectory(pdbm, dim) < 0) || inf == -INFINITE_COST): " << (!(pdbm_isUnbounded(pdbm, dim) && pdbm_getSlopeOfDelayTrajectory(pdbm, dim) < 0) || inf == -INFINITE_COST) << std::endl; - return (cache == INVALID || cache == inf) && dbm_isValid(dbm, dim) && rates[0] == 0.0 && - (!(pdbm_isUnbounded(pdbm, dim) && pdbm_getSlopeOfDelayTrajectory(pdbm, dim) < 0) || inf == -std::numeric_limits::infinity()); + return (cache == INVALID || cache == inf) && dbm_isValid(dbm, dim) && rates[0] == 0 && + (!(pdbm_isUnbounded(pdbm, dim) && pdbm_getSlopeOfDelayTrajectory(pdbm, dim) < 0) || inf == -INFINITE_COST); } void pdbm_freeClock(PDBM& pdbm, cindex_t dim, cindex_t clock) @@ -1281,7 +1290,7 @@ void pdbm_getOffset(const PDBM pdbm, cindex_t dim, int32_t* valuation) } } -void pdbm_setRate(PDBM& pdbm, cindex_t dim, cindex_t clock, double rate) +void pdbm_setRate(PDBM& pdbm, cindex_t dim, cindex_t clock, CostType rate) { assert(pdbm && dim && clock > 0 && clock < dim); @@ -1311,7 +1320,7 @@ const raw_t* pdbm_getMatrix(const PDBM pdbm, cindex_t dim) return pdbm_matrix(pdbm); } -const double* pdbm_getRates(const PDBM pdbm, cindex_t dim) +const CostType* pdbm_getRates(const PDBM pdbm, cindex_t dim) { assert(pdbm && dim); return pdbm_rates(pdbm); @@ -1326,19 +1335,18 @@ bool pdbm_constrainToFacet(PDBM& pdbm, cindex_t dim, cindex_t i, cindex_t j) void pdbm_print(FILE* f, const PDBM pdbm, cindex_t dim) { - double infimum = pdbm_getInfimum(pdbm, dim); + CostType infimum = pdbm_getInfimum(pdbm, dim); dbm_print(f, pdbm_matrix(pdbm), dim); fprintf(f, "Rates:"); for (cindex_t i = 1; i < dim; i++) { - fprintf(f, " %f", pdbm_getRate(pdbm, dim, i)); +// fprintf(f, " %f", pdbm_getRate(pdbm, dim, i)); } fprintf(f, "\n"); - fprintf(f, "Offset: %f Infimum: %f\n", pdbm_cost(pdbm), infimum); } void pdbm_print(std::ostream& o, const PDBM pdbm, cindex_t dim) { - double infimum = pdbm_getInfimum(pdbm, dim); + CostType infimum = pdbm_getInfimum(pdbm, dim); dbm_cppPrint(o, pdbm_matrix(pdbm), dim); o << "Rates:"; for (cindex_t i = 1; i < dim; i++) { @@ -1365,7 +1373,7 @@ void pdbm_freeDown(PDBM& pdbm, cindex_t dim, cindex_t index) /* Move offset point. */ - double rate = pdbm_rates(pdbm)[index]; + CostType rate = pdbm_rates(pdbm)[index]; int32_t bound = -dbm_raw2bound(DBM(0, index)); pdbm_cost(pdbm) -= bound * rate; @@ -1376,7 +1384,7 @@ void pdbm_freeDown(PDBM& pdbm, cindex_t dim, cindex_t index) void pdbm_normalise(PDBM pdbm, cindex_t dim) { - double* rates = pdbm_rates(pdbm); + CostType* rates = pdbm_rates(pdbm); cindex_t next[dim]; cindex_t i; @@ -1402,7 +1410,7 @@ void pdbm_normalise(PDBM pdbm, cindex_t dim) bool pdbm_hasNormalForm(PDBM pdbm, cindex_t dim) { - double* rates = pdbm_rates(pdbm); + CostType* rates = pdbm_rates(pdbm); cindex_t next[dim]; cindex_t i; From 009a1e1ac53bca548e7306db24df0a408a31a006 Mon Sep 17 00:00:00 2001 From: Ragusaen Date: Fri, 24 Mar 2023 10:47:25 +0100 Subject: [PATCH 20/32] fixed bug with inifinity in CostType --- src/priced.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/priced.cpp b/src/priced.cpp index d72ed25..f5c6d7e 100644 --- a/src/priced.cpp +++ b/src/priced.cpp @@ -51,7 +51,7 @@ struct PDBM_s #define pdbm_count(pdbm) ((pdbm)->count) /** Constant to mark the cached infimum as void. */ -#define INVALID std::numeric_limits::infinity() +#define INVALID INFINITE_COST #ifndef NDEBUG /** @@ -946,7 +946,7 @@ void pdbm_incrementCost(PDBM& pdbm, cindex_t dim, CostType value) pdbm_prepare(pdbm, dim); pdbm_cost(pdbm) += value; - if (pdbm_cache(pdbm) != INVALID && pdbm_cache(pdbm) != -std::numeric_limits::infinity()) { + if (pdbm_cache(pdbm) != INVALID && pdbm_cache(pdbm) != -INFINITE_COST) { pdbm_cache(pdbm) += value; } From 5821a64b16cca68f9dc6de1733c26a5907ff61d0 Mon Sep 17 00:00:00 2001 From: Ragusaen Date: Mon, 27 Mar 2023 13:01:30 +0200 Subject: [PATCH 21/32] setUniformCost --- include/dbm/pfed.h | 6 ++++++ src/pfed.cpp | 13 +++++++++++++ 2 files changed, 19 insertions(+) diff --git a/include/dbm/pfed.h b/include/dbm/pfed.h index fd02453..2a3842f 100644 --- a/include/dbm/pfed.h +++ b/include/dbm/pfed.h @@ -165,6 +165,9 @@ namespace dbm /** @see dbm_t::readFromMinDBM() */ static pdbm_t readFromMinDBM(cindex_t dimension, const int32_t*); + /** Sets the offset to and all rates to 0 */ + void setUniformCost(CostType cost); + /// @return string representation of the /// constraints of this PDBM. A clock @@ -471,6 +474,9 @@ namespace dbm /** Returns the infimum of the federation. */ CostType getInfimum() const; + /** Sets the offset to and all rates to 0 */ + void setUniformCost(CostType cost); + /** * Check if the federation satisfies a given constraint. * diff --git a/src/pfed.cpp b/src/pfed.cpp index a2b7078..9dc22e3 100644 --- a/src/pfed.cpp +++ b/src/pfed.cpp @@ -98,6 +98,12 @@ namespace dbm return inf; } + void pfed_t::setUniformCost(CostType cost) { + for (auto it = beginMutable(); it != endMutable(); ++it) { + it->setUniformCost(cost); + } + } + CostType pfed_t::getInfimumValuation(IntValuation& valuation, const bool* free) const { uint32_t dim = ptr->dim; @@ -585,6 +591,13 @@ namespace dbm return false; } + void pdbm_t::setUniformCost(CostType cost) { + pdbm_setCostAtOffset(pdbm, dim, cost); + for (cindex_t x = 1; x < dim; ++x) { + pdbm_setRate(pdbm, dim, x, 0); + } + } + bool pdbm_t::isEmpty() const { return pdbm_isEmpty(pdbm, dim); } From bd684d266c78824880367e15e9f883603d161584 Mon Sep 17 00:00:00 2001 From: Ragusaen Date: Fri, 31 Mar 2023 11:18:10 +0200 Subject: [PATCH 22/32] smoll --- CMakeLists.txt | 4 +++- include/dbm/pfed.h | 10 ++++++++++ include/dbm/priced.h | 20 ++++++++++++++++++++ src/pfed.cpp | 42 +++++++++++++++++++++++++++++++++++++++--- src/priced.cpp | 20 ++++++++++++++++++++ 5 files changed, 92 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 67d3510..929e8f9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -30,7 +30,9 @@ if(STATIC) endif(STATIC) -set(CMAKE_BUILD_TYPE Debug) +#set(CMAKE_BUILD_TYPE Release) +#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3") + target_include_directories(UDBM PRIVATE diff --git a/include/dbm/pfed.h b/include/dbm/pfed.h index 2a3842f..6312830 100644 --- a/include/dbm/pfed.h +++ b/include/dbm/pfed.h @@ -106,8 +106,12 @@ namespace dbm [[nodiscard]] CostType getInfimum() const { return pdbm_getInfimum(pdbm, dim); }; + [[nodiscard]] CostType getSupremum() const { return pdbm_getSupremum(pdbm, dim); }; + [[nodiscard]] const CostType* getRates() const { return pdbm_getRates(pdbm, dim); }; + [[nodiscard]] bool canDelay() const; + bool constrain(cindex_t i, cindex_t j, raw_t c); /** @@ -474,6 +478,12 @@ namespace dbm /** Returns the infimum of the federation. */ CostType getInfimum() const; + /** Returns the supremum of the federation */ + CostType getSupremum() const; + + + bool canDelay() const; + /** Sets the offset to and all rates to 0 */ void setUniformCost(CostType cost); diff --git a/include/dbm/priced.h b/include/dbm/priced.h index 2912461..fb55727 100644 --- a/include/dbm/priced.h +++ b/include/dbm/priced.h @@ -282,6 +282,16 @@ relation_t pdbm_relationWithMinDBM(const PDBM pdbm, cindex_t dim, const mingraph */ CostType pdbm_getInfimum(const PDBM pdbm, cindex_t dim); +/** + * Computes the supremum cost of the priced DBM. + * This does not cache the result and it is recomputed every time! + * + * @param pdbm is a closed priced DBM of dimension \a dim + * @param dim is the dimension of \a pdbm. + * @return The supremum cost of \a pdbm. + */ +CostType pdbm_getSupremum(const PDBM pdbm, cindex_t dim); + /** * Generates a valuation which has the infimum cost of the priced DBM. * @@ -335,6 +345,16 @@ bool pdbm_isEmpty(const PDBM pdbm, cindex_t dim); */ bool pdbm_isUnbounded(const PDBM pdbm, cindex_t dim); + +/** + * Sets the cost of a priced zone to be uniform + * + * @param pdbm is a priced DBM of \a dim + * @param dim is the dimension of \a pdbm + * @param is the cost to set + */ +void pdbm_setUniformCost(PDBM pdbm, cindex_t dim, CostType cost); + /** * Compute a hash value for a priced DBM. * diff --git a/src/pfed.cpp b/src/pfed.cpp index 9dc22e3..0498dc4 100644 --- a/src/pfed.cpp +++ b/src/pfed.cpp @@ -88,6 +88,7 @@ namespace dbm } static CostType min(CostType a, CostType b) { return a < b ? a : b; } + static CostType max(CostType a, CostType b) { return a > b ? a : b; } CostType pfed_t::getInfimum() const { @@ -98,6 +99,25 @@ namespace dbm return inf; } + CostType pfed_t::getSupremum() const + { + CostType sup = -INFINITE_COST; + for (const auto& zone : *this) { + sup = max(sup, pdbm_getSupremum(zone, ptr->dim)); + } + return sup; + } + + + bool pfed_t::canDelay() const { + for (const auto& zone : *this) { + if (zone.canDelay()) { + return true; + } + } + return false; + } + void pfed_t::setUniformCost(CostType cost) { for (auto it = beginMutable(); it != endMutable(); ++it) { it->setUniformCost(cost); @@ -592,9 +612,8 @@ namespace dbm } void pdbm_t::setUniformCost(CostType cost) { - pdbm_setCostAtOffset(pdbm, dim, cost); - for (cindex_t x = 1; x < dim; ++x) { - pdbm_setRate(pdbm, dim, x, 0); + if (!isEmpty()) { + pdbm_setUniformCost(pdbm, dim, cost); } } @@ -704,5 +723,22 @@ namespace dbm } cindex_t pdbm_t::pdim() const { return dim; } + + +#define DBM_IJ(DBM, I, J) DBM[(I)*dim + (J)] +#define DBM(I, J) DBM_IJ(dbm, I, J) + + bool pdbm_t::canDelay() const { + if (isEmpty()) + return false; + const raw_t* dbm = const_dbm(); + cindex_t dim = pdim(); + for (cindex_t i = 1; i < dim; ++i) { + if (dbm_rawIsWeak(DBM(i, 0)) && dbm_rawIsWeak(DBM(0, i)) && DBM(i, 0) == dbm_weakNegRaw(DBM(0, i))) { + return false; + } + } + return true; + } } // namespace dbm diff --git a/src/priced.cpp b/src/priced.cpp index f5c6d7e..46c3a2a 100644 --- a/src/priced.cpp +++ b/src/priced.cpp @@ -639,6 +639,26 @@ CostType pdbm_getInfimum(const PDBM pdbm, cindex_t dim) return cache; } +CostType pdbm_getSupremum(const PDBM pdbm, cindex_t dim) +{ + assert(pdbm && dim); + assert(dbm_isValid(pdbm_matrix(pdbm), dim)); + + // Supremum is infimum of zone where rates are inversed + CostType inv_rates[dim]; + std::transform(pdbm_rates(pdbm), pdbm_rates(pdbm) + dim, inv_rates, [](CostType c){ return -c; }); + return -pdbm_infimum(pdbm_matrix(pdbm), dim, -pdbm_cost(pdbm), inv_rates); +} + +void pdbm_setUniformCost(PDBM pdbm, cindex_t dim, CostType cost) { + pdbm_setCostAtOffset(pdbm, dim, cost); + for (cindex_t x = 1; x < dim; ++x) { + pdbm_setRate(pdbm, dim, x, 0); + } + pdbm_cache(pdbm) = cost; +} + + CostType pdbm_getInfimumValuation(const PDBM pdbm, cindex_t dim, int32_t* valuation, const bool* free) { assert(pdbm && dim && valuation); From 0907e936d150c4ab2e749cabbbd9a3491a3801d0 Mon Sep 17 00:00:00 2001 From: Ragusaen Date: Tue, 11 Apr 2023 13:25:31 +0200 Subject: [PATCH 23/32] something --- CMakeLists.txt | 6 +- include/dbm/cost_type.h | 2 + include/dbm/pfed.h | 16 +++++ include/dbm/priced.h | 2 + src/cost_type.cpp | 9 +++ src/pfed.cpp | 9 +++ src/priced.cpp | 129 +++++++++++++++++++++++++++++++++++++++- 7 files changed, 169 insertions(+), 4 deletions(-) create mode 100644 src/cost_type.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 929e8f9..d8a45eb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -21,7 +21,7 @@ find_package(UUtils 1.1.1 REQUIRED COMPONENTS base hash debug) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/libs) -add_library(UDBM src/DBMAllocator.cpp src/dbm.c src/fed_dbm.cpp src/mingraph.c src/mingraph_read.c src/partition.cpp src/print.cpp src/gen.c src/mingraph_cache.cpp src/mingraph_relation.c src/pfed.cpp src/fed.cpp src/infimum.cpp src/mingraph_equal.c src/mingraph_write.c src/priced.cpp) +add_library(UDBM src/DBMAllocator.cpp src/dbm.c src/fed_dbm.cpp src/mingraph.c src/mingraph_read.c src/partition.cpp src/print.cpp src/gen.c src/mingraph_cache.cpp src/mingraph_relation.c src/pfed.cpp src/fed.cpp src/infimum.cpp src/mingraph_equal.c src/mingraph_write.c src/priced.cpp src/cost_type.cpp) target_link_libraries(UDBM UUtils::base UUtils::udebug UUtils::hash) if(STATIC) @@ -30,8 +30,8 @@ if(STATIC) endif(STATIC) -#set(CMAKE_BUILD_TYPE Release) -#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3") +set(CMAKE_BUILD_TYPE Release) +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3") target_include_directories(UDBM diff --git a/include/dbm/cost_type.h b/include/dbm/cost_type.h index 766b1c0..233ee9c 100644 --- a/include/dbm/cost_type.h +++ b/include/dbm/cost_type.h @@ -13,4 +13,6 @@ typedef boost::rational CostType; const CostType INFINITE_COST = (CostType)INT_MAX; +uint32_t hash_cost_type(const CostType& val); + #endif // UDBM_COST_TYPE_H diff --git a/include/dbm/pfed.h b/include/dbm/pfed.h index 6312830..6fc5f80 100644 --- a/include/dbm/pfed.h +++ b/include/dbm/pfed.h @@ -151,6 +151,22 @@ namespace dbm /** @see pdbm_relationWithMinDBM() */ relation_t relation(const int32_t*, raw_t*) const; + + /* + * Same as relation + */ + [[nodiscard]] relation_t relation(const pdbm_t& other) const; + + /* + * Strict relation, requires cost to be stricly cheaper. Warning return relation may not be as expected. + * Returns + * (Z,c) ⊃ (Z',c') iff (Z ⊇ Z' ∧ c < c') // (Z,c) strictly dominates (Z',c') + * (Z,c) ⊂ (Z',c') iff (Z ⊆ Z' ∧ c > c') ∨ (Z ⊂ Z' ∧ c ≥ c') // (Z',c') weakly dominates (Z,c) + * (Z,c) = (Z',c') iff Z = Z' ∧ c = c' // (Z,c) = (Z',c') + */ + [[nodiscard]] relation_t strict_relation(const pdbm_t& other) const; + + /* * Compares the cost of this pdbm with the cost of the other pdbm, where their zones are identical. * Returns a pair of the relation between the two costs and a strictness. diff --git a/include/dbm/priced.h b/include/dbm/priced.h index fb55727..d1a3858 100644 --- a/include/dbm/priced.h +++ b/include/dbm/priced.h @@ -246,6 +246,8 @@ bool pdbm_constrainToFacet(PDBM& pdbm, cindex_t dim, cindex_t i, cindex_t j); */ relation_t pdbm_relation(const PDBM pdbm1, const PDBM pdbm2, cindex_t dim); +relation_t pdbm_relation_strict(const PDBM pdbm1, const PDBM pdbm2, cindex_t dim); + /* * Compares the costs of two identical DBMs. * If the zones are not identical, it returns {base_DIFFERENT, false} diff --git a/src/cost_type.cpp b/src/cost_type.cpp new file mode 100644 index 0000000..52d1b68 --- /dev/null +++ b/src/cost_type.cpp @@ -0,0 +1,9 @@ +// +// Created by ragusa on 4/5/23. +// + +#include "dbm/cost_type.h" + +uint32_t hash_cost_type(const CostType& val) { + return ((uint32_t)val.numerator() << 16) ^ (uint32_t)val.denominator(); +} diff --git a/src/pfed.cpp b/src/pfed.cpp index 0498dc4..38a7745 100644 --- a/src/pfed.cpp +++ b/src/pfed.cpp @@ -740,5 +740,14 @@ namespace dbm } return true; } + relation_t pdbm_t::relation(const pdbm_t& other) const { + assert(dim == other.dim); + return pdbm_relation(pdbm, other.pdbm, dim); + } + + relation_t pdbm_t::strict_relation(const pdbm_t& other) const { + assert(dim == other.dim); + return pdbm_relation_strict(pdbm, other.pdbm, dim); + } } // namespace dbm diff --git a/src/priced.cpp b/src/priced.cpp index 46c3a2a..583c6bd 100644 --- a/src/priced.cpp +++ b/src/priced.cpp @@ -343,6 +343,36 @@ inline static bool leq(const CostType* first, const CostType* last, const CostTy return std::equal(first, last, rate, std::less_equal<>()); } +/** + * Given two planes, returns true if the slope of the first is strictly less + * than to the slope of the other. + * + * @param first is a pointer to the first coefficient of the first plane. + * @param last is a pointer to the last coefficient of the first plane. + * @param rate is a pointer to the first coefficient of the second plane. + */ +inline static bool le(const CostType* first, const CostType* last, const CostType* rate) +{ + assert(first && last && rate); + + return std::equal(first, last, rate, std::less<>()); +} + +/** + * Given two planes, returns true if the slope of the first is equal to + * the slope of the other. + * + * @param first is a pointer to the first coefficient of the first plane. + * @param last is a pointer to the last coefficient of the first plane. + * @param rate is a pointer to the first coefficient of the second plane. + */ +inline static bool eq(const CostType* first, const CostType* last, const CostType* rate) +{ + assert(first && last && rate); + + return std::equal(first, last, rate, std::equal_to<>()); +} + /** * Given two planes, returns true if the slope of the first is less * than to the slope of the other. @@ -422,6 +452,12 @@ std::pair pdbm_compare_cost_identical_pdbms(const PDBM pdbm1, return {base_DIFFERENT, false}; } +/* + * Returns + * (Z,c) ⊃ (Z',c') iff (Z ⊃ Z' ∧ c ≤ c') ∨ (Z = Z' ∧ c ≤ c') + * (Z,c) ⊂ (Z',c') iff (Z ⊂ Z' ∧ c ≥ c') ∨ (Z = Z' ∧ c ≥ c') + * (Z,c) = (Z',c') iff Z = Z' ∧ c = c' + */ relation_t pdbm_relation(const PDBM pdbm1, const PDBM pdbm2, cindex_t dim) { assert(pdbm1 && pdbm2 && dim); @@ -516,6 +552,92 @@ relation_t pdbm_relation(const PDBM pdbm1, const PDBM pdbm2, cindex_t dim) } } +/* + * Returns + * (Z,c) ⊃ (Z',c') iff (Z ⊇ Z' ∧ c < c') // (Z,c) strictly dominates (Z',c') + * (Z,c) ⊂ (Z',c') iff (Z ⊆ Z' ∧ c > c') ∨ (Z ⊂ Z' ∧ c ≥ c') // (Z',c') weakly dominates (Z,c) + * (Z,c) = (Z',c') iff Z = Z' ∧ c = c' // (Z,c) = (Z',c') + */ +relation_t pdbm_relation_strict(const PDBM pdbm1, const PDBM pdbm2, cindex_t dim) +{ + assert(pdbm1 && pdbm2 && dim); + + raw_t* dbm1 = pdbm_matrix(pdbm1); + raw_t* dbm2 = pdbm_matrix(pdbm2); + CostType* rates1 = pdbm_rates(pdbm1); + CostType* rates2 = pdbm_rates(pdbm2); + CostType cost1 = pdbm_cost(pdbm1); + CostType cost2 = pdbm_cost(pdbm2); + + bool a, b; + CostType c, d; + + switch (dbm_relation(dbm1, dbm2, dim)) { + case base_SUPERSET: + // pdbm2 is smaller. Check whether it is also strictly more expensive: + cost1 = costAtOtherOffset(dbm1, rates1, cost1, dbm2, dim); + if (cost1 < cost2 && + (le(rates1, rates1 + dim, rates2) || infOfDiff(dbm2, dim, cost2, rates2, cost1, rates1) > 0)) { + return base_SUPERSET; + } else { + return base_DIFFERENT; + } + + case base_SUBSET: + // pdbm2 is bigger. Check whether it is also weakly less expensive: + cost2 = costAtOtherOffset(dbm2, rates2, cost2, dbm1, dim); + if (cost2 <= cost1 && + (leq(rates2, rates2 + dim, rates1) || infOfDiff(dbm1, dim, cost1, rates1, cost2, rates2) >= 0)) { + return base_SUBSET; + } else { + return base_DIFFERENT; + } + + case base_EQUAL: + /* Both have the same size. We need to compare the planes to + * see which one is cheaper. + */ + + /* Do sound and cheap comparison first. + */ + if (cost1 == cost2 && eq(rates1, rates1 + dim, rates2)) { + return base_EQUAL; + } else if (cost1 < cost2 && le(rates1, rates1 + dim, rates2)) { + return base_SUPERSET; + } else if (cost2 <= cost1 && leq(rates2, rates2 + dim, rates1)) { + return base_SUBSET; + } + + /* The planes are incomparable, so we need to do the + * subtraction. Notice that priced zones are not canonical, + * so the two zones can in fact be equal even though the rates + * are different. Therefore we must also check for the + * situation where both infima are zero. + * + * Notice that dbm1 equals dbm2, hence we do not need to + * unpack dbm2. + */ + c = infOfDiff(dbm1, dim, cost2, rates2, cost1, rates1); + if (c > 0) { + /* Early return to avoid unnecessary computation of the + * second subtraction. + */ + return base_SUPERSET; + } + + d = infOfDiff(dbm1, dim, cost1, rates1, cost2, rates2); + if (c == 0 && d == 0) { + return base_EQUAL; + } + if (d >= 0) { + return base_SUBSET; + } + return base_DIFFERENT; + + default: return base_DIFFERENT; + } +} + relation_t pdbm_relationWithMinDBM(const PDBM pdbm1, cindex_t dim, const mingraph_t pdbm2, raw_t* dbm2) { throw std::logic_error("pdbm_relationWithMinDBM not implemented!"); @@ -723,7 +845,12 @@ bool pdbm_isUnbounded(const PDBM pdbm, cindex_t dim) uint32_t pdbm_hash(const PDBM pdbm, cindex_t dim, uint32_t seed) { assert(pdbm && dim && !(pdbm_size(dim) & 3)); - return hash_computeI32((int32_t*)pdbm, pdbm_size(dim) >> 2, seed); + uint32_t hash = seed ^ dbm_hash(pdbm_matrix(pdbm), dim); + hash ^= hash_cost_type(pdbm_cost(pdbm)); + for (cindex_t i = 1; i < dim; ++i) { + hash ^= (hash ^ hash_cost_type(pdbm_rates(pdbm)[i])) << 4; + } + return hash; } static bool isPointIncludedWeakly(const int32_t* pt, const raw_t* dbm, cindex_t dim) From 2bfb353f74fe53945a049ffe26938905ebc11f7a Mon Sep 17 00:00:00 2001 From: Ragusaen Date: Fri, 28 Apr 2023 13:04:55 +0200 Subject: [PATCH 24/32] the pdbm now remembers the cost-plane operations that have been applied on it --- include/dbm/pfed.h | 32 +++++++++++++++++++-- src/pfed.cpp | 71 +++++++++++++++++++++++++++++++++++++++++++--- src/priced.cpp | 4 +-- 3 files changed, 99 insertions(+), 8 deletions(-) diff --git a/include/dbm/pfed.h b/include/dbm/pfed.h index 6fc5f80..45e1509 100644 --- a/include/dbm/pfed.h +++ b/include/dbm/pfed.h @@ -24,6 +24,28 @@ namespace dbm { + + struct CostPlaneOperation + { + enum Type { + Delay, // delay from a facet of clock i with rate value + DiscreteOffset, // increase offset by value + ContinuousOffset, // increase offset by value * rate(i) + RelativeReset, // reset clock i on a facet relative to clock j + }; + Type type{}; + cindex_t clock_i; + union { + cindex_t clock_j; + CostType value; + }; + CostPlaneOperation(Type type, cindex_t clock_i, cindex_t clock_j) + : type(type), clock_i(clock_i), clock_j(clock_j) {} + + CostPlaneOperation(Type type, cindex_t clock_i, CostType value) + : type(type), clock_i(clock_i), value(value) {} + }; + class pdbm_t; /** @@ -48,8 +70,10 @@ namespace dbm protected: PDBM pdbm; cindex_t dim; - public: + + std::vector cost_plane_operations; + /** * The default constructor constructs an empty priced DBM of * dimension zero. This must not be assigned to another @@ -211,7 +235,7 @@ namespace dbm inline pdbm_t::pdbm_t(PDBM pdbm, cindex_t dim): pdbm(pdbm), dim(dim) { pdbm_incRef(pdbm); } - inline pdbm_t::pdbm_t(const pdbm_t& other): pdbm(other.pdbm), dim(other.dim) { pdbm_incRef(pdbm); } + inline pdbm_t::pdbm_t(const pdbm_t& other): pdbm(other.pdbm), dim(other.dim), cost_plane_operations(other.cost_plane_operations) { pdbm_incRef(pdbm); } inline pdbm_t::~pdbm_t() { pdbm_decRef(pdbm); } @@ -755,6 +779,10 @@ namespace dbm /// Not implemented bool eq(const pfed_t& arg) const; + void clear_cost_plane_operations() { + std::for_each(ptr->zones.begin(), ptr->zones.end(), [](pdbm_t& z) { z.cost_plane_operations.clear(); }); + } + /* * Non-exact union. Keeps all zones that are not subseteq of another zone. Returns true if the zones changed. diff --git a/src/pfed.cpp b/src/pfed.cpp index 38a7745..9ae7940 100644 --- a/src/pfed.cpp +++ b/src/pfed.cpp @@ -76,14 +76,56 @@ namespace dbm bool pfed_t::constrain(cindex_t i, cindex_t j, raw_t constraint) { - // lambda x . pdbm_constrain1(x, ptr->dim, i, j, constraint) - erase_if_not(bind(pdbm_constrain1, _1, ptr->dim, i, j, constraint)); +// // lambda x . pdbm_constrain1(x, ptr->dim, i, j, constraint) +// erase_if_not(bind(pdbm_constrain1, _1, ptr->dim, i, j, constraint)); + + auto it = beginMutable(); + auto end = endMutable(); + for (; it != end;) { + int prev_offset[ptr->dim]; + pdbm_getOffset(*it, ptr->dim, prev_offset); + + if (!pdbm_constrain1(*it, ptr->dim, i, j, constraint)) { + it = erase(it); + continue; + } + + int new_offset[ptr->dim]; + pdbm_getOffset(*it, ptr->dim, new_offset); + for (int x = 1; x < ptr->dim; x++) { + if (prev_offset[x] != new_offset[x]) { + it->cost_plane_operations.emplace_back(CostPlaneOperation::Type::ContinuousOffset, x, new_offset[x] - prev_offset[x]); + } + } + it++; + } return !isEmpty(); } bool pfed_t::constrain(const constraint_t* constraints, size_t n) { - erase_if_not(bind(pdbm_constrainN, _1, ptr->dim, constraints, n)); +// erase_if_not(bind(pdbm_constrainN, _1, ptr->dim, constraints, n)); + + auto it = beginMutable(); + auto end = endMutable(); + for (; it != end;) { + int prev_offset[ptr->dim]; + pdbm_getOffset(*it, ptr->dim, prev_offset); + + if (!pdbm_constrainN(*it, ptr->dim, constraints, n)) { + it = erase(it); + continue; + } + + int new_offset[ptr->dim]; + pdbm_getOffset(*it, ptr->dim, new_offset); + for (int x = 1; x < ptr->dim; x++) { + if (prev_offset[x] != new_offset[x]) { + it->cost_plane_operations.emplace_back(CostPlaneOperation::Type::ContinuousOffset, x, new_offset[x] - prev_offset[x]); + } + } + it++; + } return !isEmpty(); } @@ -259,6 +301,7 @@ namespace dbm /* This is a simple case which does not require splits. */ pdbm_upZero(*zone, dim, rate, x); + zone->cost_plane_operations.emplace_back(CostPlaneOperation::Delay, x, rate); } else if (rate < oldrate) { /* New rate is smaller than old rate, so we delay from the * lower facets @@ -270,9 +313,11 @@ namespace dbm ptr->zones.push_front(*zone); pdbm_constrainToFacet(ptr->zones.front(), dim, 0, facets[j]); pdbm_upZero(ptr->zones.front(), dim, rate, facets[j]); + zone->cost_plane_operations.emplace_back(CostPlaneOperation::Delay, x, rate); } pdbm_constrainToFacet(*zone, dim, 0, facets[count - 1]); pdbm_upZero(*zone, dim, rate, facets[count - 1]); + zone->cost_plane_operations.emplace_back(CostPlaneOperation::Delay, x, rate); } else { assert(rate > oldrate); @@ -286,6 +331,7 @@ namespace dbm ptr->zones.push_front(*zone); pdbm_constrainToFacet(ptr->zones.front(), dim, facets[j], 0); pdbm_upZero(ptr->zones.front(), dim, rate, facets[j]); + zone->cost_plane_operations.emplace_back(CostPlaneOperation::Delay, x, rate); } // pdbm_constrainToFacet(*zone, dim, facets[count - 1], 0); // pdbm_upZero(*zone, dim, rate, facets[count - 1]); @@ -326,9 +372,15 @@ namespace dbm ptr->zones.push_front(*zone); pdbm_constrainToFacet(ptr->zones.front(), dim, facets[j], clock); pdbm_updateValueZero(ptr->zones.front(), dim, clock, value, facets[j]); + if (0 != facets[j]) { + ptr->zones.front().cost_plane_operations.emplace_back(CostPlaneOperation::Type::RelativeReset, clock, facets[j]); + } } pdbm_constrainToFacet(*zone, dim, facets[count - 1], clock); pdbm_updateValueZero(*zone, dim, clock, value, facets[count - 1]); + if (0 != facets[count - 1]) { + ptr->zones.front().cost_plane_operations.emplace_back(CostPlaneOperation::Type::RelativeReset, clock, facets[count - 1]); + } } else { /* Find and reset upper facets when rate is negative. */ @@ -340,9 +392,15 @@ namespace dbm ptr->zones.push_front(*zone); pdbm_constrainToFacet(ptr->zones.front(), dim, clock, facets[j]); pdbm_updateValueZero(ptr->zones.front(), dim, clock, value, facets[j]); + if (0 != facets[j]) { + ptr->zones.front().cost_plane_operations.emplace_back(CostPlaneOperation::Type::RelativeReset, clock, facets[j]); + } } pdbm_constrainToFacet(*zone, dim, clock, facets[count - 1]); pdbm_updateValueZero(*zone, dim, clock, value, facets[count - 1]); + if (0 != facets[count - 1]) { + ptr->zones.front().cost_plane_operations.emplace_back(CostPlaneOperation::Type::RelativeReset, clock, facets[count - 1]); + } } } return *this; @@ -365,6 +423,9 @@ namespace dbm void pfed_t::incrementCost(CostType value) { + for (auto& pdbm : ptr->zones) { + pdbm.cost_plane_operations.emplace_back(CostPlaneOperation::DiscreteOffset, 0, value); + } for_each(beginMutable(), endMutable(), bind(pdbm_incrementCost, _1, ptr->dim, value)); } @@ -388,7 +449,9 @@ namespace dbm } void pfed_t::add(pdbm_t pdbm){ - add(pdbm.operator PDBM(), pdbm.pdim()); + assert(pdbm.getDimension() == ptr->dim); + prepare(); + ptr->zones.push_front(pdbm); } void pfed_t::setZero() diff --git a/src/priced.cpp b/src/priced.cpp index 583c6bd..8aa3e88 100644 --- a/src/priced.cpp +++ b/src/priced.cpp @@ -577,7 +577,7 @@ relation_t pdbm_relation_strict(const PDBM pdbm1, const PDBM pdbm2, cindex_t dim // pdbm2 is smaller. Check whether it is also strictly more expensive: cost1 = costAtOtherOffset(dbm1, rates1, cost1, dbm2, dim); if (cost1 < cost2 && - (le(rates1, rates1 + dim, rates2) || infOfDiff(dbm2, dim, cost2, rates2, cost1, rates1) > 0)) { + (leq(rates1, rates1 + dim, rates2) || infOfDiff(dbm2, dim, cost2, rates2, cost1, rates1) > 0)) { return base_SUPERSET; } else { return base_DIFFERENT; @@ -602,7 +602,7 @@ relation_t pdbm_relation_strict(const PDBM pdbm1, const PDBM pdbm2, cindex_t dim */ if (cost1 == cost2 && eq(rates1, rates1 + dim, rates2)) { return base_EQUAL; - } else if (cost1 < cost2 && le(rates1, rates1 + dim, rates2)) { + } else if (cost1 < cost2 && leq(rates1, rates1 + dim, rates2)) { return base_SUPERSET; } else if (cost2 <= cost1 && leq(rates2, rates2 + dim, rates1)) { return base_SUBSET; From 3bfcb1c276b0f7632513e1b7f3c75ef2956a64d2 Mon Sep 17 00:00:00 2001 From: Ragusaen Date: Tue, 9 May 2023 15:38:13 +0200 Subject: [PATCH 25/32] Allow changes to cost plane of pdbm --- CMakeLists.txt | 4 ++-- include/dbm/pfed.h | 11 +++++++++++ include/dbm/priced.h | 7 ++++++- src/pfed.cpp | 21 ++++++++++++++++----- src/priced.cpp | 35 ++++++++++++++++++++++++++++++++++- 5 files changed, 69 insertions(+), 9 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d8a45eb..f4f477f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -30,8 +30,8 @@ if(STATIC) endif(STATIC) -set(CMAKE_BUILD_TYPE Release) -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3") +#set(CMAKE_BUILD_TYPE Release) +#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3") target_include_directories(UDBM diff --git a/include/dbm/pfed.h b/include/dbm/pfed.h index 45e1509..1e60026 100644 --- a/include/dbm/pfed.h +++ b/include/dbm/pfed.h @@ -29,6 +29,7 @@ namespace dbm { enum Type { Delay, // delay from a facet of clock i with rate value + DelayKeep, // delay but keeping the rates of previous zone, value is delay that was overwritten DiscreteOffset, // increase offset by value ContinuousOffset, // increase offset by value * rate(i) RelativeReset, // reset clock i on a facet relative to clock j @@ -134,6 +135,12 @@ namespace dbm [[nodiscard]] const CostType* getRates() const { return pdbm_getRates(pdbm, dim); }; + void setRates(CostType* rates) { + for (cindex_t x = 1; x < dim; x++) { + pdbm_setRate(pdbm, dim, x, rates[x]); + } + }; + [[nodiscard]] bool canDelay() const; bool constrain(cindex_t i, cindex_t j, raw_t c); @@ -213,6 +220,9 @@ namespace dbm void setUniformCost(CostType cost); + pdbm_t& operator&=(const dbm::pdbm_t& other); + + /// @return string representation of the /// constraints of this PDBM. A clock /// is always positive, so "true" simply means @@ -297,6 +307,7 @@ namespace dbm return *this; } + /** * Implementation of priced federations. * diff --git a/include/dbm/priced.h b/include/dbm/priced.h index d1a3858..72f714a 100644 --- a/include/dbm/priced.h +++ b/include/dbm/priced.h @@ -355,7 +355,7 @@ bool pdbm_isUnbounded(const PDBM pdbm, cindex_t dim); * @param dim is the dimension of \a pdbm * @param is the cost to set */ -void pdbm_setUniformCost(PDBM pdbm, cindex_t dim, CostType cost); +void pdbm_setUniformCost(PDBM& pdbm, cindex_t dim, CostType cost); /** * Compute a hash value for a priced DBM. @@ -825,6 +825,11 @@ void pdbm_normalise(PDBM pdbm, cindex_t dim); PDBM pdbm_from_dbm(const int32_t* dbm, cindex_t dim); +/** + * Calculates the intersection of dst and src and saves it in dst using the cost plane of dst and ignoring the cost plane of src. + */ +void pdbm_intersect(PDBM& dst, const PDBM& src, cindex_t dim); + /////////////////////////////////////////////////////////////////////////// #endif /* INCLUDE_DBM_PRICED_H */ diff --git a/src/pfed.cpp b/src/pfed.cpp index 9ae7940..72bb9e9 100644 --- a/src/pfed.cpp +++ b/src/pfed.cpp @@ -94,7 +94,7 @@ namespace dbm pdbm_getOffset(*it, ptr->dim, new_offset); for (int x = 1; x < ptr->dim; x++) { if (prev_offset[x] != new_offset[x]) { - it->cost_plane_operations.emplace_back(CostPlaneOperation::Type::ContinuousOffset, x, new_offset[x] - prev_offset[x]); + it->cost_plane_operations.emplace_back(CostPlaneOperation::Type::ContinuousOffset, x, CostType(new_offset[x] - prev_offset[x])); } } it++; @@ -121,7 +121,7 @@ namespace dbm pdbm_getOffset(*it, ptr->dim, new_offset); for (int x = 1; x < ptr->dim; x++) { if (prev_offset[x] != new_offset[x]) { - it->cost_plane_operations.emplace_back(CostPlaneOperation::Type::ContinuousOffset, x, new_offset[x] - prev_offset[x]); + it->cost_plane_operations.emplace_back(CostPlaneOperation::Type::ContinuousOffset, x, CostType(new_offset[x] - prev_offset[x])); } } it++; @@ -313,11 +313,11 @@ namespace dbm ptr->zones.push_front(*zone); pdbm_constrainToFacet(ptr->zones.front(), dim, 0, facets[j]); pdbm_upZero(ptr->zones.front(), dim, rate, facets[j]); - zone->cost_plane_operations.emplace_back(CostPlaneOperation::Delay, x, rate); + ptr->zones.front().cost_plane_operations.emplace_back(CostPlaneOperation::Delay, facets[j], rate); } pdbm_constrainToFacet(*zone, dim, 0, facets[count - 1]); pdbm_upZero(*zone, dim, rate, facets[count - 1]); - zone->cost_plane_operations.emplace_back(CostPlaneOperation::Delay, x, rate); + zone->cost_plane_operations.emplace_back(CostPlaneOperation::Delay, facets[count - 1], rate); } else { assert(rate > oldrate); @@ -331,8 +331,9 @@ namespace dbm ptr->zones.push_front(*zone); pdbm_constrainToFacet(ptr->zones.front(), dim, facets[j], 0); pdbm_upZero(ptr->zones.front(), dim, rate, facets[j]); - zone->cost_plane_operations.emplace_back(CostPlaneOperation::Delay, x, rate); + ptr->zones.front().cost_plane_operations.emplace_back(CostPlaneOperation::Delay, facets[j], rate); } + zone->cost_plane_operations.emplace_back(CostPlaneOperation::DelayKeep, 0, rate); // pdbm_constrainToFacet(*zone, dim, facets[count - 1], 0); // pdbm_upZero(*zone, dim, rate, facets[count - 1]); } @@ -812,5 +813,15 @@ namespace dbm assert(dim == other.dim); return pdbm_relation_strict(pdbm, other.pdbm, dim); } + + pdbm_t& pdbm_t::operator&=(const dbm::pdbm_t& arg) { + assert(getDimension() == arg.getDimension()); + if (arg.isEmpty()) { + pdbm_decRef(pdbm); + pdbm = nullptr; + } else if (!isEmpty()) { + pdbm_intersect(pdbm, arg.pdbm, dim); + } + } } // namespace dbm diff --git a/src/priced.cpp b/src/priced.cpp index 8aa3e88..1620506 100644 --- a/src/priced.cpp +++ b/src/priced.cpp @@ -146,6 +146,7 @@ PDBM pdbm_reserve(cindex_t dim, void* p) pdbm_count(pdbm) = 0; pdbm_cache(pdbm) = INVALID; pdbm_rates(pdbm) = (CostType*)malloc(sizeof(CostType) * dim); + pdbm_cost(pdbm) = 0; std::fill(pdbm_rates(pdbm), pdbm_rates(pdbm) + dim, 0); return pdbm; @@ -772,7 +773,7 @@ CostType pdbm_getSupremum(const PDBM pdbm, cindex_t dim) return -pdbm_infimum(pdbm_matrix(pdbm), dim, -pdbm_cost(pdbm), inv_rates); } -void pdbm_setUniformCost(PDBM pdbm, cindex_t dim, CostType cost) { +void pdbm_setUniformCost(PDBM& pdbm, cindex_t dim, CostType cost) { pdbm_setCostAtOffset(pdbm, dim, cost); for (cindex_t x = 1; x < dim; ++x) { pdbm_setRate(pdbm, dim, x, 0); @@ -1591,4 +1592,36 @@ PDBM pdbm_from_dbm(const int32_t* dbm, cindex_t dim) { PDBM pdbm = pdbm_allocate(dim); memcpy(pdbm->data, dbm, dim * dim * sizeof(int32_t)); return pdbm; +} + +void pdbm_intersect(PDBM& dst, const PDBM& src, cindex_t dim) { + assert(dst && src && dim > 0); + pdbm_prepare(dst, dim); + + /* Compute the cost at the origin. + */ + CostType cost = pdbm_cost(dst); + CostType* rates = pdbm_rates(dst); + raw_t* dbm = pdbm_matrix(dst); + for (uint32_t k = 1; k < dim; k++) { + cost += rates[k] * dbm_raw2bound(DBM(0, k)); + } + + if (!dbm_intersection(dbm, pdbm_matrix(src), dim)) { + // If there was no intersection, dst becomes empty. + pdbm_decRef(dst); + dst = nullptr; + } else { + // Compute the cost at the new offset point and invalidate the cache. + for (uint32_t k = 1; k < dim; k++) { + cost -= rates[k] * dbm_raw2bound(DBM(0, k)); + } + pdbm_cost(dst) = cost; + pdbm_cache(dst) = INVALID; + + assertx(pdbm_isValid(dst, dim)); + + pdbm_cache(dst) = INVALID; + } + } \ No newline at end of file From c423c16243128cede2f03b2bce435c554d76d8bd Mon Sep 17 00:00:00 2001 From: Ragusaen Date: Thu, 11 May 2023 08:30:48 +0200 Subject: [PATCH 26/32] fixed some memory leaks --- include/dbm/pfed.h | 2 +- src/pfed.cpp | 2 ++ src/priced.cpp | 5 ++++- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/include/dbm/pfed.h b/include/dbm/pfed.h index 1e60026..ebdaf9e 100644 --- a/include/dbm/pfed.h +++ b/include/dbm/pfed.h @@ -247,7 +247,7 @@ namespace dbm inline pdbm_t::pdbm_t(const pdbm_t& other): pdbm(other.pdbm), dim(other.dim), cost_plane_operations(other.cost_plane_operations) { pdbm_incRef(pdbm); } - inline pdbm_t::~pdbm_t() { pdbm_decRef(pdbm); } + inline pdbm_t::~pdbm_t() { pdbm_decRef(pdbm); } inline pdbm_t& pdbm_t::operator=(const pdbm_t& other) { diff --git a/src/pfed.cpp b/src/pfed.cpp index 72bb9e9..9ecbf5d 100644 --- a/src/pfed.cpp +++ b/src/pfed.cpp @@ -460,6 +460,7 @@ namespace dbm PDBM pdbm = nullptr; pdbm_zero(pdbm, ptr->dim); *this = pfed_t(pdbm, ptr->dim); + pdbm_decRef(pdbm); // We do not reference this, the pdbm_t does now. } void pfed_t::setInit() @@ -467,6 +468,7 @@ namespace dbm PDBM pdbm = nullptr; pdbm_init(pdbm, ptr->dim); *this = pfed_t(pdbm, ptr->dim); + pdbm_decRef(pdbm); // We do not reference this, the pdbm_t does now. } void pfed_t::nil() diff --git a/src/priced.cpp b/src/priced.cpp index 1620506..e235db0 100644 --- a/src/priced.cpp +++ b/src/priced.cpp @@ -179,6 +179,8 @@ PDBM pdbm_copy(PDBM dst, const PDBM src, cindex_t dim) dst = pdbm_allocate(dim); } + free(dst->rates); // We overwrite the rates pointer in the memcpy below, so make sure to free it first. + memcpy(dst, src, pdbm_size(dim)); dst->rates = (CostType*)malloc(sizeof(CostType) * dim); std::copy(src->rates, src->rates + dim, dst->rates); @@ -774,6 +776,7 @@ CostType pdbm_getSupremum(const PDBM pdbm, cindex_t dim) } void pdbm_setUniformCost(PDBM& pdbm, cindex_t dim, CostType cost) { + pdbm_prepare(pdbm, dim); pdbm_setCostAtOffset(pdbm, dim, cost); for (cindex_t x = 1; x < dim; ++x) { pdbm_setRate(pdbm, dim, x, 0); @@ -1596,7 +1599,6 @@ PDBM pdbm_from_dbm(const int32_t* dbm, cindex_t dim) { void pdbm_intersect(PDBM& dst, const PDBM& src, cindex_t dim) { assert(dst && src && dim > 0); - pdbm_prepare(dst, dim); /* Compute the cost at the origin. */ @@ -1612,6 +1614,7 @@ void pdbm_intersect(PDBM& dst, const PDBM& src, cindex_t dim) { pdbm_decRef(dst); dst = nullptr; } else { + pdbm_prepare(dst, dim); // Compute the cost at the new offset point and invalidate the cache. for (uint32_t k = 1; k < dim; k++) { cost -= rates[k] * dbm_raw2bound(DBM(0, k)); From 12a544d47f28c36e23805133e04b365bd8f0b6d9 Mon Sep 17 00:00:00 2001 From: Ragusaen Date: Fri, 12 May 2023 11:24:48 +0200 Subject: [PATCH 27/32] Removed optimization when delaying with rate 0, as we need to know which facet is used. --- include/dbm/pfed.h | 22 ++++++++++++++++++++++ src/pfed.cpp | 12 +++++++++--- 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/include/dbm/pfed.h b/include/dbm/pfed.h index ebdaf9e..d0c83f3 100644 --- a/include/dbm/pfed.h +++ b/include/dbm/pfed.h @@ -45,6 +45,27 @@ namespace dbm CostPlaneOperation(Type type, cindex_t clock_i, CostType value) : type(type), clock_i(clock_i), value(value) {} + + friend std::ostream& operator<<(std::ostream& os, const CostPlaneOperation& op) { + switch (op.type) { + case Delay: + os << "↑" << op.clock_i << "," << op.value << ""; + break; + case DelayKeep: + os << "↑" << op.clock_i << ",?"; + break; + case DiscreteOffset: + os << "Δ" << op.value << ""; + break; + case ContinuousOffset: + os << "Δ" << op.value << "⋅r(" << op.clock_i << ")"; + break; + case RelativeReset: + os << "↓" << op.clock_i << "," << op.clock_j << ""; + break; + } + return os; + } }; class pdbm_t; @@ -791,6 +812,7 @@ namespace dbm bool eq(const pfed_t& arg) const; void clear_cost_plane_operations() { + cow(); std::for_each(ptr->zones.begin(), ptr->zones.end(), [](pdbm_t& z) { z.cost_plane_operations.clear(); }); } diff --git a/src/pfed.cpp b/src/pfed.cpp index 9ecbf5d..6252a64 100644 --- a/src/pfed.cpp +++ b/src/pfed.cpp @@ -358,10 +358,15 @@ namespace dbm cindex_t k; CostType rate = pdbm_getRate(*zone, dim, clock); - if (rate == 0) { - pdbm_updateValue(*zone, dim, clock, value); - } else if (pdbm_findZeroCycle(*zone, dim, clock, &k)) { + // Remove this because we cannot know which facet was reset +// if (rate == 0) { +// pdbm_updateValue(*zone, dim, clock, value); +// } else + if (pdbm_findZeroCycle(*zone, dim, clock, &k)) { pdbm_updateValueZero(*zone, dim, clock, value, k); + if (0 != k) { + zone->cost_plane_operations.emplace_back(CostPlaneOperation::RelativeReset, clock, k); + } } else if (rate > 0) { /* Find and reset lower facets when rate is positive. */ @@ -824,6 +829,7 @@ namespace dbm } else if (!isEmpty()) { pdbm_intersect(pdbm, arg.pdbm, dim); } + return *this; } } // namespace dbm From ba0519598b11ccc266ddd5a408f0572e070134b4 Mon Sep 17 00:00:00 2001 From: Ragusaen Date: Wed, 17 May 2023 10:46:01 +0200 Subject: [PATCH 28/32] Also remember cost plane operations when constraining to facets for updateValue and up --- include/dbm/pfed.h | 12 +++++++ include/dbm/priced.h | 5 +++ src/pfed.cpp | 86 +++++++++++++++++++++++++++----------------- src/priced.cpp | 9 +++++ 4 files changed, 80 insertions(+), 32 deletions(-) diff --git a/include/dbm/pfed.h b/include/dbm/pfed.h index d0c83f3..903c89f 100644 --- a/include/dbm/pfed.h +++ b/include/dbm/pfed.h @@ -256,6 +256,8 @@ namespace dbm /// @return dimension cindex_t pdim() const; + void simplify_rational_cost(); + bool contains(const int32_t* point, cindex_t dim) const; bool contains(const double* point, cindex_t dim) const; }; @@ -506,6 +508,14 @@ namespace dbm */ ~pfed_t(); + static pfed_t from_fed(const fed_t& fed) { + pfed_t pfed(fed.getDimension()); + for (const dbm::dbm_t& dbm : fed) { + pfed.add(pdbm_t::from_dbm(dbm)); + } + return pfed; + } + /** * Constrain x(i) to value. * @@ -631,6 +641,8 @@ namespace dbm void freeClock(cindex_t clock); + void simplify_rational_cost(); + /** * Resets the federation to the federation containing only the * origin, with a cost of 0. diff --git a/include/dbm/priced.h b/include/dbm/priced.h index 72f714a..9867fa6 100644 --- a/include/dbm/priced.h +++ b/include/dbm/priced.h @@ -830,6 +830,11 @@ PDBM pdbm_from_dbm(const int32_t* dbm, cindex_t dim); */ void pdbm_intersect(PDBM& dst, const PDBM& src, cindex_t dim); +/** + * Simplifies the rational cost values in the pdbm by approximating them as integers + */ +void pdbm_simplify_rational_cost(PDBM& pdbm, cindex_t dim); + /////////////////////////////////////////////////////////////////////////// #endif /* INCLUDE_DBM_PRICED_H */ diff --git a/src/pfed.cpp b/src/pfed.cpp index 6252a64..71be907 100644 --- a/src/pfed.cpp +++ b/src/pfed.cpp @@ -290,9 +290,24 @@ namespace dbm { cindex_t x; CostType oldrate = pdbm_getSlopeOfDelayTrajectory(*zone, dim); + int prev_offset[ptr->dim]; + pdbm_getOffset(*zone, ptr->dim, prev_offset); // pdbm_print(std::cout, zone->operator PDBM(), dim); + auto constrain_and_up = [&](pdbm_t& z, cindex_t i, cindex_t j, cindex_t zero) { + pdbm_constrainToFacet(z, dim, i, j); + pdbm_upZero(z, dim, rate, zero); + int new_offset[ptr->dim]; + pdbm_getOffset(z, ptr->dim, new_offset); + for (int x = 1; x < ptr->dim; x++) { + if (prev_offset[x] != new_offset[x]) { + z.cost_plane_operations.emplace_back(CostPlaneOperation::Type::ContinuousOffset, x, CostType(new_offset[x] - prev_offset[x])); + } + } + z.cost_plane_operations.emplace_back(CostPlaneOperation::Delay, zero, rate); + }; + if (rate == oldrate) { /* This is a simple case which does not require splits. */ @@ -311,15 +326,11 @@ namespace dbm assert(count > 0 && count <= dim); for (uint32_t j = 0; j < count - 1; j++) { ptr->zones.push_front(*zone); - pdbm_constrainToFacet(ptr->zones.front(), dim, 0, facets[j]); - pdbm_upZero(ptr->zones.front(), dim, rate, facets[j]); - ptr->zones.front().cost_plane_operations.emplace_back(CostPlaneOperation::Delay, facets[j], rate); + constrain_and_up(ptr->zones.front(), 0, facets[j], facets[j]); } - pdbm_constrainToFacet(*zone, dim, 0, facets[count - 1]); - pdbm_upZero(*zone, dim, rate, facets[count - 1]); - zone->cost_plane_operations.emplace_back(CostPlaneOperation::Delay, facets[count - 1], rate); + constrain_and_up(*zone, 0, facets[count - 1], facets[count - 1]); } else { - assert(rate > oldrate); +// assert(rate > oldrate); /* New rate is bigger than old rate, so we delay from the * upper facets. We also need the original zone. @@ -329,9 +340,7 @@ namespace dbm assert(count > 0 && count <= dim); for (uint32_t j = 0; j < count; j++) { ptr->zones.push_front(*zone); - pdbm_constrainToFacet(ptr->zones.front(), dim, facets[j], 0); - pdbm_upZero(ptr->zones.front(), dim, rate, facets[j]); - ptr->zones.front().cost_plane_operations.emplace_back(CostPlaneOperation::Delay, facets[j], rate); + constrain_and_up(ptr->zones.front(), facets[j], 0, facets[j]); } zone->cost_plane_operations.emplace_back(CostPlaneOperation::DelayKeep, 0, rate); // pdbm_constrainToFacet(*zone, dim, facets[count - 1], 0); @@ -358,6 +367,26 @@ namespace dbm cindex_t k; CostType rate = pdbm_getRate(*zone, dim, clock); + uint32_t facets[dim]; + int prev_offset[ptr->dim]; + pdbm_getOffset(*zone, ptr->dim, prev_offset); + + // Constrain to the facet i - j < m where zero is the clock in the constraint that is not clock; reset clock + auto constrain_and_reset = [&](pdbm_t& z, uint32_t i, uint32_t j, uint32_t zero) { + pdbm_constrainToFacet(z, dim, i, j); + pdbm_updateValueZero(z, dim, clock, value, zero); + if (0 != zero) { + z.cost_plane_operations.emplace_back(CostPlaneOperation::Type::RelativeReset, clock, zero); + } + int new_offset[ptr->dim]; + pdbm_getOffset(z, ptr->dim, new_offset); + for (int x = 1; x < ptr->dim; x++) { + if (prev_offset[x] != new_offset[x]) { + z.cost_plane_operations.emplace_back(CostPlaneOperation::Type::ContinuousOffset, x, CostType(new_offset[x] - prev_offset[x])); + } + } + }; + // Remove this because we cannot know which facet was reset // if (rate == 0) { // pdbm_updateValue(*zone, dim, clock, value); @@ -370,23 +399,14 @@ namespace dbm } else if (rate > 0) { /* Find and reset lower facets when rate is positive. */ - uint32_t facets[dim]; int32_t count = pdbm_getLowerRelativeFacets(*zone, dim, clock, facets); assert(count >= 1); for (int32_t j = 0; j < count - 1; j++) { ptr->zones.push_front(*zone); - pdbm_constrainToFacet(ptr->zones.front(), dim, facets[j], clock); - pdbm_updateValueZero(ptr->zones.front(), dim, clock, value, facets[j]); - if (0 != facets[j]) { - ptr->zones.front().cost_plane_operations.emplace_back(CostPlaneOperation::Type::RelativeReset, clock, facets[j]); - } - } - pdbm_constrainToFacet(*zone, dim, facets[count - 1], clock); - pdbm_updateValueZero(*zone, dim, clock, value, facets[count - 1]); - if (0 != facets[count - 1]) { - ptr->zones.front().cost_plane_operations.emplace_back(CostPlaneOperation::Type::RelativeReset, clock, facets[count - 1]); + constrain_and_reset(ptr->zones.front(), facets[j], clock, facets[j]); } + constrain_and_reset(*zone, facets[count - 1], clock, facets[count - 1]); } else { /* Find and reset upper facets when rate is negative. */ @@ -396,17 +416,9 @@ namespace dbm assert(count >= 1); for (int32_t j = 0; j < count - 1; j++) { ptr->zones.push_front(*zone); - pdbm_constrainToFacet(ptr->zones.front(), dim, clock, facets[j]); - pdbm_updateValueZero(ptr->zones.front(), dim, clock, value, facets[j]); - if (0 != facets[j]) { - ptr->zones.front().cost_plane_operations.emplace_back(CostPlaneOperation::Type::RelativeReset, clock, facets[j]); - } - } - pdbm_constrainToFacet(*zone, dim, clock, facets[count - 1]); - pdbm_updateValueZero(*zone, dim, clock, value, facets[count - 1]); - if (0 != facets[count - 1]) { - ptr->zones.front().cost_plane_operations.emplace_back(CostPlaneOperation::Type::RelativeReset, clock, facets[count - 1]); + constrain_and_reset(ptr->zones.front(), clock, facets[j], facets[j]); } + constrain_and_reset(*zone, clock, facets[count - 1], facets[count - 1]); } } return *this; @@ -498,7 +510,7 @@ namespace dbm } fed_t pfed_t::to_fed() const { - fed_t fed; + fed_t fed(getDimension()); for (const pdbm_t& pdbm : *this) { fed.add(pdbm.to_dbm()); } @@ -792,6 +804,11 @@ namespace dbm pfed_t& pfed_t::mergeReduce(size_t skip, int expensiveTry){ throw std::logic_error("pfed_t::mergeReduce not implemented"); } + void pfed_t::simplify_rational_cost() { + for (auto it = beginMutable(); it != endMutable(); ++it) { + it->simplify_rational_cost(); + } + } cindex_t pdbm_t::pdim() const { return dim; } @@ -831,5 +848,10 @@ namespace dbm } return *this; } + void pdbm_t::simplify_rational_cost() { + if (!isEmpty()) { + pdbm_simplify_rational_cost(pdbm, dim); + } + } } // namespace dbm diff --git a/src/priced.cpp b/src/priced.cpp index e235db0..29e012f 100644 --- a/src/priced.cpp +++ b/src/priced.cpp @@ -1627,4 +1627,13 @@ void pdbm_intersect(PDBM& dst, const PDBM& src, cindex_t dim) { pdbm_cache(dst) = INVALID; } +} + +void pdbm_simplify_rational_cost(PDBM& pdbm, cindex_t dim) { + pdbm_prepare(pdbm, dim); + pdbm_cost(pdbm) = pdbm_cost(pdbm).numerator() / pdbm_cost(pdbm).denominator(); + for (cindex_t i = 1; i < dim; i++) { + pdbm_rates(pdbm)[i] = pdbm_rates(pdbm)[i].numerator() / pdbm_rates(pdbm)[i].denominator(); + } + pdbm_cache(pdbm) = INVALID; } \ No newline at end of file From 0c0dff26a1627c86116b6c88069fdf19c9413207 Mon Sep 17 00:00:00 2001 From: Ragusaen Date: Thu, 18 May 2023 12:35:44 +0200 Subject: [PATCH 29/32] Fixed bugs with cost-plane operations --- src/pfed.cpp | 27 ++++++++++++++------------- src/priced.cpp | 4 ++-- 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/src/pfed.cpp b/src/pfed.cpp index 71be907..472bd5a 100644 --- a/src/pfed.cpp +++ b/src/pfed.cpp @@ -297,7 +297,6 @@ namespace dbm auto constrain_and_up = [&](pdbm_t& z, cindex_t i, cindex_t j, cindex_t zero) { pdbm_constrainToFacet(z, dim, i, j); - pdbm_upZero(z, dim, rate, zero); int new_offset[ptr->dim]; pdbm_getOffset(z, ptr->dim, new_offset); for (int x = 1; x < ptr->dim; x++) { @@ -305,19 +304,21 @@ namespace dbm z.cost_plane_operations.emplace_back(CostPlaneOperation::Type::ContinuousOffset, x, CostType(new_offset[x] - prev_offset[x])); } } + pdbm_upZero(z, dim, rate, zero); z.cost_plane_operations.emplace_back(CostPlaneOperation::Delay, zero, rate); }; - if (rate == oldrate) { - /* This is a simple case which does not require splits. - */ - pdbm_up(*zone, dim); - } else if (pdbm_findZeroCycle(*zone, dim, 0, &x)) { +// if (rate == oldrate) { +// /* This is a simple case which does not require splits. +// */ +// pdbm_up(*zone, dim); +// } else + if (pdbm_findZeroCycle(*zone, dim, 0, &x)) { /* This is a simple case which does not require splits. */ pdbm_upZero(*zone, dim, rate, x); zone->cost_plane_operations.emplace_back(CostPlaneOperation::Delay, x, rate); - } else if (rate < oldrate) { + } else if (rate <= oldrate) { /* New rate is smaller than old rate, so we delay from the * lower facets */ @@ -330,7 +331,7 @@ namespace dbm } constrain_and_up(*zone, 0, facets[count - 1], facets[count - 1]); } else { -// assert(rate > oldrate); + assert(rate > oldrate); /* New rate is bigger than old rate, so we delay from the * upper facets. We also need the original zone. @@ -374,17 +375,17 @@ namespace dbm // Constrain to the facet i - j < m where zero is the clock in the constraint that is not clock; reset clock auto constrain_and_reset = [&](pdbm_t& z, uint32_t i, uint32_t j, uint32_t zero) { pdbm_constrainToFacet(z, dim, i, j); - pdbm_updateValueZero(z, dim, clock, value, zero); - if (0 != zero) { - z.cost_plane_operations.emplace_back(CostPlaneOperation::Type::RelativeReset, clock, zero); - } int new_offset[ptr->dim]; pdbm_getOffset(z, ptr->dim, new_offset); for (int x = 1; x < ptr->dim; x++) { if (prev_offset[x] != new_offset[x]) { - z.cost_plane_operations.emplace_back(CostPlaneOperation::Type::ContinuousOffset, x, CostType(new_offset[x] - prev_offset[x])); + z.cost_plane_operations.emplace_back(CostPlaneOperation::Type::ContinuousOffset, x, CostType(new_offset[x] - prev_offset[x])); } } + pdbm_updateValueZero(z, dim, clock, value, zero); + if (0 != zero) { + z.cost_plane_operations.emplace_back(CostPlaneOperation::Type::RelativeReset, clock, zero); + } }; // Remove this because we cannot know which facet was reset diff --git a/src/priced.cpp b/src/priced.cpp index 29e012f..443f4b2 100644 --- a/src/priced.cpp +++ b/src/priced.cpp @@ -920,7 +920,7 @@ void pdbm_upZero(PDBM& pdbm, cindex_t dim, CostType rate, cindex_t zero) dbm_up(dbm, dim); rates[zero] = 0; rates[zero] = rate - pdbm_getSlopeOfDelayTrajectory(pdbm, dim); - pdbm->infimum = INVALID; + pdbm_cache(pdbm) = INVALID; assertx(pdbm_isValid(pdbm, dim)); } @@ -949,7 +949,7 @@ void pdbm_updateValueZero(PDBM& pdbm, cindex_t dim, cindex_t clock, uint32_t val if (zero) { rates[zero] += rates[clock]; } - rates[clock] = 0; +// rates[clock] = 0; dbm_updateValue(pdbm_matrix(pdbm), dim, clock, value); assertx(pdbm_isValid(pdbm, dim)); From 3a445c9c12842d3ec781c9f084ef3e371eef822e Mon Sep 17 00:00:00 2001 From: Slorup Date: Tue, 23 May 2023 10:29:56 +0200 Subject: [PATCH 30/32] small --- CMakeLists.txt | 4 ++-- include/dbm/pfed.h | 4 ++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f4f477f..d8a45eb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -30,8 +30,8 @@ if(STATIC) endif(STATIC) -#set(CMAKE_BUILD_TYPE Release) -#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3") +set(CMAKE_BUILD_TYPE Release) +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3") target_include_directories(UDBM diff --git a/include/dbm/pfed.h b/include/dbm/pfed.h index 903c89f..840374a 100644 --- a/include/dbm/pfed.h +++ b/include/dbm/pfed.h @@ -516,6 +516,10 @@ namespace dbm return pfed; } + const pdbm_t& first() { + return ptr->zones.front(); + } + /** * Constrain x(i) to value. * From 98b5ec16e0fbbdf6ce555cbf5c1846ebf798d0b8 Mon Sep 17 00:00:00 2001 From: Rasmus Tollund Date: Thu, 28 Sep 2023 15:56:55 +0200 Subject: [PATCH 31/32] added doctest and some pfed tests --- CMakeLists.txt | 1 + getlibs.sh | 10 +++++++ test/CMakeLists.txt | 11 ++++---- test/test_pfed.cpp | 65 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 81 insertions(+), 6 deletions(-) create mode 100644 test/test_pfed.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index d8a45eb..b32352a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,6 +16,7 @@ set(ENABLE_STORE_MINGRAPH 1) CONFIGURE_FILE("src/config.h.cmake" "include/dbm/config.h") set(CMAKE_PREFIX_PATH "${CMAKE_PREFIX_PATH};${CMAKE_CURRENT_SOURCE_DIR}/libs") +find_package(doctest 2.4.11 REQUIRED) find_package(xxHash 0.8.0 CONFIG REQUIRED) find_package(UUtils 1.1.1 REQUIRED COMPONENTS base hash debug) diff --git a/getlibs.sh b/getlibs.sh index 02111bf..dbc014b 100755 --- a/getlibs.sh +++ b/getlibs.sh @@ -42,3 +42,13 @@ tar -xvf boost_1_81_0.tar.gz mkdir -p "$SOURCE_DIR/libs/sources/boost_1_81_0/build" cd "$SOURCE_DIR/libs/sources/boost_1_81_0/build" cp -r "$SOURCE_DIR/libs/sources/boost_1_81_0/boost" "$SOURCE_DIR/libs/" + +cd $SOURCE_DIR/libs/sources; +wget https://github.com/doctest/doctest/archive/refs/tags/v2.4.11.tar.gz +tar -xvf v2.4.11.tar.gz +mkdir -p "$SOURCE_DIR/libs/sources/doctest-2.4.11/build" +cd "$SOURCE_DIR/libs/sources/doctest-2.4.11" +cd build +cmake $CMAKE_ARGS -DOCTEST_WITH_TESTS=OFF -DDOCTEST_WITH_MAIN_IN_STATIC_LIB=ON -DDOCTEST_USE_STD_HEADERS=ON -DCMAKE_INSTALL_PREFIX="$SOURCE_DIR/libs" .. +cmake --build . --config Release +cmake --install . --config Release diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index c356200..2ff3041 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -3,13 +3,12 @@ set(libs UDBM UUtils::udebug UUtils::base UUtils::hash m) if (TESTING) - file(GLOB test_sources "test_*.c" "test_*.cpp") + add_executable(test_dbm test_dbm.c) + target_link_libraries(test_dbm ${libs}) - foreach(source ${test_sources}) - get_filename_component(test_target ${source} NAME_WE) - add_executable(${test_target} ${source}) - target_link_libraries(${test_target} ${libs}) - endforeach() + add_executable(test_pfed test_pfed.cpp) + target_compile_definitions(test_pfed PRIVATE DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN) + target_link_libraries(test_pfed PRIVATE ${libs} doctest::doctest) # comments contain expected time of Linux debug build, YMMV, whereas timeouts are worst case add_test(NAME dbm_dbm_1_10 COMMAND test_dbm 1 10) diff --git a/test/test_pfed.cpp b/test/test_pfed.cpp new file mode 100644 index 0000000..72912ba --- /dev/null +++ b/test/test_pfed.cpp @@ -0,0 +1,65 @@ +#include "dbm/cost_type.h" +#include "dbm/pfed.h" + +#include + +void any_contains(const dbm::pfed_t& pfed, int* valuation, size_t dim, CostType expected) { + bool any_contains = false; + for (const auto& pdbm : pfed) { + if (pdbm_containsInt(pdbm, dim, valuation)) { + CHECK_MESSAGE((pdbm_getCostOfValuation(pdbm, dim, valuation) == expected), "Expected cost " << expected << " but got " << pdbm_getCostOfValuation(pdbm, dim, valuation)); + any_contains = true; + } + } + CHECK(any_contains); +} + +TEST_SUITE("pfed") +{ + TEST_CASE("delay_constraint") + { + dbm::pfed_t pfed(2); + pfed.setZero(); + pfed.up(4); + pfed.constrain(1, 0, 2, false); + pfed.constrain(0, 1, -1, false); + + REQUIRE((pfed.getInfimum() == 4)); + } + + TEST_CASE("reset") + { + dbm::pfed_t pfed(3); + pfed.setZero(); + pfed.up(1); + pfed.constrain(1, 0, 3, false); + pfed.updateValue(1, 0); + pfed.up(2); + pfed.constrain(0, 2, -1, false); + pfed.updateValue(2, 0); + pfed.up(3); + + REQUIRE((pfed.size() == 2)); + REQUIRE((pfed.getInfimum() == 1)); + + + { + + } + // Assert that some pdbm in pfed contains the valuation (1,1) and has cost 4 + { + int valuation[3] = {0, 1, 1}; + any_contains(pfed, valuation, 3, 4); + } + + { + int valuation[3] = {0, 2, 2}; + any_contains(pfed, valuation, 3, 7); + } + + { + int valuation[3] = {0, 2, 0}; + any_contains(pfed, valuation, 3, 4); + } + } +} \ No newline at end of file From 16eee00a4d73f8177c9f9a206ffccb0765860406 Mon Sep 17 00:00:00 2001 From: Rasmus Tollund Date: Fri, 29 Sep 2023 09:06:05 +0200 Subject: [PATCH 32/32] Added a test for setUniformCost --- include/dbm/pfed.h | 1 + test/test_pfed.cpp | 30 ++++++++++++++++++++++-------- 2 files changed, 23 insertions(+), 8 deletions(-) diff --git a/include/dbm/pfed.h b/include/dbm/pfed.h index 840374a..97dee89 100644 --- a/include/dbm/pfed.h +++ b/include/dbm/pfed.h @@ -645,6 +645,7 @@ namespace dbm void freeClock(cindex_t clock); + // Simplifies the rational cost to avoid large numbers, no real guarantees of what the cost is afterwards void simplify_rational_cost(); /** diff --git a/test/test_pfed.cpp b/test/test_pfed.cpp index 72912ba..643afab 100644 --- a/test/test_pfed.cpp +++ b/test/test_pfed.cpp @@ -3,7 +3,8 @@ #include -void any_contains(const dbm::pfed_t& pfed, int* valuation, size_t dim, CostType expected) { +// Asserts that the valuation is contained in some pdbm in the pfed and that the cost of that valuation is the expected cost +void any_contains_with_cost(const dbm::pfed_t& pfed, int* valuation, size_t dim, CostType expected) { bool any_contains = false; for (const auto& pdbm : pfed) { if (pdbm_containsInt(pdbm, dim, valuation)) { @@ -42,24 +43,37 @@ TEST_SUITE("pfed") REQUIRE((pfed.size() == 2)); REQUIRE((pfed.getInfimum() == 1)); - - { - - } // Assert that some pdbm in pfed contains the valuation (1,1) and has cost 4 { int valuation[3] = {0, 1, 1}; - any_contains(pfed, valuation, 3, 4); + any_contains_with_cost(pfed, valuation, 3, 4); } { int valuation[3] = {0, 2, 2}; - any_contains(pfed, valuation, 3, 7); + any_contains_with_cost(pfed, valuation, 3, 7); } { int valuation[3] = {0, 2, 0}; - any_contains(pfed, valuation, 3, 4); + any_contains_with_cost(pfed, valuation, 3, 4); + } + } + + TEST_CASE("set_uniform_cost") { + dbm::pfed_t pfed(3); + pfed.setZero(); + pfed.up(1); + pfed.setUniformCost(3); + // All valuations in the zone should now have cost 3 + { + int valuation[3] = {0, 0, 0}; + any_contains_with_cost(pfed, valuation, 3, 3); + } + + { + int valuation[3] = {0, 5, 5}; + any_contains_with_cost(pfed, valuation, 3, 3); } } } \ No newline at end of file