LMCAS
Lamina Computer Algebra System
载入中...
搜索中...
未找到
solver_imaginary.cpp
浏览该文件的文档.
2#include <cmath>
3
4namespace LMCAS::solver_detail {
5
6bool solver_number_value(const NumberNode& number, double& out_value) {
7 if (std::holds_alternative<BigInt>(number.value())) {
8 out_value = std::get<BigInt>(number.value()).to_double();
9 return true;
10 }
11 if (std::holds_alternative<Rational>(number.value())) {
12 out_value = std::get<Rational>(number.value()).to_double();
13 return true;
14 }
15 return false;
16}
17
18namespace {
19
21 if (function.type() != FunctionNode::FuncType::Sqrt || function.arguments().size() != 1) {
22 return false;
23 }
24 auto number = std::dynamic_pointer_cast<const NumberNode>(function.arguments()[0]);
25 if (!number) {
26 return false;
27 }
28 const auto& value = number->value();
29 if (const auto* integer = std::get_if<BigInt>(&value)) {
30 return *integer == BigInt(-1) || integer->is_negative();
31 }
32 if (const auto* rational = std::get_if<Rational>(&value)) {
33 return *rational == Rational(-1) || *rational < Rational(0);
34 }
35 return false;
36}
37
38bool power_is_imaginary(const PowerNode& power) {
39 auto base = std::dynamic_pointer_cast<const NumberNode>(power.base());
40 auto exponent = std::dynamic_pointer_cast<const NumberNode>(power.exponent());
41 if (!base || !exponent) {
42 return false;
43 }
44 const bool negative = std::holds_alternative<BigInt>(base->value())
45 ? std::get<BigInt>(base->value()).is_negative()
46 : std::get<Rational>(base->value()) < Rational(0);
47 return negative && std::holds_alternative<Rational>(exponent->value()) &&
48 !std::get<Rational>(exponent->value()).is_integer();
49}
50
51/**
52 * @brief 检查表达式树中的虚数分量。
53 * @note 虚数单位表示为 sqrt(-1),即 Sqrt 类型且唯一参数为数值 -1 的 FunctionNode。
54 */
56public:
57 bool found = false;
58
59 void visit(const NumberNode&) override {}
60 void visit(const VariableNode&) override {}
61
62 void visit(const AddNode& node) override {
63 for (auto& op : node.operands()) {
64 if (found) {
65 return;
66 }
67 op->accept(*this);
68 }
69 }
70
71 void visit(const MultiplyNode& node) override {
72 for (auto& op : node.operands()) {
73 if (found) {
74 return;
75 }
76 op->accept(*this);
77 }
78 }
79
80 void visit(const PowerNode& node) override {
81 if (found) {
82 return;
83 }
84
85 if (power_is_imaginary(node)) {
86 found = true;
87 return;
88 }
89 node.base()->accept(*this);
90 if (found) {
91 return;
92 }
93 node.exponent()->accept(*this);
94 }
95
96 void visit(const FunctionNode& node) override {
97 if (square_root_is_imaginary(node)) {
98 found = true;
99 return;
100 }
101 for (auto& arg : node.arguments()) {
102 if (found) {
103 return;
104 }
105 arg->accept(*this);
106 }
107 }
108
109 void visit(const MatrixNode& node) override {
110 if (std::holds_alternative<MatrixNode::DenseStorage>(node.storage())) {
111 for (auto& item : std::get<MatrixNode::DenseStorage>(node.storage())) {
112 if (found) {
113 return;
114 }
115 if (item) {
116 item->accept(*this);
117 }
118 }
119 } else {
120 for (auto& [idx, item] : std::get<MatrixNode::SparseStorage>(node.storage())) {
121 (void)idx;
122 if (found) {
123 return;
124 }
125 if (item) {
126 item->accept(*this);
127 }
128 }
129 }
130 }
131
132 void visit(const RelationalNode& node) override {
133 node.left()->accept(*this);
134 if (!found) {
135 node.right()->accept(*this);
136 }
137 }
138
139 void visit(const LogicalNode& node) override {
140 node.left()->accept(*this);
141 if (!found && node.right()) {
142 node.right()->accept(*this);
143 }
144 }
145
146 void visit(const PiecewiseNode& node) override {
147 for (const auto& branch : node.branches()) {
148 if (found) {
149 return;
150 }
151 branch.expression->accept(*this);
152 if (!found) {
153 branch.condition->accept(*this);
154 }
155 }
156 if (!found && node.default_expr()) {
157 node.default_expr()->accept(*this);
158 }
159 }
160
161 void visit(const SummationNode& node) override {
162 node.body()->accept(*this);
163 if (!found) {
164 node.lower_bound()->accept(*this);
165 }
166 if (!found) {
167 node.upper_bound()->accept(*this);
168 }
169 }
170
171 void visit(const ProductNode& node) override {
172 node.body()->accept(*this);
173 if (!found) {
174 node.lower_bound()->accept(*this);
175 }
176 if (!found) {
177 node.upper_bound()->accept(*this);
178 }
179 }
180
181 void visit(const TransformNode& node) override {
182 node.body()->accept(*this);
183 }
184
185 void visit(const QuantifierNode& node) override {
186 node.domain()->accept(*this);
187 if (!found) {
188 node.predicate()->accept(*this);
189 }
190 }
191
192 void visit(const SetBuilderNode& node) override {
193 node.domain()->accept(*this);
194 if (!found) {
195 node.predicate()->accept(*this);
196 }
197 }
198
199 void visit(const ComplexNode&) override {
200 found = true;
201 }
202 void visit(const FiniteSetNode& node) override {
203 for (const auto& element : node.elements()) {
204 if (found) {
205 return;
206 }
207 element->accept(*this);
208 }
209 }
210 void visit(const IntervalNode& node) override {
211 node.lower()->accept(*this);
212 if (!found) {
213 node.upper()->accept(*this);
214 }
215 }
216 void visit(const MembershipNode& node) override {
217 node.element()->accept(*this);
218 if (!found) {
219 node.set()->accept(*this);
220 }
221 }
222 void visit(const QuantityNode& node) override { node.value()->accept(*this); }
223};
224
225}
226bool contains_imaginary(const std::shared_ptr<SymbolicExpr>& expr) {
227 if (!expr || !LMCAS::detail::node(expr)) {
228 return false;
229 }
230 ContainsImaginaryVisitor visitor;
231 LMCAS::detail::node(expr)->accept(visitor);
232 return visitor.found;
233}
234
235}
加法节点,表示多个操作数的求和。
复数节点,表示 real + imag * i。
函数节点,表示数学函数调用(三角函数、对数、特殊函数等)。
@ Sqrt
对数、绝对值、平方根。
矩阵节点,支持稠密和稀疏两种存储方式。
乘法节点,表示多个操作数的乘积。
const std::variant< BigInt, Rational > & value() const noexcept
分段函数节点,表示条件分支表达式.
幂运算节点,表示 base^exponent。
const std::shared_ptr< const SymbolicNode > & exponent() const noexcept
const std::shared_ptr< const SymbolicNode > & base() const noexcept
连乘节点,表示符号有限/无限连乘 prod_{k=a}^{b} f(k).
求和节点,表示符号有限/无限求和 sum_{k=a}^{b} f(k).
积分变换节点,表示 Laplace,Fourier,Z 变换及其逆变换.
变量节点,表示一个符号变量。
const SymbolicNodePtr & node(const ::LMCAS::SymbolicExpr &expression) noexcept
bool solver_number_value(const NumberNode &number, double &value)
bool contains_imaginary(const std::shared_ptr< SymbolicExpr > &expression)
const ExprPtr & element
ExprResult integer(Integer)=delete
const ExprPtr RelationOp op
const ExprPtr & exponent
const std::string const ExprPtr & value
ExprResult function(const std::string &name, std::vector< ExprPtr > arguments)
ExprResult rational(const Rational &value)