LMCAS
Lamina Computer Algebra System
载入中...
搜索中...
未找到
assumption_simplification.cpp
浏览该文件的文档.
1#include <stdexcept>
3
11
12namespace LMCAS {
13namespace detail {
14
15namespace {
16template <typename Transform>
18 const char* operation, const char* name,
19 Transform&& transform) {
21 expression, context, operation, name,
22 [&](const SymbolicExpr& value) {
23 RewriteBudget budget(context, context.limits().max_recursion_depth,
24 context.limits().max_ast_nodes, operation);
25 std::optional<AssumptionFacts> facts;
26 if (context.assumptions()) { facts.emplace(*context.assumptions()); }
27 return make_expression_ptr(transform(
28 node(value), budget, facts ? static_cast<const FactsQuery&>(*facts) : no_facts()));
29 });
30}
31}
32
35 return assumed_transform(expression, context, "LMCAS.simplify", "simplify",
38 });
39}
40
42 return assumed_transform(expression, context, "LMCAS.expand", "expand",
44 return expand_node(value, budget, facts);
45 });
46}
47
49 const std::string& variable,
51 return assumed_transform(expression, context, "LMCAS.differentiate", "differentiate",
54 });
55}
56
58 const std::string& variable,
59 const ExprPtr& replacement,
61 return assumed_transform(expression, context, "LMCAS.substitute", "substitute",
64 });
65}
66
68 const ExprPtr& expression,
69 const std::vector<Binding>& replacements,
71 return assumed_transform(expression, context, "LMCAS.substitute", "substitute",
74 for (const auto& replacement : replacements) {
75 const auto symbol = std::dynamic_pointer_cast<const VariableNode>(
76 node(replacement.symbol));
77 if (!symbol || symbol->is_constant() || !replacement.value ||
78 !node(replacement.value)) {
79 throw CasError{CasErrc::InvalidArgument, "invalid substitution binding",
80 "LMCAS.substitute"};
81 }
82 value = substitute_node(value, symbol->name(), node(replacement.value),
83 budget, facts);
84 }
85 return value;
86 });
87}
88
89void AssumptionFacts::collect_names(const AssumptionContext& assumptions,
90 std::set<std::string>& names, RewriteBudget& budget) {
91 const auto include = [&](const SymbolicExpr& expression) {
92 budget.measure(node(expression));
93 auto variables = free_variables(node(expression), &budget);
94 names.merge(variables);
95 };
96 for (const auto& scope : assumptions.scope_stack_) {
97 auto access = budget.context().consume_steps(1, "assumption.names");
98 if (!access) { throw access.error(); }
99 for (auto& symbol : scope.properties.get_all_symbols()) {
100 access = budget.context().consume_steps(1, "assumption.names");
101 if (!access) { throw access.error(); }
102 for (const auto& [variable, period] : scope.properties.get_period_decls(symbol)) {
103 names.insert(variable);
104 include(period);
105 }
106 for (const auto& declaration : scope.properties.get_monotonicity_decls(symbol)) {
107 access = budget.context().consume_steps(1, "assumption.names");
108 if (!access) { throw access.error(); }
109 names.insert(declaration.variable);
110 }
111 names.insert(std::move(symbol));
112 }
113 for (const auto& relation : scope.relations.get_relations()) {
114 include(relation.lhs);
115 include(relation.rhs);
116 }
117 for (const auto& conditional : scope.conditionals) {
118 include(conditional.condition);
119 include(conditional.conclusion);
120 }
121 }
122}
123
125 const std::shared_ptr<const SymbolicNode>& node, ComputationContext& context) const {
126 auto access = context.consume_steps(0, "facts.assumptions");
127 if (!access) { return Result<Tribool>::failure(access.error()); }
128 return engine_->query_positive_checked(expression_from_node(node), context);
129}
130
132 const std::shared_ptr<const SymbolicNode>& node, ComputationContext& context) const {
133 auto access = context.consume_steps(0, "facts.assumptions");
134 if (!access) { return Result<Tribool>::failure(access.error()); }
135 return engine_->query_negative_checked(expression_from_node(node), context);
136}
137
139 const std::shared_ptr<const SymbolicNode>& node, ComputationContext& context) const {
140 auto access = context.consume_steps(0, "facts.assumptions");
141 if (!access) { return Result<Tribool>::failure(access.error()); }
142 return engine_->query_nonnegative_checked(expression_from_node(node), context);
143}
144
146 const std::shared_ptr<const SymbolicNode>& node, ComputationContext& context) const {
147 auto access = context.consume_steps(0, "facts.assumptions");
148 if (!access) { return Result<Tribool>::failure(access.error()); }
149 return engine_->query_nonzero_checked(expression_from_node(node), context);
150}
151
153 const std::shared_ptr<const SymbolicNode>& node, ComputationContext& context) const {
154 auto access = context.consume_steps(0, "facts.assumptions");
155 if (!access) { return Result<Tribool>::failure(access.error()); }
156 return engine_->query_real_checked(expression_from_node(node), context);
157}
158
159}
160
161
162}
AssumptionContext class with scoped push/pop management.
Result< void > consume_steps(std::size_t amount=1, const std::string &operation={})
static Result failure(CasErrc code, std::string message, std::string operation={})
Result< Tribool > is_nonnegative(const std::shared_ptr< const SymbolicNode > &node, ComputationContext &context) const override
Result< Tribool > is_real(const std::shared_ptr< const SymbolicNode > &node, ComputationContext &context) const override
Result< Tribool > is_nonzero(const std::shared_ptr< const SymbolicNode > &node, ComputationContext &context) const override
Result< Tribool > is_positive(const std::shared_ptr< const SymbolicNode > &node, ComputationContext &context) const override
Result< Tribool > is_negative(const std::shared_ptr< const SymbolicNode > &node, ComputationContext &context) const override
static void collect_names(const AssumptionContext &assumptions, std::set< std::string > &names, RewriteBudget &budget)
ComputationContext & context() const noexcept
std::size_t measure(const std::shared_ptr< const SymbolicNode > &node)
ExpressionResult assumed_transform(const ExprPtr &expression, ComputationContext &context, const char *operation, const char *name, Transform &&transform)
多元 Hensel 提升(单变量步)
SymbolicNodePtr differentiate_node(const SymbolicNodePtr &node, const std::string &variable, RewriteBudget &budget, const FactsQuery &facts, Domain domain)
SymbolicNodePtr expand_node(const SymbolicNodePtr &node, RewriteBudget &budget, const FactsQuery &facts, Domain domain)
ExpressionResult substitute_expression(const ExprPtr &expression, const std::string &variable, const ExprPtr &replacement, ComputationContext &context)
std::shared_ptr<::LMCAS::SymbolicExpr > make_expression_ptr(SymbolicNodePtr root)
const SymbolicNodePtr & node(const ::LMCAS::SymbolicExpr &expression) noexcept
ExpressionResult simplify_expression(const ExprPtr &expression, ComputationContext &context)
ExpressionResult checked_transform_expr(const ExprPtr &expression, ComputationContext &context, const char *operation, const char *transform_name, Transform &&transform)
const std::string & variable
const std::string const SymbolicNodePtr & replacement
std::shared_ptr< const SymbolicNode > SymbolicNodePtr
const FactsQuery & no_facts() noexcept
inline ::LMCAS::SymbolicExpr expression_from_node(SymbolicNodePtr root)
RewriteBudget const FactsQuery & facts
ComputationContext const std::string & operation
ExpressionResult expand_expression(const ExprPtr &expression, ComputationContext &context)
SymbolicNodePtr normalize_node(const SymbolicNodePtr &node, RewriteBudget &budget, const FactsQuery &facts, Domain domain)
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)
ExpressionResult differentiate_expression(const ExprPtr &expression, const std::string &variable, ComputationContext &context)
Result< std::shared_ptr< SymbolicExpr > > ExpressionResult
Result of an operation that produces a symbolic expression.
std::set< std::string > free_variables(const detail::SymbolicNodePtr &expression, detail::RewriteBudget *budget)
std::shared_ptr< SymbolicExpr > ExprPtr
ExprResult relation(const ExprPtr &lhs, const ExprPtr &rhs, RelationOp op)
const std::string const ExprPtr & value
__attribute__((visibility("default"))) Result< EqvProfile > eqv_profile_from_name(const std const std::string & name
符号规范化访问器接口。
内部 AST 定义。