include/geometry/simulator.h
author Dmitriy Morozov <morozov@cs.duke.edu>
Fri, 29 Feb 2008 15:46:12 -0500
branchar
changeset 80 f236c7d659d0
parent 68 8f2610103946
child 87 2c2e2f3b5d15
permissions -rw-r--r--
Using two simulators in ARVineyard (one for simplices and one for trajectories) - Fixes #c66 - Simulator::reached_infinity() examines the queue instead of keeping state in a variable

#ifndef __SIMULATOR_H__
#define __SIMULATOR_H__

#include "utilities/eventqueue.h"

template<class Comparison>  						class IndirectComparison;

/**
 * Simulator class. Keeps a queue of events. Infinity is reached if the Event 
 * at the front of the queue has an empty root stack. Keeps track of current time, 
 * Event addition, and processes events one by one. Degeneracies are handled by 
 * assuming that the FunctionKernel::Function responsible for the event must be 
 * positive before the Event occurs.
 *
 * \ingroup kinetic
 */
template<class FuncKernel_, template<class Event> class EventComparison_ = std::less>
class Simulator
{
	public:
		typedef						FuncKernel_								    FunctionKernel;
		typedef						typename FunctionKernel::Function	        Function;
		typedef						typename FunctionKernel::RootStack		    RootStack;
		typedef						typename FunctionKernel::RootType			RootType;
		typedef						RootType									Time;

		class Event;
		typedef						EventComparison_<Event>						EventComparison;
		typedef						EventQueue<Event*, IndirectComparison<EventComparison> >			
																				EventQueue;
		typedef						typename EventQueue::iterator				Key;
		typedef						typename EventQueue::const_iterator			const_Key;


									Simulator(Time start = FunctionKernel::root(0)):
										current_(start)         				{}


		template<class Event_> 
		Key							add(const Event_& e);
		template<class Event_> 
		Key							add(const Function& f, const Event_& e);
		void						process();
		void						update(Key k, const Function& f);
		
		void						remove(Key k)								{ queue_.remove(k); }
		Key							null_key() 									{ return queue_.end(); }

		Time						current_time() const						{ return current_; }
		Time						audit_time() const;
		bool						reached_infinity() const					{ return queue_.empty() || (*queue_.top())->root_stack().empty(); }
        
        Event*                      top() const                                 { return *(queue_.top()); }
        unsigned                    size() const                                { return queue_.size(); }

		std::ostream&				operator<<(std::ostream& out) const;

	private:
		void						update(Key i);

	private:
		Time						current_;
		EventQueue					queue_;
};


/**
 * Base class for events. Stores a root stack, subclasses need to define process(). 
 * Event with an empty root stack compares greater than any other Event, 
 * pushing those events to the end of the queue.
 */
template<class FuncKernel_, template<class Event> class EventComparison_>
class Simulator<FuncKernel_, EventComparison_>::Event
{
	public:
		typedef						FuncKernel_									FunctionKernel;
		typedef						typename FunctionKernel::RootStack		    RootStack;

        /// process() is called when the event is at the top of the queue 
        /// in the simulator.
		/// Returns true if the event needs to remain in the Simulator 
		/// (top of the root_stack() will be used for new time).
		virtual	bool				process(Simulator* s) const					=0;
		
		RootStack&					root_stack()								{ return root_stack_; }
		const RootStack&			root_stack() const							{ return root_stack_; }

		bool						operator<(const Event& e) const				
		{ 
			if (root_stack().empty())
				return false;
			else if (e.root_stack().empty())
				return true;
			else
				return root_stack().top() < e.root_stack().top();
		}

		virtual std::ostream&		operator<<(std::ostream& out) const			
        { 
            out << "Event with " << root_stack_.size() << " roots"; 
            if (!root_stack_.empty()) out << "; top root: " << root_stack_.top();
            out << ", ";
            return out;
        }

	private:
		RootStack					root_stack_;
};

/**
 * Compares elements pointed at by its arguments using the provided Comparison_ 
 * (which must not take any arguments during construction).
 */
template<class Comparison_>
class IndirectComparison: public std::binary_function<const typename Comparison_::first_argument_type*, 
													  const typename Comparison_::second_argument_type*, 
													  bool>
{
	public:
		typedef						Comparison_											Comparison;
		typedef						const typename Comparison::first_argument_type*		first_argument_type;
		typedef						const typename Comparison::second_argument_type*	second_argument_type;

		bool						operator()(first_argument_type e1, second_argument_type e2) const
		{ return Comparison()(*e1, *e2); }
};

#include "simulator.hpp"

#endif // __SIMULATOR_H__