4#include "lmmc/config.h"
12 if (
function.arguments().size() != 1) {
38 std::vector<std::shared_ptr<const SymbolicNode>> terms) {
40 return SymbolicExpr::number(0);
42 if (terms.size() == 1) {
54 const std::shared_ptr<const SymbolicNode>&
node,
const std::string& var) {
55 auto function = std::dynamic_pointer_cast<const FunctionNode>(
node);
60 auto product = std::dynamic_pointer_cast<const MultiplyNode>(
node);
64 std::vector<std::shared_ptr<const SymbolicNode>> coefficients;
65 std::shared_ptr<const FunctionNode> found;
66 for (
const auto& operand : product->operands()) {
67 auto candidate = std::dynamic_pointer_cast<const FunctionNode>(operand);
72 coefficients.push_back(operand);
86 const AddNode& sum,
const std::string& var) {
87 std::optional<ScaledFunction>
function;
88 std::vector<std::shared_ptr<const SymbolicNode>> constants;
89 for (
const auto& operand : sum.
operands()) {
98 constants.push_back(operand);
103 auto negative = SymbolicExpr::multiply(
104 constant_sum(std::move(constants)), SymbolicExpr::number(-1));
112 std::vector<std::shared_ptr<const SymbolicNode>> remaining;
113 for (std::size_t i = 0; i < product.
operands().size(); ++i) {
115 remaining.push_back(product.
operands()[i]);
118 if (remaining.size() == 1) {
126 for (std::size_t i = 0; i < product.
operands().size(); ++i) {
127 auto function = std::dynamic_pointer_cast<const FunctionNode>(product.
operands()[i]);
129 function->arguments().size() != 1) {
132 const auto& argument =
function->arguments()[0];
134 const bool equal = !remainder || !argument
135 ? remainder == argument : remainder->equals(*argument);
147 (
context).limits().max_ast_nodes,
"transform");
151 for (std::size_t index = 0; index < 2; ++index) {
152 auto exponential = std::dynamic_pointer_cast<const FunctionNode>(
156 exponential->arguments().size() != 1) {
159 const auto& argument = exponential->arguments()[0];
160 const auto& other = sum.
operands()[1 - index];
161 if (!argument || !other || !argument->equals(*other) ||
176 (
context).limits().max_ast_nodes,
"transform");
180 std::optional<std::shared_ptr<SymbolicExpr>> found;
181 std::vector<std::shared_ptr<const SymbolicNode>> constants;
182 bool other_variables =
false;
183 for (
const auto& operand : sum.
operands()) {
184 auto product = std::dynamic_pointer_cast<const MultiplyNode>(operand);
187 if (candidate && !found) {
193 constants.push_back(operand);
195 other_variables =
true;
198 if (!found || other_variables) {
202 constant_sum(std::move(constants)), SymbolicExpr::number(-1))), transform_budget));
216 std::abs(
value - 1.0) > LMMC_REAL_EPSILON) {
225 (
context).limits().max_ast_nodes,
"transform");
226 std::optional<ExpBasePattern> found;
227 std::vector<std::shared_ptr<const SymbolicNode>> constants;
228 bool other_variables =
false;
229 for (
const auto& operand : sum.
operands()) {
230 if (
auto power = std::dynamic_pointer_cast<const PowerNode>(operand)) {
232 if (candidate && !found) {
233 found = std::move(candidate);
238 constants.push_back(operand);
240 other_variables =
true;
243 if (!found || other_variables) {
247 constant_sum(std::move(constants)), SymbolicExpr::number(-1))), transform_budget));
254 const std::shared_ptr<SymbolicExpr>& expr,
const std::string& var) {
255 if (!expr || !
node(expr)) {
258 if (
auto function = std::dynamic_pointer_cast<const FunctionNode>(
node(expr))) {
259 if (invertible_function(*
function, var)) {
264 if (
auto sum = std::dynamic_pointer_cast<const AddNode>(
node(expr))) {
265 return additive_function_pattern(*sum, var);
272 if (!expr || !
node(expr)) {
275 if (
auto product = std::dynamic_pointer_cast<const MultiplyNode>(
node(expr))) {
276 auto inner = lambert_inner(*product, var);
281 if (
auto sum = std::dynamic_pointer_cast<const AddNode>(
node(expr))) {
282 return additive_lambert_pattern(*sum, var,
context);
288 const std::shared_ptr<SymbolicExpr>& expr,
const std::string& var,
290 if (!expr || !
node(expr)) {
293 if (
auto power = std::dynamic_pointer_cast<const PowerNode>(
node(expr))) {
294 auto pattern = power_pattern(*power, var,
context);
296 pattern->rhs = SymbolicExpr::number(0);
300 if (
auto sum = std::dynamic_pointer_cast<const AddNode>(
node(expr))) {
301 return additive_power_pattern(*sum, var,
context);
const std::vector< std::shared_ptr< const SymbolicNode > > & operands() const noexcept
函数节点,表示数学函数调用(三角函数、对数、特殊函数等)。
const std::vector< std::shared_ptr< const SymbolicNode > > & operands() const noexcept
const std::shared_ptr< const SymbolicNode > & exponent() const noexcept
const std::shared_ptr< const SymbolicNode > & base() const noexcept
static std::shared_ptr< const SymbolicNode > create_multiply(std::vector< std::shared_ptr< const SymbolicNode > > ops, detail::RewriteBudget *budget=nullptr)
创建乘法节点,自动扁平化嵌套乘法并消除单位元.
std::optional< LambertWPattern > opposite_exponential_lambert_pattern(const AddNode &sum, const std::string &var, ComputationContext &context)
std::optional< ScaledFunction > scaled_function(const std::shared_ptr< const SymbolicNode > &node, const std::string &var)
std::optional< LambertWPattern > additive_lambert_pattern(const AddNode &sum, const std::string &var, ComputationContext &context)
std::shared_ptr< SymbolicExpr > constant_sum(std::vector< std::shared_ptr< const SymbolicNode > > terms)
std::optional< InversePattern > additive_function_pattern(const AddNode &sum, const std::string &var)
std::optional< ExpBasePattern > additive_power_pattern(const AddNode &sum, const std::string &var, ComputationContext &context)
std::shared_ptr< const FunctionNode > function
std::shared_ptr< const SymbolicNode > product_without(const MultiplyNode &product, std::size_t index)
bool invertible_function(const FunctionNode &function, const std::string &)
std::optional< std::shared_ptr< SymbolicExpr > > lambert_inner(const MultiplyNode &product, const std::string &var)
std::shared_ptr< const SymbolicNode > coefficient
std::optional< ExpBasePattern > power_pattern(const PowerNode &power, const std::string &var, ComputationContext &context)
std::optional< LambertWPattern > decompose_lambert_w_pattern(const std::shared_ptr< SymbolicExpr > &expr, const std::string &var, ComputationContext &context)
std::optional< ExpBasePattern > decompose_exp_base_pattern(const std::shared_ptr< SymbolicExpr > &expr, const std::string &var, ComputationContext &context)
std::optional< InversePattern > decompose_trig_exp_pattern(const std::shared_ptr< SymbolicExpr > &expr, const std::string &var)
bool try_evaluate_numeric(const std::shared_ptr< SymbolicExpr > &expr, lmmc_real_t &out, ComputationContext &context)
std::shared_ptr<::LMCAS::SymbolicExpr > make_expression_ptr(SymbolicNodePtr root)
const SymbolicNodePtr & node(const ::LMCAS::SymbolicExpr &expression) noexcept
std::shared_ptr< const Node > make_node(Args &&... args)
SymbolicNodePtr normalize_node(const SymbolicNodePtr &node, RewriteBudget &budget, const FactsQuery &facts, Domain domain)
std::size_t std::size_t ComputationContext & context
bool expression_depends_on_variable(const detail::SymbolicNodePtr &expression, const std::string &variable, detail::RewriteBudget *budget)
const std::string const ExprPtr & value
ExprResult function(const std::string &name, std::vector< ExprPtr > arguments)