17 auto candidate = node;
20 if (
const auto multiply =
21 std::dynamic_pointer_cast<const MultiplyNode>(node);
22 multiply && multiply->operands().size() == 2) {
23 const auto first_number =
24 std::dynamic_pointer_cast<const NumberNode>(
25 multiply->operands()[0]);
26 const auto second_number =
27 std::dynamic_pointer_cast<const NumberNode>(
28 multiply->operands()[1]);
30 coefficient = first_number;
31 candidate = multiply->operands()[1];
32 }
else if (second_number) {
33 coefficient = second_number;
34 candidate = multiply->operands()[0];
38 std::dynamic_pointer_cast<const PowerNode>(candidate);
43 std::dynamic_pointer_cast<const FunctionNode>(power->base());
55 auto multiply = std::dynamic_pointer_cast<const MultiplyNode>(node);
56 if (!multiply) {
return std::nullopt; }
58 bool found_negative_one =
false;
59 std::vector<detail::SymbolicNodePtr> remaining;
62 remaining.reserve(multiply->operands().size());
63 for (
const auto& operand : multiply->operands()) {
65 found_negative_one =
true;
69 remaining.push_back(operand);
71 if (!found_negative_one || remaining.empty()) {
return std::nullopt; }
72 if (remaining.size() == 1) {
81 std::vector<detail::SymbolicNodePtr> rewritten;
84 rewritten.reserve(operands.size());
85 for (
const auto& operand : operands) {
93std::optional<std::pair<std::size_t, detail::SymbolicNodePtr>>
95 const std::vector<detail::SymbolicNodePtr>& nodes,
96 const std::vector<bool>& used, std::size_t index) {
98 if (!square) {
return std::nullopt; }
99 const auto complement =
103 for (std::size_t other = index + 1; other < nodes.size(); ++other) {
104 if (used[other]) {
continue; }
106 if (candidate && candidate->type == complement &&
107 square->argument->equals(*candidate->argument) &&
108 square->coefficient->equals(*candidate->coefficient)) {
109 return std::pair<std::size_t, detail::SymbolicNodePtr>{
110 other, square->coefficient};
118 std::vector<bool> used(rewritten.size(),
false);
119 std::vector<detail::SymbolicNodePtr> result_nodes;
120 std::size_t size = 0;
121 for (std::size_t index = 0; index < rewritten.size(); ++index) {
122 if (used[index]) {
continue; }
126 used[partner->first] =
true;
128 size, budget.
measure(partner->second));
129 result_nodes.push_back(partner->second);
132 result_nodes.push_back(rewritten[index]);
135 if (result_nodes.empty()) {
137 return SymbolicExpr::number(0);
145 if (arguments.size() == 1) {
147 if (positive_argument && *positive_argument) {
150 return SymbolicExpr::multiply(
151 SymbolicExpr::number(-1),
152 SymbolicExpr::sin(*positive_argument));
156 return SymbolicExpr::cos(*positive_argument);
169 if (!node) {
return nullptr; }
171 if (
auto add = std::dynamic_pointer_cast<const AddNode>(node)) {
172 return rewrite_trig_sum(*
add, budget);
174 if (
auto multiply = std::dynamic_pointer_cast<const MultiplyNode>(node)) {
176 rewrite_operands(multiply->operands(), budget), &budget));
178 if (
auto power = std::dynamic_pointer_cast<const PowerNode>(node)) {
183 return SymbolicExpr::power(base,
exponent);
185 if (
auto function = std::dynamic_pointer_cast<const FunctionNode>(node)) {
186 return rewrite_trig_function(*
function, budget);
188 if (
auto complex_node = std::dynamic_pointer_cast<const ComplexNode>(node)) {
函数节点,表示数学函数调用(三角函数、对数、特殊函数等)。
static std::shared_ptr< const SymbolicNode > create_add(std::vector< std::shared_ptr< const SymbolicNode > > ops, detail::RewriteBudget *budget=nullptr)
创建加法节点,自动扁平化嵌套加法并消除零项.
static std::shared_ptr< const SymbolicNode > create_multiply(std::vector< std::shared_ptr< const SymbolicNode > > ops, detail::RewriteBudget *budget=nullptr)
创建乘法节点,自动扁平化嵌套乘法并消除单位元.
std::size_t measure(const std::shared_ptr< const SymbolicNode > &node)
void require_nodes(std::size_t nodes) const
std::size_t append_size(std::size_t current, std::size_t child)
std::shared_ptr<::LMCAS::SymbolicExpr > make_expression_ptr(SymbolicNodePtr root)
const SymbolicNodePtr & node(const ::LMCAS::SymbolicExpr &expression) noexcept
std::shared_ptr< const SymbolicNode > SymbolicNodePtr
std::shared_ptr< const Node > make_node(Args &&... args)
detail::SymbolicNodePtr coefficient
FunctionNode::FuncType type
std::optional< std::pair< std::size_t, detail::SymbolicNodePtr > > complementary_square(const std::vector< detail::SymbolicNodePtr > &nodes, const std::vector< bool > &used, std::size_t index)
std::optional< TrigSquare > trig_square(const detail::SymbolicNodePtr &node)
std::vector< detail::SymbolicNodePtr > rewrite_operands(const std::vector< detail::SymbolicNodePtr > &operands, detail::RewriteBudget &budget)
detail::SymbolicNodePtr argument
ExprPtr rewrite_trig_sum(const AddNode &add, detail::RewriteBudget &budget)
std::optional< ExprPtr > unwrap_trig_negated_argument(const detail::SymbolicNodePtr &node, detail::RewriteBudget &budget)
ExprPtr rewrite_trig_function(const FunctionNode &function, detail::RewriteBudget &budget)
ExprPtr rewrite_trig_basic_identity(const detail::SymbolicNodePtr &node, detail::RewriteBudget &budget)
bool exact_integer_node(const std::shared_ptr< const SymbolicNode > &node, int expected)
ExprPtr rewritten_complex(const ExprPtr &real, const ExprPtr &imag, const detail::SymbolicNodePtr &original, detail::RewriteBudget &budget)
ExprResult real(const ExprPtr &expression, ComputationContext &context)
ExprResult add(const ExprPtr &lhs, const ExprPtr &rhs, ComputationContext &context)
void normalization_check_children(detail::RewriteBudget *budget, std::size_t roots, const std::shared_ptr< const Nodes > &... children)
std::shared_ptr< SymbolicExpr > ExprPtr
ExprResult function(const std::string &name, std::vector< ExprPtr > arguments)