00001 /* -*- mode: C++; c-file-style: "stroustrup"; c-basic-offset: 4; indent-tabs-mode: nil; -*- */ 00002 /********************************************************************* 00003 * 00004 * Filename : mingraph.h (dbm) 00005 * 00006 * Minimal graph representation, encoded with the cheapest format 00007 * possible. 00008 * 00009 * This file is a part of the UPPAAL toolkit. 00010 * Copyright (c) 1995 - 2003, Uppsala University and Aalborg University. 00011 * All right reserved. 00012 * 00013 * $Id: mingraph.h,v 1.22 2005/09/29 16:10:43 adavid Exp $ 00014 * 00015 **********************************************************************/ 00016 00017 #ifndef INCLUDE_DBM_MINGRAPH_H 00018 #define INCLUDE_DBM_MINGRAPH_H 00019 00020 #include "base/c_allocator.h" 00021 #include "base/intutils.h" 00022 #include "dbm/dbm.h" 00023 00024 #ifdef __cplusplus 00025 extern "C" { 00026 #endif 00027 00028 /************************************************************************* 00029 * For practical reasons we assume that DBM dimensions are 00030 * <= 2^16-1. This is large enough since the size needed is 00031 * dim*dim integers per DBM and for dim=2^16 we need 2^32 integers 00032 * for only 1 DBM, which go well beyond the addressable memory in 32 bits. 00033 *************************************************************************/ 00034 00035 00036 /** 00037 * @file 00038 * 00039 * Support for minimum graph representation. 00040 * 00041 * The minimal graph is represented internally by the cheapest format 00042 * possible, and in some cases it may even not be reduced. In addition 00043 * to this, the size of the minimal graph depends on the actual input 00044 * DBM, which makes the size of the allocated memory unpredictable 00045 * from the caller point of view. 00046 * 00047 * 00048 * 00049 * @section allocation How allocation works 00050 * 00051 * The idea is to have generic implementation that can be used with 00052 * standard allocation schemes (malloc, new) and with custom 00053 * allocators. This interface is in C to make it easy to wrap to other 00054 * languages so we use a generic function to allocate memory. The 00055 * type of this function is 00056 * \code 00057 * int32_t* function(uint32_t size, void *data) 00058 * \endcode 00059 * where: 00060 * - \a size is the size in \c int to allocate, and it returns a 00061 * pointer to a \c int32_t[size] 00062 * - \a data is other custom data. 00063 * 00064 * Possible wrappers are: 00065 * - for a custom allocator Alloc: 00066 * \code 00067 * int32_t *alloc(uint32_t size, void *data) { 00068 * return ((Alloc*)data)->alloc(size); 00069 * } 00070 * \endcode 00071 * defined as base_allocate in base/DataAllocator.h 00072 * - for malloc: 00073 * \code 00074 * int32_t *alloc(uint32_t size, void *) { 00075 * return (int32_t*) malloc(size*sizeof(int32_t)); 00076 * } 00077 * \endcode 00078 * defined as base_malloc in base/c_allocator.h 00079 * - for new: 00080 * \code 00081 * int32_t *alloc(uint32_t size, void *) { 00082 * return new int32_t[size]; 00083 * } 00084 * \endcode 00085 * defined as base_new in base/DataAllocator.h 00086 * 00087 * The allocator function and the custom data are packed 00088 * together inside the allocator_t type. 00089 * 00090 * @see base/c_allocator.h 00091 * @see dbm_writeToMinDBMWithOffset() 00092 */ 00093 00094 00095 /** Style typedef: to make the difference clear 00096 * between just allocated memory and the minimal 00097 * graph representation. 00098 */ 00099 typedef const int32_t* mingraph_t; 00100 00101 00102 00103 /** Save a DBM in minimal representation. 00104 * 00105 * The API supports allocation of larger data structures than needed 00106 * for the actual zone representation. When the \a offset argument is 00107 * bigger than zero, \a offset extra integers are allocated and the 00108 * zone is written with the given offset. Thus when \c 00109 * int32_t[data_size] is needed to represent the reduced zone, an \c 00110 * int32_t array of size \coffset+data_size\c is allocated. The 00111 * first \a offset elements can be used by the caller. It is important 00112 * to notice that the other functions typically expect a pointer to 00113 * the actual zone data and not to the beginning of the allocated 00114 * block. Thus in the following piece of code, most functions expect 00115 * \c mg and not \c memory: 00116 * 00117 * \code 00118 * int32_t *memory = dbm_writeToMinDBMWithOffset(...); 00119 * mingraph_t mg = &memory[offset]; 00120 * \endcode 00121 * 00122 * \b NOTES: 00123 * - if \a offset is 0 and \a dim is 1, NULL may be returned. 00124 * NULL is valid as an input to the other functions. 00125 * - it could be possible to send as argument the maximal 00126 * value of the constraints that can be deduced from 00127 * the maximal constants but this would tie the algorithm 00128 * to the extrapolation. 00129 * 00130 * 00131 * @param dbm: the DBM to save. 00132 * @param dim: its dimension. 00133 * @param minimizeGraph: activate minimized graph 00134 * reduction. If it is FALSE, then the DBM is copied 00135 * without its diagonal. 00136 * @param tryConstraints16: flag to try to save 00137 * constraints on 16 bits, will cost dim*dim time. 00138 * @param c_alloc: C allocator wrapper 00139 * @param offset: offset for allocation. 00140 * @return allocated memory. 00141 * @pre 00142 * - dbm is a raw_t[dim*dim] 00143 * - allocFunction allocates memory in integer units 00144 * - dbm is closed. 00145 * - dim > 0 (at least ref clock) 00146 * @post the returned memory is of size offset+something 00147 * unknown from the caller point of view. 00148 */ 00149 int32_t* dbm_writeToMinDBMWithOffset(const raw_t* dbm, cindex_t dim, 00150 BOOL minimizeGraph, 00151 BOOL tryConstraints16, 00152 allocator_t c_alloc, 00153 size_t offset); 00154 00155 00156 /** Save a pre-analyzed DBM in minimal representation. 00157 * @param dbm: the DBM to save. 00158 * @param dim: its dimension. 00159 * @param bitMatrix: bit matrix resulting from the 00160 * analysis (ie dbm_analyzeForMinDBM). 00161 * @param nbConstraints: number of constraints in the 00162 * bit matrix. 00163 * @param tryConstraints16: flag to try to save 00164 * constraints on 16 bits, will cost dim*dim time. 00165 * @param allocFunction: the allocation function. 00166 * @param offset: offset for allocation. 00167 * @return allocated memory. 00168 * @pre 00169 * - dbm is a raw_t[dim*dim] 00170 * - allocFunction allocates memory in integer units 00171 * - dbm is closed. 00172 * - dim > 0 (at least ref clock) 00173 * - bitMatrix != NULL, obtained from dbm_analyzeForMinDBM 00174 * - nbConstraints = number of bits set in bitMatrix 00175 * - bitMatrix is a uint32_t[bits2intsize(dim*dim)] 00176 * @post 00177 * - the returned memory is of size offset+something 00178 * unknown from the caller point of view. 00179 * - bitMatrix is cleaned from the constraints xi >= 0 00180 */ 00181 int32_t* dbm_writeAnalyzedDBM(const raw_t *dbm, cindex_t dim, 00182 uint32_t *bitMatrix, 00183 size_t nbConstraints, 00184 BOOL tryConstraints16, 00185 allocator_t c_alloc, 00186 size_t offset); 00187 00188 00189 /** 00190 * Analyze a DBM for its minimal graph representation. Computes the 00191 * smallest number of constraints needed to represent the same zone as 00192 * the full DBM in \a dbm. The result in returned in \a bitMatrix: If 00193 * the bit \f$ i \cdot dim + j\f$ is set, then the constraint 00194 * \f$(i,j)\f$ of \a dbm is needed. 00195 * @param dbm: DBM. 00196 * @param dim: dimension. 00197 * @param bitMatrix: bit matrix. 00198 * @return 00199 * - number of needed constraints to save 00200 * - bit matrix that marks which constraints belong to the minimal graph 00201 * @pre bitMatrix is a uint32_t[bits2intsize(dim*dim)] 00202 */ 00203 size_t dbm_analyzeForMinDBM(const raw_t *dbm, cindex_t dim, uint32_t *bitMatrix); 00204 00205 00206 /** 00207 * This is a post-processing function for dbm_analyzeForMinDBM 00208 * to remove constraints of the form x>=0 that are part of the 00209 * minimal graph but that do not give much information. 00210 * @param dbm,dim: DBM of dimension dim 00211 * @param bitMatrix: bit matrix (already computed minimal graph) 00212 * @param nbConstraints: the number of constraints of the minimal graph. 00213 * @return the updated number of constraints of the modified minimal 00214 * graph where constraints x>=0 may have been removed. 00215 * @pre dbm_analyzeForMinDBM has been called before and nbConstraints 00216 * corresponds to the number of constraints of the minimal graph. 00217 */ 00218 size_t dbm_cleanBitMatrix(const raw_t *dbm, cindex_t dim, uint32_t *bitMatrix, size_t nbConstraints); 00219 00220 00221 /** 00222 * Get back the minimal graph from the internal representation. 00223 * It might be the case that the minimal graph is recomputed if 00224 * the DBM was copied. 00225 * @param ming: internal representation of the minimal graph. 00226 * @param bitMatrix: bit matrix of the minimal graph to write. 00227 * @param isUnpacked: says if buffer contains the unpacked DBM already. 00228 * @param buffer: where to uncompress the full DBM if needed. 00229 * @return the number of constraints part of the minimal graph. 00230 * @pre let dim be the dimension of ming, bitMatrix is a uint32_t[bit2intsize(dim*dim)], 00231 * buffer is a raw_t[dim*dim], and if isUnpacked is true then buffer contains 00232 * the full DBM of ming. 00233 * @post if ming is the result of saving a given dbm A, then the resulting 00234 * bitMatrix is the same as the one given by dbm_analyzeForMinDBM(A,dim,bitMatrix) 00235 * + buffer always contains the unpacked mingraph. 00236 */ 00237 size_t dbm_getBitMatrixFromMinDBM(uint32_t *bitMatrix, mingraph_t ming, 00238 BOOL isUnpacked, raw_t *buffer); 00239 00240 00241 /** 00242 * Convert a bit matrix marking constraints to an array of indices. 00243 * Encoding: i[k] = (index[k] & 0xffff) and j[k] = (index[k] >> 16) 00244 * @param bitMatrix: the bit matrix to convert. 00245 * @param nbConstraints: number of set bit in the matrix. 00246 * @param index: the index array to write. 00247 * @param dim: dimension of the bit matrix. 00248 * @pre index is a indexij_t[dim*(dim-1)] and bits on the 00249 * diagonal are not marked, nbConstraints <= dim*(dim-1). 00250 */ 00251 void dbm_bitMatrix2indices(const uint32_t *bitMatrix, size_t nbConstraints, 00252 uint32_t *index, cindex_t dim); 00253 00254 00255 /** Read a DBM from its minimal DBM representation. 00256 * @param dbm: where to write. 00257 * @param minDBM: the minimal representation to read from. 00258 * @pre 00259 * - dbm is a raw_t[dim*dim] where dim = dbm_getDimOfMinDBM(minDBM) 00260 * - minDBM points to the data of the minDBM directly. There is no 00261 * offset. 00262 * @return dimension of DBM and unpacked DBM in dbm. 00263 */ 00264 cindex_t dbm_readFromMinDBM(raw_t *dbm, mingraph_t minDBM); 00265 00266 00267 /** Dimension of a DBM from its packed minimal representation. 00268 * @param minDBM: the minimal DBM data directly, without offset. 00269 * @return dimension of DBM. 00270 */ 00271 cindex_t dbm_getDimOfMinDBM(mingraph_t minDBM); 00272 00273 00274 /** Size of the representation of the MinDBM. 00275 * This is the size of the allocated memory (without offset) for the 00276 * minimal representation. It is at most dim*(dim-1)+1 because in the 00277 * worst case the DBM is copied without its diagonal and we need one 00278 * integer to store the size. 00279 * @param minDBM: minimal DBM representation (without offset). 00280 * @return size in int32_t allocated for the representation. 00281 * NOTE: the write function allocates exactly 00282 * int32_t[offset+dbm_getSizeOfMinDBM(minDBM)] 00283 */ 00284 size_t dbm_getSizeOfMinDBM(mingraph_t minDBM); 00285 00286 00287 /** Equality test with a full DBM. 00288 * Unfortunately, this may be expensive (dim^3) if the 00289 * minimal graph format is used. 00290 * @param dbm: full DBM. 00291 * @param dim: dimension of dbm. 00292 * @param minDBM: minimal DBM representation (without offset). 00293 * @pre dbm is a raw_t[dim*dim] and dim > 0 (at least ref clock) 00294 * @return TRUE if the DBMs are the same, FALSE otherwise. 00295 */ 00296 BOOL dbm_isEqualToMinDBM(const raw_t *dbm, cindex_t dim, mingraph_t minDBM); 00297 00298 00299 /** Equality test between 2 minimal graphs (saved 00300 * with the same function and flags). 00301 * @param mg1,mg2: minimal graph arguments. 00302 * @return TRUE if the graphs are the same, provided 00303 * they were saved with the same flags, FALSE otherwise. 00304 */ 00305 static inline 00306 BOOL dbm_areMinDBMVerbatimEqual(mingraph_t mg1, mingraph_t mg2) 00307 { 00308 assert(mg1 && mg2); /* mingraph_t == const int* */ 00309 return (BOOL) 00310 (*mg1 == *mg2 && base_areEqual(mg1+1, mg2+1, dbm_getSizeOfMinDBM(mg1)-1)); 00311 } 00312 00313 00314 /** Equality test with a full DBM. 00315 * This variant of the equality test may be used if the 00316 * DBM has already been analyzed or if you need to reuse 00317 * the result of the analysis. 00318 * @param dbm: full DBM. 00319 * @param dim: dimension of dbm. 00320 * @param bitMatrix: bit matrix resulting from the analysis 00321 * of dbm (dbm_analyzeforMinDBM). 00322 * @param nbConstraints: number of constraints marked in 00323 * the bit matrix = number of bits set. 00324 * @param minDBM: minimal DBM representation (without offset). 00325 * @pre 00326 * - dbm is a raw_t[dim*dim] and dim > 0 (at least ref clock) 00327 * - bitMatrix is a uint32_t[bits2intsize(dim*dim)] 00328 * @return TRUE if the DBMs are the same, FALSE otherwise. 00329 * @post the bitMatrix may have the bits for the constraints on 00330 * the 1st row cleaned and nbConstraints will be updated accordingly. 00331 */ 00332 BOOL dbm_isAnalyzedDBMEqualToMinDBM(const raw_t *dbm, cindex_t dim, 00333 uint32_t *bitMatrix, 00334 size_t *nbConstraints, 00335 mingraph_t minDBM); 00336 00337 00338 /** Another variant for equality checking: 00339 * this one may unpack the minimal graph if needed. 00340 * It needs a buffer as an input to do so. 00341 * @param dbm, dim: full DBM of dimension dim. 00342 * @param minDBM: minimal DBM representation (without offset). 00343 * @param buffer: buffer to unpack the DBM if needed 00344 * @pre 00345 * - dbm is a raw_t[dim*dim] and dim > 0 (at leat ref clock) 00346 * - buffer != NULL is a raw_t[dim*dim] 00347 * @post 00348 * - buffer may be written or not. If you want to know 00349 * it, you can set buffer[0] = 0, and test afterwards 00350 * if buffer[0] == 0. If mingraph is unpacked then it 00351 * is guaranteed that buffer[0] == dbm_LE_ZERO, otherwise 00352 * buffer is untouched. 00353 * @return TRUE if the DBMs are the same, FALSE otherwise. 00354 */ 00355 BOOL dbm_isUnpackedEqualToMinDBM(const raw_t *dbm, cindex_t dim, 00356 mingraph_t minDBM, raw_t *buffer); 00357 00358 00359 /** Relation between a full DBM and a minimal representation 00360 * DBM. The relation may be exact or not: 00361 * if the relation is exact then 00362 * dbm_EQUAL is returned if dbm == minDBM 00363 * dbm_SUBSET is returned if dbm < minDBM 00364 * dbm_SUPERSET is returned if dbm > minDBM 00365 * dbm_DIFFERENT is returned if dbm not comparable with minDBM 00366 * else 00367 * dbm_SUBSET is returned if dbm <= minDBM 00368 * dbm_DIFFERENT otherwise 00369 * 00370 * @param dbm: full DBM to test. 00371 * @param dim: its dimension. 00372 * @param minDBM: minimal DBM representation. 00373 * @param unpackBuffer: memory space to unpack. 00374 * if unpackBuffer == NULL then the relation is not exact 00375 * if unpackBuffer != NULL then assume that buffer = raw_t[dim*dim] 00376 * to be able to unpack the DBM and compute an exact relation. 00377 * 00378 * NOTE: unpackBuffer is sent as an argument to avoid stackoverflow 00379 * if using stack allocation. The needed size is in dim*dim*sizeof(int). 00380 * It is NOT guaranteed that unpackBuffer will be written. The dbm 00381 * MAY be unpacked only if relation != subset and unpackBuffer != NULL. 00382 * 00383 * @pre 00384 * - dbm is closed and not empty 00385 * - dbm is a raw_t[dim*dim] (full DBM) 00386 * - dim > 0 (at least ref clock) 00387 * @return relation as described above. 00388 */ 00389 relation_t dbm_relationWithMinDBM(const raw_t *dbm, cindex_t dim, 00390 mingraph_t minDBM, raw_t *unpackBuffer); 00391 00392 00393 /** Variant of the previous relation function. 00394 * This may be cheaper if what count is to know 00395 * (subset or equal) or different or superset. 00396 * if unpackBuffer != NULL then 00397 * dbm_EQUAL or dbm_SUBSET is returned if dbm == minDBM 00398 * dbm_SUBSET is returned if dbm < minDBM 00399 * dbm_SUPERSET is returned if dbm > minDBM 00400 * dbm_DIFFERENT is returned if dbm not comparable with minDBM 00401 * else 00402 * dbm_SUBSET is returned if dbm <= minDBM 00403 * dbm_DIFFERENT is returned otherwise 00404 * 00405 * @param dbm: full DBM to test. 00406 * @param dim: its dimension. 00407 * @param minDBM: minimal DBM representation. 00408 * @param unpackBuffer: memory space to unpack. 00409 * if unpackBuffer == NULL then the relation is not exact 00410 * if unpackBuffer != NULL then assume that buffer = raw_t[dim*dim] 00411 * to be able to unpack the DBM and compute an exact relation. 00412 * @pre 00413 * - dbm is closed and not empty 00414 * - dbm is a raw_t[dim*dim] (full DBM) 00415 * - dim > 0 (at least ref clock) 00416 * @return relation as described above. 00417 */ 00418 relation_t dbm_approxRelationWithMinDBM(const raw_t *dbm, cindex_t dim, 00419 mingraph_t minDBM, raw_t *unpackBuffer); 00420 00421 00422 /** Convex union. 00423 * This may cost dim^3 in time since the minimal DBM has 00424 * to be unpacked to a full DBM. 00425 * Computes dbm = dbm + minDBM 00426 * @param dbm: dbm to make the union with. 00427 * @param dim: its dimension. 00428 * @param minDBM: minDBM to add to dbm (without offset). 00429 * @param unpackBuffer: memory space to unpack the DBM. 00430 * @pre 00431 * - dbm is a raw_t[dim*dim] and dim > 0 (at least ref clock). 00432 * - DBMs have the same dimensions 00433 * - unpackBuffer != NULL and is a raw_t[dim*dim] 00434 */ 00435 void dbm_convexUnionWithMinDBM(raw_t *dbm, cindex_t dim, 00436 mingraph_t minDBM, raw_t *unpackBuffer); 00437 00438 00439 /** Simple type to allow for statistics on the different internal 00440 * formats used. The format are not user controllable and should 00441 * not be read from outside. For the tuple representation, it is 00442 * not said here if it is (i,j,c_ij) or a bunch of c_ij and (i,j). 00443 */ 00444 typedef enum 00445 { 00446 dbm_MINDBM_TRIVIAL = 0, /**< only clock ref, dim == 1 */ 00447 dbm_MINDBM_COPY32, /**< 32 bits, dbm copy without diagonal */ 00448 dbm_MINDBM_BITMATRIX32, /**< 32 bits, c_ij and a bit matrix */ 00449 dbm_MINDBM_TUPLES32, /**< 32 bits, c_ij and tuples (i,j) */ 00450 dbm_MINDBM_COPY16, /**< 16 bits, dbm copy without diagonal */ 00451 dbm_MINDBM_BITMATRIX16, /**< 16 bits, c_ij and a bit matrix */ 00452 dbm_MINDBM_TUPLES16, /**< 16 bits, c_ij and tuples (i,j) */ 00453 dbm_MINDBM_ERROR /**< should never be the case */ 00454 } 00455 representationOfMinDBM_t; 00456 00457 00458 /** @return the type of the internal format used. 00459 * @param minDBM: minimal representation (without offset) 00460 * to read. 00461 */ 00462 representationOfMinDBM_t dbm_getRepresentationType(mingraph_t minDBM); 00463 00464 00465 00466 #ifdef __cplusplus 00467 } 00468 #endif 00469 00470 #endif /* INCLUDE_DBM_MINGRAPH_H */