9#include <unordered_map>
19 mutable std::optional<CasError>
error;
22 if (!result)
error = result.error();
27 auto access =
context.consume_steps(0,
"facts.segment");
30 if (found !=
signs_.end())
return found->second;
33 if (!
value.value())
return std::optional<int>{};
38 if (!numerator)
return numerator;
39 std::optional<int> result;
40 if (numerator.value()) result = *numerator.value() * *
denominator.value();
64 int s = *
value.value();
65 bool truth =
property == 0 ? s > 0 :
property == 1 ? s < 0 : property == 2 ? s >= 0 : s != 0;
79 mutable std::unordered_map<Node, std::optional<int>>
signs_;
96 if (!left) {
return left; }
116 const int s = *
value.value();
131 if (
const auto* logical =
dynamic_cast<const LogicalNode*
>(
node.get())) {
149 for (
const auto& branch : piecewise.
branches()) {
165 "integrate.definite.convergence"};
170 bool changed =
false;
177 bool changed =
false;
184 if (!argument)
return false;
189 if (!
value.value()) {
197 ?
detail::node(SymbolicExpr::multiply(SymbolicExpr::number(-1),
216 void visit(
const PowerNode& power)
override {
221 node->accept(detector);
222 return detector.found;
228 if (!step) {
return step; }
229 if (
const auto* logical =
dynamic_cast<const LogicalNode*
>(condition.get())) {
231 if (!left) {
return left; }
243 if (polynomial->degree() <= 0) {
continue; }
246 roots.insert(
roots.end(), isolated.
value().begin(), isolated.value().end());
252 AssumptionContext assumptions =
context.assumptions() ? *
context.assumptions() : AssumptionContext{};
262 if (!step)
return step;
264 for (
const auto& branch : piecewise->branches()) {
267 if (!child)
return child;
269 if (piecewise->default_expr())
276 conditions.insert(conditions.end(),
domain.value()->begin(),
domain.value()->end());
279 AbsoluteBoundaries(std::vector<std::shared_ptr<SymbolicExpr>>& out,
const FactsQuery&
facts,
282 std::optional<CasError> error;
287 void visit(
const PowerNode& power)
override {
295 if (!nonnegative) { error = nonnegative.error();
return; }
297 if (!nonzero) { error = nonzero.error();
return; }
303 std::vector<std::shared_ptr<SymbolicExpr>>& out_;
307 node->accept(boundaries);
313 const std::string& var,
const SymbolicExpr&
lower,
const SymbolicExpr&
upper,
322 SegmentFacts
facts(assumptions.value(), var,
a.
value(),
b.value());
324 auto selected = rewrite.rewrite(
detail::node(expression));
332 std::vector<Algebraic> ordered;
333 for (
auto& root :
roots) {
338 if (left.value() >= 0 ||
right.value() >= 0) {
continue; }
339 auto position = ordered.begin();
340 bool duplicate =
false;
341 for (; position != ordered.end(); ++position) {
344 if (comparison.value() == 0) { duplicate =
true;
break; }
345 if (comparison.value() < 0) {
break; }
347 if (!duplicate) { ordered.insert(position, std::move(root)); }
353 const std::string& var,
const SymbolicExpr&
lower,
const SymbolicExpr&
upper,
358 std::vector<std::shared_ptr<SymbolicExpr>> conditions;
361 if (conditions.empty()) {
return std::vector<SymbolicExpr>{
lower,
upper}; }
366 std::vector<Algebraic>
roots;
367 for (
const auto& condition : conditions) {
373 std::vector<SymbolicExpr> result{
lower};
374 for (
const auto& root : ordered.value()) {
375 if (root.is_rational()) { result.push_back(*SymbolicExpr::number(root.lower)); }
379 result.push_back(*expression.value());
382 result.push_back(
upper);
390 const auto*
interval =
dynamic_cast<const SegmentFacts*
>(&
facts);
395 bool unknown =
false;
396 for (
const auto& condition : *conditions.value()) {
398 if (!truth) {
return truth; }
408 case F::Sin: {
return true; }
409 case F::Cos: {
return true; }
410 case F::Exp: {
return true; }
411 case F::Abs: {
return true; }
412 case F::ArcTan: {
return true; }
413 case F::Ln: {
return true; }
414 case F::Log: {
return true; }
415 case F::Sqrt: {
return true; }
416 case F::Sinh: {
return true; }
417 case F::Cosh: {
return true; }
418 case F::Tan: {
return true; }
419 case F::ArcSin: {
return true; }
420 case F::ArcCos: {
return true; }
421 default: {
return false; }
430 for (
const auto& child : children) {
432 if (!continuous || continuous.value() !=
Tribool::True) {
return continuous; }
442 if (!defined || defined.value() !=
Tribool::True) {
return defined; }
445 const auto* sum =
dynamic_cast<const AddNode*
>(
node.get());
448 const auto* power =
dynamic_cast<const PowerNode*
>(
node.get());
464 const std::string& var,
const SymbolicExpr&
lower,
const SymbolicExpr&
upper,
473 if (!everywhere || everywhere.value() !=
Tribool::Unknown) {
return everywhere; }
478 SegmentFacts
facts(assumptions.value(), var,
a.
value(),
b.value());
488 bool changed =
false;
499 if (*sign_value.value() < 0) {
500 arguments[0] =
detail::node(SymbolicExpr::multiply(SymbolicExpr::number(-1),
524 const auto& outcome = result.
value().value;
525 if (
const auto* finite = std::get_if<FiniteLimit>(&outcome))
return *finite->value;
526 if (std::holds_alternative<PositiveInfinityLimit>(outcome))
return *SymbolicExpr::infinity(1);
527 if (std::holds_alternative<NegativeInfinityLimit>(outcome))
return *SymbolicExpr::infinity(-1);
532 const std::string& var,
const SymbolicExpr&
lower,
const SymbolicExpr&
upper,
545 SegmentFacts
facts(assumptions.value(), var,
a.
value(),
b.value());
556}
catch (
const std::bad_alloc&) {
558}
catch (
const std::length_error& error) {
560}
catch (
const std::exception& error) {
565 const std::string& var,
const SymbolicExpr&
a,
const SymbolicExpr&
b,
568 (
context).limits().max_ast_nodes,
"transform");
569 if (!concrete_endpoints) {
573 "primitive substitution returned no expression",
operation); }
578 if (!high) {
return high; }
579 if (!low) {
return low; }
583 if (hs || ls) {
return *SymbolicExpr::infinity(hs ? hs : ls); }
587}
catch (
const std::bad_alloc&) {
589}
catch (
const std::length_error& error) {
591}
catch (
const std::exception& error) {
596 const SymbolicExpr& primitive,
const std::string& var,
602 SymbolicExpr candidate = primitive;
函数节点,表示数学函数调用(三角函数、对数、特殊函数等)。
@ Not
一元逻辑非,right 为 nullptr。
const std::shared_ptr< const SymbolicNode > & right() const noexcept
const std::shared_ptr< const SymbolicNode > & left() const noexcept
const std::shared_ptr< const SymbolicNode > & default_expr() const noexcept
const std::vector< Branch > & branches() const noexcept
static Result failure(CasErrc code, std::string message, std::string operation={})
static Result success(T value)
void visit(const NumberNode &) override
void set_result(SymbolicNodePtr result)
SymbolicNodePtr rewrite(const SymbolicNodePtr &node)
SymbolicNodePtr rewrite_child(const SymbolicNodePtr &child, bool &changed)
std::vector< SymbolicNodePtr > rewrite_children(const Range &children, bool &changed)
SymbolicNodePtr current() const noexcept
std::optional< CasError > error
RealPrimitiveCandidate(const SegmentFacts &facts, ComputationContext &context)
ComputationContext & context_
const SegmentFacts & facts_
void visit(const FunctionNode &node) override
void visit(const PiecewiseNode &piecewise) override
ComputationContext & context_
SegmentExpression(const SegmentFacts &facts, ComputationContext &context)
std::optional< CasError > error
bool specialize_absolute(const Node &argument)
void visit(const PowerNode &node) override
const SegmentFacts & facts_
void visit(const FunctionNode &node) override
std::unordered_map< Node, std::optional< int > > signs_
Result< Tribool > is_real(const Node &node, ComputationContext &context) const override
Result< Tribool > is_positive(const Node &node, ComputationContext &context) const override
Result< Tribool > is_negative(const Node &node, ComputationContext &context) const override
detail::AssumptionFacts base_
Result< Tribool > is_nonzero(const Node &node, ComputationContext &context) const override
SegmentFacts(const AssumptionContext &assumptions, const std::string &variable, const Boundary &lower, const Boundary &upper)
std::optional< CasError > error
Result< std::optional< int > > value_sign_impl(const Node &node, ComputationContext &context) const
Result< Tribool > property(const Node &node, int property, ComputationContext &context) const
Result< std::optional< int > > value_sign(const Node &node, ComputationContext &context) const
Result< Tribool > remember(Result< Tribool > result) const
Result< Tribool > is_nonnegative(const Node &node, ComputationContext &context) const override
static Result< Tribool > logical_predicate_truth(const LogicalNode &logical, const SegmentFacts &facts, ComputationContext &context)
static Result< Tribool > predicate_truth(const Node &node, const SegmentFacts &facts, ComputationContext &context)
static Result< Tribool > relational_predicate_truth(const RelationalNode &relation, const SegmentFacts &facts, ComputationContext &context)
static Tribool binary_logical_truth(LogicalNode::Op op, Tribool a, Tribool b)
Result< SymbolicExpr > segment_expression_checked(const SymbolicExpr &expression, const std::string &var, const SymbolicExpr &lower, const SymbolicExpr &upper, ComputationContext &context)
Result< SymbolicExpr > definite_segment_checked(const SymbolicExpr &original, const SymbolicExpr &primitive, const std::string &var, const SymbolicExpr &a, const SymbolicExpr &b, ComputationContext &context)
static Result< Tribool > defined_on_interval(const Node &node, const FactsQuery &facts, ComputationContext &context)
static Result< SymbolicExpr > boundary_value_checked(const SymbolicExpr &primitive, const std::string &var, const SymbolicExpr &point, LimitDirection direction, ComputationContext &context)
static Result< std::vector< Algebraic > > ordered_partition_roots(std::vector< Algebraic > &roots, const Boundary &a, const Boundary &b, ComputationContext &context)
static Result< void > original_conditions_checked(const Node &node, const FactsQuery &facts, std::vector< std::shared_ptr< SymbolicExpr > > &conditions, ComputationContext &context)
Result< Tribool > certify_continuity_checked(const SymbolicExpr &expression, const std::string &var, const SymbolicExpr &lower, const SymbolicExpr &upper, ComputationContext &context)
Result< std::vector< SymbolicExpr > > definite_partition_checked(const SymbolicExpr &original, const std::string &var, const SymbolicExpr &lower, const SymbolicExpr &upper, ComputationContext &context)
static Result< void > prepare_segment_primitive(SymbolicExpr &candidate, const std::string &var, const SymbolicExpr &lower, const SymbolicExpr &upper, ComputationContext &context)
static Result< void > collect_predicate_roots(const Node &condition, const std::string &var, std::vector< Algebraic > &roots, ComputationContext &context)
Result< int > compare_boundaries(const Boundary &a, const Boundary &b, ComputationContext &context)
static Result< Tribool > continuous_children(const std::vector< Node > &children, const FactsQuery &facts, ComputationContext &context)
std::shared_ptr< const SymbolicNode > Node
bool is_undecided(const CasError &error)
static Result< SymbolicExpr > evaluate_segment_endpoints(const SymbolicExpr &candidate, const std::string &var, const SymbolicExpr &a, const SymbolicExpr &b, bool concrete_endpoints, ComputationContext &context)
static Result< Tribool > structurally_continuous(const Node &node, const FactsQuery &facts, ComputationContext &context)
Result< std::optional< int > > polynomial_sign_checked(const Poly &polynomial, const Boundary &a, const Boundary &b, ComputationContext &context)
int infinity_sign(const Node &node)
Result< Boundary > boundary_checked(const SymbolicExpr &expression, ComputationContext &context)
RationalResult rational_checked(const Node &node, const std::string &var, ComputationContext &context)
bool needs_segment_expression(const Node &node)
Node absolute_argument(const SymbolicNode &node)
识别绝对值节点及公共接口的平方开根表示。
Result< std::vector< Algebraic > > roots_checked(const Poly &polynomial, ComputationContext &context)
static bool continuous_function_family(FunctionNode::FuncType type)
constexpr const char * operation
Result< AssumptionContext > real_assumptions(const std::string &var, ComputationContext &context)
std::shared_ptr<::LMCAS::SymbolicExpr > make_expression_ptr(SymbolicNodePtr root)
const SymbolicNodePtr & node(const ::LMCAS::SymbolicExpr &expression) noexcept
Result< Tribool > query_nonzero_value(const Node &node, const FactsQuery &facts, Domain domain, ComputationContext &context)
const std::string & variable
std::shared_ptr< const SymbolicNode > Node
RewriteBudget const FactsQuery Domain domain
inline ::LMCAS::SymbolicExpr expression_from_node(SymbolicNodePtr root)
Result< Tribool > query_definedness(const Node &node, const FactsQuery &facts, Domain domain, ComputationContext &context, bool *violated_real_restriction)
RewriteBudget const FactsQuery & facts
std::shared_ptr< const Node > make_node(Args &&... args)
Result< std::optional< std::vector< std::shared_ptr< SymbolicExpr > > > > domain_constraints(const Node &node, const FactsQuery &facts, Domain domain, ComputationContext &context)
Result< Tribool > query_real_value(const Node &node, const FactsQuery &facts, ComputationContext &context)
SymbolicNodePtr normalize_node(const SymbolicNodePtr &node, RewriteBudget &budget, const FactsQuery &facts, Domain domain)
Result< Tribool > query_nonnegative_value(const Node &node, const FactsQuery &facts, ComputationContext &context)
std::size_t std::size_t ComputationContext & context
SymbolicNodePtr substitute_node(const SymbolicNodePtr &node, const std::string &variable, const SymbolicNodePtr &replacement, RewriteBudget &budget, const FactsQuery &facts, Domain domain)
std::shared_ptr< SymbolicExpr > negate(const std::shared_ptr< SymbolicExpr > &expr)
const std::string const LimitExprPtr & point
LimitResult limit_checked(const LimitExprPtr &expression, const std::string &variable, const LimitExprPtr &point, LimitDirection direction, ComputationContext &context, Domain domain)
__attribute__((visibility("default"))) ExprResult function(const std __attribute__((visibility("default"))) ExprResult finite_set(std ExprPtr upper
ExprResult interval(ExprPtr lower, ExprPtr upper, bool lower_closed, bool upper_closed)
ExprResult real(const ExprPtr &expression, ComputationContext &context)
const std::string const LimitExprPtr LimitDirection direction
Tribool
Tri-state logic value for property queries.
@ Unknown
Property cannot be determined
@ True
Property definitely holds
@ False
Property definitely does not hold
RootOfConstructionResult make_rootof_checked(const std::shared_ptr< SymbolicExpr > &polynomial, const std::string &variable, std::size_t index, ComputationContext &context)
const ExprPtr RelationOp op
__attribute__((visibility("default"))) VectorCalculusExprResult curve_integral_scalar_checked(const std __attribute__((visibility("default"))) VectorCalculusExprResult curve_integral_scalar_checked(const std __attribute__((visibility("default"))) std const VectorField const std::string const std::shared_ptr< SymbolicExpr > & a
ExprSetResult roots(const ExprPtr &expression, const std::string &variable, ComputationContext &context, const SolveOptions &options)
ExprResult relation(const ExprPtr &lhs, const ExprPtr &rhs, RelationOp op)
const std::string const ExprPtr & value
std::shared_ptr< SymbolicExpr > sym_sub(const SymbolicExpr &lhs, const SymbolicExpr &rhs)
LimitDirection
Direction from which a limit approaches its point.
const ExprPtr & denominator
ExprResult function(const std::string &name, std::vector< ExprPtr > arguments)
ExprResult rational(const Rational &value)