18#ifdef DEAL_II_WITH_SYMENGINE
23# include <boost/archive/text_iarchive.hpp>
24# include <boost/archive/text_oarchive.hpp>
35 template <
typename ReturnType>
39 , ready_for_value_extraction(false)
40 , has_been_serialized(false)
45 template <
typename ReturnType>
56 template <
typename ReturnType>
59 : method(other.method)
61 , independent_variables_symbols(other.independent_variables_symbols)
62 , dependent_variables_functions(other.dependent_variables_functions)
63 , dependent_variables_output(0)
64 , map_dep_expr_vec_entry(other.map_dep_expr_vec_entry)
65 , ready_for_value_extraction(false)
66 , has_been_serialized(false)
71 template <
typename ReturnType>
80 dependent_variables_output.clear();
82 ready_for_value_extraction =
false;
83 has_been_serialized =
false;
88 template <
typename ReturnType>
97 "Cannot call set_optimization_method() once the optimizer is finalized."));
99# ifndef HAVE_SYMENGINE_LLVM
105 method = optimization_method;
106 flags = optimization_flags;
111 template <
typename ReturnType>
120 template <
typename ReturnType>
129 template <
typename ReturnType>
138 template <
typename ReturnType>
142 if (dependent_variables_output.size() > 0)
144 Assert(dependent_variables_output.size() ==
145 dependent_variables_functions.size(),
155 template <
typename ReturnType>
159 return ready_for_value_extraction;
164 template <
typename ReturnType>
169 Assert(optimized() ==
false,
171 "Cannot register symbols once the optimizer is finalized."));
176 for (
const auto &entry : substitution_map)
179 Assert(SymEngine::is_a<SymEngine::Symbol>(*(symbol.
get_RCP())),
180 ExcMessage(
"Key entry in map is not a symbol."));
185 independent_variables_symbols.insert(substitution_map.begin(),
186 substitution_map.end());
191 template <
typename ReturnType>
194 const SymEngine::map_basic_basic &substitution_map)
202 template <
typename ReturnType>
207 Assert(optimized() ==
false,
209 "Cannot register symbols once the optimizer is finalized."));
211 for (
const auto &symbol : symbols)
213 Assert(independent_variables_symbols.find(symbol) ==
214 independent_variables_symbols.end(),
216 independent_variables_symbols.insert(
223 template <
typename ReturnType>
226 const SymEngine::vec_basic &symbols)
234 template <
typename ReturnType>
243 template <
typename ReturnType>
247 return independent_variables_symbols.size();
252 template <
typename ReturnType>
256 Assert(optimized() ==
false,
258 "Cannot register functions once the optimizer is finalized."));
260 register_scalar_function(function);
265 template <
typename ReturnType>
270 Assert(optimized() ==
false,
272 "Cannot register functions once the optimizer is finalized."));
274 register_vector_functions(functions);
279 template <
typename ReturnType>
282 const SymEngine::vec_basic &functions)
290 template <
typename ReturnType>
294 return dependent_variables_functions;
299 template <
typename ReturnType>
303 if (has_been_serialized ==
false)
307 Assert(map_dep_expr_vec_entry.size() ==
308 dependent_variables_functions.size(),
311 return dependent_variables_functions.size();
316 template <
typename ReturnType>
320 Assert(optimized() ==
false,
321 ExcMessage(
"Cannot call optimize() more than once."));
324 create_optimizer(optimizer);
341 dependent_variables_functions),
342 optimization_flags());
356 dependent_variables_functions),
357 optimization_flags());
359# ifdef HAVE_SYMENGINE_LLVM
360 else if (
typename internal::LLVMOptimizer<ReturnType>::OptimizerType
361 *opt =
dynamic_cast<typename internal::LLVMOptimizer<
367 internal::LLVMOptimizer<ReturnType>>::
372 dependent_variables_functions),
373 optimization_flags());
388 dependent_variables_output.resize(n_dependent_variables());
393 template <
typename ReturnType>
401 "The optimizer is not configured to perform substitution. "
402 "This action can only performed after optimize() has been called."));
412 Assert(symbol_sub_vec.size() == symbol_vec.size(),
414 for (
unsigned int i = 0; i < symbol_sub_vec.size(); ++i)
418 "The input substitution map is either incomplete, or does "
419 "not match that used in the register_symbols() call."));
425 const std::vector<ReturnType> values =
426 Utilities::extract_values<ReturnType>(substitution_map);
432 template <
typename ReturnType>
435 const SymEngine::map_basic_basic &substitution_map)
const
443 template <
typename ReturnType>
447 const std::vector<ReturnType> & values)
const
457 template <
typename ReturnType>
460 const SymEngine::vec_basic & symbols,
461 const std::vector<ReturnType> &values)
const
470 template <
typename ReturnType>
473 const std::vector<ReturnType> &substitution_values)
const
478 "The optimizer is not configured to perform substitution. "
479 "This action can only performed after optimize() has been called."));
481 Assert(substitution_values.size() == independent_variables_symbols.size(),
483 independent_variables_symbols.size()));
493 substitute(opt, dependent_variables_output, substitution_values);
503 substitute(opt, dependent_variables_output, substitution_values);
505# ifdef HAVE_SYMENGINE_LLVM
506 else if (
typename internal::LLVMOptimizer<ReturnType>::OptimizerType
507 *opt =
dynamic_cast<typename internal::LLVMOptimizer<
513 internal::LLVMOptimizer<ReturnType>>
::
514 substitute(opt, dependent_variables_output, substitution_values);
522 ready_for_value_extraction =
true;
527 template <
typename ReturnType>
528 const std::vector<ReturnType> &
532 values_substituted() ==
true,
534 "The optimizer is not configured to perform evaluation. "
535 "This action can only performed after substitute() has been called."));
537 return dependent_variables_output;
542 template <
typename ReturnType>
546 const std::vector<ReturnType> &cached_evaluation)
const
555 const typename map_dependent_expression_to_vector_entry_t::const_iterator
556 it = map_dep_expr_vec_entry.find(func);
560 if (has_been_serialized && it == map_dep_expr_vec_entry.end())
574 auto serialize_and_deserialize_expression =
576 std::ostringstream oss;
578 boost::archive::text_oarchive oa(oss,
579 boost::archive::no_header);
585 std::istringstream iss(oss.str());
586 boost::archive::text_iarchive ia(iss,
587 boost::archive::no_header);
596 serialize_and_deserialize_expression(func);
603 for (
const auto &e : map_dep_expr_vec_entry)
606 serialize_and_deserialize_expression(e.first);
615 map_dep_expr_vec_entry[func] = e.second;
616 return extract(func, cached_evaluation);
623 "Still cannot find map entry, and there's no hope to recover from this situation."));
626 Assert(it != map_dep_expr_vec_entry.end(),
627 ExcMessage(
"Function has not been registered."));
630 return cached_evaluation[it->second];
635 template <
typename ReturnType>
640 values_substituted() ==
true,
642 "The optimizer is not configured to perform evaluation. "
643 "This action can only performed after substitute() has been called."));
645 return extract(func, dependent_variables_output);
650 template <
typename ReturnType>
651 std::vector<ReturnType>
653 const std::vector<Expression> &funcs,
654 const std::vector<ReturnType> &cached_evaluation)
const
656 std::vector<ReturnType> out;
657 out.reserve(funcs.size());
659 for (
const auto &func : funcs)
660 out.emplace_back(extract(func, cached_evaluation));
667 template <
typename ReturnType>
668 std::vector<ReturnType>
670 const std::vector<Expression> &funcs)
const
673 values_substituted() ==
true,
675 "The optimizer is not configured to perform evaluation. "
676 "This action can only performed after substitute() has been called."));
677 return extract(funcs, dependent_variables_output);
682 template <
typename ReturnType>
687 return is_valid_nonunique_dependent_variable(func.
get_RCP());
692 template <
typename ReturnType>
695 const SymEngine::RCP<const SymEngine::Basic> &func)
const
701 if (SymEngine::is_a<SymEngine::Constant>(*func))
703 if (&*func == &*SymEngine::zero)
705 if (&*func == &*SymEngine::one)
707 if (&*func == &*SymEngine::minus_one)
709 if (&*func == &*SymEngine::I)
711 if (&*func == &*SymEngine::Inf)
713 if (&*func == &*SymEngine::NegInf)
715 if (&*func == &*SymEngine::ComplexInf)
717 if (&*func == &*SymEngine::Nan)
725 template <
typename ReturnType>
731 dependent_variables_output.size() == 0,
733 "Cannot register function as the optimizer has already been finalized."));
734 dependent_variables_output.reserve(n_dependent_variables() + 1);
735 const bool entry_registered =
736 (map_dep_expr_vec_entry.find(func) != map_dep_expr_vec_entry.end());
738 if (entry_registered ==
true &&
739 is_valid_nonunique_dependent_variable(func) ==
false)
741 ExcMessage(
"Function has already been registered."));
743 if (entry_registered ==
false)
745 dependent_variables_functions.push_back(func);
746 map_dep_expr_vec_entry[func] =
747 dependent_variables_functions.size() - 1;
753 template <
typename ReturnType>
759 dependent_variables_output.size() == 0,
761 "Cannot register function as the optimizer has already been finalized."));
762 const std::size_t n_dependents_old = n_dependent_variables();
763 dependent_variables_output.reserve(n_dependents_old + funcs.size());
764 dependent_variables_functions.reserve(n_dependents_old + funcs.size());
766 for (
const auto &func : funcs)
768 const bool entry_registered =
769 (map_dep_expr_vec_entry.find(func) != map_dep_expr_vec_entry.end());
771 if (entry_registered ==
true &&
772 is_valid_nonunique_dependent_variable(func) ==
false)
774 ExcMessage(
"Function has already been registered."));
776 if (entry_registered ==
false)
778 dependent_variables_functions.push_back(func);
779 map_dep_expr_vec_entry[func] =
780 dependent_variables_functions.size() - 1;
787 template <
typename ReturnType>
790 std::unique_ptr<SymEngine::Visitor> &optimizer)
799 optimizer.reset(
new Optimizer_t());
805 optimizer.reset(
new Optimizer_t());
809# ifdef HAVE_SYMENGINE_LLVM
810 if (internal::LLVMOptimizer<ReturnType>::supported_by_LLVM)
813 typename internal::LLVMOptimizer<ReturnType>::OptimizerType;
814 optimizer.reset(
new Optimizer_t());
835# include "symengine_optimizer.inst"
bool use_symbolic_CSE() const
types::substitution_map independent_variables_symbols
types::symbol_vector dependent_variables_functions
void substitute(const types::substitution_map &substitution_map) const
enum OptimizationFlags flags
void register_scalar_function(const SD::Expression &function)
const types::symbol_vector & get_dependent_functions() const
void create_optimizer(std::unique_ptr< SymEngine::Visitor > &optimizer)
enum OptimizerType optimization_method() const
void copy_from(const BatchOptimizer &other)
void set_optimization_method(const enum OptimizerType &optimization_method, const enum OptimizationFlags &optimization_flags=OptimizationFlags::optimize_all)
enum OptimizationFlags optimization_flags() const
void register_functions(const types::symbol_vector &functions)
enum OptimizerType method
std::size_t n_dependent_variables() const
void register_symbols(const types::substitution_map &substitution_map)
const std::vector< ReturnType > & evaluate() const
void register_function(const Expression &function)
ReturnType extract(const Expression &func, const std::vector< ReturnType > &cached_evaluation) const
bool is_valid_nonunique_dependent_variable(const SD::Expression &function) const
void register_vector_functions(const types::symbol_vector &functions)
std::size_t n_independent_variables() const
types::symbol_vector get_independent_symbols() const
map_dependent_expression_to_vector_entry_t map_dep_expr_vec_entry
bool values_substituted() const
const SymEngine::RCP< const SymEngine::Basic > & get_RCP() const
const SymEngine::Basic & get_value() const
#define DEAL_II_NAMESPACE_OPEN
#define DEAL_II_NAMESPACE_CLOSE
static ::ExceptionBase & ExcNotImplemented()
#define Assert(cond, exc)
static ::ExceptionBase & ExcSymEngineLLVMReturnTypeNotSupported()
static ::ExceptionBase & ExcSymEngineLLVMNotAvailable()
static ::ExceptionBase & ExcInternalError()
static ::ExceptionBase & ExcDimensionMismatch(std::size_t arg1, std::size_t arg2)
static ::ExceptionBase & ExcNotInitialized()
static ::ExceptionBase & ExcMessage(std::string arg1)
#define AssertThrow(cond, exc)
SD::types::symbol_vector extract_symbols(const SD::types::substitution_map &substitution_values)
SD::types::substitution_map convert_basic_map_to_expression_map(const SymEngine::map_basic_basic &substitution_map)
SD::types::symbol_vector convert_basic_vector_to_expression_vector(const SymEngine::vec_basic &symbol_vector)
SymEngine::vec_basic convert_expression_vector_to_basic_vector(const SD::types::symbol_vector &symbol_vector)
bool use_symbolic_CSE(const enum OptimizationFlags &flags)
std::vector< SD::Expression > symbol_vector
std::map< SD::Expression, SD::Expression, internal::ExpressionKeyLess > substitution_map
Expression substitute(const Expression &expression, const types::substitution_map &substitution_map)
types::substitution_map make_substitution_map(const Expression &symbol, const Expression &value)
constexpr bool values_are_equal(const Number1 &value_1, const Number2 &value_2)