/* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */ /* * Main authors: * Christian Schulte * * Copyright: * Christian Schulte, 2016 * * 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. * */ namespace Gecode { /** * \brief Which events to trace * \ingroup TaskTrace */ enum TraceEvent { /// \name Events for view tracers //@{ TE_INIT = 1 << 0, ///< Trace init events TE_PRUNE = 1 << 1, ///< Trace prune events TE_FIX = 1 << 2, ///< Trace fixpoint events TE_FAIL = 1 << 3, ///< Trace fail events TE_DONE = 1 << 4, ///< Trace done events //@} /// \name Events for general tracers TE_PROPAGATE = 1 << 5, ///< Trace propagator executions TE_COMMIT = 1 << 6, ///< Trace commit operations by branchers TE_POST = 1 << 7 ///< Trace propagator posting }; /** * \brief Propagator for recording view trace information * \ingroup TaskTrace */ template class ViewTraceRecorder : public Propagator { public: /// The corresponding duplicate view type typedef typename TraceTraits::TraceView TraceView; /// The corresponding trace delta type typedef typename TraceTraits::TraceDelta TraceDelta; /// The corresponding slack value type typedef typename TraceTraits::SlackValue SlackValue; /// Collection of slack values class Slack { template friend class ViewTraceRecorder; protected: /// The initial slack value SlackValue i; /// Slack value at previous event (fixpoint or init) SlackValue p; /// Current slack value SlackValue c; public: /// Return initial slack value SlackValue initial(void) const; /// Return previous slack value SlackValue previous(void) const; /// Return current slack value SlackValue current(void) const; }; protected: /// Advisor with index information class Idx : public Advisor { protected: /// Index information int _idx; public: /// Constructor for creation Idx(Space& home, Propagator& p, Council& c, int i); /// Constructor for cloning \a a Idx(Space& home, Idx& a); /// Get index of view int idx(void) const; }; /// Duplicate views (old information) ViewArray o; /// Original views (new information) ViewArray n; /// The advisor council Council c; /// The trace filter TraceFilter tf; /// Which events to trace int te; /// The actual tracer ViewTracer& t; /// Slack information Slack s; /// Constructor for cloning \a p ViewTraceRecorder(Space& home, ViewTraceRecorder& p); public: /// Constructor for creation ViewTraceRecorder(Home home, ViewArray& x, TraceFilter tf, int te, ViewTracer& t); /// Copy propagator during cloning virtual Propagator* copy(Space& home); /// Cost function (record so that propagator runs last) virtual PropCost cost(const Space& home, const ModEventDelta& med) const; /// Schedule function virtual void reschedule(Space& home); /// Give advice to propagator virtual ExecStatus advise(Space& home, Advisor& a, const Delta& d); /// Perform propagation virtual ExecStatus propagate(Space& home, const ModEventDelta& med); /// Delete propagator and return its size virtual size_t dispose(Space& home); /// Post recorder propagator static ExecStatus post(Home home, ViewArray& x, TraceFilter tf, int te, ViewTracer& t); /// \name Trace information //@{ /// Return variable being traced at position \a i const typename View::VarType operator [](int i) const; /// Return number of variables being traced int size(void) const; /// Provide access to slack information const Slack& slack(void) const; //@} }; /** * \brief Propagator for recording trace information * * This propagator is actually never run. It only provides access * to information needed for tracing. * * \ingroup TaskTrace */ class TraceRecorder : public Propagator { public: /// The trace filter TraceFilter tf; /// Which events to trace int te; /// The actual tracer Tracer& t; /// Constructor for cloning \a p TraceRecorder(Space& home, TraceRecorder& p); public: /// Constructor for creation TraceRecorder(Home home, TraceFilter tf, int te, Tracer& t); /// Copy propagator during cloning virtual Propagator* copy(Space& home); /// Cost function (record so that propagator runs last) virtual PropCost cost(const Space& home, const ModEventDelta& med) const; /// Schedule function virtual void reschedule(Space& home); /// Perform propagation virtual ExecStatus propagate(Space& home, const ModEventDelta& med); /// Delete propagator and return its size virtual size_t dispose(Space& home); /// Post propagator static ExecStatus post(Home home, TraceFilter tf, int te, Tracer& t); /// \name Trace information //@{ /// Return trace filter const TraceFilter& filter(void) const; /// Which events to trace int events(void) const; /// Return tracer Tracer& tracer(void) const; //@} }; /* * Functions for trace support * */ template forceinline const typename View::VarType ViewTraceRecorder::operator [](int i) const { const typename View::VarType x(n[i].varimp()); return x; } template forceinline int ViewTraceRecorder::size(void) const { return n.size(); } template forceinline const typename ViewTraceRecorder::Slack& ViewTraceRecorder::slack(void) const { return s; } /* * Functions for access to slack * */ template forceinline typename ViewTraceRecorder::SlackValue ViewTraceRecorder::Slack::initial(void) const { return i; } template forceinline typename ViewTraceRecorder::SlackValue ViewTraceRecorder::Slack::previous(void) const { return p; } template forceinline typename ViewTraceRecorder::SlackValue ViewTraceRecorder::Slack::current(void) const { return c; } /* * Advisor for tracer * */ template forceinline ViewTraceRecorder::Idx::Idx(Space& home, Propagator& p, Council& c, int i) : Advisor(home,p,c), _idx(i) {} template forceinline ViewTraceRecorder::Idx::Idx(Space& home, Idx& a) : Advisor(home,a), _idx(a._idx) { } template forceinline int ViewTraceRecorder::Idx::idx(void) const { return _idx; } /* * Posting of tracer propagator * */ template forceinline ViewTraceRecorder::ViewTraceRecorder(Home home, ViewArray& x, TraceFilter tf0, int te0, ViewTracer& t0) : Propagator(home), o(home,x.size()), n(x), c(home), tf(tf0), te(te0), t(t0) { home.notice(*this, AP_VIEW_TRACE); home.notice(*this, AP_DISPOSE); for (int i=0; i forceinline ExecStatus ViewTraceRecorder::post(Home home, ViewArray& x, TraceFilter tf, int te, ViewTracer& t) { if ((x.size() > 0) && (te & (TE_INIT | TE_PRUNE | TE_FIX | TE_FAIL | TE_DONE))) (void) new (home) ViewTraceRecorder(home,x,tf,te,t); return ES_OK; } /* * Propagation for trace recorder * */ template forceinline ViewTraceRecorder::ViewTraceRecorder(Space& home, ViewTraceRecorder& p) : Propagator(home,p), tf(p.tf), te(p.te), t(p.t), s(p.s) { o.update(home, p.o); n.update(home, p.n); c.update(home, p.c); } template Propagator* ViewTraceRecorder::copy(Space& home) { return new (home) ViewTraceRecorder(home, *this); } template inline size_t ViewTraceRecorder::dispose(Space& home) { home.ignore(*this, AP_VIEW_TRACE); home.ignore(*this, AP_DISPOSE); tf.~TraceFilter(); // Cancel remaining advisors for (Advisors as(c); as(); ++as) n[as.advisor().idx()].cancel(home,as.advisor()); c.dispose(home); (void) Propagator::dispose(home); return sizeof(*this); } template PropCost ViewTraceRecorder::cost(const Space&, const ModEventDelta&) const { return PropCost::record(); } template void ViewTraceRecorder::reschedule(Space& home) { View::schedule(home,*this,ME_GEN_ASSIGNED); } template ExecStatus ViewTraceRecorder::advise(Space& home, Advisor& _a, const Delta& d) { Idx& a = static_cast(_a); int i = a.idx(); if (((te & TE_PRUNE) != 0) && !disabled() && tf(a(home)) ) { TraceDelta td(o[i],n[i],d); t._prune(home,*this,a(home),i,td); } o[i].prune(home,n[i],d); if (n[a.idx()].assigned()) a.dispose(home,c); return ES_NOFIX; } template ExecStatus ViewTraceRecorder::propagate(Space& home, const ModEventDelta&) { s.c = TraceView::slack(n[0]); for (int i=1; i