22 const std::shared_ptr<SymbolicExpr>& metric,
23 const std::vector<std::string>* coords,
25 const std::string& operation)
27 auto step =
context.consume_steps(1, operation);
32 "metric tensor cannot be null",
39 "metric tensor must be a matrix",
42 if (matrix->rows() != matrix->cols()) {
45 "metric tensor must be square",
49 if (coords->empty()) {
52 "coordinate list cannot be empty",
55 if (coords->size() != matrix->rows()) {
58 "coordinate count must match metric dimension",
61 for (
const auto& coord : *coords) {
65 "coordinate names cannot be empty",
75 const std::string&
name,
76 const std::string& operation)
78 if (idx < 0 ||
static_cast<std::size_t
>(idx) >=
dim) {
80 name +
" index is out of bounds",
87 const std::vector<std::string>&
vars,
88 const std::string& value_name,
89 const std::string& operation)
93 "variable list cannot be empty",
96 if (values.size() !=
vars.size()) {
98 value_name +
" dimension must match variable count",
101 for (
const auto& var :
vars) {
104 "variable names cannot be empty",
108 for (
const auto&
value : values) {
111 value_name +
" components cannot be null",
121 const std::string& operation)
124 k = std::min(k, n - k);
125 std::size_t
value = 1;
126 for (std::size_t i = 1; i <= k; ++i) {
127 std::size_t numerator = n - k + i;
129 const auto fraction_gcd = std::gcd(numerator,
denominator);
130 numerator /= fraction_gcd;
138 "binomial coefficient reduction was not exact",
141 if (numerator != 0 &&
value > limit / numerator) {
144 "differential-form component count exceeds the expansion budget",
152 "differential-form component count exceeds the expansion budget",
162 std::vector<std::vector<std::size_t>> combinations;
163 combinations.reserve(count);
164 if (k > n)
return combinations;
166 combinations.emplace_back();
170 std::vector<std::size_t> current(k);
171 std::iota(current.begin(), current.end(), 0);
173 combinations.push_back(current);
174 std::size_t position = k;
175 while (position > 0) {
177 if (current[position] < n - k + position)
break;
179 if (position == 0 && current[0] == n - k)
break;
181 for (std::size_t i = position + 1; i < k; ++i) {
182 current[i] = current[i - 1] + 1;
189 std::shared_ptr<SymbolicExpr>&& result,
192 const std::string& operation)
201 const std::string& operation)
205 "variable list cannot be empty", operation);
207 for (std::size_t i = 0; i <
vars.size(); ++i) {
208 if (
vars[i].empty()) {
210 "variable names cannot be empty", operation);
212 const auto current =
vars.begin() +
static_cast<std::ptrdiff_t
>(i);
213 if (std::find(
vars.begin(), current,
vars[i]) != current) {
215 "coordinate variables must be unique", operation);
222 const std::vector<std::shared_ptr<SymbolicExpr>>& form_coeffs,
224 const std::vector<std::string>&
vars,
226 const std::string& operation)
230 if (degree < 0 ||
static_cast<std::size_t
>(degree) >
vars.size()) {
233 "form degree must be between zero and the coordinate dimension", operation);
236 static_cast<std::size_t
>(degree),
237 context.limits().max_expansion_terms,
239 if (!input_count)
return input_count;
240 if (form_coeffs.size() != input_count.value()) {
243 "form coefficient count does not match degree and dimension", operation);
245 for (
const auto& coeff : form_coeffs) {
248 "form coefficients cannot be null", operation);
255 const std::vector<std::shared_ptr<SymbolicExpr>>& form_coeffs,
256 const std::vector<std::string>&
vars,
257 const std::map<std::vector<std::size_t>, std::size_t>& coefficient_index,
258 const std::vector<std::size_t>& output_index,
261 const std::string& operation)
266 auto source_index = output_index;
267 const std::size_t derivative_variable = source_index[removed];
268 source_index.erase(source_index.begin() +
static_cast<std::ptrdiff_t
>(removed));
269 const auto source = coefficient_index.find(source_index);
270 if (source == coefficient_index.end()) {
273 "exterior derivative could not locate an input coefficient", operation);
276 detail::node(form_coeffs[source->second]),
vars[derivative_variable], budget));
277 if (removed % 2 != 0) {
278 partial = SymbolicExpr::multiply(SymbolicExpr::number(-1), partial);
284}
catch (
const std::bad_alloc&) {
286}
catch (
const std::length_error& error) {
288}
catch (
const std::exception& error) {
293 const std::vector<std::shared_ptr<SymbolicExpr>>& form_coeffs,
294 const std::vector<std::string>&
vars,
295 const std::map<std::vector<std::size_t>, std::size_t>& coefficient_index,
296 const std::vector<std::size_t>& output_index,
298 const std::string& operation)
300 auto component = SymbolicExpr::number(0);
301 for (std::size_t removed = 0; removed < output_index.size(); ++removed) {
303 form_coeffs,
vars, coefficient_index, output_index, removed, budget, operation);
304 if (!partial)
return partial;
305 component = SymbolicExpr::add(component, partial.value());
310 "exterior derivative produced a null component",
314}
catch (
const std::bad_alloc&) {
316}
catch (
const std::length_error& error) {
318}
catch (
const std::exception& error) {
325 const std::shared_ptr<SymbolicExpr>&,
328 const std::shared_ptr<SymbolicExpr>&,
329 const std::shared_ptr<SymbolicExpr>&,
332 const std::shared_ptr<SymbolicExpr>&,
333 const std::vector<std::shared_ptr<SymbolicExpr>>&,
337 const std::shared_ptr<SymbolicExpr>& g_ij,
340 const std::string operation =
"metric_inverse";
341 auto metric = validate_metric_matrix(g_ij,
nullptr,
context, operation);
343 auto budget =
context.consume_steps(12, operation);
351 }
catch (
const std::bad_alloc&) {
353 "allocation failed while inverting metric",
355 }
catch (
const std::exception& ex) {
363 const std::shared_ptr<SymbolicExpr>& g_ij)
371 const std::shared_ptr<SymbolicExpr>& g_ij,
372 const std::vector<std::string>& coords,
376 const std::string operation =
"christoffel_first_kind";
377 auto metric = validate_metric_matrix(g_ij, &coords,
context, operation);
381 const std::size_t
dim = metric.
value()->rows();
382 auto k_check = validate_index(k,
dim,
"k", operation);
386 auto i_check = validate_index(i,
dim,
"i", operation);
390 auto j_check = validate_index(j,
dim,
"j", operation);
394 auto budget =
context.consume_steps(16, operation);
401 "Christoffel symbol could not be constructed",
403 }
catch (
const std::bad_alloc&) {
405 "allocation failed while calculating Christoffel symbol",
407 }
catch (
const std::exception& ex) {
415 const std::shared_ptr<SymbolicExpr>& g_ij,
416 const std::vector<std::string>& coords,
424 const std::shared_ptr<SymbolicExpr>& g_ij,
425 const std::vector<std::string>& coords,
429 (
context).limits().max_ast_nodes,
"transform");
432 if (!mat)
return SymbolicExpr::number(0);
442 auto sum12 = SymbolicExpr::add(term1, term2);
443 auto diff = SymbolicExpr::add(sum12, SymbolicExpr::multiply(term3, SymbolicExpr::number(-1)));
446 SymbolicExpr::number(Rational(BigInt(1), BigInt(2))),
447 diff)), transform_budget));
451 const std::shared_ptr<SymbolicExpr>& g_ij,
452 const std::shared_ptr<SymbolicExpr>& g_up_ij,
453 const std::vector<std::string>& coords,
457 const std::string operation =
"christoffel_second_kind";
458 auto metric = validate_metric_matrix(g_ij, &coords,
context, operation);
462 auto inverse_metric = validate_metric_matrix(g_up_ij, &coords,
context, operation);
463 if (!inverse_metric) {
466 const std::size_t
dim = metric.
value()->rows();
467 auto k_check = validate_index(k,
dim,
"k", operation);
471 auto i_check = validate_index(i,
dim,
"i", operation);
475 auto j_check = validate_index(j,
dim,
"j", operation);
479 auto budget =
context.consume_steps(
dim * 20 + 12, operation);
486 "Christoffel symbol could not be constructed",
488 }
catch (
const std::bad_alloc&) {
490 "allocation failed while calculating Christoffel symbol",
492 }
catch (
const std::exception& ex) {
500 const std::shared_ptr<SymbolicExpr>& g_ij,
501 const std::shared_ptr<SymbolicExpr>& g_up_ij,
502 const std::vector<std::string>& coords,
510 const std::shared_ptr<SymbolicExpr>& g_ij,
511 const std::shared_ptr<SymbolicExpr>& g_up_ij,
512 const std::vector<std::string>& coords,
516 (
context).limits().max_ast_nodes,
"transform");
519 if (!mat_up)
return SymbolicExpr::number(0);
521 size_t dim = coords.size();
522 auto result = SymbolicExpr::number(0);
524 for (
size_t m = 0; m <
dim; m++) {
527 auto term = SymbolicExpr::multiply(g_up_km, gamma_first);
528 result = SymbolicExpr::add(result, term);
535 const std::shared_ptr<SymbolicExpr>& g_ij,
536 const std::shared_ptr<SymbolicExpr>& g_up_ij,
537 const std::vector<std::string>& coords,
541 (
context).limits().max_ast_nodes,
"transform");
542 auto gamma_rho_nu_sigma =
544 auto gamma_rho_mu_sigma =
549 auto result = SymbolicExpr::add(
551 SymbolicExpr::multiply(term2, SymbolicExpr::number(-1)));
553 for (std::size_t lambda = 0; lambda < coords.size(); ++lambda) {
554 auto gamma_rho_mu_lambda =
556 auto gamma_lambda_nu_sigma =
558 auto gamma_rho_nu_lambda =
560 auto gamma_lambda_mu_sigma =
562 auto product_difference = SymbolicExpr::add(
563 SymbolicExpr::multiply(
564 gamma_rho_mu_lambda, gamma_lambda_nu_sigma),
565 SymbolicExpr::multiply(
566 SymbolicExpr::multiply(
567 gamma_rho_nu_lambda, gamma_lambda_mu_sigma),
568 SymbolicExpr::number(-1)));
569 result = SymbolicExpr::add(result, product_difference);
575 const std::shared_ptr<SymbolicExpr>& g_ij,
576 const std::vector<std::string>& coords,
577 int rho,
int sigma,
int mu,
int nu,
580 const std::string operation =
"riemann_curvature_tensor";
581 auto metric = validate_metric_matrix(g_ij, &coords,
context, operation);
585 const std::size_t
dim = metric.
value()->rows();
586 auto rho_check = validate_index(rho,
dim,
"rho", operation);
590 auto sigma_check = validate_index(sigma,
dim,
"sigma", operation);
594 auto mu_check = validate_index(mu,
dim,
"mu", operation);
598 auto nu_check = validate_index(nu,
dim,
"nu", operation);
602 auto budget =
context.consume_steps(
dim * 80 + 40, operation);
608 if (!inverse_metric) {
612 g_ij, inverse_metric.value(), coords, rho, sigma, mu, nu,
context);
614 "Riemann curvature component could not be constructed",
616 }
catch (
const std::bad_alloc&) {
618 "allocation failed while calculating Riemann curvature",
620 }
catch (
const std::exception& ex) {
628 const std::shared_ptr<SymbolicExpr>& g_ij,
629 const std::vector<std::string>& coords,
630 int rho,
int sigma,
int mu,
int nu)
638 const std::shared_ptr<SymbolicExpr>& f,
639 const std::vector<std::shared_ptr<SymbolicExpr>>& X,
640 const std::vector<std::string>&
vars,
644 const std::string operation =
"lie_derivative";
645 auto step =
context.consume_steps(1, operation);
649 "scalar function cannot be null",
654 "Lie derivative order must be between 0 and 64",
657 auto vector_check = validate_expr_vector(X,
vars,
"vector field", operation);
659 auto budget =
context.consume_steps(
static_cast<std::size_t
>(
order + 1) *
vars.size() * 8 + 8,
665 "Lie derivative could not be constructed",
667 }
catch (
const std::bad_alloc&) {
669 "allocation failed while calculating Lie derivative",
671 }
catch (
const std::exception& ex) {
679 const std::shared_ptr<SymbolicExpr>& f,
680 const std::vector<std::shared_ptr<SymbolicExpr>>& X,
681 const std::vector<std::string>&
vars,
689 const std::shared_ptr<SymbolicExpr>& f,
690 const std::vector<std::shared_ptr<SymbolicExpr>>& X,
691 const std::vector<std::string>&
vars,
695 (
context).limits().max_ast_nodes,
"transform");
696 if (!f || X.size() !=
vars.size())
return SymbolicExpr::number(0);
698 for (
int it = 0; it <
order; ++it) {
699 auto acc = SymbolicExpr::number(0);
700 for (
size_t i = 0; i <
vars.size(); ++i) {
702 acc = SymbolicExpr::add(acc, SymbolicExpr::multiply(X[i], partial));
710 const std::vector<std::shared_ptr<SymbolicExpr>>& form_coeffs,
712 const std::vector<std::string>&
vars,
715 const std::string operation =
"exterior_derivative";
716 auto step =
context.consume_steps(1, operation);
718 const auto input_count =
719 validate_form_coefficients(form_coeffs, degree,
vars,
context, operation);
721 const auto output_count = bounded_binomial(
vars.size(),
722 static_cast<std::size_t
>(degree) + 1,
723 context.limits().max_expansion_terms,
728 context.limits().max_ast_nodes, operation.c_str());
729 std::size_t input_nodes = 0;
730 for (
const auto& coefficient : form_coeffs) {
734 const auto input_indices = index_combinations(
vars.size(),
735 static_cast<std::size_t
>(degree),
736 input_count.
value());
737 const auto output_indices = index_combinations(
vars.size(),
738 static_cast<std::size_t
>(degree) + 1,
739 output_count.
value());
740 std::map<std::vector<std::size_t>, std::size_t> coefficient_index;
741 for (std::size_t i = 0; i < input_indices.size(); ++i) {
742 coefficient_index.emplace(input_indices[i], i);
745 std::vector<std::shared_ptr<SymbolicExpr>> result;
746 result.reserve(output_count.value());
747 std::size_t output_nodes = 0;
748 for (
const auto& output_index : output_indices) {
749 auto component = exterior_derivative_component(
750 form_coeffs,
vars, coefficient_index, output_index, budget, operation);
754 result.push_back(std::move(component.value()));
759 }
catch (
const std::bad_alloc&) {
761 "allocation failed while calculating exterior derivative",
763 }
catch (
const std::exception& ex) {
771 const std::vector<std::shared_ptr<SymbolicExpr>>& form_coeffs,
773 const std::vector<std::string>&
vars)
Result< void > consume_steps(std::size_t amount=1, const std::string &operation={})
static Result failure(CasErrc code, std::string message, std::string operation={})
static Result success(T value)
ComputationContext & context() const noexcept
std::size_t measure(const std::shared_ptr< const SymbolicNode > &node)
std::size_t append_size(std::size_t current, std::size_t child)
微分几何:度量张量,克里斯托弗符号,黎曼曲率张量.
DifferentialGeometryExprResult exterior_derivative_component(const std::vector< std::shared_ptr< SymbolicExpr > > &form_coeffs, const std::vector< std::string > &vars, const std::map< std::vector< std::size_t >, std::size_t > &coefficient_index, const std::vector< std::size_t > &output_index, detail::RewriteBudget &budget, const std::string &operation)
Result< std::size_t > validate_form_coefficients(const std::vector< std::shared_ptr< SymbolicExpr > > &form_coeffs, int degree, const std::vector< std::string > &vars, ComputationContext &context, const std::string &operation)
Result< std::shared_ptr< const MatrixNode > > validate_metric_matrix(const std::shared_ptr< SymbolicExpr > &metric, const std::vector< std::string > *coords, ComputationContext &context, const std::string &operation)
Result< void > validate_expr_vector(const std::vector< std::shared_ptr< SymbolicExpr > > &values, const std::vector< std::string > &vars, const std::string &value_name, const std::string &operation)
DifferentialGeometryExprResult checked_geometry_expression(std::shared_ptr< SymbolicExpr > &&result, CasErrc error, const char *message, const std::string &operation)
Result< std::size_t > bounded_binomial(std::size_t n, std::size_t k, std::size_t limit, const std::string &operation)
std::vector< std::vector< std::size_t > > index_combinations(std::size_t n, std::size_t k, std::size_t count)
DifferentialGeometryExprResult exterior_derivative_term(const std::vector< std::shared_ptr< SymbolicExpr > > &form_coeffs, const std::vector< std::string > &vars, const std::map< std::vector< std::size_t >, std::size_t > &coefficient_index, const std::vector< std::size_t > &output_index, std::size_t removed, detail::RewriteBudget &budget, const std::string &operation)
Result< void > validate_index(int idx, std::size_t dim, const std::string &name, const std::string &operation)
Result< void > validate_form_coordinates(const std::vector< std::string > &vars, 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
SymbolicNodePtr normalize_node(const SymbolicNodePtr &node, RewriteBudget &budget, const FactsQuery &facts, Domain domain)
DifferentialGeometryExprResult christoffel_first_kind_checked(const std::shared_ptr< SymbolicExpr > &g_ij, const std::vector< std::string > &coords, int k, int i, int j, ComputationContext &context)
DifferentialGeometryExprResult metric_inverse_checked(const std::shared_ptr< SymbolicExpr > &g_ij, ComputationContext &context)
static std::shared_ptr< SymbolicExpr > lie_derivative_impl(const std::shared_ptr< SymbolicExpr > &, const std::vector< std::shared_ptr< SymbolicExpr > > &, const std::vector< std::string > &, int, ComputationContext &context)
const std::vector< Polynomial< BigInt > > const BigInt ComputationContext & context
__attribute__((visibility("default"))) VectorCalculusFieldResult gradient_checked(const std __attribute__((visibility("default"))) VectorCalculusFieldResult gradient_checked(const std __attribute__((visibility("default"))) VectorField gradient(const std const std::vector< std::string > & vars
Result< std::shared_ptr< SymbolicExpr > > DifferentialGeometryExprResult
const std::vector< FGLMPoly > const MonomialOrder & order
ExpressionResult matrix_inverse_checked(const std::shared_ptr< SymbolicExpr > &A, ComputationContext &context)
static std::shared_ptr< SymbolicExpr > christoffel_second_kind_impl(const std::shared_ptr< SymbolicExpr > &, const std::shared_ptr< SymbolicExpr > &, const std::vector< std::string > &, int, int, int, ComputationContext &context)
DifferentialGeometryExprResult christoffel_second_kind_checked(const std::shared_ptr< SymbolicExpr > &g_ij, const std::shared_ptr< SymbolicExpr > &g_up_ij, const std::vector< std::string > &coords, int k, int i, int j, ComputationContext &context)
static std::shared_ptr< SymbolicExpr > christoffel_first_kind_impl(const std::shared_ptr< SymbolicExpr > &, const std::vector< std::string > &, int, int, int, ComputationContext &context)
DifferentialGeometryExprResult riemann_curvature_tensor_checked(const std::shared_ptr< SymbolicExpr > &g_ij, const std::vector< std::string > &coords, int rho, int sigma, int mu, int nu, ComputationContext &context)
DifferentialGeometryVectorResult exterior_derivative_checked(const std::vector< std::shared_ptr< SymbolicExpr > > &form_coeffs, int degree, const std::vector< std::string > &vars, ComputationContext &context)
__attribute__((visibility("default"))) MatrixRankResult matrix_rank_checked(const std __attribute__((visibility("default"))) MatrixRankResult matrix_rank_checked(const std __attribute__((visibility("default"))) ExpressionResult matrix_rref_checked(const std __attribute__((visibility("default"))) ExpressionResult matrix_rref_checked(const std __attribute__((visibility("default"))) MatrixNullspaceResult matrix_nullspace_checked(const std __attribute__((visibility("default"))) MatrixNullspaceResult matrix_nullspace_checked(const std __attribute__((visibility("default"))) MatrixLinearSolveResult matrix_solve_linear_checked(const std __attribute__((visibility("default"))) MatrixLinearSolveResult matrix_solve_linear_checked(const std int dim
DifferentialGeometryExprResult lie_derivative_checked(const std::shared_ptr< SymbolicExpr > &f, const std::vector< std::shared_ptr< SymbolicExpr > > &X, const std::vector< std::string > &vars, int order, ComputationContext &context)
const std::string const ExprPtr & value
const ExprPtr & denominator
Result< std::vector< std::shared_ptr< SymbolicExpr > > > DifferentialGeometryVectorResult
__attribute__((visibility("default"))) Result< EqvProfile > eqv_profile_from_name(const std const std::string & name
static std::shared_ptr< SymbolicExpr > riemann_curvature_tensor_with_inverse(const std::shared_ptr< SymbolicExpr > &g_ij, const std::shared_ptr< SymbolicExpr > &g_up_ij, const std::vector< std::string > &coords, int rho, int sigma, int mu, int nu, ComputationContext &context)
符号表达式主类 SymbolicExpr 及其工厂方法,运算接口.
符号矩阵运算:乘法、行列式、逆、旋转/反射/缩放矩阵、特征值。