LMCAS
Lamina Computer Algebra System
载入中...
搜索中...
未找到
symbolic_geometry.cpp
浏览该文件的文档.
1#include <stdexcept>
6#include "symbolic.hpp"
7#include <cmath>
8#include <exception>
9
10namespace LMCAS {
11
12namespace {
13
14Result<void> validate_geometry_inputs(const std::shared_ptr<SymbolicExpr>& function,
15 const std::shared_ptr<SymbolicExpr>& lower,
16 const std::shared_ptr<SymbolicExpr>& upper,
18 const std::string& operation)
19{
20 auto step = context.consume_steps(1, operation);
21 if (!step) return step;
24 "profile expression cannot be null",
25 operation);
26 }
29 "integration bounds cannot be null",
30 operation);
31 }
32 return Result<void>::success();
33}
34
35
36ExpressionResult simplify_geometry_checked(std::shared_ptr<SymbolicExpr> expr,
37 const std::string& operation,
38 const std::string& message, ComputationContext& context)
39try {
40
41 detail::RewriteBudget transform_budget(context, (context).limits().max_recursion_depth,
42 (context).limits().max_ast_nodes, "transform");
43 if (!expr || !LMCAS::detail::node(expr)) {
45 message, operation);
46 }
47 auto simplified = detail::make_expression_ptr(detail::normalize_node(detail::node(expr), transform_budget));
48 if (!simplified || !LMCAS::detail::node(simplified)) {
50 message, operation);
51 }
54 "geometry integral is outside the supported domain",
55 operation);
56 }
57 return ExpressionResult::success(std::move(simplified));
58} catch (const CasError& error) {
59 return ExpressionResult::failure(error);
60} catch (const std::bad_alloc&) {
61 return ExpressionResult::failure(CasErrc::ResourceLimit, "allocation failed", operation);
62} catch (const std::length_error& error) {
63 return ExpressionResult::failure(CasErrc::ResourceLimit, error.what(), operation);
64} catch (const std::exception& error) {
65 return ExpressionResult::failure(CasErrc::InternalInvariant, error.what(), operation);
66}
67
69 const std::shared_ptr<SymbolicExpr>& expr,
70 const std::string& variable,
71 const std::string& operation, ComputationContext& context)
72try {
73
74 detail::RewriteBudget transform_budget(context, (context).limits().max_recursion_depth,
75 (context).limits().max_ast_nodes, "transform");
76 auto derivative = detail::make_expression_ptr(
77 detail::differentiate_node(detail::node(expr), variable, transform_budget));
79 derivative, operation,
80 "geometry derivative is outside the supported domain", context);
81} catch (const CasError& error) {
84 "geometry derivative is outside the supported domain", operation);
85 }
86 return ExpressionResult::failure(error);
87} catch (const std::bad_alloc&) {
88 return ExpressionResult::failure(CasErrc::ResourceLimit, "allocation failed", operation);
89} catch (const std::length_error& error) {
90 return ExpressionResult::failure(CasErrc::ResourceLimit, error.what(), operation);
91} catch (const std::exception& error) {
92 return ExpressionResult::failure(CasErrc::InternalInvariant, error.what(), operation);
93}
94
96 const std::shared_ptr<SymbolicExpr>& integrand,
97 const std::string& variable,
98 const std::shared_ptr<SymbolicExpr>& lower_bound,
99 const std::shared_ptr<SymbolicExpr>& upper_bound,
100 const std::string& operation, ComputationContext& context)
101try {
102
103 if (!integrand || !LMCAS::detail::node(integrand)) {
106 "geometry integrand is outside the supported domain",
107 operation);
108 }
109 Integrator integrator;
110 auto integrated = integrator.integrate_def_checked(
111 *integrand, variable, *lower_bound, *upper_bound, context);
112 if (!integrated) { return ExpressionResult::failure(integrated.error()); }
113 auto result = detail::make_expression_ptr(std::move(integrated.value()));
117 "geometry integral is outside the supported domain",
118 operation);
119 }
121 result, operation,
122 "geometry definite integral result is outside the supported domain", context);
123} catch (const CasError& error) {
124 return ExpressionResult::failure(error);
125} catch (const std::bad_alloc&) {
126 return ExpressionResult::failure(CasErrc::ResourceLimit, "allocation failed", operation);
127} catch (const std::length_error& error) {
128 return ExpressionResult::failure(CasErrc::ResourceLimit, error.what(), operation);
129} catch (const std::exception& error) {
130 return ExpressionResult::failure(CasErrc::InternalInvariant, error.what(), operation);
131}
132
133std::shared_ptr<SymbolicExpr> squared_profile(const std::shared_ptr<SymbolicExpr>& f, ComputationContext& context) {
134
135 detail::RewriteBudget transform_budget(context, (context).limits().max_recursion_depth,
136 (context).limits().max_ast_nodes, "transform");
137 if (f) {
138 if (auto func = std::dynamic_pointer_cast<const FunctionNode>(LMCAS::detail::node(f))) {
139 if (func->type() == FunctionNode::FuncType::Sqrt && func->arguments().size() == 1) {
140 return detail::make_expression_ptr(detail::normalize_node(func->arguments()[0], transform_budget));
141 }
142 }
143 if (auto power = std::dynamic_pointer_cast<const PowerNode>(LMCAS::detail::node(f))) {
144 auto exponent = std::dynamic_pointer_cast<const NumberNode>(power->exponent());
145 if (exponent && std::holds_alternative<Rational>(exponent->value())) {
146 const auto& rational = std::get<Rational>(exponent->value());
147 if (rational.get_numerator() == BigInt(1) &&
148 rational.get_denominator() == BigInt(2)) {
149 return detail::make_expression_ptr(detail::normalize_node(power->base(), transform_budget));
150 }
151 }
152 }
153 }
154 return detail::make_expression_ptr(detail::normalize_node(detail::node(SymbolicExpr::power(f, SymbolicExpr::number(2))), transform_budget));
155}
156
158 std::shared_ptr<SymbolicExpr> f,
159 std::shared_ptr<SymbolicExpr> a,
160 std::shared_ptr<SymbolicExpr> b,
161 const std::string& variable,
163 const std::string& operation)
164try {
165 detail::RewriteBudget transform_budget(context, (context).limits().max_recursion_depth,
166 (context).limits().max_ast_nodes, "transform");
167 auto valid = validate_geometry_inputs(f, a, b, context, operation);
168 if (!valid) return ExpressionResult::failure(valid.error());
169
170 auto step = context.consume_steps(8, operation);
171 if (!step) return ExpressionResult::failure(step.error());
172
173 try {
176 auto integrand = detail::make_expression_ptr(detail::normalize_node(detail::node(SymbolicExpr::multiply(pi, squared_profile(f, context))), transform_budget));
178 integrand, variable, a, b, operation, context);
179 } catch (const std::bad_alloc&) {
181 "symbolic geometry allocation failed",
182 operation);
183 } catch (const std::length_error& error) { return ExpressionResult::failure(CasErrc::ResourceLimit, error.what(), operation); } catch (const std::exception& e) {
185 e.what(), operation);
186 }
187} catch (const CasError& error) {
188 return ExpressionResult::failure(error);
189} catch (const std::bad_alloc&) {
190 return ExpressionResult::failure(CasErrc::ResourceLimit, "allocation failed", operation);
191} catch (const std::length_error& error) {
192 return ExpressionResult::failure(CasErrc::ResourceLimit, error.what(), operation);
193} catch (const std::exception& error) {
194 return ExpressionResult::failure(CasErrc::InternalInvariant, error.what(), operation);
195}
196
198 std::shared_ptr<SymbolicExpr> f,
199 std::shared_ptr<SymbolicExpr> a,
200 std::shared_ptr<SymbolicExpr> b,
201 const std::string& variable,
203 const std::string& operation)
204{
205 auto valid = validate_geometry_inputs(f, a, b, context, operation);
206 if (!valid) return ExpressionResult::failure(valid.error());
207
208 auto step = context.consume_steps(10, operation);
209 if (!step) return ExpressionResult::failure(step.error());
210
211 try {
212 auto derivative_result = differentiate_geometry_checked(f, variable, operation, context);
213 if (!derivative_result) return derivative_result;
214 auto integrand = SymbolicExpr::sqrt(SymbolicExpr::add(
215 SymbolicExpr::number(1),
216 SymbolicExpr::power(derivative_result.value(), SymbolicExpr::number(2))));
218 integrand, variable, a, b, operation, context);
219 } catch (const std::bad_alloc&) {
221 "symbolic geometry allocation failed",
222 operation);
223 } catch (const std::exception& e) {
225 e.what(), operation);
226 }
227}
228
229}
230
232 std::shared_ptr<SymbolicExpr> fx,
233 std::shared_ptr<SymbolicExpr> a,
234 std::shared_ptr<SymbolicExpr> b,
236) {
237 return volume_of_revolution_checked_impl(
238 std::move(fx), std::move(a), std::move(b), "x",
239 context, "volume_of_revolution_x");
240}
241
243 std::shared_ptr<SymbolicExpr> fx,
244 std::shared_ptr<SymbolicExpr> a,
245 std::shared_ptr<SymbolicExpr> b
246) {
248 return volume_of_revolution_x_checked(std::move(fx), std::move(a), std::move(b),
249 context);
250}
251
252
254 std::shared_ptr<SymbolicExpr> fx,
255 std::shared_ptr<SymbolicExpr> a,
256 std::shared_ptr<SymbolicExpr> b,
258) {
259 return arc_length_checked_impl(
260 std::move(fx), std::move(a), std::move(b), "x",
261 context, "arc_length_x");
262}
263
265 std::shared_ptr<SymbolicExpr> fx,
266 std::shared_ptr<SymbolicExpr> a,
267 std::shared_ptr<SymbolicExpr> b
268) {
270 return arc_length_x_checked(std::move(fx), std::move(a), std::move(b), context);
271}
272
273
275 std::shared_ptr<SymbolicExpr> fy,
276 std::shared_ptr<SymbolicExpr> a,
277 std::shared_ptr<SymbolicExpr> b,
279) {
280 return volume_of_revolution_checked_impl(
281 std::move(fy), std::move(a), std::move(b), "y",
282 context, "volume_of_revolution_y");
283}
284
286 std::shared_ptr<SymbolicExpr> fy,
287 std::shared_ptr<SymbolicExpr> a,
288 std::shared_ptr<SymbolicExpr> b
289) {
291 return volume_of_revolution_y_checked(std::move(fy), std::move(a), std::move(b),
292 context);
293}
294
295
297 std::shared_ptr<SymbolicExpr> fy,
298 std::shared_ptr<SymbolicExpr> a,
299 std::shared_ptr<SymbolicExpr> b,
301) {
302 return arc_length_checked_impl(
303 std::move(fy), std::move(a), std::move(b), "y",
304 context, "arc_length_y");
305}
306
308 std::shared_ptr<SymbolicExpr> fy,
309 std::shared_ptr<SymbolicExpr> a,
310 std::shared_ptr<SymbolicExpr> b
311) {
313 return arc_length_y_checked(std::move(fy), std::move(a), std::move(b), context);
314}
315
316
317}
@ Sqrt
对数、绝对值、平方根。
static Result failure(CasErrc code, std::string message, std::string operation={})
static Result success(T value)
ExpressionResult volume_of_revolution_checked_impl(std::shared_ptr< SymbolicExpr > f, std::shared_ptr< SymbolicExpr > a, std::shared_ptr< SymbolicExpr > b, const std::string &variable, ComputationContext &context, const std::string &operation)
Result< void > validate_geometry_inputs(const std::shared_ptr< SymbolicExpr > &function, const std::shared_ptr< SymbolicExpr > &lower, const std::shared_ptr< SymbolicExpr > &upper, ComputationContext &context, const std::string &operation)
ExpressionResult simplify_geometry_checked(std::shared_ptr< SymbolicExpr > expr, const std::string &operation, const std::string &message, ComputationContext &context)
ExpressionResult definite_integral_geometry_checked(const std::shared_ptr< SymbolicExpr > &integrand, const std::string &variable, const std::shared_ptr< SymbolicExpr > &lower_bound, const std::shared_ptr< SymbolicExpr > &upper_bound, const std::string &operation, ComputationContext &context)
ExpressionResult arc_length_checked_impl(std::shared_ptr< SymbolicExpr > f, std::shared_ptr< SymbolicExpr > a, std::shared_ptr< SymbolicExpr > b, const std::string &variable, ComputationContext &context, const std::string &operation)
std::shared_ptr< SymbolicExpr > squared_profile(const std::shared_ptr< SymbolicExpr > &f, ComputationContext &context)
ExpressionResult differentiate_geometry_checked(const std::shared_ptr< SymbolicExpr > &expr, const std::string &variable, const std::string &operation, ComputationContext &context)
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::shared_ptr< const Node > make_node(Args &&... args)
SymbolicNodePtr normalize_node(const SymbolicNodePtr &node, RewriteBudget &budget, const FactsQuery &facts, Domain domain)
const std::string & variable
__attribute__((visibility("default"))) ExprResult function(const std __attribute__((visibility("default"))) ExprResult finite_set(std ExprPtr upper
ExprResult e()
const std::vector< Polynomial< BigInt > > const BigInt ComputationContext & context
ExpressionResult arc_length_y_checked(std::shared_ptr< SymbolicExpr > fy, std::shared_ptr< SymbolicExpr > a, std::shared_ptr< SymbolicExpr > b, ComputationContext &context)
const ExprPtr & lower
bool contains_unevaluated_integral(const std::shared_ptr< const SymbolicNode > &node)
const MultiPoly & b
Result< std::shared_ptr< SymbolicExpr > > ExpressionResult
Result of an operation that produces a symbolic expression.
const ExprPtr & exponent
__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
ExpressionResult arc_length_x_checked(std::shared_ptr< SymbolicExpr > fx, std::shared_ptr< SymbolicExpr > a, std::shared_ptr< SymbolicExpr > b, ComputationContext &context)
ExprResult pi()
ExpressionResult volume_of_revolution_x_checked(std::shared_ptr< SymbolicExpr > fx, std::shared_ptr< SymbolicExpr > a, std::shared_ptr< SymbolicExpr > b, ComputationContext &context)
ExprResult function(const std::string &name, std::vector< ExprPtr > arguments)
ExpressionResult volume_of_revolution_y_checked(std::shared_ptr< SymbolicExpr > fy, std::shared_ptr< SymbolicExpr > a, std::shared_ptr< SymbolicExpr > b, ComputationContext &context)
ExprResult rational(const Rational &value)
const std::vector< IntegrationStep > Integrator & integrator
符号表达式主类 SymbolicExpr 及其工厂方法,运算接口.
内部 AST 定义。
解析几何应用:旋转体体积、弧长公式。