16#ifndef dealii_differentiation_sd_symengine_optimizer_h
17#define dealii_differentiation_sd_symengine_optimizer_h
21#ifdef DEAL_II_WITH_SYMENGINE
24# include <symengine/basic.h>
25# include <symengine/dict.h>
26# include <symengine/symengine_exception.h>
27# include <symengine/symengine_rcp.h>
30# include <symengine/lambda_double.h>
31# include <symengine/visitor.h>
32# ifdef HAVE_SYMENGINE_LLVM
33# include <symengine/llvm_double.h>
46# include <boost/serialization/split_member.hpp>
47# include <boost/type_traits.hpp>
52# include <type_traits>
74 "SymEngine has not been built with LLVM support.");
81 "The SymEngine LLVM optimizer does not (yet) support the "
82 "selected return type.");
88 template <
typename ReturnType>
119 template <
class StreamType>
181 static_cast<unsigned int>(f2));
213 static_cast<unsigned int>(f2));
259 const bool use_agg_opt =
261 const int opt_level = (use_agg_opt ? 3 : 2);
271 template <
class StreamType>
275 s <<
" OptimizationFlags|";
298 template <
typename ReturnType,
typename T =
void>
311 template <
typename ReturnType,
typename T =
void>
315# ifdef HAVE_SYMENGINE_LLVM
325 template <
typename ReturnType,
typename T =
void>
326 struct LLVMOptimizer;
345 template <
typename ReturnType,
typename Optimizer,
typename T =
void>
357 template <
typename ReturnType_,
typename T =
void>
358 struct SupportedOptimizerTypeTraits
360 static const bool is_supported =
false;
362 using ReturnType = void;
368 template <
typename ReturnType_>
369 struct SupportedOptimizerTypeTraits<
371 std::enable_if_t<std::is_arithmetic<ReturnType_>::value>>
373 static const bool is_supported =
true;
376 typename std::conditional<std::is_same<ReturnType_, float>::value,
384 template <
typename ReturnType_>
385 struct SupportedOptimizerTypeTraits<
388 boost::is_complex<ReturnType_>::value &&
389 std::is_arithmetic<typename ReturnType_::value_type>::value>>
391 static const bool is_supported =
true;
393 using ReturnType =
typename std::conditional<
394 std::is_same<ReturnType_, std::complex<float>>::value,
396 std::complex<double>>::type;
401 template <
typename ReturnType_>
402 struct DictionaryOptimizer<ReturnType_,
403 std::enable_if_t<SupportedOptimizerTypeTraits<
404 ReturnType_>::is_supported>>
407 typename SupportedOptimizerTypeTraits<ReturnType_>::ReturnType;
409 internal::DictionarySubstitutionVisitor<ReturnType, SD::Expression>;
422 const SymEngine::vec_basic & independent_symbols,
423 const SymEngine::vec_basic & dependent_functions,
427 optimizer.init(independent_symbols,
438 template <
class Archive>
440 save(Archive & archive,
441 const unsigned int version,
444 optimizer.save(archive, version);
453 template <
class Archive>
455 load(Archive & archive,
456 const unsigned int version,
458 const SymEngine::vec_basic & ,
459 const SymEngine::vec_basic & ,
462 optimizer.load(archive, version);
482 template <
typename Stream>
484 print(Stream & stream,
486 const bool print_independent_symbols =
false,
487 const bool print_dependent_functions =
false,
488 const bool print_cse_reductions =
true)
490 optimizer.print(stream,
491 print_independent_symbols,
492 print_dependent_functions,
493 print_cse_reductions);
499 template <
typename ReturnType_>
500 struct LambdaOptimizer<ReturnType_,
501 std::enable_if_t<SupportedOptimizerTypeTraits<
502 ReturnType_>::is_supported>>
505 typename std::conditional<!boost::is_complex<ReturnType_>::value,
507 std::complex<double>>::type;
509 !boost::is_complex<ReturnType_>::value,
510 SymEngine::LambdaRealDoubleVisitor,
511 SymEngine::LambdaComplexDoubleVisitor>::type;
524 const SymEngine::vec_basic & independent_symbols,
525 const SymEngine::vec_basic & dependent_functions,
529 optimizer.init(independent_symbols,
540 template <
class Archive>
552 template <
class Archive>
557 const SymEngine::vec_basic & independent_symbols,
558 const SymEngine::vec_basic & dependent_functions,
561 initialize(optimizer,
584 template <
typename StreamType>
598# ifdef HAVE_SYMENGINE_LLVM
599 template <
typename ReturnType_>
600 struct LLVMOptimizer<
602 std::enable_if_t<std::is_arithmetic<ReturnType_>::value>>
605 typename std::conditional<std::is_same<ReturnType_, float>::value,
609 typename std::conditional<std::is_same<ReturnType_, float>::value,
610 SymEngine::LLVMFloatVisitor,
611 SymEngine::LLVMDoubleVisitor>::type;
617 static const bool supported_by_LLVM =
true;
629 initialize(OptimizerType & optimizer,
630 const SymEngine::vec_basic & independent_symbols,
631 const SymEngine::vec_basic & dependent_functions,
632 const enum OptimizationFlags &optimization_flags)
636 optimizer.init(independent_symbols,
648 template <
class Archive>
650 save(Archive &archive,
652 OptimizerType &optimizer)
654 const std::string llvm_compiled_function = optimizer.dumps();
655 archive & llvm_compiled_function;
664 template <
class Archive>
666 load(Archive &archive,
668 OptimizerType &optimizer,
669 const SymEngine::vec_basic & ,
670 const SymEngine::vec_basic & ,
671 const enum OptimizationFlags & )
673 std::string llvm_compiled_function;
674 archive & llvm_compiled_function;
675 optimizer.loads(llvm_compiled_function);
695 template <
typename StreamType>
698 const OptimizerType & ,
713 template <
typename ReturnType_>
714 struct LLVMOptimizer<
717 boost::is_complex<ReturnType_>::value &&
718 std::is_arithmetic<typename ReturnType_::value_type>::value>>
722 using ReturnType =
typename LambdaOptimizer<ReturnType_>::ReturnType;
724 typename LambdaOptimizer<ReturnType_>::OptimizerType;
730 static const bool supported_by_LLVM =
false;
742 initialize(OptimizerType & ,
743 const SymEngine::vec_basic & ,
744 const SymEngine::vec_basic & ,
745 const enum OptimizationFlags & )
756 template <
class Archive>
771 template <
class Archive>
776 const SymEngine::vec_basic & ,
777 const SymEngine::vec_basic & ,
778 const enum OptimizationFlags & )
800 template <
typename StreamType>
803 const OptimizerType & ,
817 template <
typename ReturnType,
typename Optimizer>
818 struct OptimizerHelper<
822 std::is_same<ReturnType, typename Optimizer::ReturnType>::value>>
833 initialize(
typename Optimizer::OptimizerType *optimizer,
834 const SymEngine::vec_basic & independent_symbols,
835 const SymEngine::vec_basic & dependent_functions,
843 Optimizer::initialize(*optimizer,
865 substitute(
typename Optimizer::OptimizerType *optimizer,
866 std::vector<ReturnType> & output_values,
867 const std::vector<ReturnType> & substitution_values)
870 optimizer->call(output_values.data(), substitution_values.data());
879 template <
class Archive>
881 save(Archive & archive,
882 const unsigned int version,
883 typename Optimizer::OptimizerType *optimizer)
890 Optimizer::save(archive, version, *optimizer);
899 template <
class Archive>
901 load(Archive & archive,
902 const unsigned int version,
903 typename Optimizer::OptimizerType *optimizer,
904 const SymEngine::vec_basic & independent_symbols,
905 const SymEngine::vec_basic & dependent_functions,
913 Optimizer::load(archive,
938 template <
typename Stream>
940 print(Stream & stream,
941 typename Optimizer::OptimizerType *optimizer,
942 const bool print_independent_symbols =
false,
943 const bool print_dependent_functions =
false,
944 const bool print_cse_reductions =
true)
951 Optimizer::print(stream,
953 print_independent_symbols,
954 print_dependent_functions,
955 print_cse_reductions);
959 template <
typename ReturnType,
typename Optimizer>
960 struct OptimizerHelper<
964 !std::is_same<ReturnType, typename Optimizer::ReturnType>::value>>
975 initialize(
typename Optimizer::OptimizerType *optimizer,
976 const SymEngine::vec_basic & independent_symbols,
977 const SymEngine::vec_basic & dependent_functions,
983 optimizer->init(independent_symbols,
1004 substitute(
typename Optimizer::OptimizerType *optimizer,
1005 std::vector<ReturnType> & output_values,
1006 const std::vector<ReturnType> & substitution_values)
1012 std::vector<typename Optimizer::ReturnType> int_outputs(
1013 output_values.size());
1014 std::vector<typename Optimizer::ReturnType> int_inputs(
1015 substitution_values.size());
1017 std::copy(substitution_values.begin(),
1018 substitution_values.end(),
1019 int_inputs.begin());
1020 optimizer->call(int_outputs.data(), int_inputs.data());
1021 std::copy(int_outputs.begin(),
1023 output_values.begin());
1032 template <
class Archive>
1034 save(Archive & archive,
1035 const unsigned int version,
1036 typename Optimizer::OptimizerType *optimizer)
1039 Optimizer::save(archive, version, *optimizer);
1048 template <
class Archive>
1050 load(Archive & archive,
1051 const unsigned int version,
1052 typename Optimizer::OptimizerType *optimizer,
1053 const SymEngine::vec_basic & independent_symbols,
1054 const SymEngine::vec_basic & dependent_functions,
1062 Optimizer::load(archive,
1065 independent_symbols,
1066 dependent_functions,
1067 optimization_flags);
1087 template <
typename Stream>
1089 print(Stream & stream,
1090 typename Optimizer::OptimizerType *optimizer,
1091 const bool print_cse_reductions =
true,
1092 const bool print_independent_symbols =
false,
1093 const bool print_dependent_functions =
false)
1097 optimizer->print(stream,
1098 print_independent_symbols,
1099 print_dependent_functions,
1100 print_cse_reductions);
1131 template <
typename NumberType,
1134 template <
int,
int,
typename>
1136 TensorType<rank, dim, NumberType>
1138 const TensorType<rank, dim, Expression> &symbol_tensor,
1139 const std::vector<NumberType> & cached_evaluation,
1142 TensorType<rank, dim, NumberType> out;
1143 for (
unsigned int i = 0; i < out.n_independent_components; ++i)
1146 out.unrolled_to_component_indices(i));
1148 optimizer.
extract(symbol_tensor[indices], cached_evaluation);
1176 template <
typename NumberType,
int dim>
1180 const std::vector<NumberType> & cached_evaluation,
1184 for (
unsigned int i = 0;
1185 i < SymmetricTensor<2, dim>::n_independent_components;
1187 for (
unsigned int j = 0;
1188 j < SymmetricTensor<2, dim>::n_independent_components;
1192 make_rank_4_tensor_indices<dim>(i, j);
1194 optimizer.
extract(symbol_tensor[indices], cached_evaluation);
1217 template <
typename NumberType,
typename T>
1243 template <
typename NumberType,
typename T>
1246 const std::vector<T> & functions)
1248 for (
const auto &function : functions)
1272 template <
typename NumberType,
typename T,
typename... Args>
1276 const Args &...other_functions)
1296 template <
int,
int,
typename>
1300 const TensorType<rank, dim, Expression> &symbol_tensor)
1303 out.reserve(symbol_tensor.n_independent_components);
1304 for (
unsigned int i = 0; i < symbol_tensor.n_independent_components;
1308 symbol_tensor.unrolled_to_component_indices(i));
1309 out.push_back(symbol_tensor[indices].get_RCP());
1331 for (
unsigned int i = 0;
1332 i < SymmetricTensor<2, dim>::n_independent_components;
1334 for (
unsigned int j = 0;
1335 j < SymmetricTensor<2, dim>::n_independent_components;
1339 make_rank_4_tensor_indices<dim>(i, j);
1340 out.push_back(symbol_tensor[indices].get_RCP());
1439 template <
typename ReturnType>
1516 template <typename Stream>
1518 print(Stream &stream, const
bool print_cse = false) const;
1528 template <class Archive>
1530 save(Archive &archive, const
unsigned int version) const;
1545 template <class Archive>
1547 load(Archive &archive, const
unsigned int version);
1571 template <
class Archive>
1577 BOOST_SERIALIZATION_SPLIT_MEMBER()
1660 template <
int rank,
int dim>
1668 template <
int rank,
int dim>
1696 template <
typename T>
1713 template <
typename T,
typename... Args>
1832 substitute(
const SymEngine::map_basic_basic &substitution_map)
const;
1846 const std::vector<ReturnType> &values)
const;
1859 substitute(
const SymEngine::vec_basic & symbols,
1860 const std::vector<ReturnType> &values)
const;
1899 const std::vector<ReturnType> &
1920 std::vector<ReturnType>
1921 evaluate(
const std::vector<Expression> &funcs)
const;
1931 template <
int rank,
int dim>
1944 template <
int rank,
int dim>
1958 const std::vector<ReturnType> &cached_evaluation)
const;
1968 std::vector<ReturnType>
1969 extract(
const std::vector<Expression> &funcs,
1970 const std::vector<ReturnType> &cached_evaluation)
const;
1980 template <
int rank,
int dim>
1983 const std::vector<ReturnType> & cached_evaluation)
const;
1993 template <
int rank,
int dim>
1996 const std::vector<ReturnType> &cached_evaluation)
const;
2044 const SymEngine::RCP<const SymEngine::Basic> &function)
const;
2141 substitute(
const std::vector<ReturnType> &substitution_values)
const;
2152 template <
typename ReturnType>
2153 template <
typename Stream>
2159 stream <<
"Method? " << optimization_method() <<
'\n';
2160 stream <<
"Flags: " << optimization_flags() <<
'\n';
2161 stream <<
"Optimized? " << (optimized() ?
"Yes" :
"No") <<
'\n';
2162 stream <<
"Values substituted? " << values_substituted() <<
"\n\n";
2165 stream <<
"Symbols (" << n_independent_variables()
2166 <<
" independent variables):" <<
'\n';
2168 for (SD::types::substitution_map::const_iterator it =
2169 independent_variables_symbols.begin();
2170 it != independent_variables_symbols.end();
2173 stream << cntr <<
": " << it->first <<
'\n';
2175 stream <<
'\n' << std::flush;
2178 stream <<
"Functions (" << n_dependent_variables()
2179 <<
" dependent variables):" <<
'\n';
2181 for (
typename SD::types::symbol_vector::const_iterator it =
2182 dependent_variables_functions.begin();
2183 it != dependent_variables_functions.end();
2186 stream << cntr <<
": " << (*it) <<
'\n';
2188 stream <<
'\n' << std::flush;
2191 if (optimized() ==
true && use_symbolic_CSE() ==
true)
2194 const bool print_cse_reductions =
true;
2195 const bool print_independent_symbols =
false;
2196 const bool print_dependent_functions =
false;
2200 Assert(
dynamic_cast<typename internal::DictionaryOptimizer<
2202 ExcMessage(
"Cannot cast optimizer to Dictionary type."));
2204 internal::OptimizerHelper<
2206 internal::DictionaryOptimizer<ReturnType>>::
2208 dynamic_cast<typename internal::DictionaryOptimizer<
2210 print_independent_symbols,
2211 print_dependent_functions,
2212 print_cse_reductions);
2214 stream <<
'\n' << std::flush;
2218 Assert(
dynamic_cast<typename internal::LambdaOptimizer<
2220 ExcMessage(
"Cannot cast optimizer to Lambda type."));
2222 internal::OptimizerHelper<ReturnType,
2223 internal::LambdaOptimizer<ReturnType>>::
2225 dynamic_cast<typename internal::LambdaOptimizer<
2227 print_independent_symbols,
2228 print_dependent_functions,
2229 print_cse_reductions);
2231# ifdef HAVE_SYMENGINE_LLVM
2234 Assert(
dynamic_cast<typename internal::LLVMOptimizer<
2236 ExcMessage(
"Cannot cast optimizer to LLVM type."));
2238 internal::OptimizerHelper<ReturnType,
2239 internal::LLVMOptimizer<ReturnType>>::
2241 dynamic_cast<typename internal::LLVMOptimizer<
2243 print_independent_symbols,
2244 print_dependent_functions,
2245 print_cse_reductions);
2254 if (values_substituted())
2256 stream <<
"Evaluated functions:" <<
'\n';
2257 stream << std::flush;
2259 for (
typename std::vector<ReturnType>::const_iterator it =
2260 dependent_variables_output.begin();
2261 it != dependent_variables_output.end();
2264 stream << cntr <<
": " << (*it) <<
'\n';
2266 stream <<
'\n' << std::flush;
2272 template <
typename ReturnType>
2273 template <
class Archive>
2276 const unsigned int version)
const
2281 static_cast<typename std::underlying_type<OptimizerType>::type
>(
2287 static_cast<typename std::underlying_type<OptimizationFlags>::type
>(
2294 ar &independent_variables_symbols;
2295 ar &dependent_variables_functions;
2297 ar &dependent_variables_output;
2298 ar &map_dep_expr_vec_entry;
2299 ar &ready_for_value_extraction;
2302 has_been_serialized =
true;
2303 ar &has_been_serialized;
2311 if (
typename internal::DictionaryOptimizer<ReturnType>::OptimizerType
2312 *opt =
dynamic_cast<typename internal::DictionaryOptimizer<
2317 internal::OptimizerHelper<
2319 internal::DictionaryOptimizer<ReturnType>>::save(ar, version, opt);
2321 else if (
typename internal::LambdaOptimizer<ReturnType>::OptimizerType
2322 *opt =
dynamic_cast<typename internal::LambdaOptimizer<
2327 internal::OptimizerHelper<
2329 internal::LambdaOptimizer<ReturnType>>::save(ar, version, opt);
2331# ifdef HAVE_SYMENGINE_LLVM
2332 else if (
typename internal::LLVMOptimizer<ReturnType>::OptimizerType
2333 *opt =
dynamic_cast<typename internal::LLVMOptimizer<
2338 internal::OptimizerHelper<
2340 internal::LLVMOptimizer<ReturnType>>::save(ar, version, opt);
2351 template <
typename ReturnType>
2352 template <
class Archive>
2364 typename std::underlying_type<OptimizerType>::type m;
2369 typename std::underlying_type<OptimizationFlags>::type f;
2376 ar &independent_variables_symbols;
2377 ar &dependent_variables_functions;
2379 ar &dependent_variables_output;
2380 ar &map_dep_expr_vec_entry;
2381 ar &ready_for_value_extraction;
2383 ar &has_been_serialized;
2390 create_optimizer(optimizer);
2399 if (
typename internal::DictionaryOptimizer<ReturnType>::OptimizerType
2400 *opt =
dynamic_cast<typename internal::DictionaryOptimizer<
2405 internal::OptimizerHelper<ReturnType,
2406 internal::DictionaryOptimizer<ReturnType>>::
2413 dependent_variables_functions),
2414 optimization_flags());
2416 else if (
typename internal::LambdaOptimizer<ReturnType>::OptimizerType
2417 *opt =
dynamic_cast<typename internal::LambdaOptimizer<
2422 internal::OptimizerHelper<ReturnType,
2423 internal::LambdaOptimizer<ReturnType>>::
2430 dependent_variables_functions),
2431 optimization_flags());
2433# ifdef HAVE_SYMENGINE_LLVM
2434 else if (
typename internal::LLVMOptimizer<ReturnType>::OptimizerType
2435 *opt =
dynamic_cast<typename internal::LLVMOptimizer<
2440 internal::OptimizerHelper<ReturnType,
2441 internal::LLVMOptimizer<ReturnType>>::
2448 dependent_variables_functions),
2449 optimization_flags());
2460 template <
typename ReturnType>
2461 template <
int rank,
int dim>
2466 Assert(optimized() ==
false,
2468 "Cannot register functions once the optimizer is finalised."));
2470 register_vector_functions(
2476 template <
typename ReturnType>
2477 template <
int rank,
int dim>
2482 Assert(optimized() ==
false,
2484 "Cannot register functions once the optimizer is finalised."));
2486 register_vector_functions(
2492 template <
typename ReturnType>
2493 template <
typename T,
typename... Args>
2497 const Args &...other_functions)
2505 template <
typename ReturnType>
2506 template <
typename T>
2509 const std::vector<T> &functions)
2516 template <
typename ReturnType>
2517 template <
int rank,
int dim>
2521 const std::vector<ReturnType> & cached_evaluation)
const
2530 template <
typename ReturnType>
2531 template <
int rank,
int dim>
2537 values_substituted() ==
true,
2539 "The optimizer is not configured to perform evaluation. "
2540 "This action can only performed after substitute() has been called."));
2542 return extract(funcs, dependent_variables_output);
2547 template <
typename ReturnType>
2548 template <
int rank,
int dim>
2552 const std::vector<ReturnType> & cached_evaluation)
const
2561 template <
typename ReturnType>
2562 template <
int rank,
int dim>
2568 values_substituted() ==
true,
2570 "The optimizer is not configured to perform evaluation. "
2571 "This action can only performed after substitute() has been called."));
2573 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)