/* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */ /* * Main authors: * Linnea Ingmar * Mikael Lagerkvist * Christian Schulte * * Copyright: * Linnea Ingmar, 2017 * Mikael Lagerkvist, 2007 * Christian Schulte, 2017 * * This file is part of Gecode, the generic constraint * development environment: * http://www.gecode.org * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * */ #include #include namespace Gecode { namespace Int { namespace Extensional { /// Import tuple type typedef ::Gecode::TupleSet::Tuple Tuple; /// Tuple comparison class TupleCompare { private: /// The arity of the tuples to compare int arity; public: /// Initialize with arity \a a TupleCompare(int a); /// Comparison of tuples \a a and \a b bool operator ()(const Tuple& a, const Tuple& b); }; /// Tuple comparison by position class PosCompare { private: /// The position of the tuples to compare int p; public: /// Initialize with position \a p PosCompare(int p); /// Comparison of tuples \a a and \a b bool operator ()(const Tuple& a, const Tuple& b); }; forceinline TupleCompare::TupleCompare(int a) : arity(a) {} forceinline bool TupleCompare::operator ()(const Tuple& a, const Tuple& b) { for (int i=0; i b[i]) return false; return false; } forceinline PosCompare::PosCompare(int p0) : p(p0) {} forceinline bool PosCompare::operator ()(const Tuple& a, const Tuple& b) { return a[p] < b[p]; } }}} namespace Gecode { /* * Tuple set data * */ void TupleSet::Data::finalize(void) { using namespace Int::Extensional; assert(!finalized()); // Mark as finalized n_free = -1; // Initialization if (n_tuples == 0) { heap.rfree(td); td=nullptr; return; } // Compact and copy data Region r; // Set up tuple pointers Tuple* tuple = r.alloc(n_tuples); { for (int t=0; t(n_tuples); cmb_hash(key, arity); // Copy into now possibly smaller area int* new_td = heap.alloc(n_tuples*arity); for (int t=0; t(n_tuples)); // Compute range information { /* * Pass one: compute how many values and ranges are needed */ // How many values unsigned int n_vals = 0U; // How many ranges unsigned int n_ranges = 0U; for (int a=0; a(n_ranges); // Allocate and initialize memory for supports BitSetData* cs = support = heap.alloc(n_words * n_vals); for (unsigned int i=0; i vd[a].r[j].max) j++; set(const_cast (vd[a].r[j].supports(n_words,tuple[i][a])), tuple2idx(tuple[i])); } } } assert(cs == support + n_words * n_vals); assert(cr == range + n_ranges); } if ((min < Int::Limits::min) || (max > Int::Limits::max)) throw Int::OutOfLimits("TupleSet::finalize()"); assert(finalized()); } void TupleSet::Data::resize(void) { assert(n_free == 0); int n = static_cast(1+n_tuples*1.5); td = heap.realloc(td, n_tuples * arity, n * arity); n_free = n - n_tuples; } TupleSet::Data::~Data(void) { heap.rfree(td); heap.rfree(vd); heap.rfree(range); heap.rfree(support); } /* * Tuple set * */ TupleSet::TupleSet(int a) : SharedHandle(new Data(a)) {} void TupleSet::init(int a) { object(new Data(a)); } TupleSet::TupleSet(const TupleSet& ts) : SharedHandle(ts) {} TupleSet& TupleSet::operator =(const TupleSet& ts) { (void) SharedHandle::operator =(ts); return *this; } TupleSet::TupleSet(int a, const Gecode::DFA& dfa) { /// Edges in layered graph struct Edge { int i_state; ///< Number of in-state int o_state; ///< Number of out-state }; /// State in layered graph struct State { int i_deg; ///< In-degree (number of incoming arcs) int o_deg; ///< Out-degree (number of outgoing arcs) int n_tuples; ///< Number of tuples int* tuples; ///< The tuples }; /// Support for a value struct Support { int val; ///< Supported value int n_edges; ///< Number of supporting edges Edge* edges; ///< Supporting edges }; /// Layer in layered graph struct Layer { State* states; ///< States Support* supports; ///< Supported values int n_supports; ///< Number of supported values }; // Initialize object(new Data(a)); Region r; // Number of states int max_states = dfa.n_states(); // Allocate memory for all layers and states Layer* layers = r.alloc(a+1); State* states = r.alloc(max_states*(a+1)); for (int i=0; i(1); assert(layers[0].states[0].tuples != nullptr); // Allocate temporary memory for edges and supports Edge* edges = r.alloc(dfa.max_degree()); Support* supports = r.alloc(dfa.n_symbols()); // Forward pass: accumulate for (int i=0; i(n_edges) <= dfa.max_degree()); } // Found a support for the value if (n_edges > 0) { Support& support = supports[n_supports++]; support.val = s.val(); support.n_edges = n_edges; support.edges = Heap::copy(r.alloc(n_edges),edges,n_edges); } } // Create supports if (n_supports > 0) { layers[i].supports = Heap::copy(r.alloc(n_supports),supports,n_supports); layers[i].n_supports = n_supports; } else { finalize(); return; } } // Mark final states as being reachable for (int s=dfa.final_fst(); s 0); s.edges[k] = s.edges[--s.n_edges]; } } // Lost support if (s.n_edges == 0) layers[i].supports[j] = layers[i].supports[--layers[i].n_supports]; } if (layers[i].n_supports == 0U) { finalize(); return; } } // Generate tuples for (int i=0; i((i+1)*n_tuples); layers[i+1].states[o_state].n_tuples = 0; } int n = layers[i+1].states[o_state].n_tuples; // Write tuples for (int t=0; t < layers[i].states[i_state].n_tuples; t++) { // Copy the first i number of digits from the previous layer Heap::copy(&layers[i+1].states[o_state].tuples[n*(i+1)+t*(i+1)], &layers[i].states[i_state].tuples[t*i], i); // Write the last digit layers[i+1].states[o_state].tuples[n*(i+1)+t*(i+1)+i] = s.val; } layers[i+1].states[o_state].n_tuples += layers[i].states[i_state].n_tuples; } } } // Add tuples to tuple set for (int s = dfa.final_fst(); s < dfa.final_lst(); s++) { for (int i=0; i