15#ifndef dealii_differentiation_sd_symengine_optimizer_h
16#define dealii_differentiation_sd_symengine_optimizer_h
20#ifdef DEAL_II_WITH_SYMENGINE
23# include <symengine/basic.h>
24# include <symengine/dict.h>
25# include <symengine/symengine_exception.h>
26# include <symengine/symengine_rcp.h>
29# include <symengine/lambda_double.h>
30# include <symengine/visitor.h>
31# ifdef HAVE_SYMENGINE_LLVM
32# include <symengine/llvm_double.h>
44# include <boost/serialization/split_member.hpp>
45# include <boost/type_traits.hpp>
50# include <type_traits>
72 "SymEngine has not been built with LLVM support.");
79 "The SymEngine LLVM optimizer does not (yet) support the "
80 "selected return type.");
86 template <
typename ReturnType>
117 template <
typename StreamType>
179 static_cast<unsigned int>(f2));
211 static_cast<unsigned int>(f2));
257 const bool use_agg_opt =
259 const int opt_level = (use_agg_opt ? 3 : 2);
269 template <
typename StreamType>
273 s <<
" OptimizationFlags|";
296 template <
typename ReturnType,
typename T =
void>
309 template <
typename ReturnType,
typename T =
void>
313# ifdef HAVE_SYMENGINE_LLVM
323 template <
typename ReturnType,
typename T =
void>
324 struct LLVMOptimizer;
343 template <
typename ReturnType,
typename Optimizer,
typename T =
void>
355 template <
typename ReturnType_,
typename T =
void>
356 struct SupportedOptimizerTypeTraits
358 static const bool is_supported =
false;
360 using ReturnType = void;
366 template <
typename ReturnType_>
367 struct SupportedOptimizerTypeTraits<
369 std::enable_if_t<std::is_arithmetic_v<ReturnType_>>>
371 static const bool is_supported =
true;
374 std::conditional_t<std::is_same_v<ReturnType_, float>, float,
double>;
380 template <
typename ReturnType_>
381 struct SupportedOptimizerTypeTraits<
384 boost::is_complex<ReturnType_>::value &&
385 std::is_arithmetic_v<typename ReturnType_::value_type>>>
387 static const bool is_supported =
true;
390 std::conditional_t<std::is_same_v<ReturnType_, std::complex<float>>,
392 std::complex<double>>;
397 template <
typename ReturnType_>
398 struct DictionaryOptimizer<ReturnType_,
399 std::enable_if_t<SupportedOptimizerTypeTraits<
400 ReturnType_>::is_supported>>
403 typename SupportedOptimizerTypeTraits<ReturnType_>::ReturnType;
405 internal::DictionarySubstitutionVisitor<ReturnType, SD::Expression>;
418 const SymEngine::vec_basic &independent_symbols,
419 const SymEngine::vec_basic &dependent_functions,
423 optimizer.init(independent_symbols,
434 template <
class Archive>
436 save(Archive &archive,
437 const unsigned int version,
440 optimizer.save(archive, version);
449 template <
class Archive>
451 load(Archive &archive,
452 const unsigned int version,
454 const SymEngine::vec_basic & ,
455 const SymEngine::vec_basic & ,
458 optimizer.load(archive, version);
478 template <
typename Stream>
480 print(Stream &stream,
482 const bool print_independent_symbols =
false,
483 const bool print_dependent_functions =
false,
484 const bool print_cse_reductions =
true)
486 optimizer.print(stream,
487 print_independent_symbols,
488 print_dependent_functions,
489 print_cse_reductions);
495 template <
typename ReturnType_>
496 struct LambdaOptimizer<ReturnType_,
497 std::enable_if_t<SupportedOptimizerTypeTraits<
498 ReturnType_>::is_supported>>
501 std::conditional_t<!boost::is_complex<ReturnType_>::value,
503 std::complex<double>>;
505 std::conditional_t<!boost::is_complex<ReturnType_>::value,
506 SymEngine::LambdaRealDoubleVisitor,
507 SymEngine::LambdaComplexDoubleVisitor>;
520 const SymEngine::vec_basic &independent_symbols,
521 const SymEngine::vec_basic &dependent_functions,
525 optimizer.init(independent_symbols,
536 template <
class Archive>
548 template <
class Archive>
553 const SymEngine::vec_basic &independent_symbols,
554 const SymEngine::vec_basic &dependent_functions,
557 initialize(optimizer,
580 template <
typename StreamType>
594# ifdef HAVE_SYMENGINE_LLVM
595 template <
typename ReturnType_>
596 struct LLVMOptimizer<ReturnType_,
597 std::enable_if_t<std::is_arithmetic_v<ReturnType_>>>
600 std::conditional_t<std::is_same_v<ReturnType_, float>, float,
double>;
602 std::conditional_t<std::is_same_v<ReturnType_, float>,
603 SymEngine::LLVMFloatVisitor,
604 SymEngine::LLVMDoubleVisitor>;
610 static const bool supported_by_LLVM =
true;
622 initialize(OptimizerType &optimizer,
623 const SymEngine::vec_basic &independent_symbols,
624 const SymEngine::vec_basic &dependent_functions,
625 const enum OptimizationFlags &optimization_flags)
629 optimizer.init(independent_symbols,
641 template <
class Archive>
643 save(Archive &archive,
645 OptimizerType &optimizer)
647 const std::string llvm_compiled_function = optimizer.dumps();
648 archive &llvm_compiled_function;
657 template <
class Archive>
659 load(Archive &archive,
661 OptimizerType &optimizer,
662 const SymEngine::vec_basic & ,
663 const SymEngine::vec_basic & ,
664 const enum OptimizationFlags & )
666 std::string llvm_compiled_function;
667 archive &llvm_compiled_function;
668 optimizer.loads(llvm_compiled_function);
688 template <
typename StreamType>
691 const OptimizerType & ,
706 template <
typename ReturnType_>
707 struct LLVMOptimizer<
710 boost::is_complex<ReturnType_>::value &&
711 std::is_arithmetic_v<typename ReturnType_::value_type>>>
715 using ReturnType =
typename LambdaOptimizer<ReturnType_>::ReturnType;
717 typename LambdaOptimizer<ReturnType_>::OptimizerType;
723 static const bool supported_by_LLVM =
false;
735 initialize(OptimizerType & ,
736 const SymEngine::vec_basic & ,
737 const SymEngine::vec_basic & ,
738 const enum OptimizationFlags & )
749 template <
class Archive>
764 template <
class Archive>
769 const SymEngine::vec_basic & ,
770 const SymEngine::vec_basic & ,
771 const enum OptimizationFlags & )
793 template <
typename StreamType>
796 const OptimizerType & ,
810 template <
typename ReturnType,
typename Optimizer>
811 struct OptimizerHelper<
815 std::is_same_v<ReturnType, typename Optimizer::ReturnType>>>
826 initialize(
typename Optimizer::OptimizerType *optimizer,
827 const SymEngine::vec_basic &independent_symbols,
828 const SymEngine::vec_basic &dependent_functions,
836 Optimizer::initialize(*optimizer,
858 substitute(
typename Optimizer::OptimizerType *optimizer,
859 std::vector<ReturnType> &output_values,
860 const std::vector<ReturnType> &substitution_values)
863 optimizer->call(output_values.data(), substitution_values.data());
872 template <
class Archive>
874 save(Archive &archive,
875 const unsigned int version,
876 typename Optimizer::OptimizerType *optimizer)
883 Optimizer::save(archive, version, *optimizer);
892 template <
class Archive>
894 load(Archive &archive,
895 const unsigned int version,
896 typename Optimizer::OptimizerType *optimizer,
897 const SymEngine::vec_basic &independent_symbols,
898 const SymEngine::vec_basic &dependent_functions,
906 Optimizer::load(archive,
931 template <
typename Stream>
933 print(Stream &stream,
934 typename Optimizer::OptimizerType *optimizer,
935 const bool print_independent_symbols =
false,
936 const bool print_dependent_functions =
false,
937 const bool print_cse_reductions =
true)
944 Optimizer::print(stream,
946 print_independent_symbols,
947 print_dependent_functions,
948 print_cse_reductions);
952 template <
typename ReturnType,
typename Optimizer>
953 struct OptimizerHelper<
957 !std::is_same_v<ReturnType, typename Optimizer::ReturnType>>>
968 initialize(
typename Optimizer::OptimizerType *optimizer,
969 const SymEngine::vec_basic &independent_symbols,
970 const SymEngine::vec_basic &dependent_functions,
976 optimizer->init(independent_symbols,
997 substitute(
typename Optimizer::OptimizerType *optimizer,
998 std::vector<ReturnType> &output_values,
999 const std::vector<ReturnType> &substitution_values)
1005 std::vector<typename Optimizer::ReturnType> int_outputs(
1006 output_values.size());
1007 std::vector<typename Optimizer::ReturnType> int_inputs(
1008 substitution_values.size());
1010 std::copy(substitution_values.begin(),
1011 substitution_values.end(),
1012 int_inputs.begin());
1013 optimizer->call(int_outputs.data(), int_inputs.data());
1014 std::copy(int_outputs.begin(),
1016 output_values.begin());
1025 template <
class Archive>
1027 save(Archive &archive,
1028 const unsigned int version,
1029 typename Optimizer::OptimizerType *optimizer)
1032 Optimizer::save(archive, version, *optimizer);
1041 template <
class Archive>
1043 load(Archive &archive,
1044 const unsigned int version,
1045 typename Optimizer::OptimizerType *optimizer,
1046 const SymEngine::vec_basic &independent_symbols,
1047 const SymEngine::vec_basic &dependent_functions,
1055 Optimizer::load(archive,
1058 independent_symbols,
1059 dependent_functions,
1060 optimization_flags);
1080 template <
typename Stream>
1082 print(Stream &stream,
1083 typename Optimizer::OptimizerType *optimizer,
1084 const bool print_cse_reductions =
true,
1085 const bool print_independent_symbols =
false,
1086 const bool print_dependent_functions =
false)
1090 optimizer->print(stream,
1091 print_independent_symbols,
1092 print_dependent_functions,
1093 print_cse_reductions);
1124 template <
typename NumberType,
1127 template <
int,
int,
typename>
1129 TensorType<rank, dim, NumberType>
1131 const TensorType<rank, dim, Expression> &symbol_tensor,
1132 const std::vector<NumberType> &cached_evaluation,
1135 TensorType<rank, dim, NumberType> out;
1136 for (
unsigned int i = 0; i < out.n_independent_components; ++i)
1139 out.unrolled_to_component_indices(i));
1141 optimizer.
extract(symbol_tensor[indices], cached_evaluation);
1169 template <
typename NumberType,
int dim>
1173 const std::vector<NumberType> &cached_evaluation,
1177 for (
unsigned int i = 0;
1178 i < SymmetricTensor<2, dim>::n_independent_components;
1180 for (
unsigned int j = 0;
1181 j < SymmetricTensor<2, dim>::n_independent_components;
1185 make_rank_4_tensor_indices<dim>(i, j);
1187 optimizer.
extract(symbol_tensor[indices], cached_evaluation);
1210 template <
typename NumberType,
typename T>
1236 template <
typename NumberType,
typename T>
1239 const std::vector<T> &functions)
1241 for (
const auto &function : functions)
1265 template <
typename NumberType,
typename T,
typename... Args>
1269 const Args &...other_functions)
1289 template <
int,
int,
typename>
1293 const TensorType<rank, dim, Expression> &symbol_tensor)
1296 out.reserve(symbol_tensor.n_independent_components);
1297 for (
unsigned int i = 0; i < symbol_tensor.n_independent_components;
1301 symbol_tensor.unrolled_to_component_indices(i));
1302 out.push_back(symbol_tensor[indices].get_RCP());
1324 for (
unsigned int i = 0;
1325 i < SymmetricTensor<2, dim>::n_independent_components;
1327 for (
unsigned int j = 0;
1328 j < SymmetricTensor<2, dim>::n_independent_components;
1332 make_rank_4_tensor_indices<dim>(i, j);
1333 out.push_back(symbol_tensor[indices].get_RCP());
1432 template <
typename ReturnType>
1509 template <typename Stream>
1511 print(Stream &stream, const
bool print_cse = false) const;
1521 template <class Archive>
1523 save(Archive &archive, const
unsigned int version) const;
1538 template <class Archive>
1540 load(Archive &archive, const
unsigned int version);
1564 template <
class Archive>
1570 BOOST_SERIALIZATION_SPLIT_MEMBER()
1653 template <
int rank,
int dim>
1661 template <
int rank,
int dim>
1689 template <
typename T>
1706 template <
typename T,
typename... Args>
1825 substitute(
const SymEngine::map_basic_basic &substitution_map)
const;
1839 const std::vector<ReturnType> &values)
const;
1852 substitute(
const SymEngine::vec_basic &symbols,
1853 const std::vector<ReturnType> &values)
const;
1892 const std::vector<ReturnType> &
1913 std::vector<ReturnType>
1914 evaluate(
const std::vector<Expression> &funcs)
const;
1924 template <
int rank,
int dim>
1937 template <
int rank,
int dim>
1951 const std::vector<ReturnType> &cached_evaluation)
const;
1961 std::vector<ReturnType>
1962 extract(
const std::vector<Expression> &funcs,
1963 const std::vector<ReturnType> &cached_evaluation)
const;
1973 template <
int rank,
int dim>
1976 const std::vector<ReturnType> &cached_evaluation)
const;
1986 template <
int rank,
int dim>
1989 const std::vector<ReturnType> &cached_evaluation)
const;
2037 const SymEngine::RCP<const SymEngine::Basic> &function)
const;
2134 substitute(
const std::vector<ReturnType> &substitution_values)
const;
2145 template <
typename ReturnType>
2146 template <
typename Stream>
2152 stream <<
"Method? " << optimization_method() <<
'\n';
2153 stream <<
"Flags: " << optimization_flags() <<
'\n';
2154 stream <<
"Optimized? " << (optimized() ?
"Yes" :
"No") <<
'\n';
2155 stream <<
"Values substituted? " << values_substituted() <<
"\n\n";
2158 stream <<
"Symbols (" << n_independent_variables()
2159 <<
" independent variables):" <<
'\n';
2161 for (SD::types::substitution_map::const_iterator it =
2162 independent_variables_symbols.begin();
2163 it != independent_variables_symbols.end();
2166 stream << cntr <<
": " << it->first <<
'\n';
2168 stream <<
'\n' << std::flush;
2171 stream <<
"Functions (" << n_dependent_variables()
2172 <<
" dependent variables):" <<
'\n';
2174 for (
typename SD::types::symbol_vector::const_iterator it =
2175 dependent_variables_functions.begin();
2176 it != dependent_variables_functions.end();
2179 stream << cntr <<
": " << (*it) <<
'\n';
2181 stream <<
'\n' << std::flush;
2184 if (optimized() ==
true && use_symbolic_CSE() ==
true)
2187 const bool print_cse_reductions =
true;
2188 const bool print_independent_symbols =
false;
2189 const bool print_dependent_functions =
false;
2193 Assert(
dynamic_cast<typename internal::DictionaryOptimizer<
2195 ExcMessage(
"Cannot cast optimizer to Dictionary type."));
2197 internal::OptimizerHelper<
2199 internal::DictionaryOptimizer<ReturnType>>::
2201 dynamic_cast<typename internal::DictionaryOptimizer<
2203 print_independent_symbols,
2204 print_dependent_functions,
2205 print_cse_reductions);
2207 stream <<
'\n' << std::flush;
2211 Assert(
dynamic_cast<typename internal::LambdaOptimizer<
2213 ExcMessage(
"Cannot cast optimizer to Lambda type."));
2215 internal::OptimizerHelper<ReturnType,
2216 internal::LambdaOptimizer<ReturnType>>::
2218 dynamic_cast<typename internal::LambdaOptimizer<
2220 print_independent_symbols,
2221 print_dependent_functions,
2222 print_cse_reductions);
2224# ifdef HAVE_SYMENGINE_LLVM
2227 Assert(
dynamic_cast<typename internal::LLVMOptimizer<
2229 ExcMessage(
"Cannot cast optimizer to LLVM type."));
2231 internal::OptimizerHelper<ReturnType,
2232 internal::LLVMOptimizer<ReturnType>>::
2234 dynamic_cast<typename internal::LLVMOptimizer<
2236 print_independent_symbols,
2237 print_dependent_functions,
2238 print_cse_reductions);
2247 if (values_substituted())
2249 stream <<
"Evaluated functions:" <<
'\n';
2250 stream << std::flush;
2252 for (
typename std::vector<ReturnType>::const_iterator it =
2253 dependent_variables_output.begin();
2254 it != dependent_variables_output.end();
2257 stream << cntr <<
": " << (*it) <<
'\n';
2259 stream <<
'\n' << std::flush;
2265 template <
typename ReturnType>
2266 template <
class Archive>
2269 const unsigned int version)
const
2274 static_cast<std::underlying_type_t<OptimizerType>
>(method);
2279 static_cast<std::underlying_type_t<OptimizationFlags>
>(flags);
2285 ar &independent_variables_symbols;
2286 ar &dependent_variables_functions;
2288 ar &dependent_variables_output;
2289 ar &map_dep_expr_vec_entry;
2290 ar &ready_for_value_extraction;
2293 has_been_serialized =
true;
2294 ar &has_been_serialized;
2302 if (
typename internal::DictionaryOptimizer<ReturnType>::OptimizerType
2303 *opt =
dynamic_cast<typename internal::DictionaryOptimizer<
2308 internal::OptimizerHelper<
2310 internal::DictionaryOptimizer<ReturnType>>::save(ar, version, opt);
2312 else if (
typename internal::LambdaOptimizer<ReturnType>::OptimizerType
2313 *opt =
dynamic_cast<typename internal::LambdaOptimizer<
2318 internal::OptimizerHelper<
2320 internal::LambdaOptimizer<ReturnType>>::save(ar, version, opt);
2322# ifdef HAVE_SYMENGINE_LLVM
2323 else if (
typename internal::LLVMOptimizer<ReturnType>::OptimizerType
2324 *opt =
dynamic_cast<typename internal::LLVMOptimizer<
2329 internal::OptimizerHelper<
2331 internal::LLVMOptimizer<ReturnType>>::save(ar, version, opt);
2342 template <
typename ReturnType>
2343 template <
class Archive>
2355 std::underlying_type_t<OptimizerType> m;
2360 std::underlying_type_t<OptimizationFlags> f;
2367 ar &independent_variables_symbols;
2368 ar &dependent_variables_functions;
2370 ar &dependent_variables_output;
2371 ar &map_dep_expr_vec_entry;
2372 ar &ready_for_value_extraction;
2374 ar &has_been_serialized;
2381 create_optimizer(optimizer);
2390 if (
typename internal::DictionaryOptimizer<ReturnType>::OptimizerType
2391 *opt =
dynamic_cast<typename internal::DictionaryOptimizer<
2396 internal::OptimizerHelper<ReturnType,
2397 internal::DictionaryOptimizer<ReturnType>>::
2404 dependent_variables_functions),
2405 optimization_flags());
2407 else if (
typename internal::LambdaOptimizer<ReturnType>::OptimizerType
2408 *opt =
dynamic_cast<typename internal::LambdaOptimizer<
2413 internal::OptimizerHelper<ReturnType,
2414 internal::LambdaOptimizer<ReturnType>>::
2421 dependent_variables_functions),
2422 optimization_flags());
2424# ifdef HAVE_SYMENGINE_LLVM
2425 else if (
typename internal::LLVMOptimizer<ReturnType>::OptimizerType
2426 *opt =
dynamic_cast<typename internal::LLVMOptimizer<
2431 internal::OptimizerHelper<ReturnType,
2432 internal::LLVMOptimizer<ReturnType>>::
2439 dependent_variables_functions),
2440 optimization_flags());
2451 template <
typename ReturnType>
2452 template <
int rank,
int dim>
2457 Assert(optimized() ==
false,
2459 "Cannot register functions once the optimizer is finalised."));
2461 register_vector_functions(
2467 template <
typename ReturnType>
2468 template <
int rank,
int dim>
2473 Assert(optimized() ==
false,
2475 "Cannot register functions once the optimizer is finalised."));
2477 register_vector_functions(
2483 template <
typename ReturnType>
2484 template <
typename T,
typename... Args>
2488 const Args &...other_functions)
2496 template <
typename ReturnType>
2497 template <
typename T>
2500 const std::vector<T> &functions)
2507 template <
typename ReturnType>
2508 template <
int rank,
int dim>
2512 const std::vector<ReturnType> &cached_evaluation)
const
2521 template <
typename ReturnType>
2522 template <
int rank,
int dim>
2528 values_substituted() ==
true,
2530 "The optimizer is not configured to perform evaluation. "
2531 "This action can only performed after substitute() has been called."));
2533 return extract(funcs, dependent_variables_output);
2538 template <
typename ReturnType>
2539 template <
int rank,
int dim>
2543 const std::vector<ReturnType> &cached_evaluation)
const
2552 template <
typename ReturnType>
2553 template <
int rank,
int dim>
2559 values_substituted() ==
true,
2561 "The optimizer is not configured to perform evaluation. "
2562 "This action can only performed after substitute() has been called."));
2564 return extract(funcs, dependent_variables_output);
SymmetricTensor< rank, dim, ReturnType > extract(const SymmetricTensor< rank, dim, Expression > &funcs, const std::vector< ReturnType > &cached_evaluation) const
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_functions(const T &functions, const Args &...other_functions)
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)
bool ready_for_value_extraction
void print(Stream &stream, const bool print_cse=false) const
enum OptimizerType optimization_method() const
void copy_from(const BatchOptimizer &other)
void register_function(const Tensor< rank, dim, Expression > &function_tensor)
void set_optimization_method(const enum OptimizerType &optimization_method, const enum OptimizationFlags &optimization_flags=OptimizationFlags::optimize_all)
SymmetricTensor< rank, dim, ReturnType > evaluate(const SymmetricTensor< rank, dim, Expression > &funcs) const
void save(Archive &archive, const unsigned int version) const
enum OptimizationFlags optimization_flags() const
void register_functions(const types::symbol_vector &functions)
std::vector< ReturnType > dependent_variables_output
enum OptimizerType method
Tensor< rank, dim, ReturnType > extract(const Tensor< rank, dim, Expression > &funcs, const std::vector< ReturnType > &cached_evaluation) const
std::size_t n_dependent_variables() const
void serialize(Archive &archive, const unsigned int version)
void register_symbols(const types::substitution_map &substitution_map)
const std::vector< ReturnType > & evaluate() const
std::map< SD::Expression, std::size_t, SD::types::internal::ExpressionKeyLess > map_dependent_expression_to_vector_entry_t
void register_function(const Expression &function)
Tensor< rank, dim, ReturnType > evaluate(const Tensor< rank, dim, Expression > &funcs) const
std::unique_ptr< SymEngine::Visitor > optimizer
ReturnType extract(const Expression &func, const std::vector< ReturnType > &cached_evaluation) const
BatchOptimizer(BatchOptimizer &&) noexcept=default
void load(Archive &archive, const unsigned int version)
void register_functions(const std::vector< T > &functions)
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
void register_function(const SymmetricTensor< rank, dim, Expression > &function_tensor)
map_dependent_expression_to_vector_entry_t map_dep_expr_vec_entry
bool values_substituted() const
static constexpr unsigned int n_independent_components
#define DEAL_II_NAMESPACE_OPEN
#define DEAL_II_NAMESPACE_CLOSE
static ::ExceptionBase & ExcNotImplemented()
#define Assert(cond, exc)
static ::ExceptionBase & ExcSymEngineLLVMReturnTypeNotSupported()
#define DeclExceptionMsg(Exception, defaulttext)
static ::ExceptionBase & ExcSymEngineLLVMNotAvailable()
static ::ExceptionBase & ExcInternalError()
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)
SymEngine::vec_basic convert_expression_vector_to_basic_vector(const SD::types::symbol_vector &symbol_vector)
TensorType< rank, dim, NumberType > tensor_evaluate_optimized(const TensorType< rank, dim, Expression > &symbol_tensor, const std::vector< NumberType > &cached_evaluation, const BatchOptimizer< NumberType > &optimizer)
bool use_symbolic_CSE(const enum OptimizationFlags &flags)
types::symbol_vector unroll_to_expression_vector(const TensorType< rank, dim, Expression > &symbol_tensor)
int get_LLVM_optimization_level(const enum OptimizationFlags &flags)
void register_functions(BatchOptimizer< NumberType > &optimizer, const T &function)
std::vector< SD::Expression > symbol_vector
std::map< SD::Expression, SD::Expression, internal::ExpressionKeyLess > substitution_map
OptimizationFlags & operator|=(OptimizationFlags &f1, const OptimizationFlags f2)
Expression operator|(const Expression &lhs, const Expression &rhs)
Expression operator&(const Expression &lhs, const Expression &rhs)
Expression substitute(const Expression &expression, const types::substitution_map &substitution_map)
std::ostream & operator<<(std::ostream &stream, const Expression &expression)
OptimizationFlags & operator&=(OptimizationFlags &f1, const OptimizationFlags f2)
constexpr ReturnType< rank, T >::value_type & extract(T &t, const ArrayType &indices)