23 const std::string& operation)
25 auto step =
context.consume_steps(1, operation);
26 if (!step)
return step;
29 "expression cannot be null", operation);
35 const std::shared_ptr<SymbolicExpr>& expr,
37 const std::shared_ptr<SymbolicExpr>& z0,
40 const std::string& operation)
42 auto step =
context.consume_steps(1, operation);
43 if (!step)
return step;
46 "complex-analysis expressions cannot be null",
51 "complex variable name cannot be empty",
56 "complex-analysis order must be between 1 and 13",
87 if (!
found_) RecursiveSymbolicVisitor::visit_child(child);
93 for (
const auto& argument : arguments) {
126 if (!
found_) RecursiveSymbolicVisitor::visit_child(child);
134 if (!node)
return false;
137 return finder.
found();
154 if (!
found_) RecursiveSymbolicVisitor::visit_child(child);
159 for (
const auto& argument : arguments) {
172 const std::string& z) {
173 if (!node)
return false;
176 return finder.
found();
180 if (!node)
return false;
183 return finder.
found();
189 const std::shared_ptr<SymbolicExpr>&,
191 const std::shared_ptr<SymbolicExpr>&,
193 ComputationContext&);
195 const std::shared_ptr<SymbolicExpr>&,
197 const std::shared_ptr<SymbolicExpr>&,
198 int, ComputationContext&);
200 const std::shared_ptr<SymbolicExpr>&,
201 const std::string&, ComputationContext&
context);
204 const std::shared_ptr<SymbolicExpr>& f,
205 const std::string& z,
206 const std::shared_ptr<SymbolicExpr>& z0,
210 const std::string operation =
"calculate_residue";
211 auto input = validate_complex_expr_point_input(f, z, z0,
order,
context, operation);
213 auto budget =
context.consume_steps(
static_cast<std::size_t
>(
order) * 12 + 12,
220 if (!calculated)
return calculated;
221 auto result = std::move(calculated.value());
225 "residue could not be constructed in the supported symbolic domain",
229 }
catch (
const std::bad_alloc&) {
231 "allocation failed while calculating residue",
233 }
catch (
const std::exception& ex) {
241 const std::shared_ptr<SymbolicExpr>& f,
242 const std::string& z,
243 const std::shared_ptr<SymbolicExpr>& z0,
251 const std::shared_ptr<SymbolicExpr>& f,
252 const std::string& z,
253 const std::shared_ptr<SymbolicExpr>& z0,
257 (
context).limits().max_ast_nodes,
"transform");
258 if (
order < 1)
return SymbolicExpr::number(0);
260 auto var_z = SymbolicExpr::variable(z);
261 auto z_minus_z0 = SymbolicExpr::add(var_z, SymbolicExpr::multiply(z0, SymbolicExpr::number(-1)));
262 auto pow_term = SymbolicExpr::power(z_minus_z0, SymbolicExpr::number(
order));
264 auto F = SymbolicExpr::multiply(pow_term, f);
266 for (
int i = 0; i <
order - 1; i++) {
270 auto fact = BigInt::factorial_checked(BigInt(
order - 1),
context);
273 F = SymbolicExpr::divide(F, SymbolicExpr::number(fact.value()));
277}
catch (
const CasError& error) {
279}
catch (
const std::bad_alloc&) {
281}
catch (
const std::length_error& error) {
283}
catch (
const std::exception& error) {
288 const std::shared_ptr<SymbolicExpr>& f,
289 const std::string& z,
290 const std::shared_ptr<SymbolicExpr>& z0,
294 const std::string operation =
"cauchy_integral";
295 auto input = validate_complex_expr_point_input(f, z, z0, n,
context, operation);
297 auto budget =
context.consume_steps(
static_cast<std::size_t
>(n) * 12 + 12,
303 if (!calculated)
return calculated;
304 auto result = std::move(calculated.value());
308 "Cauchy integral formula could not be constructed in the supported symbolic domain",
312 }
catch (
const std::bad_alloc&) {
314 "allocation failed while applying Cauchy integral formula",
316 }
catch (
const std::exception& ex) {
324 const std::shared_ptr<SymbolicExpr>& f,
325 const std::string& z,
326 const std::shared_ptr<SymbolicExpr>& z0,
334 const std::shared_ptr<SymbolicExpr>& f,
335 const std::string& z,
336 const std::shared_ptr<SymbolicExpr>& z0,
339 (
context).limits().max_ast_nodes,
"transform");
342 if (n < 1)
return SymbolicExpr::number(0);
345 for (
int i = 0; i < n - 1; i++) {
351 auto fact = BigInt::factorial_checked(BigInt(n - 1),
context);
354 auto term = SymbolicExpr::divide(f_n_minus_1_z0, SymbolicExpr::number(fact.value()));
364 auto two_pi_i = SymbolicExpr::multiply(SymbolicExpr::number(2), SymbolicExpr::multiply(pi_expr, i_expr));
367}
catch (
const CasError& error) {
369}
catch (
const std::bad_alloc&) {
371}
catch (
const std::length_error& error) {
373}
catch (
const std::exception& error) {
378 const std::shared_ptr<SymbolicExpr>& f,
379 const std::string&) {
382 (
context).limits().max_ast_nodes,
"transform");
393 const std::shared_ptr<const SymbolicNode>& node) {
394 auto number = std::dynamic_pointer_cast<const NumberNode>(node);
395 if (!number)
return std::nullopt;
397 if (
const auto*
integer = std::get_if<BigInt>(&number->value())) {
399 }
else if (
const auto*
rational = std::get_if<Rational>(&number->value())) {
400 if (!
rational->is_integer())
return std::nullopt;
404 return static_cast<int>(*
exponent.try_to_int64());
410 std::shared_ptr<SymbolicExpr>& re,
414 (
context).limits().max_ast_nodes,
"transform");
415 re = SymbolicExpr::number(0);
416 im = SymbolicExpr::number(0);
420 if (
auto cn = std::dynamic_pointer_cast<const ComplexNode>(node)) {
425 if (
auto add = std::dynamic_pointer_cast<const AddNode>(node)) {
426 for (
const auto&
op :
add->operands()) {
427 std::shared_ptr<SymbolicExpr> r2, i2;
429 re = SymbolicExpr::add(re, r2);
430 im = SymbolicExpr::add(im, i2);
436 if (
auto mul = std::dynamic_pointer_cast<const MultiplyNode>(node)) {
438 std::shared_ptr<SymbolicExpr> accR = SymbolicExpr::number(1);
439 std::shared_ptr<SymbolicExpr> accI = SymbolicExpr::number(0);
440 for (
const auto&
op :
mul->operands()) {
441 std::shared_ptr<SymbolicExpr> r2, i2;
443 auto ac = SymbolicExpr::multiply(accR, r2);
444 auto bd = SymbolicExpr::multiply(accI, i2);
445 auto ad = SymbolicExpr::multiply(accR, i2);
446 auto bc = SymbolicExpr::multiply(accI, r2);
454 if (
auto pw = std::dynamic_pointer_cast<const PowerNode>(node)) {
457 std::shared_ptr<SymbolicExpr> baseR, baseI;
462 std::shared_ptr<SymbolicExpr> accR = SymbolicExpr::number(1);
463 std::shared_ptr<SymbolicExpr> accI = SymbolicExpr::number(0);
464 for (
int k = 0; k < *
exponent; ++k) {
465 auto ac = SymbolicExpr::multiply(accR, baseR);
466 auto bd = SymbolicExpr::multiply(accI, baseI);
467 auto ad = SymbolicExpr::multiply(accR, baseI);
468 auto bc = SymbolicExpr::multiply(accI, baseR);
472 re = accR; im = accI;
478 im = SymbolicExpr::number(0);
483 im = SymbolicExpr::number(0);
488 im = SymbolicExpr::number(0);
496 (
context).limits().max_ast_nodes,
"transform");
497 const std::string operation =
"real_part";
498 auto input = validate_complex_expr_input(expr,
context, operation);
503 "real part of functions with complex arguments is outside the current support domain",
507 std::shared_ptr<SymbolicExpr> re, im;
512 "real part construction failed",
516}
catch (
const CasError& error) {
518}
catch (
const std::bad_alloc&) {
520}
catch (
const std::length_error& error) {
522}
catch (
const std::exception& error) {
535 (
context).limits().max_ast_nodes,
"transform");
536 const std::string operation =
"imag_part";
537 auto input = validate_complex_expr_input(expr,
context, operation);
542 "imaginary part of functions with complex arguments is outside the current support domain",
546 std::shared_ptr<SymbolicExpr> re, im;
551 "imaginary part construction failed",
555}
catch (
const CasError& error) {
557}
catch (
const std::bad_alloc&) {
559}
catch (
const std::length_error& error) {
561}
catch (
const std::exception& error) {
574 (
context).limits().max_ast_nodes,
"transform");
575 const std::string operation =
"conjugate";
576 auto input = validate_complex_expr_input(expr,
context, operation);
581 "conjugate of functions with complex arguments is outside the current support domain",
585 std::shared_ptr<SymbolicExpr> re, im;
591 "conjugate construction failed",
598 "conjugate construction failed",
607 "conjugate construction failed",
611}
catch (
const CasError& error) {
613}
catch (
const std::bad_alloc&) {
615}
catch (
const std::length_error& error) {
617}
catch (
const std::exception& error) {
628 const std::string& z,
630 const std::string operation =
"is_analytic";
631 auto input = validate_complex_expr_input(f,
context, operation);
635 "complex variable name cannot be empty",
642 "analyticity of functions depending on the complex variable is outside the current support domain",
645 auto budget =
context.consume_steps(24, operation);
650 }
catch (
const std::bad_alloc&) {
652 "allocation failed while checking analyticity",
654 }
catch (
const std::length_error& error) {
656 }
catch (
const std::exception& ex) {
664 const std::string& z) {
670 const std::shared_ptr<SymbolicExpr>& expression,
674 (
context).limits().max_ast_nodes,
"transform");
676 return SymbolicExpr::number(0);
684 (
context).limits().max_ast_nodes,
"transform");
685 if (!f)
return false;
687 std::string xr = z +
"_re";
688 std::string xi = z +
"_im";
689 auto zr = SymbolicExpr::variable(xr);
690 auto zi = SymbolicExpr::variable(xi);
695 auto z_sub = SymbolicExpr::add(zr, SymbolicExpr::multiply(i_unit, zi));
698 if (!fz)
return false;
701 std::shared_ptr<SymbolicExpr>
u,
v;
717 const std::shared_ptr<SymbolicExpr>& f,
718 const std::string& z,
719 const std::shared_ptr<SymbolicExpr>& z0,
726 const std::shared_ptr<SymbolicExpr>& f,
727 const std::string& z,
728 const std::shared_ptr<SymbolicExpr>& z0,
函数节点,表示数学函数调用(三角函数、对数、特殊函数等)。
连乘节点,表示符号有限/无限连乘 prod_{k=a}^{b} f(k).
static Result failure(CasErrc code, std::string message, std::string operation={})
static Result success(T value)
求和节点,表示符号有限/无限求和 sum_{k=a}^{b} f(k).
static std::shared_ptr< const SymbolicNode > create_complex(std::shared_ptr< const SymbolicNode > real, std::shared_ptr< const SymbolicNode > imag)
创建复数节点,自动简化(若虚部为 0,则返回实部).
virtual void accept(LMCAS::detail::SymbolicVisitor &visitor) const =0
virtual bool is_zero() const
bool found() const noexcept
void visit_child(const detail::SymbolicNodePtr &child) override
void visit(const ComplexNode &) override
void visit(const SummationNode &node) override
const std::string & variable_
void visit(const IntegralNode &node) override
void visit(const UninterpretedFunctionNode &node) override
void visit(const TransformNode &node) override
void visit(const ProductNode &node) override
void visit(const QuantifierNode &node) override
void visit(const SetBuilderNode &node) override
FunctionDependencyFinder(const std::string &variable)
bool found() const noexcept
void visit_child(const detail::SymbolicNodePtr &child) override
void visit_function(const std::vector< detail::SymbolicNodePtr > &arguments)
void visit(const FunctionNode &node) override
void visit(const LimitNode &node) override
void visit_binder(const SymbolicNode &node)
void visit(const UninterpretedFunctionNode &node) override
void visit_child(const detail::SymbolicNodePtr &child) override
bool found() const noexcept
void visit_function(const std::vector< detail::SymbolicNodePtr > &arguments)
void visit(const FunctionNode &node) override
void visit_children(const Range &children)
void split_real_imag(const std::shared_ptr< const SymbolicNode > &node, std::shared_ptr< SymbolicExpr > &re, std::shared_ptr< SymbolicExpr > &im, ComputationContext &context)
递归地将表达式分解为 (实部, 虚部),把 ComplexNode 视为 a+bi。 仅处理加法、乘法、数值与 ComplexNode 组合;其余子表达式视为实值。
bool has_function_of_explicit_complex(const detail::SymbolicNodePtr &node)
std::optional< int > bounded_complex_power(const std::shared_ptr< const SymbolicNode > &node)
Result< void > validate_complex_expr_point_input(const std::shared_ptr< SymbolicExpr > &expr, const std::string &z, const std::shared_ptr< SymbolicExpr > &z0, int order, ComputationContext &context, const std::string &operation)
bool contains_explicit_complex(const detail::SymbolicNodePtr &node)
bool has_z_dependent_function(const detail::SymbolicNodePtr &node, const std::string &z)
Result< void > validate_complex_expr_input(const std::shared_ptr< SymbolicExpr > &expr, ComputationContext &context, const std::string &operation)
SymbolicNodePtr differentiate_node(const SymbolicNodePtr &node, const std::string &variable, RewriteBudget &budget, const FactsQuery &facts, Domain domain)
std::shared_ptr<::LMCAS::SymbolicExpr > make_expression_ptr(SymbolicNodePtr root)
const SymbolicNodePtr & node(const ::LMCAS::SymbolicExpr &expression) noexcept
std::optional< BinderView > binder_view(const SymbolicNode &node)
std::shared_ptr< const SymbolicNode > SymbolicNodePtr
std::shared_ptr< const Node > make_node(Args &&... args)
SymbolicNodePtr normalize_node(const SymbolicNodePtr &node, RewriteBudget &budget, const FactsQuery &facts, Domain domain)
SymbolicNodePtr substitute_node(const SymbolicNodePtr &node, const std::string &variable, const SymbolicNodePtr &replacement, RewriteBudget &budget, const FactsQuery &facts, Domain domain)
static ExpressionResult calculate_residue_impl(const std::shared_ptr< SymbolicExpr > &, const std::string &, const std::shared_ptr< SymbolicExpr > &, int, ComputationContext &)
Result< bool > ComplexBoolResult
const std::string & variable
__attribute__((visibility("default"))) VectorCalculusExprResult surface_integral_scalar_checked(const std __attribute__((visibility("default"))) VectorCalculusExprResult surface_integral_scalar_checked(const std __attribute__((visibility("default"))) std const VectorField const std::string const std::string & v
const std::vector< Polynomial< BigInt > > const BigInt ComputationContext & context
ExprResult integer(Integer)=delete
const std::vector< FGLMPoly > const MonomialOrder & order
@ Complex
Complex numbers (default, least specific)
ExprResult mul(const ExprPtr &lhs, const ExprPtr &rhs, ComputationContext &context)
bool expression_depends_on_variable(const detail::SymbolicNodePtr &expression, const std::string &variable, detail::RewriteBudget *budget)
static ExpressionResult cauchy_integral_impl(const std::shared_ptr< SymbolicExpr > &, const std::string &, const std::shared_ptr< SymbolicExpr > &, int, ComputationContext &)
ExpressionResult real_part_checked(const std::shared_ptr< SymbolicExpr > &expr, ComputationContext &context)
ExprResult add(const ExprPtr &lhs, const ExprPtr &rhs, ComputationContext &context)
LimitExpressionResult limit_expression_checked(const LimitExprPtr &expression, const std::string &variable, const LimitExprPtr &point, LimitDirection direction, ComputationContext &context, Domain domain)
Result< std::shared_ptr< SymbolicExpr > > ExpressionResult
Result of an operation that produces a symbolic expression.
std::shared_ptr< SymbolicExpr > analytic_continuation(const std::shared_ptr< SymbolicExpr > &f, const std::string &)
const ExprPtr RelationOp op
static bool is_analytic_impl(const std::shared_ptr< SymbolicExpr > &, const std::string &, ComputationContext &context)
ExpressionResult calculate_residue_checked(const std::shared_ptr< SymbolicExpr > &f, const std::string &z, const std::shared_ptr< SymbolicExpr > &z0, int order, ComputationContext &context)
ExpressionResult conjugate_checked(const std::shared_ptr< SymbolicExpr > &expr, ComputationContext &context)
static std::shared_ptr< SymbolicExpr > differentiate_if_dependent(const std::shared_ptr< SymbolicExpr > &expression, const std::string &variable, ComputationContext &context)
ExpressionResult imag_part_checked(const std::shared_ptr< SymbolicExpr > &expr, ComputationContext &context)
ExprResult rational(const Rational &value)
ExpressionResult residue_checked(const std::shared_ptr< SymbolicExpr > &f, const std::string &z, const std::shared_ptr< SymbolicExpr > &z0, int order, ComputationContext &context)
ExpressionResult cauchy_integral_checked(const std::shared_ptr< SymbolicExpr > &f, const std::string &z, const std::shared_ptr< SymbolicExpr > &z0, int n, ComputationContext &context)
ComplexBoolResult is_analytic_checked(const std::shared_ptr< SymbolicExpr > &f, const std::string &z, ComputationContext &context)
__attribute__((visibility("default"))) VectorCalculusExprResult surface_integral_scalar_checked(const std __attribute__((visibility("default"))) VectorCalculusExprResult surface_integral_scalar_checked(const std __attribute__((visibility("default"))) std const VectorField const std::string & u
符号表达式主类 SymbolicExpr 及其工厂方法,运算接口.