LMCAS
Lamina Computer Algebra System
载入中...
搜索中...
未找到
normalization_functions.cpp
浏览该文件的文档.
3
4namespace LMCAS {
5
8 const std::vector<std::shared_ptr<const SymbolicNode>>& arguments) {
9 if (type == FunctionNode::FuncType::Ln && arguments.size() == 1) {
10 return normalize_natural_logarithm(arguments.front());
11 }
12 if (type != FunctionNode::FuncType::Log || arguments.size() != 2) {
13 return false;
14 }
15 if (const auto power = std::dynamic_pointer_cast<const PowerNode>(arguments.front())) {
18 std::vector<std::shared_ptr<const SymbolicNode>>{arguments[1]});
19 if (power->base()->compare(*arguments[1]) == 0 &&
23 set_result(power->exponent());
24 return true;
25 }
26 }
29 std::vector<std::shared_ptr<const SymbolicNode>>{arguments[0]});
32 std::vector<std::shared_ptr<const SymbolicNode>>{arguments[1]});
35 auto quotient = make_normalized_multiply_node({numerator, reciprocal}, rewrite_budget());
37 quotient->accept(visitor);
38 set_result(visitor.get_result());
39 return true;
40}
41
43 const std::shared_ptr<const SymbolicNode>& argument) {
44 if (const auto power = std::dynamic_pointer_cast<const PowerNode>(argument)) {
47 return false;
48 }
51 std::vector<std::shared_ptr<const SymbolicNode>>{power->base()});
52 auto product = make_normalized_multiply_node({power->exponent(), logarithm}, rewrite_budget());
54 product->accept(visitor);
55 set_result(visitor.get_result());
56 return true;
57 }
58 const auto function = std::dynamic_pointer_cast<const FunctionNode>(argument);
60 return false;
61 }
62 if (function->arguments().size() != 1 ||
64 return false;
65 }
66 set_result(function->arguments().front());
67 return true;
68}
69
71 FunctionNode::FuncType type, const std::shared_ptr<const SymbolicNode>& argument) {
72 std::shared_ptr<const SymbolicNode> positive;
73 if (!check_negative_arg(argument, positive, rewrite_budget())) {
74 return false;
75 }
76 switch (type) {
83 std::vector<std::shared_ptr<const SymbolicNode>>{positive});
86 return true;
87 }
91 std::vector<std::shared_ptr<const SymbolicNode>>{positive}));
92 return true;
93 default:
94 return false;
95 }
96}
97
99 FunctionNode::FuncType type, const std::shared_ptr<const SymbolicNode>& argument) {
100 Rational coefficient;
101 if (get_pi_coeff(argument, coefficient)) {
102 if (auto value = normalization_pi_function(type, coefficient, rewrite_budget())) {
103 set_result(std::move(value));
104 return true;
105 }
106 }
107 return normalize_function_parity(type, argument);
108}
109
111 std::shared_ptr<const SymbolicNode> argument;
112 if (try_normalize_squared_norm(node, argument)) {
113 return;
114 }
115 std::vector<std::shared_ptr<const SymbolicNode>> arguments;
116 std::size_t nodes = 0;
117 if (argument) {
118 normalization_append(rewrite_budget(), nodes, arguments, argument);
119 } else {
120 for (const auto& operand : node.arguments()) {
121 operand->accept(*this);
122 normalization_append(rewrite_budget(), nodes, arguments, result);
123 }
124 }
125 if (arguments.size() == 1) {
126 if (const auto number = std::dynamic_pointer_cast<const NumberNode>(arguments.front())) {
127 if (auto value = normalization_numeric_function(node.type(), number, rewrite_budget())) {
128 set_result(std::move(value));
129 return;
130 }
131 }
132 }
133 if (normalize_logarithm(node.type(), arguments)) {
134 return;
135 }
136 if (arguments.size() == 1 && normalize_unary_function(node.type(), arguments.front())) {
137 return;
138 }
139 if (rewrite_budget()) { rewrite_budget()->append_size(1, nodes); }
140 auto function = detail::make_node<FunctionNode>(node.type(), arguments);
141 if (auto simplified = try_assumption_simplify(function)) {
142 simplified->accept(*this);
143 return;
144 }
146}
147
149 std::vector<std::shared_ptr<const SymbolicNode>> arguments;
150 std::size_t nodes = 1;
151 normalization_check_count(rewrite_budget(), node.arguments().size());
152 arguments.reserve(node.arguments().size());
153 for (const auto& argument : node.arguments()) {
154 argument->accept(*this);
155 normalization_append(rewrite_budget(), nodes, arguments, result);
156 }
158 node.name(), std::move(arguments)));
159}
160std::shared_ptr<const SymbolicNode> NormalizationVisitor::simplify_assumed_square_root(
161 const std::shared_ptr<const SymbolicNode>& argument) const {
162 const auto power = std::dynamic_pointer_cast<const PowerNode>(argument);
163 if (!power) {
164 return nullptr;
165 }
166 const auto exponent = std::dynamic_pointer_cast<const NumberNode>(power->exponent());
167 BigInt value;
169 return nullptr;
170 }
171 if (value != BigInt(2)) {
172 return nullptr;
173 }
174 auto nonnegative = detail::query_nonnegative_value(power->base(), facts_, context_);
175 if (normalization_proved(nonnegative)) {
176 return power->base();
177 }
178 auto real = detail::query_real_value(power->base(), facts_, context_);
179 if (!real) {
180 throw real.error();
181 }
182 if (real.value() != Tribool::True) {
183 return nullptr;
184 }
185 normalization_check_children(rewrite_budget(), 1, power->base());
187 std::vector<std::shared_ptr<const SymbolicNode>>{power->base()});
188}
189
190std::shared_ptr<const SymbolicNode> NormalizationVisitor::simplify_assumed_absolute(
191 const std::shared_ptr<const SymbolicNode>& argument) const {
192 auto positive = detail::query_nonnegative_value(argument, facts_, context_);
193 if (normalization_proved(positive)) {
194 return argument;
195 }
198 return nullptr;
199 }
201 detail::make_node<NumberNode>(BigInt(-1)), argument}, rewrite_budget());
202}
203
204std::shared_ptr<const SymbolicNode> NormalizationVisitor::try_assumption_simplify(
205 const std::shared_ptr<const SymbolicNode>& node) {
206 const auto function = std::dynamic_pointer_cast<const FunctionNode>(node);
207 if (!function) {
208 return nullptr;
209 }
210 if (function->arguments().size() != 1) {
211 return nullptr;
212 }
213 const auto& argument = function->arguments().front();
214 switch (function->type()) {
216 return simplify_assumed_square_root(argument);
218 return simplify_assumed_absolute(argument);
219 default:
220 return nullptr;
221 }
222}
223
224}
virtual Result< Tribool > is_negative(const std::shared_ptr< const SymbolicNode > &node, ComputationContext &context) const =0
函数节点,表示数学函数调用(三角函数、对数、特殊函数等)。
@ Sqrt
对数、绝对值、平方根。
bool try_normalize_squared_norm(const SymbolicNode &node, std::shared_ptr< const SymbolicNode > &argument)
bool normalize_unary_function(FunctionNode::FuncType type, const std::shared_ptr< const SymbolicNode > &argument)
std::shared_ptr< const SymbolicNode > try_assumption_simplify(const std::shared_ptr< const SymbolicNode > &node)
void visit(const NumberNode &node) override
bool normalize_natural_logarithm(const std::shared_ptr< const SymbolicNode > &argument)
bool normalize_logarithm(FunctionNode::FuncType type, const std::vector< std::shared_ptr< const SymbolicNode > > &arguments)
NormalizationVisitor(detail::RewriteBudget &budget, const FactsQuery &facts, Domain domain)
void set_result(std::shared_ptr< const SymbolicNode > candidate)
std::shared_ptr< const SymbolicNode > simplify_assumed_square_root(const std::shared_ptr< const SymbolicNode > &argument) const
std::shared_ptr< const SymbolicNode > result
bool normalize_function_parity(FunctionNode::FuncType type, const std::shared_ptr< const SymbolicNode > &argument)
std::shared_ptr< const SymbolicNode > simplify_assumed_absolute(const std::shared_ptr< const SymbolicNode > &argument) const
CasError & error()
std::size_t append_size(std::size_t current, std::size_t child)
RewriteBudget * rewrite_budget() const noexcept
Result< Tribool > query_nonzero_value(const Node &node, const FactsQuery &facts, Domain domain, ComputationContext &context)
std::shared_ptr< const Node > make_node(Args &&... args)
Result< Tribool > query_real_value(const Node &node, const FactsQuery &facts, ComputationContext &context)
Result< Tribool > query_nonnegative_value(const Node &node, const FactsQuery &facts, ComputationContext &context)
Result< Tribool > query_positive_value(const Node &node, const FactsQuery &facts, ComputationContext &context)
bool try_get_integer_value(const std::shared_ptr< const NumberNode > &node, BigInt &value)
ExprResult real(const ExprPtr &expression, ComputationContext &context)
@ Real
Real numbers
@ True
Property definitely holds
std::size_t normalization_check_count(detail::RewriteBudget *budget, std::size_t rows, std::size_t cols=1, bool wrapped=true)
std::shared_ptr< const SymbolicNode > normalization_numeric_function(FunctionNode::FuncType type, const std::shared_ptr< const NumberNode > &number, detail::RewriteBudget *budget=nullptr)
const ExprPtr & exponent
void normalization_check_children(detail::RewriteBudget *budget, std::size_t roots, const std::shared_ptr< const Nodes > &... children)
bool check_negative_arg(const std::shared_ptr< const SymbolicNode > &argument, std::shared_ptr< const SymbolicNode > &positive, detail::RewriteBudget *budget=nullptr)
std::shared_ptr< const SymbolicNode > normalization_pi_function(FunctionNode::FuncType type, const Rational &coefficient, detail::RewriteBudget *budget=nullptr)
const std::string const ExprPtr & value
bool normalization_proved(const Result< Tribool > &result)
std::shared_ptr< const SymbolicNode > make_normalized_multiply_node(const std::vector< std::shared_ptr< const SymbolicNode > > &operands, detail::RewriteBudget *budget=nullptr)
bool get_pi_coeff(const std::shared_ptr< const SymbolicNode > &node, Rational &coefficient)
const ExprPtr & denominator
ExprResult function(const std::string &name, std::vector< ExprPtr > arguments)
void normalization_append(detail::RewriteBudget *budget, std::size_t &nodes, std::vector< std::shared_ptr< const SymbolicNode > > &children, std::shared_ptr< const SymbolicNode > child)
符号规范化访问器接口。