|  |  | @ -1,4 +1,4 @@ | 
			
		
	
		
			
				
					|  |  |  | /**  | 
			
		
	
		
			
				
					|  |  |  | /** | 
			
		
	
		
			
				
					|  |  |  |  * @file:   ExpressionEvaluation.h | 
			
		
	
		
			
				
					|  |  |  |  * @author: Sebastian Junges | 
			
		
	
		
			
				
					|  |  |  |  * | 
			
		
	
	
		
			
				
					|  |  | @ -20,73 +20,74 @@ | 
			
		
	
		
			
				
					|  |  |  | #include "src/storage/parameters.h" | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  | namespace storm { | 
			
		
	
		
			
				
					|  |  |  | namespace expressions { | 
			
		
	
		
			
				
					|  |  |  | 	 | 
			
		
	
		
			
				
					|  |  |  | 	template<typename T> | 
			
		
	
		
			
				
					|  |  |  | 	struct StateType | 
			
		
	
		
			
				
					|  |  |  | 	{ | 
			
		
	
		
			
				
					|  |  |  | 		typedef int type; | 
			
		
	
		
			
				
					|  |  |  | 	}; | 
			
		
	
		
			
				
					|  |  |  | 	 | 
			
		
	
		
			
				
					|  |  |  |     namespace expressions { | 
			
		
	
		
			
				
					|  |  |  |          | 
			
		
	
		
			
				
					|  |  |  |         template<typename T> | 
			
		
	
		
			
				
					|  |  |  |         struct StateType | 
			
		
	
		
			
				
					|  |  |  |         { | 
			
		
	
		
			
				
					|  |  |  |             typedef int type; | 
			
		
	
		
			
				
					|  |  |  |         }; | 
			
		
	
		
			
				
					|  |  |  |          | 
			
		
	
		
			
				
					|  |  |  | #ifdef PARAMETRIC_SYSTEMS | 
			
		
	
		
			
				
					|  |  |  | 	template<> | 
			
		
	
		
			
				
					|  |  |  | 	struct StateType<Polynomial> | 
			
		
	
		
			
				
					|  |  |  | 	{ | 
			
		
	
		
			
				
					|  |  |  | 		typedef std::map<std::string, carl::Variable> type; | 
			
		
	
		
			
				
					|  |  |  | 	}; | 
			
		
	
		
			
				
					|  |  |  | 	 | 
			
		
	
		
			
				
					|  |  |  | 	template<> | 
			
		
	
		
			
				
					|  |  |  | 	struct StateType<RationalFunction> | 
			
		
	
		
			
				
					|  |  |  | 	{ | 
			
		
	
		
			
				
					|  |  |  | 		typedef std::map<std::string, carl::Variable> type; | 
			
		
	
		
			
				
					|  |  |  | 	}; | 
			
		
	
		
			
				
					|  |  |  |      | 
			
		
	
		
			
				
					|  |  |  |     struct ExpressionEvaluationSettings { | 
			
		
	
		
			
				
					|  |  |  |         static const bool useFactorizedPolynomials = false; | 
			
		
	
		
			
				
					|  |  |  |     }; | 
			
		
	
		
			
				
					|  |  |  |      | 
			
		
	
		
			
				
					|  |  |  |     struct FactorizedPolynomialsEvaluationSettings : ExpressionEvaluationSettings { | 
			
		
	
		
			
				
					|  |  |  |         static const bool useFactorizedPolynomials = true; | 
			
		
	
		
			
				
					|  |  |  |     }; | 
			
		
	
		
			
				
					|  |  |  |         template<> | 
			
		
	
		
			
				
					|  |  |  |         struct StateType<Polynomial> | 
			
		
	
		
			
				
					|  |  |  |         { | 
			
		
	
		
			
				
					|  |  |  |             typedef std::map<std::string, carl::Variable> type; | 
			
		
	
		
			
				
					|  |  |  |         }; | 
			
		
	
		
			
				
					|  |  |  |          | 
			
		
	
		
			
				
					|  |  |  |         template<> | 
			
		
	
		
			
				
					|  |  |  |         struct StateType<RationalFunction> | 
			
		
	
		
			
				
					|  |  |  |         { | 
			
		
	
		
			
				
					|  |  |  |             typedef std::map<std::string, carl::Variable> type; | 
			
		
	
		
			
				
					|  |  |  |         }; | 
			
		
	
		
			
				
					|  |  |  | #endif | 
			
		
	
		
			
				
					|  |  |  | 		 | 
			
		
	
		
			
				
					|  |  |  | 	template<typename T, typename S, typename X = FactorizedPolynomialsEvaluationSettings> | 
			
		
	
		
			
				
					|  |  |  | 	class ExpressionEvaluationVisitor : public ExpressionVisitor | 
			
		
	
		
			
				
					|  |  |  | 	{ | 
			
		
	
		
			
				
					|  |  |  |         template<typename T, typename S> | 
			
		
	
		
			
				
					|  |  |  |         class ExpressionEvaluationVisitor : public ExpressionVisitor | 
			
		
	
		
			
				
					|  |  |  |         { | 
			
		
	
		
			
				
					|  |  |  | 		public: | 
			
		
	
		
			
				
					|  |  |  | 			ExpressionEvaluationVisitor(S* sharedState) | 
			
		
	
		
			
				
					|  |  |  | 			: mSharedState(sharedState), cache(new carl::Cache<carl::PolynomialFactorizationPair<RawPolynomial>>()) | 
			
		
	
		
			
				
					|  |  |  | 			{ | 
			
		
	
		
			
				
					|  |  |  | 				 | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  | 			} | 
			
		
	
		
			
				
					|  |  |  | 			 | 
			
		
	
		
			
				
					|  |  |  | 			virtual ~ExpressionEvaluationVisitor() { | 
			
		
	
		
			
				
					|  |  |  |              | 
			
		
	
		
			
				
					|  |  |  |             ExpressionEvaluationVisitor(S* sharedState, std::shared_ptr<carl::Cache<carl::PolynomialFactorizationPair<RawPolynomial>>> cache) | 
			
		
	
		
			
				
					|  |  |  |             : mSharedState(sharedState), cache(cache) | 
			
		
	
		
			
				
					|  |  |  |             { | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |              | 
			
		
	
		
			
				
					|  |  |  |              | 
			
		
	
		
			
				
					|  |  |  | 			virtual ~ExpressionEvaluationVisitor() { | 
			
		
	
		
			
				
					|  |  |  |                  | 
			
		
	
		
			
				
					|  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  | 			 | 
			
		
	
		
			
				
					|  |  |  | 			virtual void visit(IfThenElseExpression const* expression)  | 
			
		
	
		
			
				
					|  |  |  | 			virtual void visit(IfThenElseExpression const* expression) | 
			
		
	
		
			
				
					|  |  |  | 			{ | 
			
		
	
		
			
				
					|  |  |  | 				std::cout << "ite" << std::endl; | 
			
		
	
		
			
				
					|  |  |  | 				 | 
			
		
	
		
			
				
					|  |  |  | 			} | 
			
		
	
		
			
				
					|  |  |  | 		 | 
			
		
	
		
			
				
					|  |  |  |             virtual void visit(BinaryBooleanFunctionExpression const* expression)  | 
			
		
	
		
			
				
					|  |  |  |              | 
			
		
	
		
			
				
					|  |  |  |             virtual void visit(BinaryBooleanFunctionExpression const* expression) | 
			
		
	
		
			
				
					|  |  |  | 			{ | 
			
		
	
		
			
				
					|  |  |  | 				std::cout << "bbf" << std::endl; | 
			
		
	
		
			
				
					|  |  |  | 			} | 
			
		
	
		
			
				
					|  |  |  |             virtual void visit(BinaryNumericalFunctionExpression const* expression)  | 
			
		
	
		
			
				
					|  |  |  |             virtual void visit(BinaryNumericalFunctionExpression const* expression) | 
			
		
	
		
			
				
					|  |  |  | 			{ | 
			
		
	
		
			
				
					|  |  |  | 				ExpressionEvaluationVisitor* visitor = new ExpressionEvaluationVisitor(mSharedState); | 
			
		
	
		
			
				
					|  |  |  | 				ExpressionEvaluationVisitor* visitor = new ExpressionEvaluationVisitor(mSharedState, this->cache); | 
			
		
	
		
			
				
					|  |  |  | 				expression->getFirstOperand()->accept(visitor); | 
			
		
	
		
			
				
					|  |  |  | 				mValue = visitor->value(); | 
			
		
	
		
			
				
					|  |  |  | 				expression->getSecondOperand()->accept(visitor);				 | 
			
		
	
		
			
				
					|  |  |  | 				expression->getSecondOperand()->accept(visitor); | 
			
		
	
		
			
				
					|  |  |  | 				switch(expression->getOperatorType()) | 
			
		
	
		
			
				
					|  |  |  | 				{ | 
			
		
	
		
			
				
					|  |  |  | 					case BinaryNumericalFunctionExpression::OperatorType::Plus: | 
			
		
	
		
			
				
					|  |  |  | 						mValue += visitor->value(); | 
			
		
	
		
			
				
					|  |  |  | 						break; | 
			
		
	
		
			
				
					|  |  |  | 					case BinaryNumericalFunctionExpression::OperatorType::Minus: | 
			
		
	
		
			
				
					|  |  |  |                         std::cout << "mValue: " << mValue << " - " << visitor->value() << std::endl; | 
			
		
	
		
			
				
					|  |  |  | 						mValue -= visitor->value(); | 
			
		
	
		
			
				
					|  |  |  |                         std::cout << mValue << std::endl; | 
			
		
	
		
			
				
					|  |  |  | 						break; | 
			
		
	
		
			
				
					|  |  |  | 					case BinaryNumericalFunctionExpression::OperatorType::Times: | 
			
		
	
		
			
				
					|  |  |  | 						mValue *= visitor->value(); | 
			
		
	
	
		
			
				
					|  |  | @ -101,13 +102,13 @@ namespace expressions { | 
			
		
	
		
			
				
					|  |  |  | 				 | 
			
		
	
		
			
				
					|  |  |  | 				delete visitor; | 
			
		
	
		
			
				
					|  |  |  | 			} | 
			
		
	
		
			
				
					|  |  |  |             virtual void visit(BinaryRelationExpression const* expression)  | 
			
		
	
		
			
				
					|  |  |  |             virtual void visit(BinaryRelationExpression const* expression) | 
			
		
	
		
			
				
					|  |  |  | 			{ | 
			
		
	
		
			
				
					|  |  |  | 				std::cout << "br" << std::endl; | 
			
		
	
		
			
				
					|  |  |  | 			} | 
			
		
	
		
			
				
					|  |  |  |            virtual void visit(VariableExpression const* expression)  | 
			
		
	
		
			
				
					|  |  |  |             virtual void visit(VariableExpression const* expression) | 
			
		
	
		
			
				
					|  |  |  | 			{ | 
			
		
	
		
			
				
					|  |  |  | 			   std::string const& varName= expression->getVariableName(); | 
			
		
	
		
			
				
					|  |  |  |                 std::string const& varName= expression->getVariableName(); | 
			
		
	
		
			
				
					|  |  |  | 				auto it =  mSharedState->find(varName); | 
			
		
	
		
			
				
					|  |  |  | 				if(it != mSharedState->end()) | 
			
		
	
		
			
				
					|  |  |  | 				{ | 
			
		
	
	
		
			
				
					|  |  | @ -120,89 +121,90 @@ namespace expressions { | 
			
		
	
		
			
				
					|  |  |  |                     mValue = convertVariableToPolynomial(nVar); | 
			
		
	
		
			
				
					|  |  |  | 				} | 
			
		
	
		
			
				
					|  |  |  | 			} | 
			
		
	
		
			
				
					|  |  |  |             virtual void visit(UnaryBooleanFunctionExpression const* expression)  | 
			
		
	
		
			
				
					|  |  |  |             virtual void visit(UnaryBooleanFunctionExpression const* expression) | 
			
		
	
		
			
				
					|  |  |  | 			{ | 
			
		
	
		
			
				
					|  |  |  | 				std::cout << "ubf" << std::endl; | 
			
		
	
		
			
				
					|  |  |  | 			} | 
			
		
	
		
			
				
					|  |  |  |             virtual void visit(UnaryNumericalFunctionExpression const* expression)  | 
			
		
	
		
			
				
					|  |  |  |             virtual void visit(UnaryNumericalFunctionExpression const* expression) | 
			
		
	
		
			
				
					|  |  |  | 			{ | 
			
		
	
		
			
				
					|  |  |  | 				std::cout << "unf" << std::endl; | 
			
		
	
		
			
				
					|  |  |  | 			} | 
			
		
	
		
			
				
					|  |  |  |             virtual void visit(BooleanLiteralExpression const* expression)  | 
			
		
	
		
			
				
					|  |  |  |             virtual void visit(BooleanLiteralExpression const* expression) | 
			
		
	
		
			
				
					|  |  |  | 			{ | 
			
		
	
		
			
				
					|  |  |  | 				std::cout << "bl" << std::endl; | 
			
		
	
		
			
				
					|  |  |  | 			} | 
			
		
	
		
			
				
					|  |  |  |             virtual void visit(IntegerLiteralExpression const* expression)  | 
			
		
	
		
			
				
					|  |  |  |             virtual void visit(IntegerLiteralExpression const* expression) | 
			
		
	
		
			
				
					|  |  |  | 			{ | 
			
		
	
		
			
				
					|  |  |  |                 mValue = T(typename T::PolyType(typename T::CoeffType(expression->getValue()))); | 
			
		
	
		
			
				
					|  |  |  | 			} | 
			
		
	
		
			
				
					|  |  |  |             virtual void visit(DoubleLiteralExpression const* expression)  | 
			
		
	
		
			
				
					|  |  |  |             virtual void visit(DoubleLiteralExpression const* expression) | 
			
		
	
		
			
				
					|  |  |  | 			{ | 
			
		
	
		
			
				
					|  |  |  | 				std::stringstream str; | 
			
		
	
		
			
				
					|  |  |  | 				str << std::fixed << std::setprecision( 3 ) << expression->getValue(); | 
			
		
	
		
			
				
					|  |  |  |                 mValue = T(carl::rationalize<cln::cl_RA>(str.str())); | 
			
		
	
		
			
				
					|  |  |  | 			} | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |         template<typename TP = typename T::PolyType, carl::EnableIf<carl::needs_cache<TP>> = carl::dummy> | 
			
		
	
		
			
				
					|  |  |  |         T convertVariableToPolynomial(carl::Variable const& nVar) { | 
			
		
	
		
			
				
					|  |  |  |             return T(typename T::PolyType(typename T::PolyType::PolyType(nVar), cache)); | 
			
		
	
		
			
				
					|  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |          | 
			
		
	
		
			
				
					|  |  |  |         template<typename TP = typename T::PolyType, carl::DisableIf<carl::needs_cache<TP>> = carl::dummy> | 
			
		
	
		
			
				
					|  |  |  |         T convertVariableToPolynomial(carl::Variable const& nVar) { | 
			
		
	
		
			
				
					|  |  |  |             return T(nVar); | 
			
		
	
		
			
				
					|  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |          | 
			
		
	
		
			
				
					|  |  |  | 		const T& value() const | 
			
		
	
		
			
				
					|  |  |  | 		{ | 
			
		
	
		
			
				
					|  |  |  | 			return mValue; | 
			
		
	
		
			
				
					|  |  |  | 		} | 
			
		
	
		
			
				
					|  |  |  | 		 | 
			
		
	
		
			
				
					|  |  |  |              | 
			
		
	
		
			
				
					|  |  |  |             template<typename TP = typename T::PolyType, carl::EnableIf<carl::needs_cache<TP>> = carl::dummy> | 
			
		
	
		
			
				
					|  |  |  |             T convertVariableToPolynomial(carl::Variable const& nVar) { | 
			
		
	
		
			
				
					|  |  |  |                 return T(typename T::PolyType(typename T::PolyType::PolyType(nVar), cache)); | 
			
		
	
		
			
				
					|  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |              | 
			
		
	
		
			
				
					|  |  |  |             template<typename TP = typename T::PolyType, carl::DisableIf<carl::needs_cache<TP>> = carl::dummy> | 
			
		
	
		
			
				
					|  |  |  |             T convertVariableToPolynomial(carl::Variable const& nVar) { | 
			
		
	
		
			
				
					|  |  |  |                 return T(nVar); | 
			
		
	
		
			
				
					|  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |              | 
			
		
	
		
			
				
					|  |  |  |             const T& value() const | 
			
		
	
		
			
				
					|  |  |  |             { | 
			
		
	
		
			
				
					|  |  |  |                 return mValue; | 
			
		
	
		
			
				
					|  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |              | 
			
		
	
		
			
				
					|  |  |  | 		private: | 
			
		
	
		
			
				
					|  |  |  | 		S* mSharedState; | 
			
		
	
		
			
				
					|  |  |  | 		T mValue; | 
			
		
	
		
			
				
					|  |  |  |         carl::Cache<carl::PolynomialFactorizationPair<RawPolynomial>>* cache; | 
			
		
	
		
			
				
					|  |  |  | 	}; | 
			
		
	
		
			
				
					|  |  |  | 	 | 
			
		
	
		
			
				
					|  |  |  | 	template<typename T> | 
			
		
	
		
			
				
					|  |  |  | 	class ExpressionEvaluation | 
			
		
	
		
			
				
					|  |  |  | 	{ | 
			
		
	
		
			
				
					|  |  |  |             S* mSharedState; | 
			
		
	
		
			
				
					|  |  |  |             T mValue; | 
			
		
	
		
			
				
					|  |  |  |             std::shared_ptr<carl::Cache<carl::PolynomialFactorizationPair<RawPolynomial>>> cache; | 
			
		
	
		
			
				
					|  |  |  |         }; | 
			
		
	
		
			
				
					|  |  |  |          | 
			
		
	
		
			
				
					|  |  |  |         template<typename T> | 
			
		
	
		
			
				
					|  |  |  |         class ExpressionEvaluation | 
			
		
	
		
			
				
					|  |  |  |         { | 
			
		
	
		
			
				
					|  |  |  | 		public: | 
			
		
	
		
			
				
					|  |  |  | 		ExpressionEvaluation() : mState() | 
			
		
	
		
			
				
					|  |  |  | 		{ | 
			
		
	
		
			
				
					|  |  |  | 			 | 
			
		
	
		
			
				
					|  |  |  | 		} | 
			
		
	
		
			
				
					|  |  |  | 		 | 
			
		
	
		
			
				
					|  |  |  | 		 | 
			
		
	
		
			
				
					|  |  |  | 		T evaluate(Expression const& expr, storm::expressions::SimpleValuation const* val) | 
			
		
	
		
			
				
					|  |  |  | 		{ | 
			
		
	
		
			
				
					|  |  |  | 			ExpressionEvaluationVisitor<T, typename StateType<T>::type>* visitor = new ExpressionEvaluationVisitor<T, typename StateType<T>::type>(&mState); | 
			
		
	
		
			
				
					|  |  |  |             Expression expressionToTranslate = expr.substitute(*val); | 
			
		
	
		
			
				
					|  |  |  | 			expressionToTranslate.getBaseExpression().accept(visitor); | 
			
		
	
		
			
				
					|  |  |  | 			T result = visitor->value(); | 
			
		
	
		
			
				
					|  |  |  | //			result.simplify(); | 
			
		
	
		
			
				
					|  |  |  | 			delete visitor; | 
			
		
	
		
			
				
					|  |  |  | 			return result; | 
			
		
	
		
			
				
					|  |  |  | 		} | 
			
		
	
		
			
				
					|  |  |  | 		 | 
			
		
	
		
			
				
					|  |  |  |             ExpressionEvaluation() : mState(), cache(new carl::Cache<carl::PolynomialFactorizationPair<RawPolynomial>>()) | 
			
		
	
		
			
				
					|  |  |  |             { | 
			
		
	
		
			
				
					|  |  |  |                 // Intentionally left empty. | 
			
		
	
		
			
				
					|  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |              | 
			
		
	
		
			
				
					|  |  |  |              | 
			
		
	
		
			
				
					|  |  |  |             T evaluate(Expression const& expr, storm::expressions::SimpleValuation const* val) | 
			
		
	
		
			
				
					|  |  |  |             { | 
			
		
	
		
			
				
					|  |  |  |                 ExpressionEvaluationVisitor<T, typename StateType<T>::type>* visitor = new ExpressionEvaluationVisitor<T, typename StateType<T>::type>(&mState, cache); | 
			
		
	
		
			
				
					|  |  |  |                 Expression expressionToTranslate = expr.substitute(*val); | 
			
		
	
		
			
				
					|  |  |  |                 expressionToTranslate.getBaseExpression().accept(visitor); | 
			
		
	
		
			
				
					|  |  |  |                 T result = visitor->value(); | 
			
		
	
		
			
				
					|  |  |  |                 //			result.simplify(); | 
			
		
	
		
			
				
					|  |  |  |                 delete visitor; | 
			
		
	
		
			
				
					|  |  |  |                 return result; | 
			
		
	
		
			
				
					|  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |              | 
			
		
	
		
			
				
					|  |  |  | 		protected: | 
			
		
	
		
			
				
					|  |  |  | 			typename StateType<T>::type mState; | 
			
		
	
		
			
				
					|  |  |  | 	}; | 
			
		
	
		
			
				
					|  |  |  | 	 | 
			
		
	
		
			
				
					|  |  |  | 	/** | 
			
		
	
		
			
				
					|  |  |  | 	 * For doubles, we keep using the getValueAs from the expressions, as this should be more efficient. | 
			
		
	
		
			
				
					|  |  |  | 	 */ | 
			
		
	
		
			
				
					|  |  |  | 	template<> | 
			
		
	
		
			
				
					|  |  |  | 	class ExpressionEvaluation<double> | 
			
		
	
		
			
				
					|  |  |  | 	{ | 
			
		
	
		
			
				
					|  |  |  |             std::shared_ptr<carl::Cache<carl::PolynomialFactorizationPair<RawPolynomial>>> cache; | 
			
		
	
		
			
				
					|  |  |  |         }; | 
			
		
	
		
			
				
					|  |  |  |          | 
			
		
	
		
			
				
					|  |  |  |         /** | 
			
		
	
		
			
				
					|  |  |  |          * For doubles, we keep using the getValueAs from the expressions, as this should be more efficient. | 
			
		
	
		
			
				
					|  |  |  |          */ | 
			
		
	
		
			
				
					|  |  |  |         template<> | 
			
		
	
		
			
				
					|  |  |  |         class ExpressionEvaluation<double> | 
			
		
	
		
			
				
					|  |  |  |         { | 
			
		
	
		
			
				
					|  |  |  | 		public: | 
			
		
	
		
			
				
					|  |  |  | 		double evaluate(Expression const& expr, storm::expressions::SimpleValuation const* val) const | 
			
		
	
		
			
				
					|  |  |  | 		{ | 
			
		
	
		
			
				
					|  |  |  | 			return expr.evaluateAsDouble(val); | 
			
		
	
		
			
				
					|  |  |  | 		} | 
			
		
	
		
			
				
					|  |  |  | 	}; | 
			
		
	
		
			
				
					|  |  |  | 	 | 
			
		
	
		
			
				
					|  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |             double evaluate(Expression const& expr, storm::expressions::SimpleValuation const* val) const | 
			
		
	
		
			
				
					|  |  |  |             { | 
			
		
	
		
			
				
					|  |  |  |                 return expr.evaluateAsDouble(val); | 
			
		
	
		
			
				
					|  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |         }; | 
			
		
	
		
			
				
					|  |  |  |          | 
			
		
	
		
			
				
					|  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  | } | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  | #endif |