00001 /* -*- mode: C++; c-file-style: "stroustrup"; c-basic-offset: 4; indent-tabs-mode: nil; -*- */ 00002 /********************************************************************* 00003 * 00004 * Filename: dbm.h (dbm) 00005 * C header. 00006 * 00007 * Basic DBM operations. 00008 * 00009 * This file is a part of the UPPAAL toolkit. 00010 * Copyright (c) 1995 - 2000, Uppsala University and Aalborg University. 00011 * All right reserved. 00012 * 00013 * Not reviewed. 00014 * $Id: dbm.h,v 1.46 2005/09/29 16:10:43 adavid Exp $ 00015 * 00016 **********************************************************************/ 00017 00018 #ifndef INCLUDE_DBM_DBM_H 00019 #define INCLUDE_DBM_DBM_H 00020 00021 #include "base/intutils.h" 00022 #include "hash/compute.h" 00023 #include "base/relation.h" 00024 #include "dbm/constraints.h" 00025 00026 #ifdef __cplusplus 00027 extern "C" { 00028 #endif 00029 00030 /** 00031 * @mainpage 00032 * 00033 * A dbm is defined as a squared matrix of raw_t. raw_t 00034 * is the encoded clock constraint @see constraints.h. 00035 * 00036 * IMPORTANT NOTE: in the system, you will typically have clocks 00037 * x1,x2...,xn. The dbm will have x0 as the reference clock, hence 00038 * dimension = n + 1 => ASSUME dimension > 0 00039 * 00040 * Format of a dbm of dimension dim: 00041 * dbm[i,j] = dbm[i*dim+j] 00042 * where dbm[i,j] = constraint xi-xj < or <= c_ij 00043 * The constraint encoding is described in constraints.h 00044 * 00045 * The API does not support indirection table for clocks. 00046 * Dynamic mappings must be resolved before calling these 00047 * functions. Be careful when dealing with operation that 00048 * involve arrays of constraints (e.g. kExtrapolate). 00049 * As a common assumption for all operations on DBM: 00050 * dim > 0, which means at least the reference clock is 00051 * in the DBM. 00052 * DBM non empty means the represented zone is non empty, 00053 * which is, for a closed dbm the diagonal elements are =0. 00054 * 00055 * Common pre-condition: DBMs are always of dimension >= 1. 00056 */ 00057 00058 00059 /** Initialize a DBM with: 00060 * - <= 0 on the diagonal and the 1st row 00061 * - <= infinity elsewhere 00062 * @param dbm: DBM to initialize. 00063 * @param dim: dimension. 00064 * @return initialized DBM. 00065 * @post DBM is closed. 00066 */ 00067 void dbm_init(raw_t *dbm, cindex_t dim); 00068 00069 00070 /** Set the DBM so that it contains only 0. 00071 * @param dbm: DBM to set to 0 00072 * @param dim: dimension 00073 * @return zeroed DBM 00074 * @post DBM is closed 00075 */ 00076 static inline 00077 void dbm_zero(raw_t *dbm, cindex_t dim) 00078 { 00079 base_fill(dbm, dim*dim, dbm_LE_ZERO); 00080 } 00081 00082 00083 /** Equality test with trivial dbm as obtained from 00084 * dbm_init(dbm, dim). 00085 * @param dbm: DBM to test 00086 * @param dim: dimension. 00087 */ 00088 BOOL dbm_isEqualToInit(const raw_t *dbm, cindex_t dim); 00089 00090 00091 /** Equality test with dbm as obtained from dbm_zero(dbm, dim, tauClock) 00092 * @param dbm: DBM to test 00093 * @param tauClock: clock that should not be set to 0. 00094 * @param dim: dimension 00095 * @return zeroed DBM 00096 * @post DBM is closed 00097 * @pre 00098 * - tauClock > 0 (not reference clock) 00099 */ 00100 static inline 00101 BOOL dbm_isEqualToZero(const raw_t *dbm, cindex_t dim) 00102 { 00103 return (BOOL)(base_diff(dbm, dim*dim, dbm_LE_ZERO) == 0); 00104 } 00105 00106 00107 /** Convex hull union between 2 DBMs. 00108 * @param dbm1,dbm2: DBMs. 00109 * @param dim: dimension 00110 * @pre 00111 * - both DBMs have the same dimension 00112 * - both DBMs are closed and non empty 00113 * @return dbm1 = dbm1 U dbm2 00114 * @post dbm1 is closed. 00115 */ 00116 void dbm_convexUnion(raw_t *dbm1, const raw_t *dbm2, cindex_t dim); 00117 00118 00119 /** Intersection of 2 DBMs. 00120 * @param dbm1,dbm2: DBMs. 00121 * @param dim: dimension. 00122 * @pre 00123 * - both DBMs have the same dimension 00124 * - both DBMs are closed and non empty 00125 * @return dbm1 = dbm1 intersected with dbm2 and 00126 * TRUE if dbm1 is non empty. 00127 * @post dbm1 is closed and non empty OR dbm1 is empty. 00128 */ 00129 BOOL dbm_intersection(raw_t *dbm1, const raw_t *dbm2, cindex_t dim); 00130 00131 00132 /** Relaxed intersection of 2 DBMs. 00133 * @param dbm1,dbm2: DBMs. 00134 * @param dim: dimension. 00135 * @pre 00136 * - both DBMs have the same dimension 00137 * - both DBMs are closed and non empty 00138 * - dim > 0 00139 * @return dst = relaxed(dbm1) intersected with relaxed(dbm2) and 00140 * TRUE if dst is non empty. 00141 * @post dst is closed and non empty OR dst is empty. 00142 */ 00143 BOOL dbm_relaxedIntersection(raw_t *dst, const raw_t *dbm1, const raw_t *dbm2, cindex_t dim); 00144 00145 00146 /** Test if 2 DBMs have an intersection. 00147 * @param dbm1,dbm2: DBMs to test. 00148 * @param dim: dimension of both DBMs. 00149 * @return FALSE if dbm1 intersection dbm2 is empty 00150 * and TRUE if it *may* be non empty (not guaranteed). 00151 */ 00152 BOOL dbm_haveIntersection(const raw_t *dbm1, const raw_t *dbm2, cindex_t dim); 00153 00154 00155 /** Constrain a DBM with a constraint. 00156 * USAGE: 00157 * -# dbm must be closed. 00158 * -# reset touched: base_resetBits(touched, size) 00159 * -# apply constraints: dbm_constrain(...) 00160 * -# if not empty dbm_close(dbm, dim, touched) 00161 * @param dbm: DBM. 00162 * @param dim: dimension. 00163 * @param i,j,constraint: the clock constraint xi-xj <= constraint 00164 * (or < constraint) according to the clock constraint encoding. 00165 * @param touched: bit table to keep track of modified clocks. 00166 * @return: FALSE if the DBM is empty, TRUE otherwise, the constrained 00167 * DBM, and which clocks were modified (touched). 00168 * It is not guaranteed that the DBM is non empty, but 00169 * if FALSE is returned then the DBM is guaranteed to be empty. 00170 * @pre 00171 * - touched is at least a uint32_t[bits2intsize(dim)] 00172 * - constraint is finite 00173 * - dim > 1 induced by i < dim & j < dim & i != j 00174 * - i < dim, j < dim, i != j 00175 * @post THE RESULTING DBM MAY NOT BE CLOSED, calls to isEmpty 00176 * can return erroneous results. 00177 */ 00178 BOOL dbm_constrain(raw_t *dbm, cindex_t dim, 00179 cindex_t i, cindex_t j, raw_t constraint, 00180 uint32_t *touched); 00181 00182 00183 /** Constrain a DBM with several constraints. 00184 * USAGE: 00185 * @param dbm: DBM 00186 * @param dim: dimension. 00187 * @param constraints, n: the n constraints to use. 00188 * @pre 00189 * - DBM closed and non empty. 00190 * - valid constraint: not of the form xi-xi <= something 00191 * - dim > 1 induced by i < dim & j < dim & i != j 00192 * - constraints[*].{i,j} < dim 00193 * @return TRUE if the DBM is non empty, the constrained 00194 * DBM 00195 * @post the resulting DBM is closed if it is non empty. 00196 */ 00197 BOOL dbm_constrainN(raw_t *dbm, cindex_t dim, 00198 const constraint_t *constraints, size_t n); 00199 00200 00201 /** Constrain a DBM with several constraints using a table for 00202 * index translation (translates absolute clock indices to 00203 * local clock indices for this DBM). 00204 * USAGE: 00205 * @param dbm: DBM 00206 * @param dim: dimension. 00207 * @param indexTable: table for index translation 00208 * @param constraints, n: the n constraints to use. 00209 * @pre 00210 * - DBM closed and non empty. 00211 * - valid constraint: not of the form xi-xi <= something 00212 * - dim > 1 induced by i < dim & j < dim & i != j 00213 * - constraints[*].{i,j} < dim 00214 * @return TRUE if the DBM is non empty, the constrained 00215 * DBM 00216 * @post the resulting DBM is closed if it is non empty. 00217 */ 00218 BOOL dbm_constrainIndexedN(raw_t *dbm, cindex_t dim, const cindex_t *indexTable, 00219 const constraint_t *constraints, size_t n); 00220 00221 00222 /** Constrain a DBM with one constraint. 00223 * If you have several constraints, it may be better to 00224 * use the previous functions. 00225 * @param dbm: DBM, ASSUME: closed. 00226 * @param dim: dimension. 00227 * @param i,j,constraint: constraint for xi-xj to use 00228 * @pre 00229 * - DBM is closed and non empty 00230 * - dim > 1 induced by i < dim & j < dim & i != j 00231 * - as a consequence: i>=0 & j>=0 & i!=j => (i or j) > 0 00232 * and dim > (i or j) > 0 => dim > 1 00233 * - i < dim, j < dim, i != j 00234 * @return TRUE if the DBM is non empty and the constrained 00235 * DBM. 00236 * @post the resulting DBM is closed if it is non empty. 00237 */ 00238 BOOL dbm_constrain1(raw_t *dbm, cindex_t dim, 00239 cindex_t i, cindex_t j, raw_t constraint); 00240 00241 00242 /** Wrapper for constrain1. 00243 * @param dbm: DBM, assume closed 00244 * @param dim: dimension 00245 * @param c: the constraint to apply 00246 * @return TRUE if the DBM is non empty 00247 * @post the resulting DBM is closed if it is non empty 00248 */ 00249 static inline 00250 BOOL dbm_constrainC(raw_t *dbm, cindex_t dim, constraint_t c) 00251 { 00252 return dbm_constrain1(dbm, dim, c.i, c.j, c.value); 00253 } 00254 00255 00256 /** Delay operation. 00257 * Remove constraints of the form xi-x0 <= ci 00258 * and replace them by xi-x0 < infinity. 00259 * It is also called strongest post-condition. 00260 * @param dbm: DBM. 00261 * @param dim: dimension. 00262 * @pre 00263 * - DBM closed and non empty 00264 * @post DBM is closed. 00265 */ 00266 void dbm_up(raw_t *dbm, cindex_t dim); 00267 00268 00269 /** Internal dbm_down, don't use directly */ 00270 void dbm_downFrom(raw_t *dbm, cindex_t dim, cindex_t j0); 00271 00272 /** Inverse delay operation. 00273 * Also called weakest pre-condition. 00274 * @param dbm: DBM. 00275 * @param dim: dimension. 00276 * @pre 00277 * - DBM closed and non empty 00278 * @post DBM is closed. 00279 */ 00280 static inline 00281 void dbm_down(raw_t *dbm, cindex_t dim) 00282 { 00283 dbm_downFrom(dbm, dim, 1); 00284 } 00285 00286 00287 /** Former "reset" operation, properly called update. 00288 * Implement the operation x := v, where x is a clock and v 00289 * a positive integer. 00290 * @param dbm: DBM 00291 * @param dim: dimension. 00292 * @param index: clock index. 00293 * @param value: value to reset to (may be non null), must be >=0.. 00294 * @pre 00295 * - DBM closed and non empty 00296 * - dim > 1 induced by index > 0 and index < dim 00297 * - index > 0: never reset reference clock, index < dim 00298 * - value is finite and not an encoded clock constraint 00299 * - value >= 0 (int used for type convenience and compatibility). 00300 * @post DBM is closed. 00301 */ 00302 void dbm_updateValue(raw_t *dbm, cindex_t dim, 00303 cindex_t index, int32_t value); 00304 00305 00306 /** Free operation. Remove all constraints (lower and upper 00307 * bounds) for a given clock, i.e., set them to infinity, 00308 * except for x0-xk <= 0. 00309 * @param dbm: DBM. 00310 * @param dim: dimension. 00311 * @param index: the clock to free. 00312 * @pre 00313 * - DBM is closed and non empty 00314 * - dim > 1 induced by index > 0 && index < dim 00315 * - index > 0, index < dim 00316 * @post DBM is closed. 00317 */ 00318 void dbm_freeClock(raw_t *dbm, cindex_t dim, cindex_t index); 00319 00320 00321 /** Free all upper bounds for a given clock. 00322 * @param dbm: DBM. 00323 * @param dim: dimension. 00324 * @param index: the concerned clock. 00325 * @pre DBM closed and non empty and 0 < index < dim 00326 * @post DBM is closed and non empty. 00327 */ 00328 void dbm_freeUp(raw_t *dbm, cindex_t dim, cindex_t index); 00329 00330 00331 /** Free all upper bounds for all clocks. 00332 * @param dbm: DBM. 00333 * @param dim: dimension. 00334 * @pre DBM closed and non empty. 00335 * @post DBM closed and non empty. 00336 */ 00337 void dbm_freeAllUp(raw_t* dbm, cindex_t dim); 00338 00339 00340 /** @return true if dbm_freeAllUp(dbm,dim) has 00341 * no effect on dbm. 00342 * @param dbm,dim: DBM of dimension dim to test. 00343 */ 00344 BOOL dbm_isFreedAllUp(const raw_t *dbm, cindex_t dim); 00345 00346 00347 /** @return 0 if dbm_freeAllDown(dbm,dim) has 00348 * no effect on dbm, or (j << 16)|i otherwise 00349 * where i and j are the indices from where dbm 00350 * differs from its expected result. 00351 * @param dbm,dim: DBM of dimension dim to test. 00352 */ 00353 uint32_t dbm_testFreeAllDown(const raw_t *dbm, cindex_t dim); 00354 00355 00356 /** Free all lower bounds for a given clock. 00357 * @param dbm: DBM. 00358 * @param dim: dimension. 00359 * @param index: index of the clock to "down-free" 00360 * @pre 00361 * - dim > 1 induced by index > 0 && index < dim 00362 * - index > 0, index < dim 00363 * - DBM closed and non empty 00364 * @post DBM is closed and non empty. 00365 */ 00366 void dbm_freeDown(raw_t *dbm, cindex_t dim, cindex_t index); 00367 00368 00369 /** Free all lower bounds for all clocks. 00370 * @param dbm: DBM. 00371 * @param dim: dimension. 00372 * @pre DBM closed and non empty. 00373 * @post DBM closed and non empty. 00374 */ 00375 void dbm_freeAllDown(raw_t *dbm, cindex_t dim); 00376 00377 00378 /** Clock copy operation = update clock: 00379 * xi := xj, where xi and xj are clocks. 00380 * @param dbm: DBM. 00381 * @param dim: dimension. 00382 * @param i,j: indices of the clocks. 00383 * @pre 00384 * - DBM closed and non empty. 00385 * - dim > 1 induced by i > 0 & i < dim 00386 * - i > 0, j > 0, i < dim, j < dim 00387 * @post DBM is closed. 00388 */ 00389 void dbm_updateClock(raw_t *dbm, cindex_t dim, 00390 cindex_t i, cindex_t j); 00391 00392 00393 /** Increment operation: xi := xi + value, where xi is a clock. 00394 * WARNING: if offset is negative it may be incorrect to use this. 00395 * @param dbm: DBM. 00396 * @param dim: dimension. 00397 * @param i: index of the clock. 00398 * @param value: the increment. 00399 * @pre 00400 * - DBM closed and non empty. 00401 * - dim > 1 induced by i > 0 && i < dim 00402 * - i > 0, i < dim 00403 * - if value < 0, then |value| <= min bound of clock i 00404 * @post DBM is closed. 00405 */ 00406 void dbm_updateIncrement(raw_t *dbm, cindex_t dim, 00407 cindex_t i, int32_t value); 00408 00409 00410 /** More general update operation: xi := xj + value, 00411 * where xi and yi are clocks. 00412 * WARNING: if offset is negative it may be incorrect to use this. 00413 * @param dbm: DBM. 00414 * @param dim: dimension. 00415 * @param i,j: indices of the clocks. 00416 * @param value: the increment. 00417 * @pre 00418 * - DBM is closed and non empty. 00419 * - dim > 1 induced by i > 0 && i < dim 00420 * - i > 0, j > 0, j < dim, i < dim 00421 * - if value < 0 then |value| <= min bound of clock j 00422 * @post DBM is closed. 00423 */ 00424 void dbm_update(raw_t *dbm, cindex_t dim, 00425 cindex_t i, cindex_t j, int32_t value); 00426 00427 00428 /** @return constraint clock to == value, and return 00429 * if the result is non empty. 00430 * @param dbm,dim: DBM of dimension dim 00431 * @param clock: clock index for the reset 00432 * @param value: reset value to apply 00433 * @pre clock != 0 (not ref clock) && clock < dim 00434 */ 00435 BOOL dbm_constrainClock(raw_t *dbm, cindex_t dim, cindex_t clock, int32_t value); 00436 00437 00438 /** Satisfy operation. 00439 * Check if a DBM satisfies a constraint. The DBM is not modified. 00440 * WARNING: using this for conjunction of constraints is incorrect 00441 * because the DBM is not modified. 00442 * @param dbm: DBM. 00443 * @param dim: dimension. 00444 * @param i,j: indices of clocks for the clock constraint. 00445 * @param constraint: the encoded constraint. 00446 * @pre 00447 * - DBM is closed and non empty. 00448 * - dim > 0 00449 * - i != j (don't touch the diagonal) 00450 * - i < dim, j < dim 00451 * @return TRUE if the DBM satisfies the constraint. 00452 */ 00453 static inline 00454 BOOL dbm_satisfies(const raw_t *dbm, cindex_t dim, 00455 cindex_t i, cindex_t j, raw_t constraint) 00456 { 00457 assert(dbm && dim && i < dim && j < dim && i != j && dim > 0); 00458 return (BOOL) 00459 !(dbm[i*dim+j] > constraint && /* tightening ? */ 00460 dbm_negRaw(constraint) >= dbm[j*dim+i]); /* too tight ? */ 00461 } 00462 00463 00464 /** Check if a DBM is empty by looking 00465 * at its diagonal. There should be only == 0 00466 * constraints. 00467 * NOTE: one should never need to call this function 00468 * manually, unless for debugging. 00469 * @param dbm: DBM. 00470 * @param dim: dimension. 00471 * @pre 00472 * - the close function was run before on the dbm 00473 * @return: TRUE if empty, FALSE otherwise. 00474 */ 00475 BOOL dbm_isEmpty(const raw_t *dbm, cindex_t dim); 00476 00477 00478 /** Close operation. Complexity: cubic in dim. 00479 * Apply Floyd's shortest path algorithm. 00480 * @param dbm: DBM. 00481 * @param dim: dimension. 00482 * @return TRUE if the DBM is non empty. 00483 * @post DBM is closed *if* non empty. 00484 * @pre if dim == 1 then *dbm==dbm_LE_ZERO: close has 00485 * not sense and will not work for dim == 1. 00486 */ 00487 BOOL dbm_close(raw_t *dbm, cindex_t dim); 00488 00489 00490 /** Check that a DBM is closed. This test is as 00491 * expensive as dbm_close! It is there mainly for 00492 * testing/debugging purposes. 00493 * @param dbm: DBM to check. 00494 * @param dim: dimension. 00495 * @return TRUE if DBM is closed and non empty, 00496 * FALSE otherwise. 00497 */ 00498 BOOL dbm_isClosed(const raw_t *dbm, cindex_t dim); 00499 00500 00501 /** Close operation. Complexity: custom*dim*dim, 00502 * where custom is the number of clocks to look at. 00503 * @param dbm: DBM. 00504 * @param dim: dimension. 00505 * @param touched: bit table that tells which clocks 00506 * to look at. 00507 * @pre 00508 * - touched is at least a uint32_t[bit2intsize(dim)] 00509 * - if there is no bit set (nothing to do) then 00510 * the input DBM is non empty. 00511 * @return TRUE if the dbm is non empty. 00512 */ 00513 BOOL dbm_closex(raw_t *dbm, cindex_t dim, const uint32_t *touched); 00514 00515 00516 /** Close operation for 1 clock. Complexity: dim*dim. 00517 * @param dbm: DBM. 00518 * @param dim: dimension. 00519 * @param k: the clock for which the closure applies. 00520 * @pre 00521 * - k < dim 00522 * @return TRUE if the DBM is non empty. 00523 */ 00524 BOOL dbm_close1(raw_t *dbm, cindex_t dim, cindex_t k); 00525 00526 00527 /** Specialization of close valid if only one 00528 * constraint cij is tightened, ie, DBM is closed, 00529 * you tighten DBM[i,j] only, then this function 00530 * recomputes the closure more efficiently than 00531 * calling close1(i) and close1(j). 00532 * @param dbm: DBM 00533 * @param dim: dimension 00534 * @param i,j: the constraint that was tightened 00535 * @see Rokicki's thesis page 171. 00536 * @pre 00537 * - dim > 1 induced by i!=j & i < dim & j < dim 00538 * - i != j, i < dim, j < dim 00539 * - DBM non empty: 00540 * DBM[i,j] + DBM[j,i] >= 0, ie, the tightening 00541 * still results in a non empty DBM. If we have 00542 * < 0 then this close should not be called 00543 * at all because we know the DBM is empty. 00544 * @post DBM is not empty 00545 */ 00546 void dbm_closeij(raw_t *dbm, cindex_t dim, cindex_t i, cindex_t j); 00547 00548 00549 /** Tighten with a constraint c and maintain the closed form. 00550 * @param dbm,dim DBM of dimension dim 00551 * @param i,j,c constraint c_ij to tighten 00552 * @pre c_ij < dbm[i,j] (it is a tightening) and -c_ij < dbm[j,i] 00553 * (it does not tighten too much, ie, to an empty DBM). 00554 * @post dbm is not empty. 00555 */ 00556 static inline 00557 void dbm_tighten(raw_t* dbm, cindex_t dim, cindex_t i, cindex_t j, raw_t c) 00558 { 00559 // it is a tightening and it does not tighten too much 00560 assert(dbm[i*dim+j] > c && dbm_negRaw(c) < dbm[j*dim+i]); 00561 dbm[i*dim+j] = c; 00562 dbm_closeij(dbm, dim, i, j); 00563 assert(!dbm_isEmpty(dbm, dim)); 00564 } 00565 00566 00567 /** Check if a DBM is unbounded, i.e., if one point 00568 * can delay infinitely. 00569 * @param dbm: DBM. 00570 * @param dim: dimension. 00571 * @return TRUE if unbounded, FALSE otherwise. 00572 * @pre 00573 * - dbm_isValid(dbm, dim) 00574 */ 00575 BOOL dbm_isUnbounded(const raw_t *dbm, cindex_t dim); 00576 00577 00578 /** Relation between 2 dbms. 00579 * See relation_t. 00580 * @param dbm1,dbm2: DBMs to be tested. 00581 * @param dim: dimension of the DBMS. 00582 * @pre 00583 * - dbm1 and dbm2 have the same dimension 00584 * - dbm_isValid for both DBMs 00585 * @return: exact relation result, @see relation_t. 00586 */ 00587 relation_t dbm_relation(const raw_t *dbm1, const raw_t *dbm2, cindex_t dim); 00588 00589 00590 /** Test only if dbm1 <= dbm2. 00591 * @param dbm1,dbm2: DBMs to be tested. 00592 * @param dim: dimension of the DBMs. 00593 * @pre 00594 * - dbm1 and dbm2 have the same dimension 00595 * - dbm_isValid for both DBMs 00596 * @return TRUE if dbm1 <= dbm2, FALSE otherwise. 00597 */ 00598 BOOL dbm_isSubsetEq(const raw_t *dbm1, const raw_t *dbm2, cindex_t dim); 00599 00600 /** Symmetric relation, just for completeness. 00601 * @return TRUE if dbm1 >= dbm2, FALSE otherwise. 00602 */ 00603 static inline 00604 BOOL dbm_isSupersetEq(const raw_t *dbm1, const raw_t *dbm2, cindex_t dim) 00605 { 00606 return dbm_isSubsetEq(dbm2, dbm1, dim); 00607 } 00608 00609 00610 /** Relax upper bounds of a given clocks, ie, make them weak. 00611 * @param dbm, dim: DBM of dimension dim 00612 * @param clock: clock to relax. 00613 * @pre (dim > 0 induced by) clock >= 0 && clock < dim 00614 * && dbm_isValid(dbm,dim) 00615 * @post DBM is closed and non empty 00616 */ 00617 void dbm_relaxUpClock(raw_t *dbm, cindex_t dim, cindex_t clock); 00618 00619 00620 /** Relax lower bounds of a given clocks, ie, make them weak. 00621 * @param dbm, dim: DBM of dimension dim 00622 * @param clock: clock to relax. 00623 * @pre (dim > 0 induced by) clock >= 0 && clock < dim 00624 * && dbm_isValid(dbm,dim) 00625 * @post DBM is closed and non empty 00626 */ 00627 void dbm_relaxDownClock(raw_t* dbm, cindex_t dim, cindex_t clock); 00628 00629 00630 /** Relax all bounds so that they are non strict (except 00631 * for infinity). 00632 * @param dbm,dim: DBM of dimension dim. 00633 * @pre dbm_isValid(dbm, dim) 00634 * @post dbm_isValid(dbm, dim) 00635 */ 00636 void dbm_relaxAll(raw_t* dbm, cindex_t dim); 00637 00638 00639 /** Smallest possible delay. Render upper bounds xi-x0 <= ci0 00640 * non strict if possible. 00641 * @param dbm: DBM. 00642 * @param dim: dimension. 00643 * @pre 00644 * - dbm_isValid(dbm, dim) 00645 * @post DBM is closed and non empty (if dim > 0) 00646 */ 00647 static inline 00648 void dbm_relaxUp(raw_t *dbm, cindex_t dim) 00649 { 00650 // down of the ref clock == up of all other clocks 00651 dbm_relaxDownClock(dbm, dim, 0); 00652 } 00653 00654 00655 /** Smallest possible inverse delay. Render lower bounds x0-xi <= c0i 00656 * non strict if possible. 00657 * @param dbm: DBM. 00658 * @param dim: dimension. 00659 * @pre 00660 * - dbm_isValid(dbm, dim) 00661 * @post DBM is closed and non empty (if dim > 0) 00662 */ 00663 static inline 00664 void dbm_relaxDown(raw_t *dbm, cindex_t dim) 00665 { 00666 // up of the ref clock == down of all other clocks 00667 dbm_relaxUpClock(dbm, dim, 0); 00668 } 00669 00670 00671 /** Copy DBMs. 00672 * @param src: source. 00673 * @param dst: destination. 00674 * @param dim: dimension. 00675 * @pre src and dst are raw_t[dim*dim] 00676 */ 00677 static inline 00678 void dbm_copy(raw_t *dst, const raw_t *src, cindex_t dim) 00679 { 00680 base_copyBest(dst, src, dim*dim); 00681 } 00682 00683 00684 /** Test equality. 00685 * @param dbm1,dbm2: DBMs to compare. 00686 * @param dim: dimension. 00687 * @pre dbm1 and dbm2 are raw_t[dim*dim] 00688 * @return TRUE if dbm1 == dbm2 00689 */ 00690 static inline 00691 BOOL dbm_areEqual(const raw_t *dbm1, const raw_t *dbm2, cindex_t dim) 00692 { 00693 return base_areEqual(dbm1, dbm2, dim*dim); 00694 } 00695 00696 00697 /** Compute a hash value for a DBM. 00698 * @param dbm: input DBM. 00699 * @param dim: dimension. 00700 * @pre dbm is a raw_t[dim*dim] 00701 * @return hash value. 00702 */ 00703 static inline 00704 uint32_t dbm_hash(const raw_t *dbm, cindex_t dim) 00705 { 00706 return hash_computeI32(dbm, dim*dim, dim); 00707 } 00708 00709 00710 /** Test if a (discrete) point is included in the 00711 * zone represented by the DBM. 00712 * @param pt: the point 00713 * @param dbm: DBM 00714 * @param dim: dimension 00715 * @pre 00716 * - pt is a int32_t[dim] 00717 * - dbm is a raw_t[dim*dim] 00718 * - dbm is closed 00719 * @return TRUE if the pt satisfies the constraints of dbm 00720 */ 00721 BOOL dbm_isPointIncluded(const int32_t *pt, const raw_t *dbm, cindex_t dim); 00722 00723 00724 /** Test if a (real) point is included in the 00725 * zone represented by the DBM. 00726 * @param pt: the point 00727 * @param dbm: DBM 00728 * @param dim: dimension 00729 * @pre 00730 * - pt is a int32_t[dim] 00731 * - dbm is a raw_t[dim*dim] 00732 * - dbm is closed 00733 * @return TRUE if the pt satisfies the constraints of dbm 00734 */ 00735 BOOL dbm_isRealPointIncluded(const double *pt, const raw_t *dbm, cindex_t dim); 00736 00737 00738 /** Classical extrapolation based on maximal bounds, 00739 * formerly called k-normalization. 00740 * 00741 * Extrapolate the zone using maximal constants: 00742 * - if dbm[i,j] > max_xi then set it to infinity 00743 * - if dbm[i,j] < -max_xj then set it to < -max_xj 00744 * - otherwise don't touch dbm[i,j] 00745 * 00746 * @param dbm: DBM. 00747 * @param dim: dimension. 00748 * @param max: table of maximal constants to use for the clocks. 00749 * @pre 00750 * - DBM is closed and non empty 00751 * - max is a int32_t[dim] 00752 * - max[0] = 0 (reference clock) 00753 * @post DBM is closed 00754 */ 00755 void dbm_extrapolateMaxBounds(raw_t *dbm, cindex_t dim, const int32_t *max); 00756 00757 00758 /** Diagonal extrapolation based on maximal bounds. 00759 * 00760 * Update dbm[i,j] with 00761 * - infinity if dbm[i,j] > max_xi 00762 * - infinity if dbm[0,i] < -max_xi 00763 * - infinity if dbm[0,j] < -max_xj, i != 0 00764 * - <-max_xj if dbm[i,j] < -max_xj, i == 0 00765 * - dbm[i,j] otherwise 00766 * 00767 * @param dbm: DBM. 00768 * @param dim: dimension. 00769 * @param max: table of maximal constants. 00770 * @pre 00771 * - DBM is closed and non empty 00772 * - max is a int32_t[dim] 00773 * - max[0] = 0 (reference clock) 00774 * @post DBM is closed. 00775 */ 00776 void dbm_diagonalExtrapolateMaxBounds(raw_t *dbm, cindex_t dim, const int32_t *max); 00777 00778 00779 /** Extrapolation based on lower-upper bounds. 00780 * 00781 * - if dbm[i,j] > lower_xi then dbm[i,j] = infinity 00782 * - if dbm[i,j] < -upper_xj then dbm[i,j] = < -upper_xj 00783 * 00784 * @param dbm: DBM. 00785 * @param dim: dimension. 00786 * @param lower: lower bounds. 00787 * @param upper: upper bounds. 00788 * @pre 00789 * - DBM is closed 00790 * - lower and upper are int32_t[dim] 00791 * - lower[0] = upper[0] = 0 (reference clock) 00792 * @post DBM is closed. 00793 */ 00794 void dbm_extrapolateLUBounds(raw_t *dbm, cindex_t dim, 00795 const int32_t *lower, const int32_t *upper); 00796 00797 00798 /** Diagonal extrapolation based on lower-upper bounds. 00799 * Most general approximation. 00800 * 00801 * Update dbm[i,j] with 00802 * - infinity if dbm[i,j] > lower_xi 00803 * - infinity if dbm[0,i] < -lower_xi 00804 * - infinity if dbm[0,j] < -upper_xj for i != 0 00805 * - <-upper_xj if dbm[0,j] < -upper_xj for i = 0 00806 * - dbm[i,j] otherwise 00807 * 00808 * @param dbm: DBM. 00809 * @param dim: dimension. 00810 * @param lower: lower bounds. 00811 * @param upper: upper bounds. 00812 * @pre 00813 * - DBM is closed and non empty 00814 * - lower and upper are int32_t[dim] 00815 * - lower[0] = upper[0] = 0 (reference clock) 00816 * @post DBM is closed. 00817 */ 00818 void dbm_diagonalExtrapolateLUBounds(raw_t *dbm, cindex_t dim, 00819 const int32_t *lower, const int32_t *upper); 00820 00821 00822 /** Shrink and expand a DBM: 00823 * - takes 2 bit arrays: the source array marks which 00824 * clocks are used in the source DBM, and the 00825 * destination array marks the clocks in the destination 00826 * DBM 00827 * - removes clock constraints in source and not 00828 * in destination 00829 * - adds clock constraints not in source and in 00830 * destination 00831 * - leaves clock constraints that are in source 00832 * and in destination 00833 * 00834 * @param dbmSrc: source DBM 00835 * @param dimSrc: dimension of dbmSrc 00836 * @param dbmDst: destination DBM 00837 * @param bitSrc: source bit array 00838 * @param bitDst: destination bit array 00839 * @param bitSize: size in int of the bit arrays \a bitSrc and \a bitDst 00840 * @param table: where to write the indirection table for the 00841 * destination DBM, \a dbmDst. If bit \a i is set in the bitDst, then 00842 * table[i] gives the index used in the \a dbmDst. 00843 * 00844 * @return dimDst = dimension of dbmDst. 00845 * @pre let maxDim = bitSize * 32: 00846 * - dbmDst is at least a raw_t[resultDim*resultDim] where 00847 * resultDim = base_countBitsN(bitDst, bitSize) 00848 * - dimSrc = number of bits set in bitSrc 00849 * - bitSrc and bitDst are uint32_t[bitSize] 00850 * - table is at least a uint32_t[maxDim] 00851 * - bitSize <= bits2intsize(maxDim) 00852 * - dimSrc > 0 00853 * - first bit in bitSrc is set 00854 * - first bit in bitDst is set 00855 * - bitSrc and bitDst are different (contents): 00856 * the function is supposed to be called only 00857 * if there is work to do 00858 * - dbmSrc != dbmDst (pointers): we do not 00859 * modify the source DBM 00860 * - bitSize > 0 because at least ref clock 00861 * @post 00862 * - dimDst (returned) == number of bits in bitDst 00863 * - for all bits set in bitDst at positions i, 00864 * then table[i] is defined and gives the proper 00865 * indirection ; for other bits, table[i] is 00866 * untouched. 00867 */ 00868 cindex_t dbm_shrinkExpand(const raw_t *dbmSrc, 00869 raw_t *dbmDst, 00870 cindex_t dimSrc, 00871 const uint32_t *bitSrc, 00872 const uint32_t *bitDst, 00873 size_t bitSize, 00874 cindex_t *table); 00875 00876 00877 /** Variant of dbm_shrinkExpand: Instead of giving 00878 * bit arrays, you provide one array of the clocks 00879 * you want in the destination. 00880 * @param dbmDst, dimDst: destination DBM of dimension dimDst 00881 * @param dbmSrc, dimSrc: source DBM of dimension dimSrc 00882 * @param cols: indirection table to copy the DBM, ie, 00883 * rows (and columns) i of the destination come from 00884 * cols[i] in the source if ~cols[i] (ie != ~0). 00885 * @pre cols is a cindex_t[dimDst], cols[0] is ignored 00886 * since the ref clock is always at 0, and 00887 * for all i < dimDst: cols[i] < dimSrc. 00888 */ 00889 void dbm_updateDBM(raw_t *dbmDst, const raw_t *dbmSrc, 00890 cindex_t dimDst, cindex_t dimSrc, 00891 const cindex_t *cols); 00892 00893 00894 /** Swap clocks. 00895 * @param dbm,dim: DBM of dimension dim. 00896 * @param x,y: clocks to swap. 00897 */ 00898 void dbm_swapClocks(raw_t *dbm, cindex_t dim, cindex_t x, cindex_t y); 00899 00900 00901 /** Test if the diagonal is correct. 00902 * Constraints on the diagonal should be <0 if the 00903 * DBM is empty or <=0 for non empty DBMs. Positive 00904 * constraints are allowed in principle but such DBMs 00905 * are not canonical. 00906 * @param dbm: DBM. 00907 * @param dim: dimension. 00908 * @return TRUE if the diagonal <=0. 00909 */ 00910 BOOL dbm_isDiagonalOK(const raw_t *dbm, cindex_t dim); 00911 00912 00913 /** Test if 00914 * - dbm is closed 00915 * - dbm is not empty 00916 * - constraints in the 1st row are at most <=0 00917 */ 00918 BOOL dbm_isValid(const raw_t *dbm, cindex_t dim); 00919 00920 00921 /** Convert code to string. 00922 * @param rel: relation result to translate. 00923 * @return string to print. 00924 * DO NOT deallocate or touch the result string. 00925 */ 00926 const char* dbm_relation2string(relation_t rel); 00927 00928 00929 /** Go through a DBM (dim*dim) and 00930 * compute the max range needed to store 00931 * the constraints, excluding infinity. 00932 * @param dbm: DBM. 00933 * @param dim: dimension. 00934 * @return max range, positive value. 00935 */ 00936 raw_t dbm_getMaxRange(const raw_t *dbm, cindex_t dim); 00937 00938 00939 #ifdef __cplusplus 00940 } 00941 #endif 00942 00943 #endif /* INCLUDE_DBM_DBM_H */ 00944