12#include "lmmc/config.h"
21 const std::shared_ptr<SymbolicExpr>& expr,
23 if (!expr)
return false;
28 out =
static_cast<lmmc_real_t
>(*numeric);
36 (
context).limits().max_ast_nodes,
"transform");
38 auto sol = SymbolicExpr::lambertw(
c);
46 const std::shared_ptr<SymbolicExpr>& base,
49 (
context).limits().max_ast_nodes,
"transform");
58 auto ln_c = SymbolicExpr::ln(
c);
59 auto ln_a = SymbolicExpr::ln(base);
67 auto predicate =
relation ? original : SymbolicExpr::eq(original, SymbolicExpr::number(0));
74 return SymbolicExpr::add(left, SymbolicExpr::multiply(SymbolicExpr::number(-1),
right));
85 if (!affine || !affine.value()) {
return affine; }
90 for (
auto* coefficient : {&affine.value()->slope, &affine.value()->offset}) {
93 *coefficient = std::move(normalized.value());
100 for (
const auto& coefficient : {affine.
slope, affine.
offset}) {
155 type, std::vector<SymbolicNodePtr>{
detail::node(offset)}));
168 context.limits().max_ast_nodes,
"solve.parameter");
170 occupied.insert(var);
174 std::string parameter =
"_k";
175 for (std::size_t suffix = 1; occupied.count(parameter); ++suffix) {
177 parameter =
"_k" + std::to_string(suffix);
185 auto principal =
inverse_trig(type == Type::Sin ? Type::ArcSin : Type::ArcCos,
rhs);
186 const auto positive_half = SymbolicExpr::number(Rational(1, 2));
187 const auto negative_half = SymbolicExpr::number(Rational(-1, 2));
189 principal = SymbolicExpr::multiply(SymbolicExpr::number(
190 type == Type::Sin ? Rational(1, 6) : Rational(1, 3)),
pi);
192 principal = SymbolicExpr::multiply(SymbolicExpr::number(
193 type == Type::Sin ? Rational(-1, 6) : Rational(2, 3)),
pi);
202 (
context).limits().max_ast_nodes,
"transform");
206 auto integer_pi = SymbolicExpr::multiply(SymbolicExpr::variable(parameter),
pi);
207 auto twice_integer_pi = SymbolicExpr::multiply(SymbolicExpr::number(2), integer_pi);
208 auto half_pi = SymbolicExpr::multiply(SymbolicExpr::number(Rational(1, 2)),
pi);
210 std::vector<ExprPtr> values;
211 if (type == Type::Tan) {
213 SymbolicExpr::multiply(SymbolicExpr::number(Rational(*
integer, 4)),
pi) :
215 values.push_back(SymbolicExpr::add(principal, integer_pi));
217 values.push_back(type == Type::Sin ? integer_pi :
218 SymbolicExpr::add(half_pi, integer_pi));
220 auto principal = type == Type::Sin ?
221 SymbolicExpr::multiply(SymbolicExpr::number(*
integer), half_pi) :
222 (*
integer == 1 ? SymbolicExpr::number(0) :
pi);
223 values.push_back(SymbolicExpr::add(principal, twice_integer_pi));
226 values.push_back(SymbolicExpr::add(principal, twice_integer_pi));
227 values.push_back(SymbolicExpr::add(
229 SymbolicExpr::multiply(SymbolicExpr::number(-1), principal),
246 std::vector<ExprPtr> conditions;
249 return std::move(*decided);
258 const auto& parameter = fresh.value();
261 for (
const auto&
value : values) {
266 std::move(mapped.value()), {parameter}, conditions});
274 (
context).limits().max_ast_nodes,
"transform");
287}
catch (
const std::bad_alloc&) {
289}
catch (
const std::length_error& error) {
291}
catch (
const std::exception& error) {
298 (
context).limits().max_ast_nodes,
"transform");
306}
catch (
const std::bad_alloc&) {
308}
catch (
const std::length_error& error) {
310}
catch (
const std::exception& error) {
320 (
context).limits().max_ast_nodes,
"transform");
321 auto step =
context.consume_steps(1,
"solve.inverse");
323 std::optional<detail::AssumptionFacts> assumption_facts;
324 if (
context.assumptions()) { assumption_facts.emplace(*
context.assumptions()); }
338 return invert_trigonometric(pattern,
rhs, original, var,
facts,
context);
345 "Inverse requires a complete solution-set representation",
"solve.inverse");
349}
catch (
const std::bad_alloc&) {
351}
catch (
const std::length_error& error) {
353}
catch (
const std::exception& error) {
AssumptionContext class with scoped push/pop management.
static Result failure(CasErrc code, std::string message, std::string operation={})
static void collect_names(const AssumptionContext &assumptions, std::set< std::string > &names, RewriteBudget &budget)
ExprPtr subtract(const ExprPtr &left, const ExprPtr &right)
Result< std::optional< detail::AffineForm > > prepare_trigonometric_affine(const ExprPtr &inner, const std::string &var, ComputationContext &context)
SolveResult invert_trigonometric(const InversePattern &pattern, const ExprPtr &rhs, const ExprPtr &original, const std::string &var, const FactsQuery &facts, ComputationContext &context)
SolveResult invert_exponential(const ExprPtr &rhs, const ExprPtr &original, const std::string &var, const FactsQuery &facts, ComputationContext &context)
ExprPtr inverse_trig(FunctionNode::FuncType type, const ExprPtr &target)
std::optional< SolveResult > trigonometric_target_range(FunctionNode::FuncType type, const ExprPtr &rhs, const ExprPtr &original, const std::string &var, const FactsQuery &facts, ComputationContext &context, std::vector< ExprPtr > &conditions)
Result< std::string > capture_free_integer_parameter(const ExprPtr &original, const std::string &var, ComputationContext &context)
SolveResult invert_logarithm(const ExprPtr &rhs, const ExprPtr &original, const std::string &var, const FactsQuery &facts, ComputationContext &context)
std::vector< ExprPtr > trigonometric_periodic_values(FunctionNode::FuncType type, const ExprPtr &rhs, const std::string ¶meter, ComputationContext &context)
Result< bool > real_affine_coefficients(const detail::AffineForm &affine, Tribool nonzero, const FactsQuery &facts, ComputationContext &context)
ExprPtr trigonometric_principal_value(FunctionNode::FuncType type, const ExprPtr &rhs, const ExprPtr &pi)
SolveResult constant_trigonometric_preimage(FunctionNode::FuncType type, const ExprPtr &offset, const ExprPtr &rhs, const ExprPtr &original, const std::string &var, const FactsQuery &facts, ComputationContext &context)
std::vector< std::shared_ptr< SymbolicExpr > > invert_lambert_w(const std::shared_ptr< SymbolicExpr > &c, ComputationContext &context)
SolutionSet conditional_preimage(const ExprPtr &original, const std::string &var)
FunctionNode::FuncType func_type
SolveResult invert_function(const InversePattern &pattern, const ExprPtr &original, const std::string &var, ComputationContext &context, const SolveOptions &options)
std::vector< std::shared_ptr< SymbolicExpr > > invert_exp_base(const std::shared_ptr< SymbolicExpr > &base, const std::shared_ptr< SymbolicExpr > &c, ComputationContext &context)
std::shared_ptr< SymbolicExpr > rhs
bool try_evaluate_numeric(const std::shared_ptr< SymbolicExpr > &expr, lmmc_real_t &out, ComputationContext &context)
std::shared_ptr< SymbolicExpr > coefficient
std::shared_ptr< SymbolicExpr > inner
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)
std::shared_ptr< SymbolicExpr > slope
Result< Tribool > query_nonzero_value(const Node &node, const FactsQuery &facts, Domain domain, ComputationContext &context)
const FactsQuery & no_facts() noexcept
std::optional< double > try_finite_numeric(const SymbolicExpr &expression, ComputationContext &context)
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< 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
std::set< std::string > all_variable_names(const SymbolicNodePtr &expression, RewriteBudget *budget=nullptr)
Result< std::optional< AffineForm > > recognize_affine(const SymbolicExpr &expression, const std::string &variable, ComputationContext &context)
Result< Tribool > query_positive_value(const Node &node, const FactsQuery &facts, ComputationContext &context)
std::shared_ptr< SymbolicExpr > offset
__attribute__((visibility("default"))) ExprResult function(const std __attribute__((visibility("default"))) ExprResult finite_set(std ExprPtr upper
ExprResult integer(Integer)=delete
ExprResult real(const ExprPtr &expression, ComputationContext &context)
Result< SolutionSet > SolveResult
const VectorField const VectorField & c
Tribool
Tri-state logic value for property queries.
@ True
Property definitely holds
@ False
Property definitely does not hold
std::optional< int > exact_small_integer_node(const detail::SymbolicNodePtr &node, int min_value, int max_value)
std::shared_ptr< SymbolicExpr > ExprPtr
ExprResult relation(const ExprPtr &lhs, const ExprPtr &rhs, RelationOp op)
std::variant< EmptySolutions, UniversalSolutions, FiniteSolutions, IntervalSolutions, ConditionalSolutions, ParametricSolutions > SolutionSet
成功的 SolveResult 表示操作定义域内的完整解集。 完备性未决时返回外层 Inconclusive 错误;EmptySolutions 表示已证明的空解集。
const std::string const ExprPtr & value
std::vector< ParametricSolution > values
conditions 是在操作上下文假设下须同时满足的条件。 空条件保留原表达式定义域且不增加约束;整数参数遍历全体整数。