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

dbm.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: 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 

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