00001 /* -*- mode: C++; c-file-style: "stroustrup"; c-basic-offset: 4; indent-tabs-mode: nil; -*- */ 00002 /********************************************************************* 00003 * 00004 * Filename : dbmfederation.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: dbmfederation.h,v 1.28 2005/07/22 12:55:54 adavid Exp $ 00011 * 00012 **********************************************************************/ 00013 00014 #ifndef INCLUDE_DBM_DBMFEDERATION_H 00015 #define INCLUDE_DBM_DBMFEDERATION_H 00016 00017 #include <stdio.h> 00018 #include <stdlib.h> 00019 #include "dbm/dbm.h" 00020 #include "debug/monitor.h" 00021 00022 #ifdef __cplusplus 00023 #include <iostream> 00024 extern "C" { 00025 #endif 00026 00027 /* 00028 * THIS API IS DEPRECATED AND NOT SUPPORTED ANY LONGER. 00029 */ 00030 00031 /** DBM Federation type: such federations 00032 * have one dimension and several DBMs of 00033 * the same dimension. This is the list 00034 * of DBMs for the federation. 00035 */ 00036 typedef struct dbmlist_s 00037 { 00038 struct dbmlist_s *next; /**< next DBM in the federation */ 00039 raw_t dbm[]; /**< DBM of size dim*dim */ 00040 } DBMList_t; 00041 00042 00043 /** DBM Federation. 00044 */ 00045 typedef struct 00046 { 00047 DBMList_t *dbmList; 00048 cindex_t dim; 00049 } DBMFederation_t; 00050 00051 00052 /** DBM factory: wrapper around an allocator. 00053 * The allocated DBM is of dimension = max 00054 * possible dimension. 00055 */ 00056 typedef struct 00057 { 00058 DBMList_t *freeDBM; /**< list of deallocated DBMs */ 00059 size_t sizeOfAlloc; /**< sizeof(DBMList_t)+maxDim*maxDim*sizeof(raw_t) 00060 in the preconditions, we refer to factory->dim for simplicity */ 00061 cindex_t maxDim; /**< maximal dimension handled by this factory */ 00062 } DBMAllocator_t; 00063 00064 00065 #define SIZEOF_DBMLIST(DIM) (sizeof(DBMList_t) + (DIM)*(DIM)*sizeof(raw_t)) 00066 00067 /** Assertion to check that requested DBMs 00068 * have their dim <= max dim of the factory. 00069 */ 00070 #define dbmf_CHECKDIM(FACTORY,DIM) \ 00071 assert((FACTORY) && (FACTORY)->sizeOfAlloc >= SIZEOF_DBMLIST(DIM) && \ 00072 (DIM) <= (FACTORY)->maxDim && SIZEOF_DBMLIST((FACTORY)->maxDim) == (FACTORY)->sizeOfAlloc) 00073 00074 00075 /**************************************************** 00076 ** Allocation/deallocation of DBMs with a factory ** 00077 ****************************************************/ 00078 00079 00080 /** Initialize a factory. 00081 * @param factory: the factory to initialize. 00082 * @param dim: maximal dimension of used DBMs. 00083 */ 00084 static inline 00085 void dbmf_initFactory(DBMAllocator_t *factory, cindex_t dim) 00086 { 00087 assert(factory); 00088 factory->freeDBM = NULL; 00089 factory->sizeOfAlloc = SIZEOF_DBMLIST(dim); 00090 factory->maxDim = dim; 00091 } 00092 00093 00094 /** Check a factory -- for debugging. 00095 * May detect memory corruption. 00096 * @param factory: allocator to check. 00097 */ 00098 #ifndef NDEBUG 00099 #define dbmf_checkFactory(F) assert(dbmf_internCheckFactory(F)) 00100 BOOL dbmf_internCheckFactory(const DBMAllocator_t *factory); 00101 #else 00102 #define dbmf_checkFactory(F) 00103 #endif 00104 00105 00106 /** Allocate DBMs with the factory. 00107 * @param factory 00108 * @return allocated DBMList_t or NULL if out-of-memory 00109 * @pre factory != NULL 00110 */ 00111 DBMList_t *dbmf_internAllocate(DBMAllocator_t *factory); 00112 00113 00114 /** Give back ONE DBM to its factory. 00115 * @param factory: factory (= owner) 00116 * @param dbm: DBM to deallocate 00117 * @pre dbm was obtained from dbmf_allocate(factory) 00118 */ 00119 static inline 00120 void dbmf_internDeallocate(DBMAllocator_t *factory, DBMList_t *dbm) 00121 { 00122 assert(dbm && factory); 00123 dbm->next = factory->freeDBM; 00124 factory->freeDBM = dbm; 00125 } 00126 00127 /** Give back a LIST of DBMs to its factory. 00128 * @param factory: factory (= owner) 00129 * @param dbmList: DBM list to deallocate 00130 * @pre dbm was obtained from dbmf_allocate(factory) 00131 */ 00132 void dbmf_internDeallocateList(DBMAllocator_t *factory, DBMList_t *dbmList); 00133 00134 00135 #ifndef ENABLE_MONITOR 00136 #define dbmf_allocate(F) dbmf_internAllocate(F) 00137 #define dbmf_deallocate(F,D) dbmf_internDeallocate(F,D) 00138 #define dbmf_deallocateList(F,L) dbmf_internDeallocateList(F,L) 00139 #else 00140 #define dbmf_allocate(F)\ 00141 debug_remember(DBMList_t*, dbmf_internAllocate(F)) 00142 #define dbmf_deallocate(F,D)\ 00143 do { debug_forget(D); dbmf_internDeallocate(F,D); } while(0) 00144 #define dbmf_deallocateList(F,L)\ 00145 do { debug_push(); dbmf_internDeallocateList(F,L); } while(0) 00146 #endif 00147 00148 /** Same as deallocateList but for a federation. 00149 * @pre federation not empty. 00150 * @param fed: federation to deallocate. 00151 * @param factory: allocator. 00152 */ 00153 static inline 00154 void dbmf_deallocateFederation(DBMAllocator_t *factory, DBMFederation_t *fed) 00155 { 00156 assert(factory && fed && fed->dim <= factory->maxDim); 00157 if (fed->dbmList) 00158 { 00159 dbmf_deallocateList(factory, fed->dbmList); 00160 fed->dbmList = NULL; 00161 } 00162 } 00163 00164 00165 /** Clear a factory. 00166 * @param factory: factory to clear (deallocate its freeDBM) 00167 */ 00168 void dbmf_clearFactory(DBMAllocator_t *factory); 00169 00170 00171 /************************************* 00172 ** Basic functions for federations ** 00173 *************************************/ 00174 00175 00176 /** Initialize a federation. 00177 * @param fed: federation 00178 * @param dim: dimension of the DBMs 00179 * @pre 00180 * - fed != NULL 00181 * - dim > 0 (at least reference clock) 00182 * - fed is a new uninitialized federation 00183 * (the list of DBMs is reset) 00184 */ 00185 static inline 00186 void dbmf_initFederation(DBMFederation_t *fed, cindex_t dim) 00187 { 00188 assert(dim && fed); 00189 fed->dim = dim; 00190 fed->dbmList = NULL; 00191 } 00192 00193 00194 /** Add a DBM in the federation (at the beginning of the list). 00195 * @param dbm: dbm to add 00196 * @param fed: federation 00197 * @pre dbm->next is NULL or invalid: if there is a linked list 00198 * then it is lost. 00199 */ 00200 static inline 00201 void dbmf_addDBM(DBMList_t *dbm, DBMFederation_t *fed) 00202 { 00203 assert(dbm && fed); 00204 dbm->next = fed->dbmList; 00205 fed->dbmList = dbm; 00206 } 00207 00208 00209 /** Clean up the federation from empty DBMs. 00210 * Operations on federations assume that the 00211 * DBMs in the federation are not empty, so 00212 * if for some strange reason you have empty 00213 * DBMs there then remove them. 00214 * @param fed: federation to clean up. 00215 * @param factory: allocator for deallocation. 00216 * @pre factory->dim >= fed->dim 00217 */ 00218 void dbmf_cleanUp(DBMFederation_t *fed, DBMAllocator_t *factory); 00219 00220 00221 /** Append a list to another. 00222 * @param dbmList: list argument 00223 * @param endList: list to append at the tail of dbmList 00224 * @pre dbmList != NULL 00225 */ 00226 static inline 00227 void dbmf_appendList(DBMList_t *dbmList, DBMList_t *endList) 00228 { 00229 assert(dbmList); 00230 if (endList) 00231 { 00232 while(dbmList->next) dbmList = dbmList->next; 00233 dbmList->next = endList; 00234 } 00235 } 00236 00237 00238 /** Test if a federation has a particular DBM. 00239 * Useful for testing. This is not an inclusion check, 00240 * only a DBM match function. 00241 * @param fed: federation. 00242 * @param dbm: DBM to test. 00243 * @return TRUE if dbm is in fed, FALSE otherwise. 00244 */ 00245 BOOL dbmf_hasDBM(const DBMList_t *fed, const raw_t *dbm, cindex_t dim); 00246 00247 00248 /** Wrapper for DBMFederation_t 00249 * @see dbmf_hasDBM 00250 */ 00251 static inline 00252 BOOL dbmf_federationHasDBM(const DBMFederation_t fed, const raw_t *dbm) 00253 { 00254 return dbmf_hasDBM(fed.dbmList, dbm, fed.dim); 00255 } 00256 00257 00258 /** Size of a federation. 00259 * @param dbmList: list of DBMs (maybe NULL). 00260 * @return size of the list. 00261 */ 00262 size_t dbmf_getSize(const DBMList_t *dbmList); 00263 00264 00265 /** Copy a federation. 00266 * @param src: source 00267 * @param dst: destination 00268 * @param factory: compatible factory 00269 * @return 0 if success, -1 if out-of-memory 00270 * @pre 00271 * - factory != NULL && factory->dim >= src->dim && factory->dim >= dst->dim 00272 * - all DBMs were obtained from factory 00273 * - dst is initialized or contains DBMs 00274 * @post 00275 * - order of DBMs is preserved 00276 * - if out-of-memory then dst is emptied 00277 */ 00278 int dbmf_copy(DBMFederation_t *dst, const DBMFederation_t src, 00279 DBMAllocator_t *factory); 00280 00281 00282 /** Copy a DBM to a federation. 00283 * @param dbm: DBM to copy 00284 * @param dim: dimension of the DBM 00285 * @param factory: compatible factory 00286 * @pre factory != NULL && factory->dim >= dim && dim && dim > 0 00287 * @return federation with a copy of dbm 00288 * @post if out-of-memory then the federation is empty. 00289 */ 00290 DBMFederation_t dbmf_copyDBM(const raw_t *dbm, cindex_t dim, DBMAllocator_t *factory); 00291 00292 00293 /** Copy a DBM to a DBMList_t 00294 * @param dbm: DBM to copy 00295 * @param dim: dimension of the DBM 00296 * @param factory: compatible factory 00297 * @pre factory != NULL && factory->dim >= dim && dim && dim > 0 00298 * @return a copy of dbm as a DBMList_t or NULL if out-of-memory 00299 */ 00300 DBMList_t* dbmf_copyDBM2List(const raw_t *dbm, cindex_t dim, DBMAllocator_t *factory); 00301 00302 00303 /** Copy a list of DBMs. 00304 * @param dbmList: list to copy 00305 * @param dim: dimension of the DBMs 00306 * @param factory: compatible factory 00307 * @param valid: pointer for validation (memory allocation) 00308 * @return copy of dbmList. 00309 * @pre factory->maxDim >= dim, valid != NULL 00310 * @post order is respected, *valid = FALSE if out-of-memory 00311 * (and nothing is copied), TRUE if allocation successful. 00312 */ 00313 DBMList_t* dbmf_copyDBMList(const DBMList_t *dbmList, cindex_t dim, 00314 BOOL *valid, DBMAllocator_t *factory); 00315 00316 00317 /** Similar to dbmf_copyDBMList: wrapper for federations. 00318 * @param fed: original federation to copy. 00319 * @param factory: allocator. 00320 * @param valid: pointer for validation (memory allocation). 00321 * @pre factory->maxDim >= fed.dim, valid!=NULL. 00322 */ 00323 static inline 00324 DBMFederation_t dbmf_copyFederation(const DBMFederation_t fed, BOOL *valid, 00325 DBMAllocator_t *factory) 00326 { 00327 DBMFederation_t result; 00328 result.dim = fed.dim; 00329 result.dbmList = dbmf_copyDBMList(fed.dbmList, fed.dim, valid, factory); 00330 return result; 00331 } 00332 00333 00334 /** Copy a list of DBMs and append the result 00335 * to a federation. 00336 * @param fed: federation that collects the copy. 00337 * @param dbmList: the list of DBMs to copy. 00338 * @param factory: DBM allocator. 00339 * @pre factory->dim >= fed->dim, valid!=NULL, all DBMS 00340 * of dbmList are of dimension fed->dim. 00341 * @return -1 if out-of-memory, 0 otherwise. 00342 */ 00343 static inline 00344 int dbmf_addCopy(DBMFederation_t *fed, const DBMList_t *dbmList, 00345 DBMAllocator_t *factory) 00346 { 00347 BOOL valid; 00348 DBMList_t *copyList; 00349 assert(fed && factory); 00350 copyList = dbmf_copyDBMList(dbmList, fed->dim, &valid, factory); 00351 if (!valid) return -1; 00352 if (!fed->dbmList) 00353 { 00354 fed->dbmList = copyList; /* initialize list */ 00355 } 00356 else /* append list */ 00357 { 00358 dbmf_appendList(fed->dbmList, copyList); 00359 } 00360 return 0; 00361 } 00362 00363 00364 /** Add to the federation 1 DBM that 00365 * contains only 0. @see dbm_zero. 00366 * @param fed: federation 00367 * @param factory: compatible factory 00368 * @return 0 if success, -1 if out-of-memory 00369 * @pre 00370 * - factory != NULL & factory->dim >= fed->dim 00371 * - fed is initialized or contains valid DBMs 00372 */ 00373 int dbmf_addZero(DBMFederation_t *fed, DBMAllocator_t *factory); 00374 00375 00376 /** Add to the federation 1 DBM that 00377 * is not constrained (all clocks >= 0, that's all). 00378 * @param fed: federation 00379 * @param factory: compatible factory 00380 * @return 0 if success, -1 if out-of-memory 00381 * @pre factory != NULL && factory->dim >= fed->dim 00382 */ 00383 int dbmf_addInit(DBMFederation_t *fed, DBMAllocator_t *factory); 00384 00385 00386 /** Apply the same operation to all DBMs of a federation. 00387 */ 00388 #define APPLY_TO_FEDERATION(FED, OPERATION) \ 00389 do { \ 00390 DBMList_t *_first = (FED).dbmList; \ 00391 while(_first) \ 00392 { \ 00393 OPERATION; \ 00394 _first = _first->next; \ 00395 } \ 00396 } while(0) 00397 00398 00399 /******************************************* 00400 ** DBM operations applied to federations ** 00401 *******************************************/ 00402 00403 00404 /** Union of a list of DBMs and a federation: add DBMs to 00405 * the federation. fed += DBMs. Note: union means that 00406 * inclusion check is done. 00407 * @param fed: federation 00408 * @param dbmList: list of DBMs to add 00409 * @param factory: compatible factory 00410 * @return TRUE if one dbm was accepted, FALSE otherwise 00411 * @pre 00412 * - all DBMs were allocated by factory 00413 * - DBMs are of dimension fed->dim 00414 * - factory->dim >= fed->dim 00415 * - dbmList is a list, ie, dbmList->next is initialized. 00416 * @post 00417 * - DBMs in dbmList are deallocated or belong to fed. 00418 */ 00419 BOOL dbmf_union(DBMFederation_t *fed, DBMList_t *dbmList, 00420 DBMAllocator_t *factory); 00421 00422 00423 /** Union of a list of DBMs and a federation: add DBMs to 00424 * the federation. fed += DBMs. The argument is copied this 00425 * time. Note: union means that inclusion check is done. 00426 * It is possible to encode this function with other 00427 * functions but useless intermediate copies may be produced. 00428 * @param fed: federation 00429 * @param dbmList: list of DBMs to add 00430 * @param factory: compatible factory 00431 * @param valid: return flag for the allocation. 00432 * @return TRUE if one dbm was accepted, FALSE otherwise 00433 * @pre 00434 * - all DBMs were allocated by factory 00435 * - DBMs are of dimension fed->dim 00436 * - factory->dim >= fed->dim 00437 * - dbmList is a list, ie, dbmList->next is initialized. 00438 * @post 00439 * - *valid = TRUE if the allocation succeeded, FALSE 00440 * otherwise. If the allocation failed then fed has 00441 * an incomplete result. 00442 */ 00443 BOOL dbmf_unionWithCopy(DBMFederation_t *fed, const DBMList_t *dbmList, 00444 DBMAllocator_t *factory, BOOL *valid); 00445 00446 00447 /** Computes the convex hull union between one DBM 00448 * and a list of DBMs: dbm = dbm + list of dbm 00449 * @param dbm: DBM 00450 * @param dim: dimension of all the DBMs 00451 * @param dbmList: list of DBMs 00452 * @pre 00453 * - all the DBMs are of dimension dim 00454 * - dbmList != NULL 00455 * - dbm != NULL 00456 */ 00457 void dbmf_convexUnion(raw_t *dbm, cindex_t dim, const DBMList_t *dbmList); 00458 00459 00460 /** Computes the convex hull union between one DBM 00461 * and a federation: dbm = dbm + federation 00462 * @param dbm: DBM 00463 * @param fed: federation 00464 * @pre 00465 * - dbm is of dimension fed->dim 00466 */ 00467 static inline 00468 void dbmf_convexUnionWithFederation(raw_t *dbm, const DBMFederation_t fed) 00469 { 00470 assert(dbm); 00471 if (fed.dbmList) 00472 { 00473 dbmf_convexUnion(dbm, fed.dim, fed.dbmList); 00474 } 00475 } 00476 00477 00478 /** Computes the convex hull union from all the 00479 * DBMs of a federation. 00480 * @param fed: federation 00481 * @param factory: compatible factory 00482 * @pre factory != NULL & factory->dim >= fed->dim 00483 * @post the federation has only one DBM = union 00484 * of all previous DBMs. 00485 */ 00486 void dbmf_convexUnionWithSelf(DBMFederation_t *fed, DBMAllocator_t *factory); 00487 00488 00489 /** Computes the intersection between one DBM 00490 * and a list of DBMs = dbm intersec list of dbm. 00491 * result = dbm intersected with dbmList 00492 * @param dbm: DBM 00493 * @param dim: dimension of all the DBMs 00494 * @param dbmList: list of DBMs 00495 * @param factory: compatible factory 00496 * @param valid: where to validate the result 00497 * @pre 00498 * - all the DBMs are of dimension dim 00499 * - dbmList != NULL 00500 * - dbm != NULL 00501 * - valid != NULL 00502 * @return the result of dbm intersec dbmList (may be NULL) and 00503 * set valid to FALSE if out-of-memory (and return NULL), TRUE otherwise 00504 */ 00505 DBMList_t* dbmf_intersection(const raw_t *dbm, cindex_t dim, const DBMList_t *dbmList, 00506 BOOL* valid, DBMAllocator_t *factory); 00507 00508 00509 00510 /** Computes the intersection between 2 federations. 00511 * The arguments are preserved, the result is a newly allocated federation 00512 * (list of DBMs). Arguments are DBMList_t* for more flexibility. 00513 * @param fed1, fed2: federations (lists of DBMs) to compute intersection of 00514 * (may be both NULL). 00515 * @param dim: dimension of all the DBMs 00516 * @param valid: where to validate the result 00517 * @param factory: compatible factory 00518 * @pre 00519 * - all the DBMs are of dimension dim 00520 * - valid != NULL 00521 * @return the result as a newly allocated DBM list (maybe NULL if intersection is empty). 00522 */ 00523 DBMList_t* dbmf_intersectionWithFederation(const DBMList_t *fed1, const DBMList_t *fed2, 00524 cindex_t dim, BOOL *valid, DBMAllocator_t *factory); 00525 00526 00527 /** Computes the intersection between one DBM 00528 * and a federation. result = updated fed = fed intersected with dbm. 00529 * @param fed: federation 00530 * @param dbm: DBM 00531 * @param factory: factory for deallocation of DBMs 00532 * @return fed->dbmList != NULL 00533 */ 00534 BOOL dbmf_intersectsDBM(DBMFederation_t *fed, const raw_t *dbm, DBMAllocator_t *factory); 00535 00536 00537 /** Computes the intersection between one federation 00538 * and a federation. result = updated fed1 = fed1 intersected with fed2. 00539 * @param fed1,fed2: federations 00540 * @param factory: factory for deallocation of DBMs 00541 * @pre 00542 * - DBMs in fed2 have the same dimension as those in fed1. 00543 * - fed1 != NULL, fed2 may be NULL 00544 * - factory is a compatible factory 00545 * @return -1 if out-of-memory, 0 otherwise. 00546 */ 00547 int dbmf_intersectsFederation(DBMFederation_t *fed1, const DBMList_t *fed2, DBMAllocator_t *factory); 00548 00549 00550 /** Test if a list of DBMs and a DBM have an intersection. 00551 * @param dbmList: list of DBMs. 00552 * @param dbm: DBM to test. 00553 * @param dim: dimension of all the DBMs. 00554 * @return TRUE if there is an intersection, FALSE otherwise. 00555 */ 00556 BOOL dbmf_DBMsHaveIntersection(const DBMList_t *dbmList, const raw_t *dbm, cindex_t dim); 00557 00558 00559 /** Test if a federation and a DBM have an intersection. 00560 * @param fed: federation. 00561 * @param dbm: DBM to test. 00562 * @pre dbm is of dimension fed->dim. 00563 * @return TRUE if there is an intersection, FALSE otherwise. 00564 */ 00565 static inline 00566 BOOL dbmf_federationHasIntersection(const DBMFederation_t fed, const raw_t *dbm) 00567 { 00568 return dbmf_DBMsHaveIntersection(fed.dbmList, dbm, fed.dim); 00569 } 00570 00571 00572 /** Test if 2 federations have an intersection. 00573 * @param fed1,fed2: federations to test. 00574 * @pre the federations have the same dimension. 00575 */ 00576 static inline 00577 BOOL dbmf_federationsHaveIntersection(const DBMFederation_t fed1, const DBMFederation_t fed2) 00578 { 00579 assert(fed1.dim == fed2.dim); 00580 APPLY_TO_FEDERATION(fed1, 00581 if (dbmf_federationHasIntersection(fed2, _first->dbm)) 00582 return TRUE); 00583 return FALSE; 00584 } 00585 00586 00587 /** Constrain a federation with several constraints. 00588 * @param fed: federation 00589 * @param constraints,n: the n constraints to use. 00590 * @param factory: compatible factory 00591 * @pre 00592 * - valid constraints: not of the form xi-xi <= something 00593 * - constraints[*].{i,j} < fed->dim 00594 * - factory != NULL & factory->dim >= fed->dim 00595 */ 00596 void dbmf_constrainN(DBMFederation_t *fed, const constraint_t *constraints, size_t n, 00597 DBMAllocator_t *factory); 00598 00599 00600 /** Constrain a federation with several constraints using an index 00601 * table to translate constraint indices to DBM indices. 00602 * @param fed: federation 00603 * @param indexTable: table for index translation 00604 * @param constraints,n: the n constraints to use. 00605 * @param factory: compatible factory 00606 * @pre 00607 * - valid constraints: not of the form xi-xi <= something 00608 * - indexTable[constraints[*].{i,j}] < fed->dim and no out-of-bound for indexTable 00609 * - factory != NULL & factory->dim >= fed->dim 00610 */ 00611 void dbmf_constrainIndexedN(DBMFederation_t *fed, const cindex_t *indexTable, 00612 const constraint_t *constraints, size_t n, 00613 DBMAllocator_t *factory); 00614 00615 00616 /** Constrain a federation with one constraint 00617 * constraint1 once is cheaper than constrainN with 1 00618 * constraintN with n > 1 is cheaper than constrain1 n times 00619 * @param fed: federation 00620 * @param i,j,constraint: constraint for xi-xj to use 00621 * @param factory: compatible factory 00622 * @pre 00623 * - valid constraint: i != j & i < fed->dim & j < fed->dim 00624 * - factory != NULL & factory->dim >= fed->dim 00625 */ 00626 void dbmf_constrain1(DBMFederation_t *fed, cindex_t i, cindex_t j, raw_t constraint, 00627 DBMAllocator_t *factory); 00628 00629 00630 /** Up/delay operation (strongest post-condition). 00631 * @param fed: federation. 00632 */ 00633 void dbmf_up(DBMFederation_t fed); 00634 00635 00636 /** Down operation (weakest pre-condition). 00637 * @param fed: federation. 00638 */ 00639 void dbmf_down(DBMFederation_t fed); 00640 00641 00642 /** Reduce a federation: remove DBMs that are included 00643 * in other DBMs of the same federation. 00644 * Cost: 1/2 * dim^2 * (nb DBMs)^2 00645 * This performs simple inclusion checks between the DBMs. 00646 * @param fed: federation to reduce 00647 * @param factory: compatible factory 00648 * @pre factory != NULL & fed != NULL & factory->dim >= fed->dim 00649 */ 00650 void dbmf_reduce(DBMFederation_t *fed, DBMAllocator_t *factory); 00651 00652 00653 /** Reduce a federation: remove DBMs that are redundant. 00654 * This computes substractions to determine if a DBM 00655 * should be kept or not. 00656 * This function is here only for experimental purposes and should 00657 * not be used in practice because of its horrible complexity: 00658 * O(dim^(4*size)). Memory consumption may explode just for the needs 00659 * of one "reduce" computation (and thus it is not a reduce anymore). 00660 * @param fed: federation to reduce 00661 * @param factory: compatible factory 00662 * @pre factory != NULL & fed != NULL & factory->dim >= fed->dim 00663 * @return 0 if internal allocations were successful, -1 otherwise. 00664 * If -1 is returned then there is no guarantee that fed is reduced. 00665 * The factory is reset if -1 is returned to try to free memory. 00666 */ 00667 int dbmf_expensiveReduce(DBMFederation_t *fed, DBMAllocator_t *factory); 00668 00669 00670 /** Free operation: remove all constraints for a given clock. 00671 * @param fed: federation 00672 * @param clock: clock to free 00673 * @pre clock > 0 & clock < fed->dim 00674 */ 00675 void dbmf_freeClock(DBMFederation_t fed, cindex_t clock); 00676 00677 00678 /** Update a clock value: x := value 00679 * @param fed: federation 00680 * @param clock: clock to update 00681 * @param value: new value 00682 * @pre clock > 0 & clock < fed->dim 00683 */ 00684 void dbmf_updateValue(DBMFederation_t fed, cindex_t clock, int32_t value); 00685 00686 00687 /** Copy a clock: x := y 00688 * @param fed: federation 00689 * @param x: clock to copy to 00690 * @param y: clock to copy from 00691 * @pre x > 0, y > 0, x < fed->dim, y < fed->dim 00692 */ 00693 void dbmf_updateClock(DBMFederation_t fed, cindex_t x, cindex_t y); 00694 00695 00696 /** Increment a clock: x += value. 00697 * @param fed: federation 00698 * @param clock: clock to increment 00699 * @param value: value to increment 00700 * @pre 00701 * - clock > 0 && clock < fed->dim 00702 * - if value < 0 then |value| <= min bound of clock 00703 */ 00704 void dbmf_updateIncrement(DBMFederation_t fed, cindex_t clock, int32_t value); 00705 00706 00707 /** General update: x := x + value 00708 * @param fed: federation 00709 * @param x: clock to copy to 00710 * @param y: clock to copy from 00711 * @param value: value to increment 00712 * @pre 00713 * - x > 0, y > 0, x < fed->dim, y < fed->dim 00714 * - if value < 0 then |value| <= min bound of y 00715 */ 00716 void dbmf_update(DBMFederation_t fed, cindex_t x, cindex_t y, int32_t value); 00717 00718 00719 /** Check if a federation satisfies a constraint. 00720 * @param fed: federation 00721 * @param i,j,constraint: constraint xi-xj to check 00722 * @return TRUE if there is one DBM that satisfies the constraint, 00723 * FALSE otherwise 00724 * @pre i != j, i < fed->dim, j < fed->dim 00725 */ 00726 BOOL dbmf_satisfies(const DBMFederation_t fed, cindex_t i, cindex_t j, raw_t constraint); 00727 00728 00729 /** Test for emptiness. 00730 * @param fed: federation 00731 * @return TRUE if federation is empty, FALSE otherwise 00732 */ 00733 static inline 00734 BOOL dbmf_isEmpty(const DBMFederation_t fed) 00735 { 00736 return (BOOL)(fed.dbmList == NULL); 00737 } 00738 00739 00740 /** Test if a federation is unbounded, ie, if 00741 * one of its DBM is unbounded. 00742 * @param fed: federation to test 00743 * @return TRUE if one of its DBM is unbounded, 00744 * FALSE otherwise 00745 */ 00746 BOOL dbmf_isUnbounded(const DBMFederation_t fed); 00747 00748 00749 /** Partial relation between one DBM and a federation: 00750 * apply the relation to all the DBMs of a federation. 00751 * This relation computation is partial in the sense that 00752 * it will miss inclusions that result from the (non-convex) union 00753 * of several DBMs, ie, the true semantics of a federation. 00754 * @param dbm: DBM to test 00755 * @param fed: federation 00756 * @pre dbm is of dimension fed->dim, dbm closed non empty 00757 * @return safe approximate relation: 00758 * dbm_SUBSET if dbm included in one DBM of fed 00759 * dbm_SUPERSET if dbm includes all DBMs of fed 00760 * dbm_EQUAL if subset & superset 00761 * dbm_DIFFERENT otherwise 00762 */ 00763 relation_t dbmf_partialRelation(const raw_t *dbm, const DBMFederation_t fed); 00764 00765 00766 /** Relation between one DBM and a federation. 00767 * This computation is more expensive but it is correct 00768 * with respect to the semantics of a federation. 00769 * @param dbm: DBM to test 00770 * @param fed: federation 00771 * @param factory: compatible factory 00772 * @param valid: pointer to validate internal memory allocation. 00773 * @pre dbm is of dimension fed->dim, dbm closed non empty, 00774 * factory->dim >= fed.dim, valid != NULL 00775 * @return the relation between dbm and fed. The result is validated 00776 * by the flag *valid. 00777 * @post if *valid = FALSE then the relation cannot be computed, 00778 * dbm_DIFFERENT is returned, and the factory is reset. 00779 */ 00780 relation_t dbmf_relation(const raw_t *dbm, const DBMFederation_t fed, 00781 BOOL *valid, DBMAllocator_t *factory); 00782 00783 00784 /** Remove DBMs of fed that are (partially) included 00785 * in arg. 00786 * @return TRUE if fed is not empty afterwards, FALSE otherwise. 00787 * @param fed: federation to shrink 00788 * @param arg: list of DBM to test for inclusion 00789 * @param factory: the DBM allocator 00790 * @pre 00791 * - DBMs of arg are of dimension fed->dim 00792 * - fed!=NULL 00793 * - factory->maxDim>=fed->dim 00794 */ 00795 BOOL dbmf_removePartialIncluded(DBMFederation_t *fed, const DBMList_t *arg, 00796 DBMAllocator_t *factory); 00797 00798 00799 /** Test if a DBM is included in a list of DBMs. 00800 * @param dbm: dbm to test. 00801 * @param dbmList: list argument. 00802 * @param dim: dimension of all the DBMs. 00803 * @return TRUE if dbm is included in a DBM of dbmList, FALSE otherwise. 00804 */ 00805 BOOL dbmf_isIncludedIn(const raw_t *dbm, const DBMList_t *dbmList, cindex_t dim); 00806 00807 00808 /** Test if a DBM is really included in a federation semantically. 00809 * This is MORE EXPENSIVE than the dbmf_isIncludedIn function. 00810 * @param dbm: dbm to test. 00811 * @param fed: federation to test. 00812 * @param valid: to tell if the result is valid (invalid = out of memory occured) 00813 * @param factory: the DBM allocator 00814 * @pre 00815 * - all DBMs of fed are of dimension fed.dim 00816 * - factory->maxDim >= fed.dim 00817 * @return TRUE if dbm is included in a DBM of dbmList, FALSE otherwise. 00818 */ 00819 static inline 00820 BOOL dbmf_isReallyIncludedIn(const raw_t *dbm, const DBMFederation_t fed, 00821 BOOL *valid, DBMAllocator_t *factory) 00822 { 00823 return (BOOL)((dbmf_relation(dbm, fed, valid, factory) & base_SUBSET) != 0); 00824 } 00825 00826 00827 /** Test if all the DBMs of l1 are included in some DBMs of l2. 00828 * @param l1, l2: lists of DBMs to test. 00829 * @param dim: dimension of all the DBMs. 00830 * @return TRUE if forall DBMs d1 of l1, there exists d2 in l2 s.t. d1 included in d2. 00831 */ 00832 BOOL dbmf_areDBMsIncludedIn(const DBMList_t *l1, const DBMList_t *l2, cindex_t dim); 00833 00834 00835 /** Test if all the DBMs of l1 are included semantically in l2. 00836 * @param l1, l2: lists of DBMs to test. 00837 * @param valid: to tell if the result is valid (invalid = out of memory occured) 00838 * @param factory: the DBM allocator 00839 * @pre 00840 * - all DBMs of fed are of dimension fed.dim 00841 * - factory->maxDim >= fed.dim 00842 * @return TRUE if forall DBMs d of l1, d included in federation l2. 00843 */ 00844 BOOL dbmf_areDBMsReallyIncludedIn(const DBMList_t *l1, const DBMFederation_t l2, 00845 BOOL *valid, DBMAllocator_t *factory); 00846 00847 00848 /** Stretch-up operation for approximation. 00849 * Remove all upper bounds for all clocks. 00850 * @param fed: federation 00851 */ 00852 void dbmf_stretchUp(DBMFederation_t fed); 00853 00854 00855 /** Stretch-down operation for approximation. 00856 * Remove all lower bounds for a given clock. 00857 * @param fed: federation 00858 * @param clock: clock to "down-free" 00859 * @pre clock > 0, clock < fed->dim 00860 */ 00861 void dbmf_stretchDown(DBMFederation_t fed, cindex_t clock); 00862 00863 00864 /** Smallest possible delay. Render upper bounds xi-x0 <= ci0 00865 * non strict. 00866 * @param fed: federation 00867 */ 00868 void dbmf_microDelay(DBMFederation_t fed); 00869 00870 00871 /** Test semantic equality. Expensive test, computes fed1-fed2 00872 * and fed2-fed1. 00873 * This is *very* expensive. 00874 * @param fed1, fed2: federations to test. 00875 * @param factory: compatible factory 00876 * @param valid: pointer to validate internal memory allocation. 00877 * @return TRUE if fed1 == fed2, FALSE otherwise. 00878 * @pre factory->dim >= fed1.dim && factory->dim >= fed2.dim, valid != NULL 00879 * @post if *valid == FALSE then the result cannot be trusted and the factory 00880 * is reset. 00881 */ 00882 BOOL dbmf_areEqual(const DBMFederation_t fed1, const DBMFederation_t fed2, 00883 BOOL *valid, DBMAllocator_t *factory); 00884 00885 00886 /** Check if a discrete point is included in a federation. 00887 * @param fed: federation 00888 * @param pt: point 00889 * @pre pt is a int32_t[fed->dim] 00890 * @return TRUE if pt satisfies the constraints of one 00891 * DBM in fed, FALSE otherwise 00892 */ 00893 BOOL dbmf_isPointIncluded(const int32_t *pt, const DBMFederation_t fed); 00894 00895 00896 /** Check if a real point is included in a federation. 00897 * @param fed: federation 00898 * @param pt: point 00899 * @pre pt is a int32_t[fed->dim] 00900 * @return TRUE if pt satisfies the constraints of one 00901 * DBM in fed, FALSE otherwise 00902 */ 00903 BOOL dbmf_isRealPointIncluded(const double *pt, const DBMFederation_t fed); 00904 00905 00906 /** Substraction operation: computes C = A - B 00907 * @param dbm: input DBM to substract from (A) 00908 * @param fed: federation to substract (B) 00909 * @param factory: compatible factory 00910 * @param valid: pointer to validate memory allocation 00911 * @return C as a list of DBMs (may be NULL if empty) 00912 * @pre 00913 * - dbm is of dimension fed.dim 00914 * - factory->dim >= fed.dim 00915 * - valid != NULL 00916 * @post 00917 * - the result (if != NULL) is allocated by the factory 00918 * - if *valid == FALSE then memory went out and the result =NULL 00919 */ 00920 DBMList_t* dbmf_substractFederationFromDBM(const raw_t *dbm, const DBMFederation_t fed, 00921 BOOL *valid, DBMAllocator_t *factory); 00922 00923 00924 /** Substraction operation: computes C = A - B 00925 * @param dbm1: DBM to substract from (A) 00926 * @param dbm2: DBM to substract (B) 00927 * @param dim: dimension of the DBMs 00928 * @param factory: compatible factory 00929 * @param valid: pointer to validate memory allocation 00930 * @return C as a list of DBMs (may be NULL if empty) 00931 * @pre 00932 * - both DBMs have same dimension 00933 * - factory->dim >= dim 00934 * - valid != NULL 00935 * @post 00936 * - the result (if != NULL) is allocated by the factory 00937 * - the resulting federation may be non disjoint 00938 * - if *valid == FALSE then memory went out and the result =NULL 00939 */ 00940 DBMList_t* dbmf_substractDBMFromDBM(const raw_t *dbm1, const raw_t *dbm2, cindex_t dim, 00941 BOOL *valid, DBMAllocator_t *factory); 00942 00943 00944 /** Substraction operation: computes C = A - B 00945 * @param fed: input federation to substract from (A) 00946 * @param dbm: DBM to substract (B) 00947 * @param factory: compatible factory 00948 * @param valid: pointer to validate memory allocation 00949 * @return C 00950 * @pre 00951 * - dbm is of dimension fed.dim 00952 * - factory->dim >= fed.dim 00953 * - valid != NULL 00954 * @post 00955 * - the DBMList of the result (if != NULL) is allocated by the factory 00956 * - if *valid == FALSE then memory went out and result =NULL 00957 */ 00958 DBMFederation_t dbmf_substractDBMFromFederation(const DBMFederation_t fed, const raw_t *dbm, 00959 BOOL *valid, DBMAllocator_t *factory); 00960 00961 00962 /** Substraction operation: computes C = A - B 00963 * @param fed1: input federation to substract from (A) 00964 * @param fed2: federation to substract (B) 00965 * @param factory: compatible factory 00966 * @param valid: pointer to validate memory allocation 00967 * @return C 00968 * @pre 00969 * - fed1.dim == fed2.dim 00970 * - factory->dim >= fed1.dim 00971 * - valid != NULL 00972 * @post 00973 * - the DBMList of the result (if != NULL) is allocated by the factory 00974 * - if *valid == FALSE then memory went out and the result =NULL 00975 */ 00976 DBMFederation_t dbmf_substractFederationFromFederation(const DBMFederation_t fed1, 00977 const DBMFederation_t fed2, 00978 BOOL *valid, DBMAllocator_t *factory); 00979 00980 00981 /** Substraction operation: computes A = A - B 00982 * @param fed: input federation to substract from (A) 00983 * @param dbm: DBM to substract (B) 00984 * @param factory: compatible factory 00985 * @return A = A - B, 0 if allocation successful, -1 if 00986 * out-of-memory and the federation is empty. 00987 * @pre 00988 * - dbm is of dimension fed.dim 00989 * - factory->dim >= fed.dim 00990 */ 00991 int dbmf_substractDBM(DBMFederation_t *fed, const raw_t *dbm, 00992 DBMAllocator_t *factory); 00993 00994 00995 /** Substraction operation: computes A = A - B 00996 * @param fed1: input federation to substract from (A) 00997 * @param fed2: federation to substract (B) 00998 * @param factory: compatible factory 00999 * @return A = A - B (maybe NULL), 0 if allocation successful, 01000 * -1 if out-of-memory and the federation is empty. 01001 * @pre 01002 * - fed1->dim == dim of fed2 (if fed2 != NULL) 01003 * - factory->dim >= fed1->dim 01004 * @post fed1 is deallocated if out-of-memory 01005 */ 01006 int dbmf_substractFederation(DBMFederation_t *fed1, const DBMList_t *fed2, 01007 DBMAllocator_t *factory); 01008 01009 01010 /** Operation similar to down but constrained: 01011 * predecessors of fed avoiding the states that 01012 * could reach bad. 01013 * @param fed: federation to compute the predecessors 01014 * from. 01015 * @param bad: list of DBMs to avoid 01016 * @param factory: DBM allocator 01017 * @pre fed->dim <= factory->dim, all DBMs of bad are 01018 * of dimension fed->dim, fed!=NULL, factory!=NULL. 01019 * @post 01020 * - bad is deallocated 01021 * - fed contains all the (symbolic) states from which 01022 * you can reach the original fed while avoiding bad. 01023 * @return -1 if out-of-memory and fed is empty, 0 otherwise. 01024 * THIS IMPLEMENTATION IS KNOWN TO BE WRONG. 01025 * Please use the API from DBM v2.x. fed_t::predt is correct. 01026 */ 01027 int dbmf_predt(DBMFederation_t *fed, DBMFederation_t *bad, DBMAllocator_t *factory); 01028 01029 01030 01031 /** Similarly, on federations. 01032 * @param fed: federation 01033 * @param bitSrc: source bit array 01034 * @param bitDst: destination bit array 01035 * @param bitSize: size in int of the bit arrays 01036 * @param table: indirection table to write 01037 * @param factory: compatible factory 01038 * @pre 01039 * - factory->dim >= fed->dim & factory->dim >= resulting dim 01040 * factory->dim == max possible dim 01041 * - @see dbm_shrinkExpand 01042 * @post 01043 * - fed->dim updated 01044 * - table written as by dbm_shrinkExpand 01045 */ 01046 void dbmf_shrinkExpand(DBMFederation_t *fed, 01047 const uint32_t *bitSrc, 01048 const uint32_t *bitDst, 01049 size_t bitSize, 01050 cindex_t *table, 01051 DBMAllocator_t *factory); 01052 01053 /** Classical extrapolation based on maximal bounds, 01054 * formerly called k-normalization. 01055 * Note: you may want to call dbmf_reduce afterwards. 01056 * @see dbm_classicExtrapolateMaxBounds 01057 * @param fed: federation 01058 * @param max: table of maximal constants to use for the clocks. 01059 * - max is a int32_t[fed->dim] 01060 * - max[0] = 0 (reference clock) 01061 */ 01062 void dbmf_extrapolateMaxBounds(DBMFederation_t fed, const int32_t *max); 01063 01064 01065 /** Diagonal extrapolation based on maximal bounds. 01066 * Note: you may want to call dbmf_reduce afterwards. 01067 * @see dbm_diagonalExtrapolateMaxBounds 01068 * @param fed: federation 01069 * @param max: table of maximal constants. 01070 * @pre 01071 * - fed->dim > 0 01072 * - max is a int32_t[fed->dim] 01073 * - max[0] = 0 (reference clock) 01074 */ 01075 void dbmf_diagonalExtrapolateMaxBounds(DBMFederation_t fed, const int32_t *max); 01076 01077 01078 /** Extrapolation based on lower-upper bounds. 01079 * Note: you may want to call dbmf_reduce afterwards. 01080 * @see dbm_extrapolateLUBounds 01081 * @param fed: federation 01082 * @param lower: lower bounds. 01083 * @param upper: upper bounds. 01084 * @pre 01085 * - fed->dim > 0 01086 * - lower and upper are int32_t[fed->dim] 01087 * - lower[0] = upper[0] = 0 (reference clock) 01088 */ 01089 void dbmf_extrapolateLUBounds(DBMFederation_t fed, const int32_t *lower, const int32_t *upper); 01090 01091 01092 /** Diagonal extrapolation based on lower-upper bounds. 01093 * Most general approximation. 01094 * Note: you may want to call dbmf_reduce afterwards. 01095 * @see dbm_diagonalExtrapolateLUBounds 01096 * @param fed: federation 01097 * @param lower: lower bounds. 01098 * @param upper: upper bounds. 01099 * @pre 01100 * - fed->dim > 0 01101 * - lower and upper are a int32_t[fed->dim] 01102 * - lower[0] = upper[0] = 0 01103 */ 01104 void dbmf_diagonalExtrapolateLUBounds(DBMFederation_t fed, const int32_t *lower, const int32_t *upper); 01105 01106 01107 01108 /******** moved here temporary print functions related to federations *************/ 01109 01110 01111 /** Pretty print of a federation. 01112 * @param dbmList: list of DBMs. 01113 * @param dim: dimension of all the DBMs. 01114 * @param out: output stream. 01115 */ 01116 void dbm_printFederation(FILE* out, const DBMList_t *dbmList, cindex_t dim); 01117 01118 #ifdef __cplusplus 01119 01120 /** Pretty print of a DBM federation. 01121 * @param dbmList: list of DBMs to print. 01122 * @param dim: dimension of all the DBMs. 01123 * @param out: output stream. 01124 */ 01125 std::ostream& dbm_cppPrintFederation(std::ostream& out, const DBMList_t *dbmList, cindex_t dim); 01126 01127 } 01128 #endif 01129 01130 #endif /* INCLUDE_DBM_DBMFEDERATION_H */ 01131