15 const std::shared_ptr<SymbolicExpr>& f,
const std::string&
t,
16 const std::string& omega) {
24 auto function = std::dynamic_pointer_cast<const FunctionNode>(node);
26 function->arguments().size() != 1)
return false;
27 auto argument = std::dynamic_pointer_cast<const VariableNode>(
function->arguments()[0]);
28 return argument && !argument->is_constant() && argument->name() ==
variable;
34 (
context).limits().max_ast_nodes,
"transform");
37 function->arguments().size() != 1)
return nullptr;
46 const std::shared_ptr<SymbolicExpr>& rate) {
47 auto product = std::dynamic_pointer_cast<const MultiplyNode>(
detail::node(rate));
49 std::vector<std::shared_ptr<const SymbolicNode>> factors;
50 for (
const auto& factor : product->operands()) {
51 auto number = std::dynamic_pointer_cast<const NumberNode>(factor);
52 if (!number || !number->is_positive()) factors.push_back(factor);
59 const AssumptionContext& assumptions,
60 std::vector<std::shared_ptr<SymbolicExpr>>& conditions,
62 InferenceEngine inference(assumptions);
63 auto real = inference.query_real_checked(*rate,
context);
71 auto positive = inference.query_positive_checked(*rate,
context);
73 throw positive.error();
78 auto nonpositive = inference.query_nonpositive_checked(*rate,
context);
80 throw nonpositive.error();
93 (
context).limits().max_ast_nodes,
"transform");
101 two,
detail::node(rate), reciprocal}), transform_budget));
105 const Rational& rate,
const std::string& omega) {
107 auto coefficient = SymbolicExpr::sqrt(
108 SymbolicExpr::divide(
pi, SymbolicExpr::number(rate)));
109 auto exponent = SymbolicExpr::multiply(SymbolicExpr::number(-Rational(1) / (Rational(4) * rate)),
110 SymbolicExpr::power(SymbolicExpr::variable(omega), SymbolicExpr::number(2)));
111 return SymbolicExpr::multiply(coefficient, SymbolicExpr::exp(
exponent));
116 const std::shared_ptr<SymbolicExpr>& f,
const std::string&
t,
117 const std::string& omega, ComputationContext&
context,
118 const AssumptionContext& assumptions,
119 std::vector<std::shared_ptr<SymbolicExpr>>& conditions);
122 const AddNode& addition,
const std::string&
t,
const std::string& omega,
124 std::vector<std::shared_ptr<SymbolicExpr>>& conditions) {
125 std::shared_ptr<SymbolicExpr> result;
126 for (
const auto& operand : addition.
operands()) {
128 t, omega,
context, assumptions, conditions);
129 if (!transformed)
return nullptr;
130 result = result ? SymbolicExpr::add(result, transformed) : transformed;
136 const std::shared_ptr<SymbolicExpr>& f,
const std::string&
t,
138 const AssumptionContext& assumptions,
139 std::vector<std::shared_ptr<SymbolicExpr>>& conditions) {
140 auto step =
context.consume_steps(1,
"fourier_transform.recursive");
150 auto addition = std::dynamic_pointer_cast<const AddNode>(
detail::node(f));
155 if (!coefficient->is_one()) {
158 return SymbolicExpr::multiply(coefficient, transformed);
175 const std::shared_ptr<SymbolicExpr>& f,
176 const std::string&
t,
177 const std::string& omega,
179 const std::string operation =
"fourier_transform";
182 auto step =
context.consume_steps(8, operation);
185 AssumptionContext empty_assumptions;
186 const auto& assumptions =
context.assumptions() ? *
context.assumptions() : empty_assumptions;
187 std::vector<std::shared_ptr<SymbolicExpr>> conditions;
189 auto final_access =
context.consume_steps(0, operation);
194 if (result) result.value().value.conditions = std::move(conditions);
198 }
catch (
const std::bad_alloc&) {
200 "transform allocation failed",
202 }
catch (
const std::exception&
e) {
204 e.what(), operation);
209 const std::shared_ptr<SymbolicExpr>& f,
210 const std::string&
t,
211 const std::string& omega) {
217 const std::shared_ptr<SymbolicExpr>& F,
const std::string& omega,
220 (
context).limits().max_ast_nodes,
"transform");
221 auto step =
context.consume_steps(1,
"inverse_fourier_transform.recursive");
222 if (!step)
return nullptr;
224 auto tv = SymbolicExpr::variable(
t);
232 std::shared_ptr<SymbolicExpr> result;
233 for (
auto&
op : add_node->operands()) {
241 result = result ? SymbolicExpr::add(result, ift) : ift;
250 std::vector<std::shared_ptr<const SymbolicNode>>{
detail::node(tv)}));
251 return SymbolicExpr::exp(SymbolicExpr::multiply(
252 SymbolicExpr::number(-1), abs_t));
257 auto coefficient = SymbolicExpr::divide(SymbolicExpr::number(1),
258 SymbolicExpr::sqrt(SymbolicExpr::multiply(
259 SymbolicExpr::number(Rational(4) * *rate),
pi)));
260 auto exponent = SymbolicExpr::multiply(
261 SymbolicExpr::number(-Rational(1) / (Rational(4) * *rate)),
262 SymbolicExpr::power(tv, SymbolicExpr::number(2)));
263 return SymbolicExpr::multiply(
264 coefficient, SymbolicExpr::exp(
exponent));
272 const std::shared_ptr<SymbolicExpr>& F,
273 const std::string& omega,
274 const std::string&
t,
276 const std::string operation =
"inverse_fourier_transform";
279 auto step =
context.consume_steps(8, operation);
284 auto final_access =
context.consume_steps(0, operation);
289 if (!result)
return result;
290 AssumptionContext empty_assumptions;
291 const auto& assumptions =
context.assumptions() ? *
context.assumptions() : empty_assumptions;
292 std::vector<std::shared_ptr<SymbolicExpr>> conditions;
294 expression,
t, omega,
context, assumptions, conditions);
295 if (!round_trip || !conditions.empty() ||
299 "inverse Fourier round trip is not proved", operation);
303 if (!std::holds_alternative<ProvedZeroResidual>(verified.value())) {
306 "inverse Fourier round trip is not proved", operation);
308 result.value().certificate =
313 }
catch (
const std::bad_alloc&) {
315 "transform allocation failed",
317 }
catch (
const std::exception&
e) {
319 e.what(), operation);
324 const std::shared_ptr<SymbolicExpr>& F,
325 const std::string& omega,
326 const std::string&
t) {
AssumptionContext class with scoped push/pop management.
const std::vector< std::shared_ptr< const SymbolicNode > > & operands() const noexcept
static Result failure(CasErrc code, std::string message, std::string operation={})
static std::shared_ptr< const SymbolicNode > create_add(std::vector< std::shared_ptr< const SymbolicNode > > ops, detail::RewriteBudget *budget=nullptr)
创建加法节点,自动扁平化嵌套加法并消除零项.
static std::shared_ptr< const SymbolicNode > create_variable(const std::string &name)
static std::shared_ptr< const SymbolicNode > create_power(std::shared_ptr< const SymbolicNode > base, std::shared_ptr< const SymbolicNode > exponent)
创建幂运算节点,自动处理指数为 0/1 及底数为 0/1 的情况.
static std::shared_ptr< const SymbolicNode > create_multiply(std::vector< std::shared_ptr< const SymbolicNode > > ops, detail::RewriteBudget *budget=nullptr)
创建乘法节点,自动扁平化嵌套乘法并消除单位元.
static std::shared_ptr< const SymbolicNode > create_number(const ::LMCAS::BigInt &v)
InferenceEngine class for deriving properties of composite expressions.
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
static std::shared_ptr< SymbolicExpr > te_fourier_unevaluated(const std::shared_ptr< SymbolicExpr > &f, const std::string &t, const std::string &omega)
static std::shared_ptr< SymbolicExpr > te_gaussian_fourier(const Rational &rate, const std::string &omega)
const std::vector< Polynomial< BigInt > > const BigInt ComputationContext & context
ResidualCheckResult check_equivalent(const ExprPtr &left, const ExprPtr &right, ComputationContext &context, const LMCAS::EqvOptions &options)
ExprResult real(const ExprPtr &expression, ComputationContext &context)
static std::shared_ptr< SymbolicExpr > te_abs_fourier(const std::shared_ptr< SymbolicExpr > &rate, const std::string &omega, ComputationContext &context)
static std::shared_ptr< SymbolicExpr > te_decay_condition(const std::shared_ptr< SymbolicExpr > &rate)
static std::shared_ptr< SymbolicExpr > inverse_fourier_transform_core(const std::shared_ptr< SymbolicExpr > &F, const std::string &omega, const std::string &t, ComputationContext &context)
@ True
Property definitely holds
@ False
Property definitely does not hold
TransformEngineResult inverse_fourier_transform_checked(const std::shared_ptr< SymbolicExpr > &F, const std::string &omega, const std::string &t, ComputationContext &context)
static bool te_accept_decay(const std::shared_ptr< SymbolicExpr > &rate, const AssumptionContext &assumptions, std::vector< std::shared_ptr< SymbolicExpr > > &conditions, ComputationContext &context)
static std::shared_ptr< SymbolicExpr > fourier_transform_core(const std::shared_ptr< SymbolicExpr > &f, const std::string &t, const std::string &omega, ComputationContext &context, const AssumptionContext &assumptions, std::vector< std::shared_ptr< SymbolicExpr > > &conditions)
static bool te_is_abs_variable(const std::shared_ptr< const SymbolicNode > &node, const std::string &variable)
const ExprPtr RelationOp op
Result< Verified< EvaluatedTransform > > TransformEngineResult
static std::shared_ptr< SymbolicExpr > te_abs_decay(const std::shared_ptr< SymbolicExpr > &f, const std::string &t, ComputationContext &context)
static std::shared_ptr< SymbolicExpr > te_fourier_sum(const AddNode &addition, const std::string &t, const std::string &omega, ComputationContext &context, const AssumptionContext &assumptions, std::vector< std::shared_ptr< SymbolicExpr > > &conditions)
TransformEngineResult fourier_transform_checked(const std::shared_ptr< SymbolicExpr > &f, const std::string &t, const std::string &omega, ComputationContext &context)
const ExprPtr & denominator
ExprResult function(const std::string &name, std::vector< ExprPtr > arguments)
__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 & t