13#ifndef dealii_differentiation_sd_symengine_optimizer_h
14#define dealii_differentiation_sd_symengine_optimizer_h
18#ifdef DEAL_II_WITH_SYMENGINE
21# include <symengine/basic.h>
22# include <symengine/dict.h>
23# include <symengine/symengine_exception.h>
24# include <symengine/symengine_rcp.h>
27# include <symengine/lambda_double.h>
28# include <symengine/visitor.h>
29# ifdef HAVE_SYMENGINE_LLVM
30# include <symengine/llvm_double.h>
42# include <boost/serialization/split_member.hpp>
43# include <boost/type_traits.hpp>
48# include <type_traits>
56#ifdef DEAL_II_WITH_SYMENGINE
71 "SymEngine has not been built with LLVM support.");
78 "The SymEngine LLVM optimizer does not (yet) support the "
79 "selected return type.");
85 template <
typename ReturnType>
116 template <
typename StreamType>
178 static_cast<unsigned int>(f2));
210 static_cast<unsigned int>(f2));
256 const bool use_agg_opt =
258 const int opt_level = (use_agg_opt ? 3 : 2);
268 template <
typename StreamType>
272 s <<
" OptimizationFlags|";
295 template <
typename ReturnType,
typename T =
void>
308 template <
typename ReturnType,
typename T =
void>
312# ifdef HAVE_SYMENGINE_LLVM
322 template <
typename ReturnType,
typename T =
void>
323 struct LLVMOptimizer;
342 template <
typename ReturnType,
typename Optimizer,
typename T =
void>
354 template <
typename ReturnType_,
typename T =
void>
355 struct SupportedOptimizerTypeTraits
357 static const bool is_supported =
false;
359 using ReturnType = void;
365 template <
typename ReturnType_>
366 struct SupportedOptimizerTypeTraits<
368 std::enable_if_t<std::is_arithmetic_v<ReturnType_>>>
370 static const bool is_supported =
true;
373 std::conditional_t<std::is_same_v<ReturnType_, float>, float,
double>;
379 template <
typename ReturnType_>
380 struct SupportedOptimizerTypeTraits<
383 boost::is_complex<ReturnType_>::value &&
384 std::is_arithmetic_v<typename ReturnType_::value_type>>>
386 static const bool is_supported =
true;
389 std::conditional_t<std::is_same_v<ReturnType_, std::complex<float>>,
391 std::complex<double>>;
396 template <
typename ReturnType_>
397 struct DictionaryOptimizer<ReturnType_,
398 std::enable_if_t<SupportedOptimizerTypeTraits<
399 ReturnType_>::is_supported>>
402 typename SupportedOptimizerTypeTraits<ReturnType_>::ReturnType;
404 internal::DictionarySubstitutionVisitor<ReturnType, SD::Expression>;
417 const SymEngine::vec_basic &independent_symbols,
418 const SymEngine::vec_basic &dependent_functions,
422 optimizer.init(independent_symbols,
433 template <
class Archive>
435 save(Archive &archive,
436 const unsigned int version,
439 optimizer.save(archive, version);
448 template <
class Archive>
450 load(Archive &archive,
451 const unsigned int version,
453 const SymEngine::vec_basic & ,
454 const SymEngine::vec_basic & ,
457 optimizer.load(archive, version);
477 template <
typename Stream>
479 print(Stream &stream,
481 const bool print_independent_symbols =
false,
482 const bool print_dependent_functions =
false,
483 const bool print_cse_reductions =
true)
485 optimizer.print(stream,
486 print_independent_symbols,
487 print_dependent_functions,
488 print_cse_reductions);
494 template <
typename ReturnType_>
495 struct LambdaOptimizer<ReturnType_,
496 std::enable_if_t<SupportedOptimizerTypeTraits<
497 ReturnType_>::is_supported>>
500 std::conditional_t<!boost::is_complex<ReturnType_>::value,
502 std::complex<double>>;
504 std::conditional_t<!boost::is_complex<ReturnType_>::value,
505 SymEngine::LambdaRealDoubleVisitor,
506 SymEngine::LambdaComplexDoubleVisitor>;
519 const SymEngine::vec_basic &independent_symbols,
520 const SymEngine::vec_basic &dependent_functions,
524 optimizer.init(independent_symbols,
535 template <
class Archive>
547 template <
class Archive>
552 const SymEngine::vec_basic &independent_symbols,
553 const SymEngine::vec_basic &dependent_functions,
556 initialize(optimizer,
579 template <
typename StreamType>
593# ifdef HAVE_SYMENGINE_LLVM
594 template <
typename ReturnType_>
595 struct LLVMOptimizer<ReturnType_,
596 std::enable_if_t<std::is_arithmetic_v<ReturnType_>>>
599 std::conditional_t<std::is_same_v<ReturnType_, float>, float,
double>;
601 std::conditional_t<std::is_same_v<ReturnType_, float>,
602 SymEngine::LLVMFloatVisitor,
603 SymEngine::LLVMDoubleVisitor>;
609 static const bool supported_by_LLVM =
true;
621 initialize(OptimizerType &optimizer,
622 const SymEngine::vec_basic &independent_symbols,
623 const SymEngine::vec_basic &dependent_functions,
624 const enum OptimizationFlags &optimization_flags)
628 optimizer.init(independent_symbols,
640 template <
class Archive>
642 save(Archive &archive,
644 OptimizerType &optimizer)
646 const std::string llvm_compiled_function = optimizer.dumps();
647 archive &llvm_compiled_function;
656 template <
class Archive>
658 load(Archive &archive,
660 OptimizerType &optimizer,
661 const SymEngine::vec_basic & ,
662 const SymEngine::vec_basic & ,
663 const enum OptimizationFlags & )
665 std::string llvm_compiled_function;
666 archive &llvm_compiled_function;
667 optimizer.loads(llvm_compiled_function);
687 template <
typename StreamType>
690 const OptimizerType & ,
705 template <
typename ReturnType_>
706 struct LLVMOptimizer<
709 boost::is_complex<ReturnType_>::value &&
710 std::is_arithmetic_v<typename ReturnType_::value_type>>>
714 using ReturnType =
typename LambdaOptimizer<ReturnType_>::ReturnType;
716 typename LambdaOptimizer<ReturnType_>::OptimizerType;
722 static const bool supported_by_LLVM =
false;
734 initialize(OptimizerType & ,
735 const SymEngine::vec_basic & ,
736 const SymEngine::vec_basic & ,
737 const enum OptimizationFlags & )
748 template <
class Archive>
763 template <
class Archive>
768 const SymEngine::vec_basic & ,
769 const SymEngine::vec_basic & ,
770 const enum OptimizationFlags & )
792 template <
typename StreamType>
795 const OptimizerType & ,
809 template <
typename ReturnType,
typename Optimizer>
810 struct OptimizerHelper<
814 std::is_same_v<ReturnType, typename Optimizer::ReturnType>>>
825 initialize(
typename Optimizer::OptimizerType *optimizer,
826 const SymEngine::vec_basic &independent_symbols,
827 const SymEngine::vec_basic &dependent_functions,
835 Optimizer::initialize(*optimizer,
857 substitute(
typename Optimizer::OptimizerType *optimizer,
858 std::vector<ReturnType> &output_values,
859 const std::vector<ReturnType> &substitution_values)
862 optimizer->call(output_values.data(), substitution_values.data());
871 template <
class Archive>
873 save(Archive &archive,
874 const unsigned int version,
875 typename Optimizer::OptimizerType *optimizer)
882 Optimizer::save(archive, version, *optimizer);
891 template <
class Archive>
893 load(Archive &archive,
894 const unsigned int version,
895 typename Optimizer::OptimizerType *optimizer,
896 const SymEngine::vec_basic &independent_symbols,
897 const SymEngine::vec_basic &dependent_functions,
905 Optimizer::load(archive,
930 template <
typename Stream>
932 print(Stream &stream,
933 typename Optimizer::OptimizerType *optimizer,
934 const bool print_independent_symbols =
false,
935 const bool print_dependent_functions =
false,
936 const bool print_cse_reductions =
true)
943 Optimizer::print(stream,
945 print_independent_symbols,
946 print_dependent_functions,
947 print_cse_reductions);
951 template <
typename ReturnType,
typename Optimizer>
952 struct OptimizerHelper<
956 !std::is_same_v<ReturnType, typename Optimizer::ReturnType>>>
967 initialize(
typename Optimizer::OptimizerType *optimizer,
968 const SymEngine::vec_basic &independent_symbols,
969 const SymEngine::vec_basic &dependent_functions,
975 optimizer->init(independent_symbols,
996 substitute(
typename Optimizer::OptimizerType *optimizer,
997 std::vector<ReturnType> &output_values,
998 const std::vector<ReturnType> &substitution_values)
1004 std::vector<typename Optimizer::ReturnType> int_outputs(
1005 output_values.size());
1006 std::vector<typename Optimizer::ReturnType> int_inputs(
1007 substitution_values.size());
1009 std::copy(substitution_values.begin(),
1010 substitution_values.end(),
1011 int_inputs.begin());
1012 optimizer->call(int_outputs.data(), int_inputs.data());
1013 std::copy(int_outputs.begin(),
1015 output_values.begin());
1024 template <
class Archive>
1026 save(Archive &archive,
1027 const unsigned int version,
1028 typename Optimizer::OptimizerType *optimizer)
1031 Optimizer::save(archive, version, *optimizer);
1040 template <
class Archive>
1042 load(Archive &archive,
1043 const unsigned int version,
1044 typename Optimizer::OptimizerType *optimizer,
1045 const SymEngine::vec_basic &independent_symbols,
1046 const SymEngine::vec_basic &dependent_functions,
1054 Optimizer::load(archive,
1057 independent_symbols,
1058 dependent_functions,
1059 optimization_flags);
1079 template <
typename Stream>
1081 print(Stream &stream,
1082 typename Optimizer::OptimizerType *optimizer,
1083 const bool print_cse_reductions =
true,
1084 const bool print_independent_symbols =
false,
1085 const bool print_dependent_functions =
false)
1089 optimizer->print(stream,
1090 print_independent_symbols,
1091 print_dependent_functions,
1092 print_cse_reductions);
1123 template <
typename NumberType,
1126 template <
int,
int,
typename>
1128 TensorType<rank, dim, NumberType>
1130 const TensorType<rank, dim, Expression> &symbol_tensor,
1131 const std::vector<NumberType> &cached_evaluation,
1134 TensorType<rank, dim, NumberType> out;
1135 for (
unsigned int i = 0; i < out.n_independent_components; ++i)
1138 out.unrolled_to_component_indices(i));
1140 optimizer.
extract(symbol_tensor[indices], cached_evaluation);
1168 template <
typename NumberType,
int dim>
1172 const std::vector<NumberType> &cached_evaluation,
1176 for (
unsigned int i = 0;
1177 i < SymmetricTensor<2, dim>::n_independent_components;
1179 for (
unsigned int j = 0;
1180 j < SymmetricTensor<2, dim>::n_independent_components;
1184 make_rank_4_tensor_indices<dim>(i, j);
1186 optimizer.
extract(symbol_tensor[indices], cached_evaluation);
1209 template <
typename NumberType,
typename T>
1235 template <
typename NumberType,
typename T>
1238 const std::vector<T> &functions)
1240 for (
const auto &function : functions)
1264 template <
typename NumberType,
typename T,
typename... Args>
1268 const Args &...other_functions)
1288 template <
int,
int,
typename>
1292 const TensorType<rank, dim, Expression> &symbol_tensor)
1295 out.reserve(symbol_tensor.n_independent_components);
1296 for (
unsigned int i = 0; i < symbol_tensor.n_independent_components;
1300 symbol_tensor.unrolled_to_component_indices(i));
1301 out.push_back(symbol_tensor[indices].get_RCP());
1323 for (
unsigned int i = 0;
1324 i < SymmetricTensor<2, dim>::n_independent_components;
1326 for (
unsigned int j = 0;
1327 j < SymmetricTensor<2, dim>::n_independent_components;
1331 make_rank_4_tensor_indices<dim>(i, j);
1332 out.push_back(symbol_tensor[indices].get_RCP());
1431 template <
typename ReturnType>
1508 template <typename Stream>
1510 print(Stream &stream, const
bool print_cse = false) const;
1520 template <class Archive>
1522 save(Archive &archive, const
unsigned int version) const;
1537 template <class Archive>
1539 load(Archive &archive, const
unsigned int version);
1563 template <
class Archive>
1569 BOOST_SERIALIZATION_SPLIT_MEMBER()
1652 template <
int rank,
int dim>
1660 template <
int rank,
int dim>
1688 template <
typename T>
1705 template <
typename T,
typename... Args>
1824 substitute(
const SymEngine::map_basic_basic &substitution_map)
const;
1838 const std::vector<ReturnType> &values)
const;
1851 substitute(
const SymEngine::vec_basic &symbols,
1852 const std::vector<ReturnType> &values)
const;
1891 const std::vector<ReturnType> &
1912 std::vector<ReturnType>
1913 evaluate(
const std::vector<Expression> &funcs)
const;
1923 template <
int rank,
int dim>
1936 template <
int rank,
int dim>
1950 const std::vector<ReturnType> &cached_evaluation)
const;
1960 std::vector<ReturnType>
1961 extract(
const std::vector<Expression> &funcs,
1962 const std::vector<ReturnType> &cached_evaluation)
const;
1972 template <
int rank,
int dim>
1975 const std::vector<ReturnType> &cached_evaluation)
const;
1985 template <
int rank,
int dim>
1988 const std::vector<ReturnType> &cached_evaluation)
const;
2036 const SymEngine::RCP<const SymEngine::Basic> &function)
const;
2133 substitute(
const std::vector<ReturnType> &substitution_values)
const;
2144 template <
typename ReturnType>
2145 template <
typename Stream>
2151 stream <<
"Method? " << optimization_method() <<
'\n';
2152 stream <<
"Flags: " << optimization_flags() <<
'\n';
2153 stream <<
"Optimized? " << (optimized() ?
"Yes" :
"No") <<
'\n';
2154 stream <<
"Values substituted? " << values_substituted() <<
"\n\n";
2157 stream <<
"Symbols (" << n_independent_variables()
2158 <<
" independent variables):" <<
'\n';
2160 for (SD::types::substitution_map::const_iterator it =
2161 independent_variables_symbols.begin();
2162 it != independent_variables_symbols.end();
2165 stream << cntr <<
": " << it->first <<
'\n';
2167 stream <<
'\n' << std::flush;
2170 stream <<
"Functions (" << n_dependent_variables()
2171 <<
" dependent variables):" <<
'\n';
2173 for (
typename SD::types::symbol_vector::const_iterator it =
2174 dependent_variables_functions.begin();
2175 it != dependent_variables_functions.end();
2178 stream << cntr <<
": " << (*it) <<
'\n';
2180 stream <<
'\n' << std::flush;
2183 if (optimized() ==
true && use_symbolic_CSE() ==
true)
2186 const bool print_cse_reductions =
true;
2187 const bool print_independent_symbols =
false;
2188 const bool print_dependent_functions =
false;
2192 Assert(
dynamic_cast<typename internal::DictionaryOptimizer<
2194 ExcMessage(
"Cannot cast optimizer to Dictionary type."));
2196 internal::OptimizerHelper<
2198 internal::DictionaryOptimizer<ReturnType>>::
2200 dynamic_cast<typename internal::DictionaryOptimizer<
2202 print_independent_symbols,
2203 print_dependent_functions,
2204 print_cse_reductions);
2206 stream <<
'\n' << std::flush;
2210 Assert(
dynamic_cast<typename internal::LambdaOptimizer<
2212 ExcMessage(
"Cannot cast optimizer to Lambda type."));
2214 internal::OptimizerHelper<ReturnType,
2215 internal::LambdaOptimizer<ReturnType>>::
2217 dynamic_cast<typename internal::LambdaOptimizer<
2219 print_independent_symbols,
2220 print_dependent_functions,
2221 print_cse_reductions);
2223# ifdef HAVE_SYMENGINE_LLVM
2226 Assert(
dynamic_cast<typename internal::LLVMOptimizer<
2228 ExcMessage(
"Cannot cast optimizer to LLVM type."));
2230 internal::OptimizerHelper<ReturnType,
2231 internal::LLVMOptimizer<ReturnType>>::
2233 dynamic_cast<typename internal::LLVMOptimizer<
2235 print_independent_symbols,
2236 print_dependent_functions,
2237 print_cse_reductions);
2246 if (values_substituted())
2248 stream <<
"Evaluated functions:" <<
'\n';
2249 stream << std::flush;
2251 for (
typename std::vector<ReturnType>::const_iterator it =
2252 dependent_variables_output.begin();
2253 it != dependent_variables_output.end();
2256 stream << cntr <<
": " << (*it) <<
'\n';
2258 stream <<
'\n' << std::flush;
2264 template <
typename ReturnType>
2265 template <
class Archive>
2268 const unsigned int version)
const
2273 static_cast<std::underlying_type_t<OptimizerType>
>(method);
2278 static_cast<std::underlying_type_t<OptimizationFlags>
>(flags);
2284 ar &independent_variables_symbols;
2285 ar &dependent_variables_functions;
2287 ar &dependent_variables_output;
2288 ar &map_dep_expr_vec_entry;
2289 ar &ready_for_value_extraction;
2292 has_been_serialized =
true;
2293 ar &has_been_serialized;
2301 if (
typename internal::DictionaryOptimizer<ReturnType>::OptimizerType
2302 *opt =
dynamic_cast<typename internal::DictionaryOptimizer<
2307 internal::OptimizerHelper<
2309 internal::DictionaryOptimizer<ReturnType>>::save(ar, version, opt);
2311 else if (
typename internal::LambdaOptimizer<ReturnType>::OptimizerType
2312 *opt =
dynamic_cast<typename internal::LambdaOptimizer<
2317 internal::OptimizerHelper<
2319 internal::LambdaOptimizer<ReturnType>>::save(ar, version, opt);
2321# ifdef HAVE_SYMENGINE_LLVM
2322 else if (
typename internal::LLVMOptimizer<ReturnType>::OptimizerType
2323 *opt =
dynamic_cast<typename internal::LLVMOptimizer<
2328 internal::OptimizerHelper<
2330 internal::LLVMOptimizer<ReturnType>>::save(ar, version, opt);
2341 template <
typename ReturnType>
2342 template <
class Archive>
2354 std::underlying_type_t<OptimizerType> m;
2359 std::underlying_type_t<OptimizationFlags> f;
2366 ar &independent_variables_symbols;
2367 ar &dependent_variables_functions;
2369 ar &dependent_variables_output;
2370 ar &map_dep_expr_vec_entry;
2371 ar &ready_for_value_extraction;
2373 ar &has_been_serialized;
2380 create_optimizer(optimizer);
2389 if (
typename internal::DictionaryOptimizer<ReturnType>::OptimizerType
2390 *opt =
dynamic_cast<typename internal::DictionaryOptimizer<
2395 internal::OptimizerHelper<ReturnType,
2396 internal::DictionaryOptimizer<ReturnType>>::
2403 dependent_variables_functions),
2404 optimization_flags());
2406 else if (
typename internal::LambdaOptimizer<ReturnType>::OptimizerType
2407 *opt =
dynamic_cast<typename internal::LambdaOptimizer<
2412 internal::OptimizerHelper<ReturnType,
2413 internal::LambdaOptimizer<ReturnType>>::
2420 dependent_variables_functions),
2421 optimization_flags());
2423# ifdef HAVE_SYMENGINE_LLVM
2424 else if (
typename internal::LLVMOptimizer<ReturnType>::OptimizerType
2425 *opt =
dynamic_cast<typename internal::LLVMOptimizer<
2430 internal::OptimizerHelper<ReturnType,
2431 internal::LLVMOptimizer<ReturnType>>::
2438 dependent_variables_functions),
2439 optimization_flags());
2450 template <
typename ReturnType>
2451 template <
int rank,
int dim>
2456 Assert(optimized() ==
false,
2458 "Cannot register functions once the optimizer is finalised."));
2460 register_vector_functions(
2466 template <
typename ReturnType>
2467 template <
int rank,
int dim>
2472 Assert(optimized() ==
false,
2474 "Cannot register functions once the optimizer is finalised."));
2476 register_vector_functions(
2482 template <
typename ReturnType>
2483 template <
typename T,
typename... Args>
2487 const Args &...other_functions)
2495 template <
typename ReturnType>
2496 template <
typename T>
2499 const std::vector<T> &functions)
2506 template <
typename ReturnType>
2507 template <
int rank,
int dim>
2511 const std::vector<ReturnType> &cached_evaluation)
const
2520 template <
typename ReturnType>
2521 template <
int rank,
int dim>
2527 values_substituted() ==
true,
2529 "The optimizer is not configured to perform evaluation. "
2530 "This action can only performed after substitute() has been called."));
2532 return extract(funcs, dependent_variables_output);
2537 template <
typename ReturnType>
2538 template <
int rank,
int dim>
2542 const std::vector<ReturnType> &cached_evaluation)
const
2551 template <
typename ReturnType>
2552 template <
int rank,
int dim>
2558 values_substituted() ==
true,
2560 "The optimizer is not configured to perform evaluation. "
2561 "This action can only performed after substitute() has been called."));
2563 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)
void load(Archive &ar, ::std_cxx26::inplace_vector< T, N > &vec, const unsigned int)
void save(Archive &ar, const ::std_cxx26::inplace_vector< T, N > &vec, const unsigned int)