this repo has no description
1/* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */ 2/* 3 * Main authors: 4 * Christian Schulte <schulte@gecode.org> 5 * 6 * Copyright: 7 * Christian Schulte, 2004 8 * 9 * This file is part of Gecode, the generic constraint 10 * development environment: 11 * http://www.gecode.org 12 * 13 * Permission is hereby granted, free of charge, to any person obtaining 14 * a copy of this software and associated documentation files (the 15 * "Software"), to deal in the Software without restriction, including 16 * without limitation the rights to use, copy, modify, merge, publish, 17 * distribute, sublicense, and/or sell copies of the Software, and to 18 * permit persons to whom the Software is furnished to do so, subject to 19 * the following conditions: 20 * 21 * The above copyright notice and this permission notice shall be 22 * included in all copies or substantial portions of the Software. 23 * 24 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 25 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 26 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 27 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 28 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 29 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 30 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 31 * 32 */ 33 34#include <sstream> 35 36namespace Gecode { 37 38 /** 39 * \brief Data stored for a %DFA 40 * 41 */ 42 class DFA::DFAI : public SharedHandle::Object { 43 public: 44 /// Number of states 45 int n_states; 46 /// Number of symbols 47 unsigned int n_symbols; 48 /// Number of transitions 49 int n_trans; 50 /// Maximal degree (in-degree and out-degree of any state) and maximal number of transitions per symbol 51 unsigned int max_degree; 52 /// First final state 53 int final_fst; 54 /// Last final state 55 int final_lst; 56 /// Hash key 57 std::size_t key; 58 /// The transitions 59 Transition* trans; 60 /// Specification of transition range 61 class HashEntry { 62 public: 63 int symbol; ///< Symbol 64 const Transition* fst; ///< First transition for the symbol 65 const Transition* lst; ///< Last transition for the symbol 66 }; 67 /// The transition hash table by symbol 68 HashEntry* table; 69 /// Size of table (as binary logarithm) 70 int n_log; 71 /// Fill hash table 72 void fill(void); 73 /// Initialize automaton implementation with \a nt transitions 74 DFAI(int nt); 75 /// Initialize automaton implementation as empty 76 GECODE_INT_EXPORT DFAI(void); 77 /// Delete automaton implemenentation 78 virtual ~DFAI(void); 79 }; 80 81 forceinline 82 DFA::DFAI::DFAI(int nt) 83 : trans(nt == 0 ? nullptr : heap.alloc<Transition>(nt)) {} 84 85 forceinline 86 DFA::DFAI::~DFAI(void) { 87 if (n_trans > 0) 88 heap.rfree(trans); 89 heap.rfree(table); 90 } 91 92 forceinline void 93 DFA::DFAI::fill(void) { 94 key = static_cast<std::size_t>(n_states); 95 cmb_hash(key, n_trans); 96 cmb_hash(key, n_symbols); 97 cmb_hash(key, final_fst); 98 cmb_hash(key, final_lst); 99 // Compute smallest logarithm larger than n_symbols 100 n_log = 1; 101 while (n_symbols >= static_cast<unsigned int>(1<<n_log)) 102 n_log++; 103 // Allocate memory 104 table = heap.alloc<HashEntry>(1<<n_log); 105 // Initialize table 106 for (int i=(1<<n_log); i--; ) 107 table[i].fst = table[i].lst = nullptr; 108 int mask = (1 << n_log) - 1; 109 // Enter transitions to table 110 for (int i = 0; i<n_trans; ) { 111 cmb_hash(key, trans[i].i_state); 112 cmb_hash(key, trans[i].symbol); 113 cmb_hash(key, trans[i].o_state); 114 int s = trans[i].symbol; 115 Transition* fst = &trans[i]; 116 i++; 117 while ((i<n_trans) && (trans[i].symbol == s)) 118 i++; 119 Transition* lst = &trans[i]; 120 // Enter with linear collision resolution 121 int p = s & mask; 122 while (table[p].fst != nullptr) 123 p = (p+1) & mask; 124 table[p].symbol = s; 125 table[p].fst = fst; 126 table[p].lst = lst; 127 } 128 } 129 130 forceinline 131 DFA::DFA(void) {} 132 133 134 forceinline 135 DFA::DFA(const DFA& d) 136 : SharedHandle(d) {} 137 138 forceinline int 139 DFA::n_states(void) const { 140 const DFAI* d = static_cast<DFAI*>(object()); 141 return (d == nullptr) ? 1 : d->n_states; 142 } 143 144 forceinline unsigned int 145 DFA::n_symbols(void) const { 146 const DFAI* d = static_cast<DFAI*>(object()); 147 return (d == nullptr) ? 0 : d->n_symbols; 148 } 149 150 forceinline int 151 DFA::n_transitions(void) const { 152 const DFAI* d = static_cast<DFAI*>(object()); 153 return (d == nullptr) ? 0 : d->n_trans; 154 } 155 156 forceinline unsigned int 157 DFA::max_degree(void) const { 158 const DFAI* d = static_cast<DFAI*>(object()); 159 return (d == nullptr) ? 0 : d->max_degree; 160 } 161 162 forceinline int 163 DFA::final_fst(void) const { 164 const DFAI* d = static_cast<DFAI*>(object()); 165 return (d == nullptr) ? 0 : d->final_fst; 166 } 167 168 forceinline int 169 DFA::final_lst(void) const { 170 const DFAI* d = static_cast<DFAI*>(object()); 171 return (d == nullptr) ? 0 : d->final_lst; 172 } 173 174 forceinline int 175 DFA::symbol_min(void) const { 176 const DFAI* d = static_cast<DFAI*>(object()); 177 return ((d != nullptr) && (d->n_trans > 0)) ? 178 d->trans[0].symbol : Int::Limits::min; 179 } 180 181 forceinline int 182 DFA::symbol_max(void) const { 183 const DFAI* d = static_cast<DFAI*>(object()); 184 return ((d != nullptr) && (d->n_trans > 0)) ? 185 d->trans[d->n_trans-1].symbol : Int::Limits::max; 186 } 187 188 forceinline std::size_t 189 DFA::hash(void) const { 190 const DFAI* d = static_cast<DFAI*>(object()); 191 return (d != nullptr) ? d->key : 0; 192 } 193 194 195 /* 196 * Constructing transitions 197 * 198 */ 199 200 forceinline 201 DFA::Transition::Transition(void) {} 202 203 forceinline 204 DFA::Transition::Transition(int i_state0, int symbol0, int o_state0) 205 : i_state(i_state0), symbol(symbol0), o_state(o_state0) {} 206 207 /* 208 * Iterating over all transitions 209 * 210 */ 211 212 forceinline 213 DFA::Transitions::Transitions(const DFA& d) { 214 const DFAI* o = static_cast<DFAI*>(d.object()); 215 if (o != nullptr) { 216 c_trans = &o->trans[0]; 217 e_trans = c_trans+o->n_trans; 218 } else { 219 c_trans = e_trans = nullptr; 220 } 221 } 222 223 forceinline 224 DFA::Transitions::Transitions(const DFA& d, int n) { 225 const DFAI* o = static_cast<DFAI*>(d.object()); 226 if (o != nullptr) { 227 int mask = (1<<o->n_log)-1; 228 int p = n & mask; 229 while ((o->table[p].fst != nullptr) && (o->table[p].symbol != n)) 230 p = (p+1) & mask; 231 c_trans = o->table[p].fst; 232 e_trans = o->table[p].lst; 233 } else { 234 c_trans = e_trans = nullptr; 235 } 236 } 237 238 forceinline bool 239 DFA::Transitions::operator ()(void) const { 240 return c_trans < e_trans; 241 } 242 243 forceinline void 244 DFA::Transitions::operator ++(void) { 245 c_trans++; 246 } 247 248 forceinline int 249 DFA::Transitions::i_state(void) const { 250 return c_trans->i_state; 251 } 252 253 forceinline int 254 DFA::Transitions::symbol(void) const { 255 return c_trans->symbol; 256 } 257 258 forceinline int 259 DFA::Transitions::o_state(void) const { 260 return c_trans->o_state; 261 } 262 263 /* 264 * Iterating over symbols 265 * 266 */ 267 268 forceinline 269 DFA::Symbols::Symbols(const DFA& d) { 270 const DFAI* o = static_cast<DFAI*>(d.object()); 271 if (o != nullptr) { 272 c_trans = &o->trans[0]; 273 e_trans = c_trans+o->n_trans; 274 } else { 275 c_trans = e_trans = nullptr; 276 } 277 } 278 279 forceinline bool 280 DFA::Symbols::operator ()(void) const { 281 return c_trans < e_trans; 282 } 283 284 forceinline void 285 DFA::Symbols::operator ++(void) { 286 int s = c_trans->symbol; 287 do { 288 c_trans++; 289 } while ((c_trans < e_trans) && (s == c_trans->symbol)); 290 } 291 292 forceinline int 293 DFA::Symbols::val(void) const { 294 return c_trans->symbol; 295 } 296 297 298 template<class Char, class Traits> 299 std::basic_ostream<Char,Traits>& 300 operator <<(std::basic_ostream<Char,Traits>& os, const DFA& d) { 301 std::basic_ostringstream<Char,Traits> st; 302 st.copyfmt(os); st.width(0); 303 st << "Start state: 0" << std::endl 304 << "States: 0..." << d.n_states()-1 << std::endl 305 << "Transitions:"; 306 for (int s = 0; s < static_cast<int>(d.n_states()); s++) { 307 DFA::Transitions t(d); 308 int n = 0; 309 while (t()) { 310 if (t.i_state() == s) { 311 if ((n % 4) == 0) 312 st << std::endl << "\t"; 313 st << "[" << t.i_state() << "]" 314 << "- " << t.symbol() << " >" 315 << "[" << t.o_state() << "] "; 316 ++n; 317 } 318 ++t; 319 } 320 } 321 st << std::endl << "Final states: " 322 << std::endl 323 << "\t[" << d.final_fst() << "] ... [" 324 << d.final_lst()-1 << "]" 325 << std::endl; 326 return os << st.str(); 327 } 328 329 forceinline bool 330 DFA::operator ==(const DFA& d) const { 331 if (n_states() != d.n_states()) 332 return false; 333 if (n_transitions() != d.n_transitions()) 334 return false; 335 if (n_symbols() != d.n_symbols()) 336 return false; 337 if (max_degree() != d.max_degree()) 338 return false; 339 if (final_fst() != d.final_fst()) 340 return false; 341 if (final_lst() != d.final_lst()) 342 return false; 343 return equal(d); 344 } 345 346 forceinline bool 347 DFA::operator !=(const DFA& d) const { 348 return !(*this == d); 349 } 350 351 352} 353 354 355// STATISTICS: int-prop 356