Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members

Federation.h

Go to the documentation of this file.
00001 // -*- mode: C++; c-file-style: "stroustrup"; c-basic-offset: 4; indent-tabs-mode: nil; -*-
00002 ////////////////////////////////////////////////////////////////////
00003 //
00004 // Filename : Federation.h (dbm)
00005 //
00006 // This file is a part of the UPPAAL toolkit.
00007 // Copyright (c) 1995 - 2003, Uppsala University and Aalborg University.
00008 // All right reserved.
00009 //
00010 // $Id: Federation.h,v 1.21 2005/05/03 19:46:52 adavid Exp $
00011 //
00012 ///////////////////////////////////////////////////////////////////
00013 
00014 #ifndef INCLUDE_DBM_FEDERATION_H
00015 #define INCLUDE_DBM_FEDERATION_H
00016 
00017 #include <new>
00018 #include <cstddef>
00019 #include <iostream>
00020 #include "dbm/dbmfederation.h"
00021 #include "base/bitstring.h"
00022 
00023 //
00024 // THIS API IS DEPRECATED AND NOT SUPPORTED ANY LONGER.
00025 //
00026 
00027 /** Macro to check common assumptions on clock indices
00028  * to be translated to DBM indices.
00029  * @param I: index to check.
00030  */
00031 #define ASSERT_CLOCK_INDEX(I) \
00032 assert(dbmAllocator && (I) < dbmAllocator->maxDim && indexTable[I] < getNumberOfClocks())
00033 
00034 
00035 /** Macro to declare on the stack a Federation (hack).
00036  * @param NAME: name of the federation to use (as a pointer)
00037  * @param NBCLOCKS: number of clocks for the federation
00038  * @param FACTORY: factory to use for this federation
00039  * Note: this hack only works because there is no virtual method.
00040  */
00041 #define LOCAL_FEDERATION(NAME, NBCLOCKS, FACTORY) \
00042 char local_##NAME[Federation::getSizeOfFederationFor((FACTORY)->maxDim)];\
00043 Federation *NAME = (Federation*) local_##NAME; \
00044 NAME->initFederation(FACTORY, NBCLOCKS)
00045 
00046 
00047 /** Similar macro to LOCAL_FEDERATION with active clocks.
00048  * @param NAME: name of the federation to use (as a pointer)
00049  * @param NBCLOCKS: number of clocks for the federation
00050  * @param FACTORY: factory to use for this federation
00051  * @param ACTIVE: bitstring marking active clocks
00052  * @param ACTIVESIZE: size of ACTIVE (in ints)
00053  * Note: this hack only works because there is no virtual method.
00054  */
00055 #define LOCAL_ACTIVE_FEDERATION(NAME, NBCLOCKS, FACTORY, ACTIVE, ACTIVESIZE) \
00056 char local_##NAME[Federation::getSizeOfFederationFor((FACTORY)->maxDim)];\
00057 Federation *NAME = (Federation*) local_##NAME; \
00058 NAME->initFederation(FACTORY, NBCLOCKS, ACTIVE, ACTIVESIZE)
00059 
00060 // Declaration in namespace to have it friend.
00061 namespace state
00062 {
00063     class SymbolicState;
00064 }
00065 
00066 namespace dbm
00067 {
00068     class Federation
00069     {
00070     public:
00071 
00072         /** Create a federation, given a factory and a number of clocks.
00073          * @param factory: factory to (de-)allocate DBMs
00074          * @param nbClocks: number of clocks for this federation (=dimension of the DBMs)
00075          * @return a new federation
00076          */
00077         static Federation* createFederation(DBMAllocator_t *factory, cindex_t nbClocks) throw (std::bad_alloc)
00078         {
00079             assert(factory && nbClocks && factory->maxDim >= nbClocks);
00080             return new (allocateFor(factory->maxDim)) Federation(factory, nbClocks);
00081         }
00082 
00083         /** Create a federation, given an original federation, ie, copy.
00084          * @param original: the original federation to copy.
00085          * @return a new federation
00086          */
00087         static Federation* createFederation(const Federation *original) throw (std::bad_alloc)
00088         {
00089             assert(original);
00090             return new (allocateFor(original->dbmAllocator->maxDim)) Federation(*original);
00091         }
00092 
00093         /** Create a federation, given a factory, a number of clocks, and an active clock mapping (bit string).
00094          * @param factory: factory to (de-)allocate DBMs
00095          * @param nbClocks: number of clocks (=dimension of the DBMs)
00096          * @param activeClocks,size: bitstring (of 'size' ints) marking the active clocks
00097          * @pre (activeClocks[0] & 1) == 1 (reference clock), size <= factory->maxDim.
00098          */
00099         static Federation* createFederation(DBMAllocator_t *factory, cindex_t nbClocks,
00100                                             const uint32_t *activeClocks, size_t size) throw (std::bad_alloc)
00101         {
00102             assert(factory && nbClocks && factory->maxDim >= nbClocks);
00103             assert(activeClocks && size <= factory->maxDim);
00104             return new (allocateFor(factory->maxDim)) Federation(factory, nbClocks, activeClocks, size);
00105         }
00106 
00107         /** Destructor:
00108          * purge all the zones from this federation,
00109          * ie, give them back to the factory.
00110          * Warning: the factory does not belong to this federation
00111          * so it is not destroyed.
00112          */
00113         ~Federation();
00114 
00115         /** Unshare its allocator.
00116          */
00117         void unshareAllocator() { dbmf_initFactory(dbmAllocator, dbmFederation.dim); }
00118 
00119 
00120         /** Operator =
00121          * @pre factories are the same.
00122          */
00123         Federation& operator = (const Federation& original) throw (std::bad_alloc)
00124         {
00125             assert(dbmAllocator == original.dbmAllocator);
00126             if (dbmf_copy(&dbmFederation, original.dbmFederation, dbmAllocator))
00127             {
00128                 throw std::bad_alloc();
00129             }
00130             base_copySmall(indexTable, original.indexTable,
00131                            (sizeof(cindex_t) == sizeof(uint32_t)) // removed at compile time (-O2)
00132                             ? original.dbmAllocator->maxDim
00133                             : intsizeof(cindex_t[original.dbmAllocator->maxDim]));
00134             return *this;
00135         }
00136 
00137         /** Steal DBMs from a federation and computes the union with this federation:
00138          * the argument federation looses its DBMs.
00139          * @param fed: federation to steal from.
00140          * @pre getNumberOfClocks() == fed->getNumberOfClocks()
00141          */
00142         void stealDBMs(Federation *fed)
00143         {
00144             assert(fed && getNumberOfClocks() == fed->getNumberOfClocks());
00145             if (fed->dbmFederation.dbmList)
00146             {
00147                 dbmf_union(&dbmFederation, fed->dbmFederation.dbmList, dbmAllocator);
00148                 fed->dbmFederation.dbmList = NULL;
00149             }
00150         }
00151 
00152         /** Serialize this federation to a stream.
00153          * @param os: output stream.
00154          */
00155         std::ostream& serialize(std::ostream& os) const;
00156 
00157         /** Unserialize this federation from a stream.
00158          * @param is: input stream.
00159          */
00160         void unserialize(std::istream& is) throw (std::bad_alloc);
00161 
00162         /** Pretty print this federation to a stream.
00163          * @param os: output stream.
00164          */
00165         std::ostream& prettyPrint(std::ostream& os) const;
00166 
00167         /** Number of clocks used in this federation:
00168          * all the zones have the same number of clocks.
00169          * @return number of clocks.
00170          */
00171         cindex_t getNumberOfClocks() const { return dbmFederation.dim; }
00172 
00173         /** (Re-)initialize the federation so that it contains
00174          * only 0. The federation may be empty or not, it does not matter.
00175          */
00176         void initToZero();
00177 
00178         /** (Re-)initialize the federation so that it is completely
00179          * unconstrained. The federation may be empty or not, it does not matter.
00180          */
00181         void initUnconstrained();
00182 
00183         /** Intersection with one DBM.
00184          * @param dbm: DBM to intersect with.
00185          * @pre DBM dimension == getNumberOfClocks()
00186          * @return true if federation is not empty.
00187          */
00188         bool intersection(const raw_t *dbm)
00189         {
00190             assert(dbm);
00191             return (bool) dbmf_intersectsDBM(&dbmFederation, dbm, dbmAllocator);
00192         }
00193 
00194         /** Intersection with a federation.
00195          * @param anotherFed: federation to intersec with.
00196          * @return true if federation is not empty.
00197          */
00198         bool intersection(const Federation *anotherFed) throw (std::bad_alloc)
00199         {
00200             assert(anotherFed);
00201             if (dbmf_intersectsFederation(&dbmFederation, anotherFed->dbmFederation.dbmList, dbmAllocator))
00202             {
00203                 throw std::bad_alloc();
00204             }
00205             return dbmFederation.dbmList != NULL;
00206         }
00207 
00208         /** Apply a constraint to the federation = tighten a constraint.
00209          * @param clockIndexI,clockIndexJ,rawBound: bound for the constraint xi-xj (raw format)
00210          * @pre clockIndexI and clockIndexJ < maximal number of clocks
00211          * and indexTable[clockIndexI and clockIndexJ] < getNumberOfClocks()
00212          * @return true if the federation is non empty.
00213          */
00214         bool constrain(cindex_t clockIndexI, cindex_t clockIndexJ, raw_t rawBound)
00215         {
00216             ASSERT_CLOCK_INDEX(clockIndexI);
00217             ASSERT_CLOCK_INDEX(clockIndexJ);
00218             dbmf_constrain1(&dbmFederation,
00219                             indexTable[clockIndexI], indexTable[clockIndexJ], rawBound,
00220                             dbmAllocator);
00221             return dbmFederation.dbmList != NULL;
00222         }
00223 
00224         /** Apply several constraints to the federation.
00225          * @param constraints: constraints to apply
00226          * @param n: number of constraints
00227          * @pre constraints is a constraint_t[n], indices i must be s.t.
00228          * indexTable[i] < getNumberOfClocks() and i < dbmAllocator->maxDim
00229          * @return true if the federation is non empty.
00230          */
00231         bool constrainN(const constraint_t *constraints, size_t n)
00232         {
00233             dbmf_constrainIndexedN(&dbmFederation, indexTable,
00234                                    constraints, n,
00235                                    dbmAllocator);
00236             return dbmFederation.dbmList != NULL;
00237         }
00238 
00239         /** Wrapper for constrain(uint,uint,raw_t)
00240          * @param c: constraint to set
00241          */
00242         bool constrain(constraint_t c)
00243         {
00244             return constrain(c.i, c.j, c.value);
00245         }
00246 
00247         /** Wrapper for constrain(uint,uint,raw_t)
00248          * @param clockIndexI,clockIndexJ,bound,isStrict: bound with a isStrict flag for
00249          * the constraint xi-xj.
00250          * @pre clockIndexI and clockIndexJ < maximal number of clocks
00251          * and indexTable[clockIndexI and clockIndexJ] < getNumberOfClocks()
00252          */
00253         bool constrain(cindex_t clockIndexI, cindex_t clockIndexJ, int32_t bound, bool isStrict)
00254         {
00255             return constrain(clockIndexI, clockIndexJ, dbm_boundbool2raw(bound, (BOOL) isStrict));
00256         }
00257 
00258         /** Wrapper for constrain(uint,uint,raw_t)
00259          * @param clockIndexI,clockIndexJ,bound,strictness: bound with a strictness for
00260          * the constraint xi-xj.
00261          * @pre clockIndexI and clockIndexJ < maximal number of clocks
00262          * and indexTable[clockIndexI and clockIndexJ] < getNumberOfClocks()
00263          */
00264         bool constrain(cindex_t clockIndexI, cindex_t clockIndexJ, int32_t bound, strictness_t strictness)
00265         {
00266             return constrain(clockIndexI, clockIndexJ, dbm_bound2raw(bound, strictness));
00267         }
00268 
00269         /** @return true if the federation satisfies the constraint.
00270          * @param clockIndexI,clockIndexJ,rawConstraint: constraint (raw format) to
00271          * be satisfied by xi-xj.
00272          * @pre clockIndexI and clockIndexJ < maximal number of clocks
00273          * and indexTable[clockIndexI and clockIndexJ] < getNumberOfClocks()
00274          */
00275         bool satisfies(cindex_t clockIndexI, cindex_t clockIndexJ, raw_t rawConstraint) const
00276         {
00277             ASSERT_CLOCK_INDEX(clockIndexI);
00278             ASSERT_CLOCK_INDEX(clockIndexJ);
00279             return (bool) dbmf_satisfies(dbmFederation,
00280                                          indexTable[clockIndexI], indexTable[clockIndexJ], rawConstraint);
00281         }
00282 
00283         /** Wrapper for satisfies(uint,uint,raw_t)
00284          * @param constraint: the constraint to test
00285          * @pre see satisfies(cindex_t,cindex_t,raw_t)
00286           */
00287         bool satisfies(constraint_t constraint) const
00288         {
00289             return satisfies(constraint.i, constraint.j, constraint.value);
00290         }
00291 
00292         /** Wrapper for satisfies(uint,uint,raw_t)
00293          * @param clockIndexI,clockIndexJ,bound,isStrict: bound with a isStrict flag for
00294          * the constraint xi-xj.
00295          * @pre see satisfies(cindex_t,cindex_t,raw_t)
00296          */
00297         bool satisfies(cindex_t clockIndexI, cindex_t clockIndexJ, int32_t bound, bool isStrict) const
00298         {
00299             return satisfies(clockIndexI, clockIndexJ, dbm_boundbool2raw(bound, (BOOL) isStrict));
00300         }
00301 
00302         /** Wrapper for satisfies(uint,uint,raw_t)
00303          * @param clockIndexI,clockIndexJ,bound,strictness: bound with a strictness for
00304          * the constraint xi-xj.
00305          * @pre see satisfies(cindex_t,cindex_t,raw_t)
00306          */
00307         bool satisfies(cindex_t clockIndexI, cindex_t clockIndexJ, int32_t bound, strictness_t strictness) const
00308         {
00309             return satisfies(clockIndexI, clockIndexJ, dbm_bound2raw(bound, strictness));
00310         }
00311 
00312         /** Up operation = strongest post-condition
00313          * = delay = future computation.
00314          */
00315         void up()
00316         {
00317             dbmf_up(dbmFederation);
00318         }
00319 
00320         /** Down operation = weakest pre-condition
00321          * = past computation.
00322          */
00323         void down()
00324         {
00325             dbmf_down(dbmFederation);
00326         }
00327 
00328         /** @return true if the federation is unbounded,
00329          * ie, if one zone is unbounded.
00330          */
00331         bool isUnbounded() const
00332         {
00333             return (bool) dbmf_isUnbounded(dbmFederation);
00334         }
00335         
00336         /** @return true if the federation is empty.
00337          */
00338         bool isEmpty() const
00339         {
00340             return dbmFederation.dbmList == NULL;
00341         }
00342 
00343         /** "Micro" delay operation: render upper
00344          * bounds xi <= bound non strict: xi < bound
00345          */
00346         void microDelay()
00347         {
00348             dbmf_microDelay(dbmFederation);
00349         }
00350 
00351         /** Substract a DBM from this federation.
00352          * @param dbm: DBM to substract
00353          * @pre dimension of the DBM = getNumberOfClocks()
00354          * @return true if this federation is non empty
00355          */
00356         bool substract(const raw_t *dbm) throw (std::bad_alloc)
00357         {        
00358             if (dbmf_substractDBM(&dbmFederation, dbm, dbmAllocator))
00359             {
00360                 throw std::bad_alloc();
00361             }
00362             return dbmFederation.dbmList != NULL;
00363         }
00364         
00365         /** Substract a federation from this federation.
00366          * @param fed: federation to substract
00367          * @pre fed->getNumberOfClocks() == getNumberOfClocks()
00368          * and fed has the same factory.
00369          * @return true if this federation is non empty
00370          */
00371         bool substract(const Federation *fed) throw (std::bad_alloc)
00372         {
00373             assert(fed && fed->getNumberOfClocks() == getNumberOfClocks() &&
00374                    fed->dbmAllocator == dbmAllocator);
00375             if (dbmf_substractFederation(&dbmFederation, fed->dbmFederation.dbmList, dbmAllocator))
00376             {
00377                 throw std::bad_alloc();
00378             }
00379             return dbmFederation.dbmList != NULL;
00380         }
00381 
00382         /** For convenience: -= operator.
00383          * @see substract
00384          */
00385         Federation& operator -= (const Federation& fed) throw (std::bad_alloc)
00386         {
00387             assert(fed.getNumberOfClocks() == getNumberOfClocks() &&
00388                    fed.dbmAllocator == dbmAllocator);
00389             if (dbmf_substractFederation(&dbmFederation, fed.dbmFederation.dbmList, dbmAllocator))
00390             {
00391                 throw std::bad_alloc();
00392             }
00393             return *this;
00394         }
00395 
00396         /** Approximate inclusion check: if it is included
00397          * then it is for sure but if it is not, then maybe
00398          * it could have been.
00399          * @param fed: federation to test
00400          * @return true if this federation is maybe included in fed
00401          */
00402         bool isMaybeIncludedIn(const Federation *fed)
00403         {
00404             assert(fed && fed->getNumberOfClocks() == getNumberOfClocks() &&
00405                    fed->dbmAllocator == dbmAllocator);
00406             return dbmf_areDBMsIncludedIn(dbmFederation.dbmList, fed->dbmFederation.dbmList, getNumberOfClocks());
00407         }
00408 
00409         /** Exact inclusion check. EXPENSIVE.
00410          * @param fed: federation to test
00411          * @return true if this federation is really included in fed
00412          */
00413         bool isReallyIncludedIn(const Federation *fed)
00414         {
00415             assert(fed && fed->getNumberOfClocks() == getNumberOfClocks() &&
00416                    fed->dbmAllocator == dbmAllocator);
00417             BOOL valid;
00418             BOOL isIn = dbmf_areDBMsReallyIncludedIn(dbmFederation.dbmList, fed->dbmFederation, &valid, dbmAllocator);
00419             if (!valid) throw std::bad_alloc();
00420             return isIn;
00421         }
00422 
00423         /** Free a given clock: remove all the constraints (except >= 0)
00424          * for a given clock.
00425          * @param clockIndex: index of the clock to free
00426          * @pre clockIndex < dbmAllocator->maxDim && indexTable[clockIndex] < getNumberOfClocks()
00427          */
00428         void freeClock(cindex_t clockIndex)
00429         {
00430             ASSERT_CLOCK_INDEX(clockIndex);
00431             dbmf_freeClock(dbmFederation, indexTable[clockIndex]);
00432         }
00433 
00434         /** Update of the form x := value, where x is a clock and value
00435          * an integer.
00436          * @param clockIndex: index of the clock (x) to update.
00437          * @param value: value to set.
00438          * @pre clockIndex < dbmAllocator->maxDim && indexTable[clockIndex] < getNumberOfClocks()
00439          */
00440         void updateValue(cindex_t clockIndex, int32_t value)
00441         {
00442             ASSERT_CLOCK_INDEX(clockIndex);
00443             dbmf_updateValue(dbmFederation, indexTable[clockIndex], value);
00444         }
00445 
00446         /** Update of the form xi := xj, where xi and xj are clocks.
00447          * @param clockIndexI,clockIndexJ: clock indices of xi and xj.
00448          * @pre clockIndexI/J < dbmAllocator->maxDim && indexTable[clockIndexI/J] < getNumberOfClocks()
00449          */
00450         void updateClock(cindex_t clockIndexI, cindex_t clockIndexJ)
00451         {
00452             ASSERT_CLOCK_INDEX(clockIndexI);
00453             ASSERT_CLOCK_INDEX(clockIndexJ);
00454             dbmf_updateClock(dbmFederation, indexTable[clockIndexI], indexTable[clockIndexJ]);
00455         }
00456 
00457         /** Update of the form x += inc, where x is a clock and inc
00458          * an integer. Warning: inc may be < 0. The operation may
00459          * be wrong when used on an unbounded federation, or if the
00460          * "decrement" is too big (negative time). The operation is
00461          * there but be careful in its usage. Decidability is at stake.
00462          * @param clockIndex: index of the clock (x) to increment
00463          * @param increment: increment to apply
00464          * @pre clockIndex < dbmAllocator->maxDim && indexTable[clockIndex] < getNumberOfClocks()
00465          */
00466         void updateIncrement(cindex_t clockIndex, int32_t increment)
00467         {
00468             ASSERT_CLOCK_INDEX(clockIndex);
00469             dbmf_updateIncrement(dbmFederation, indexTable[clockIndex], increment);
00470         }
00471 
00472         /** General update of the form: xi := xj + inc, where xi and xj
00473          * are clocks and inc an integer. Warning: same remark as for updateIncrement.
00474          * @param clockIndexI, clockIndexJ: clock indices of clocks (xi,xj)
00475          * @param increment: increment to apply
00476          * @pre clockIndexI/J < dbmAllocator->maxDim && indexTable[clockIndexI/J] < getNumberOfClocks()
00477          */
00478         void update(cindex_t clockIndexI, cindex_t clockIndexJ, int32_t increment)
00479         {
00480             ASSERT_CLOCK_INDEX(clockIndexI);
00481             ASSERT_CLOCK_INDEX(clockIndexJ);
00482             dbmf_update(dbmFederation, indexTable[clockIndexI], indexTable[clockIndexJ], increment);
00483         }
00484 
00485         /** Partial relation with a DBM (from DBM point of view).
00486          * The result is partial in the sense that it can be
00487          * dbm_DIFFERENT although it could be refined as dbm_SUBSET.
00488          * @param dbm: DBM to test
00489          * @pre dimension of dbm == getNumberOfClocks()
00490          * @return relation dbm (?) this federation where
00491          * (?) can be
00492          * - dbm_EQUAL: this federation represents exactly the zone
00493          *   of dbm
00494          * - dbm_SUBSET: dbm is a subset of this federation, ie,
00495          *   is included in one of the DBMs of this federation
00496          * - dbm_SUPERSET: dbm is a superset of this federation, ie,
00497          *   includes all the DBMs of this federation
00498          * - dbm_DIFFERENT: dbm is not (easily) comparable to this federation.
00499          */
00500         relation_t partialRelation(const raw_t *dbm) const
00501         {
00502             return dbmf_partialRelation(dbm, dbmFederation);
00503         }
00504 
00505         /** Exact (and very expensive) relation with a DBM, in contrast
00506          * to partialRelation.
00507          * @param dbm: DBM to test
00508          * @pre dimension of dbm == getNumberOfClocks()
00509          * @return relation dbm (?) this federation as partialRelation.
00510          */
00511         relation_t relation(const raw_t *dbm) const throw (std::bad_alloc)
00512         {
00513             BOOL valid;
00514             relation_t result = dbmf_relation(dbm, dbmFederation, &valid, dbmAllocator);
00515             if (!valid) throw std::bad_alloc();
00516             return result;
00517         }
00518 
00519         /** Compute union of federations with inclusion checking.
00520          * Argument is deallocated or belongs to this federation.
00521          * @param fed: list of DBMs to add to this federation.
00522          */
00523         void unionWith(DBMList_t *fed)
00524         {
00525             dbmf_union(&dbmFederation, fed, dbmAllocator);
00526         }
00527 
00528         /** As unionWith but copy the argument when needed.
00529          * @param fed: list of DBMs to add.
00530          */
00531         void unionWithCopy(const DBMList_t *fed) throw (std::bad_alloc)
00532         {
00533             BOOL valid;
00534             dbmf_unionWithCopy(&dbmFederation, fed, dbmAllocator, &valid);
00535             if (!valid) throw std::bad_alloc();
00536         }
00537 
00538         /** Compute convex union of the DBMs of this federation.
00539          */
00540         void convexUnion()
00541         {
00542             dbmf_convexUnionWithSelf(&dbmFederation, dbmAllocator);
00543         }
00544 
00545         /** Stretch-up: remove all upper bounds for all clocks.
00546          */
00547         void stretchUp()
00548         {
00549             dbmf_stretchUp(dbmFederation);
00550         }
00551 
00552         /** Stretch-down: remove all lower bounds for a given clock.
00553          * @param clockIndex: index of the concerned clock.
00554          * @pre clockIndex < dbmAllocator->maxDim && indexTable[clockIndex] < getNumberOfClocks()
00555          */
00556         void stretchDown(cindex_t clockIndex)
00557         {
00558             ASSERT_CLOCK_INDEX(clockIndex);
00559             dbmf_stretchDown(dbmFederation, indexTable[clockIndex]);
00560         }
00561 
00562         /** Operation similar to down but constrained:
00563          * predecessors of fed avoiding the states that
00564          * could reach bad.
00565          * @param bad: the list of DBMs to avoid.
00566          * @pre the list of DBMs has the same number of clocks
00567          * as this federation and the active clocks match.
00568          * @post DBMs of bad are deallocated.
00569          */
00570         void predt(Federation *bad)
00571         {
00572             if (dbmf_predt(&dbmFederation, &bad->dbmFederation, dbmAllocator)) throw std::bad_alloc();
00573         }
00574 
00575         /** Add DBMs to this federation.
00576          * @arg dbmList: list of DBMs
00577          * @pre DBMs have the same dimension as this federation.
00578          */
00579         void add(const DBMList_t *dbmList) throw (std::bad_alloc)
00580         {
00581             if (dbmf_addCopy(&dbmFederation, dbmList, dbmAllocator)) throw std::bad_alloc();
00582         }
00583 
00584         /** Add DBMs of a federation to this federation.
00585          * @pre DBMs have the same dimension as this federation.
00586          */
00587         Federation* add(const Federation *arg) throw (std::bad_alloc)
00588         {
00589             assert(arg && arg->getNumberOfClocks() == getNumberOfClocks());
00590             add(arg->dbmFederation.dbmList);
00591             return this;
00592         }
00593 
00594         /** Operator +=: add DBMs of another federation.
00595          */
00596         Federation& operator += (const Federation& arg) throw (std::bad_alloc)
00597         {
00598             assert(arg.getNumberOfClocks() == getNumberOfClocks());
00599             add(arg.dbmFederation.dbmList);
00600             return *this;
00601         }
00602 
00603         /** Simple reduce: try to remove redundant DBMs.
00604          */
00605         void reduce()
00606         {
00607             dbmf_reduce(&dbmFederation, dbmAllocator);
00608         }
00609 
00610         /** Very EXPENSIVE reduce, follows full semantics of federation.
00611          */
00612         void expensiveReduce()
00613         {
00614             dbmf_expensiveReduce(&dbmFederation, dbmAllocator);
00615         }
00616 
00617         /** Remove partially included DBMs in the argument federation.
00618          * @return TRUE if this federation is not empty afterwards.
00619          * @param arg: argument federation.
00620          */
00621         bool removePartialIncludedIn(const Federation *arg)
00622         {
00623             assert(arg);
00624             return dbmf_removePartialIncluded(&dbmFederation, arg->dbmFederation.dbmList, dbmAllocator);
00625         }
00626 
00627         /** Access to the factory: for allocation/deallocation.
00628          * @return this factory.
00629          */
00630         DBMAllocator_t *getAllocator()
00631         {
00632             return dbmAllocator;
00633         }
00634 
00635         /** const access to factory, only for debug (use in assert).
00636          */
00637         const DBMAllocator_t* getAllocator() const
00638         {
00639             return dbmAllocator;
00640         }
00641 
00642         /** const access to the DBMs.
00643          * @return the head of the list of DBMs.
00644          */
00645         const DBMList_t* getDBMList() const
00646         {
00647             return dbmFederation.dbmList;
00648         }
00649 
00650         /** Access to the DBMs.
00651          * @return the head of the list of DBMs.
00652          */
00653         DBMList_t* getDBMList()
00654         {
00655             return dbmFederation.dbmList;
00656         }
00657 
00658         /** Access to the DBMs.
00659          * @return the pointer to the head of the list of DBMs.
00660          */
00661         DBMList_t** getAtDBMList()
00662         {
00663             return &dbmFederation.dbmList;
00664         }
00665 
00666         /** Access to the first DBM.
00667          * @pre federation not empty.
00668          */
00669         raw_t *getFirstDBM()
00670         {
00671             assert(dbmFederation.dbmList);
00672             return dbmFederation.dbmList->dbm;
00673         }
00674           
00675         /** Size of federation
00676          * @return the number of zones in the federation.
00677          */
00678         size_t getSize() const
00679         {
00680             return dbmf_getSize(dbmFederation.dbmList);
00681         }
00682 
00683         /** Allocate and add a DBM.
00684          * @return newly added and allocated DBM.
00685          * @post the DBM is not initialized and is invalid. It *must* be 
00686          * written afterwards.
00687          */
00688         raw_t *newDBM() throw (std::bad_alloc())
00689         {
00690             DBMList_t *freshNew = dbmf_allocate(dbmAllocator);
00691             if (!freshNew) throw std::bad_alloc();
00692             dbmf_addDBM(freshNew, &dbmFederation);
00693             return freshNew->dbm;
00694         }
00695 
00696         /** Reset the federation to empty.
00697          */
00698         void reset()
00699         {
00700             if (dbmFederation.dbmList)
00701             {
00702                 dbmf_deallocateList(dbmAllocator, dbmFederation.dbmList);
00703                 dbmFederation.dbmList = NULL;
00704             }
00705         }
00706 
00707         /** Classical extrapolation based on maximal bounds,
00708          * formerly called k-normalization.
00709          * @see dbm_classicExtrapolateMaxBounds
00710          * @param max: table of maximal constants to use for the active clocks.
00711          * - max is a int32_t[getNumberOfClocks()]
00712          * - max[0] = 0 (reference clock)
00713          */
00714         void extrapolateMaxBounds(const int32_t *max)
00715         {
00716             dbmf_extrapolateMaxBounds(dbmFederation, max);
00717         }
00718 
00719         /** Diagonal extrapolation based on maximal bounds.
00720          * @see dbm_diagonalExtrapolateMaxBounds
00721          * @param max: table of maximal constants for the active clocks.
00722          * @pre
00723          * - max is a int32_t[getNumberOfClocks()]
00724          * - max[0] = 0 (reference clock)
00725          */
00726         void diagonalExtrapolateMaxBounds(const int32_t *max)
00727         {
00728             dbmf_diagonalExtrapolateMaxBounds(dbmFederation, max);
00729         }
00730 
00731         /** Extrapolation based on lower-upper bounds.
00732          * @see dbm_extrapolateLUBounds
00733          * @param lower: lower bounds for the active clocks.
00734          * @param upper: upper bounds for the active clocks.
00735          * @pre
00736          * - lower and upper are int32_t[getNumberOfClocks()]
00737          * - lower[0] = upper[0] = 0 (reference clock)
00738          */
00739         void extrapolateLUBounds(const int32_t *lower, const int32_t *upper)
00740         {
00741             dbmf_extrapolateLUBounds(dbmFederation, lower, upper);
00742         }
00743 
00744         /** Diagonal extrapolation based on lower-upper bounds.
00745          * Most general approximation.
00746          * @see dbm_diagonalExtrapolateLUBounds
00747          * @param lower: lower bounds for the active clocks.
00748          * @param upper: upper bounds for the active clocks.
00749          * @pre
00750          * - lower and upper are a int32_t[getNumberOfClocks()]
00751          * - lower[0] = upper[0] = 0
00752          */
00753         void diagonalExtrapolateLUBounds(const int32_t *lower, const int32_t *upper)
00754         {
00755             dbmf_diagonalExtrapolateLUBounds(dbmFederation, lower, upper);
00756         }
00757 
00758         /** Initialize the indirection table to identity.
00759          * Warning: the DBMs are all deallocated.
00760          * @param newDim: new dimension of all the DBMs
00761          */
00762         void initIndexTable(cindex_t newDim)
00763         {
00764             assert(dbmAllocator && dbmAllocator->maxDim && dbmAllocator->maxDim >= newDim);
00765             
00766             dbmFederation.dim = newDim;
00767             reset();
00768 
00769             cindex_t i = 0, max = dbmAllocator->maxDim;
00770             cindex_t *table = indexTable;
00771             do { table[i] = i; } while(++i < max);
00772         }
00773 
00774         /** Initialize the indirection table according to a bitstring
00775          * marking active clocks. Warning: the DBMs are all deallocated.
00776          * @param activeClocks,size: bitstring (of 'size' ints) marking active clocks
00777          * @pre (activeClocks[0] & 1) == 1 (always reference clock)
00778          * and n <= getBitTableSize(), and size > 0 (reference clock).
00779          */
00780         void initIndexTable(const uint32_t *activeClocks, size_t size)
00781         {
00782             assert(activeClocks && size);
00783             dbmFederation.dim = base_countBitsN(activeClocks, size);
00784             reset();
00785             base_bits2indexTable(activeClocks, size, indexTable);
00786         }
00787 
00788         /** Initialize a federation, given a factory and a number of clocks.
00789          * @param dbmf: DBM factory
00790          * @param nbClocks: number of clocks (=dimension of the DBMs)
00791          * @pre nbClocks < dbmf->maxDim
00792          */
00793         void initFederation(DBMAllocator_t *dbmf, cindex_t nbClocks)
00794         {
00795             dbmAllocator = dbmf;
00796             dbmFederation.dbmList = NULL;
00797             initIndexTable(nbClocks);
00798         }
00799 
00800         /** Initialize a federation, given a factory, a number of clocks,
00801          * and a bitstring marking the active clocks.
00802          * @param dbmf: DBM factory
00803          * @param nbClocks: number of clocks (=dimension of the DBMs)
00804          * @param activeClocks,size: bitstring (of 'size' ints) marking the active clocks
00805          * @pre nbClocks < dbmf->maxDim and (activeClocks[0] & 1) == 1 (reference clock),
00806          * size <= dbmf->maxDim/32 rounded up, and the index of the highest bit in activeClocks
00807          * < dbmAllocator->maxDim.
00808          */
00809         void initFederation(DBMAllocator_t *dbmf, cindex_t nbClocks,
00810                             const uint32_t *activeClocks, size_t size)
00811         {
00812             assert(dbmf && activeClocks && nbClocks < dbmf->maxDim &&
00813                    size <= (size_t) ((dbmf->maxDim + 31) >> 5));
00814             dbmf_initFederation(&dbmFederation, nbClocks);
00815             dbmAllocator = dbmf;
00816             initIndexTable(activeClocks, size);
00817         }
00818 
00819         /** Change the set of active clocks.
00820          * @param oldClocks: old set of active clocks, MUST correspond to the
00821          * current index table.
00822          * @param newClocks: new set of active clocks, the index table will be
00823          * updated according to these clocks
00824          * @param size: size (int ints) of the bitstrings
00825          */
00826         void changeClocks(const uint32_t *oldClocks, const uint32_t *newClocks, size_t size)
00827         {
00828             if (!base_areBitsEqual(oldClocks, newClocks, size))
00829             {
00830                 dbmf_shrinkExpand(&dbmFederation, oldClocks, newClocks, size, indexTable, dbmAllocator);
00831             }
00832         }
00833 
00834     private: // Constructors are private: use the static methods createXX.
00835 
00836         friend class state::SymbolicState;
00837 
00838         /** Copy the federation without the index table.
00839          * @param original: original federation.
00840          */
00841         void copyFromFederation(const Federation *original) throw (std::bad_alloc)
00842         {
00843             assert(original && dbmAllocator == original->dbmAllocator);
00844             if (dbmf_copy(&dbmFederation, original->dbmFederation, dbmAllocator))
00845             {
00846                 throw std::bad_alloc();
00847             }
00848         }
00849 
00850         /** Allocate memory for a Federation of maxDim clocks. The
00851          * index table is allocated rounded up to the next 32 multiple
00852          * of maxDim.
00853          */
00854         static void* allocateFor(cindex_t maxDim)
00855         {
00856             return new char[getSizeOfFederationFor(maxDim)];
00857         }
00858 
00859         /** @return needed size for a federation with a given maximal dimension.
00860          */
00861         static size_t getSizeOfFederationFor(cindex_t maxDim)
00862         {
00863             return sizeof(Federation)+sizeof(cindex_t[maxDim]);
00864         }
00865 
00866         /** @return size needed in ints in addition to this class.
00867          * If pointers are on 64 bits then we pad on 64 bits and not 32.
00868          * The Federation object must be padded on 64 bits too on 64 bits,
00869          * which is done by the compiler since Federation contains pointers.
00870          */
00871         static size_t getPaddedIntOffsetFor(cindex_t maxDim)
00872         {
00873             // the tests are removed at compile time
00874             return (sizeof(uintptr_t) == sizeof(uint32_t) || (intsizeof(Federation) & 1))
00875                 ? ((sizeof(cindex_t) == sizeof(uint32_t)) ? maxDim : intsizeof(cindex_t[maxDim]))
00876                 : ((sizeof(cindex_t[maxDim]) + 7) >> 3);
00877         }
00878 
00879         /** Constructor.
00880          * @param dbmf: zone factory
00881          * @param nbClocks: number of clocks for all the DBMs in this federation.
00882          * @post the federation is empty
00883          */
00884         Federation(DBMAllocator_t *dbmf, cindex_t nbClocks)
00885         {
00886             initFederation(dbmf, nbClocks);
00887         }
00888 
00889         /** Copy constructor.
00890          * Warning: this calls copy, which means, be careful, therefor it is private.
00891          */
00892         Federation(const Federation& original) throw (std::bad_alloc)
00893         {
00894             dbmAllocator = original.dbmAllocator;
00895             /* reset this because the copy operates
00896              * on a valid federation */
00897             dbmFederation.dim = original.dbmFederation.dim;
00898             dbmFederation.dbmList = NULL;
00899             *this = original;
00900         }
00901 
00902         /** Constructor with active clocks given.
00903          * @param dbmf: zone factory
00904          * @param nbClocks: number of clocks for all the DBMs in this federation.
00905          * @param activeClocks,size: bitstring (of 'size' ints) marking the active clocks.
00906          * @post the federation is empty
00907          */
00908         Federation(DBMAllocator_t *dbmf, cindex_t nbClocks,
00909                    const uint32_t *activeClocks, size_t size)
00910         {
00911             initFederation(dbmf, nbClocks, activeClocks, size);
00912         }
00913 
00914 
00915         DBMFederation_t dbmFederation; ///< wrapped federation (C struct)
00916         DBMAllocator_t *dbmAllocator;  ///< allocator to (de-)allocate DBMs
00917         cindex_t indexTable[];         ///< indirection index table
00918     };
00919 
00920 } // namespace dbm
00921 
00922 
00923 // Wrappers
00924 
00925 static inline
00926 std::ostream& operator << (std::ostream& os, const dbm::Federation& fed)
00927 {
00928     return fed.serialize(os);
00929 }
00930 
00931 static inline
00932 void operator >> (std::istream& is, dbm::Federation& fed)
00933 {
00934     fed.unserialize(is);
00935 }
00936 
00937 #endif // INCLUDE_DBM_FEDERATION_H
00938 

Generated on Fri Jun 30 00:02:45 2006 for Module dbm by  doxygen 1.4.2