LMCAS
Lamina Computer Algebra System
Toggle main menu visibility
载入中...
搜索中...
未找到
exact_algebraic_refinement.cpp
浏览该文件的文档.
1
#include "
internal/exact_algebraic.hpp
"
2
#include "
internal/exact_sturm.hpp
"
3
4
#include <algorithm>
5
#include <cmath>
6
#include <exception>
7
8
namespace
LMCAS::detail
{
9
namespace
{
10
11
struct
DyadicProposal
{
12
Rational
base
;
13
Rational
span
;
14
Rational
fraction
;
15
int
initial_depth
;
16
};
17
18
double
evaluate_polynomial_double
(
const
Polynomial<Rational>
& polynomial,
19
double
point
) {
20
double
result = 0.0;
21
for
(std::size_t position = polynomial.
coeffs
.size(); position-- > 0;) {
22
result = result *
point
+ polynomial.
coeffs
[position].to_double();
23
}
24
return
result;
25
}
26
27
double
approximate_root
(
const
ExactRealAlgebraic
&
value
) {
28
double
lower
=
value
.lower.to_double();
29
double
upper
=
value
.upper.to_double();
30
double
lower_value =
evaluate_polynomial_double
(
value
.polynomial,
lower
);
31
for
(
int
iteration = 0; iteration < 128; ++iteration) {
32
const
double
midpoint = (
lower
+
upper
) * 0.5;
33
const
double
midpoint_value =
evaluate_polynomial_double
(
value
.polynomial, midpoint);
34
if
(!std::isfinite(midpoint_value) || midpoint_value == 0.0) {
35
lower
= midpoint;
36
upper
= midpoint;
37
break
;
38
}
39
if
((lower_value < 0.0) != (midpoint_value < 0.0)) {
40
upper
= midpoint;
41
}
else
{
42
lower
= midpoint;
43
lower_value = midpoint_value;
44
}
45
}
46
return
(
lower
+
upper
) * 0.5;
47
}
48
49
Result<DyadicProposal>
propose_dyadic_bracket
(
50
const
ExactRealAlgebraic
&
value
,
double
absolute_tolerance
,
51
double
relative_tolerance
,
const
std::string&
operation
) {
52
const
Rational base =
value
.lower;
53
const
Rational span =
value
.upper -
value
.lower;
54
const
double
approximation =
approximate_root
(
value
);
55
const
double
target_tolerance =
absolute_tolerance
+
56
relative_tolerance
* std::abs(approximation);
57
const
double
span_double = span.to_double();
58
double
requested_depth = 1.0;
59
if
(span_double > 2.0 * target_tolerance) {
60
requested_depth = std::ceil(std::log2(
61
span_double / (2.0 * target_tolerance))) + 2.0;
62
}
63
if
(!std::isfinite(approximation) || !std::isfinite(target_tolerance) ||
64
!std::isfinite(span_double) || !std::isfinite(requested_depth) ||
65
requested_depth > 60.0) {
66
return
Result<DyadicProposal>::failure
(
67
CasErrc::NumericFailure
,
68
"requested algebraic tolerance is finer than the double evaluation boundary"
,
69
operation
);
70
}
71
const
int
initial_depth =
static_cast<
int
>
(std::max(1.0, requested_depth));
72
const
Rational fraction = std::clamp(
73
(Rational::from_double(approximation) - base) / span,
74
Rational(0), Rational(1));
75
return
Result<DyadicProposal>::success
(
76
DyadicProposal
{base, span, fraction, initial_depth});
77
}
78
79
Result<bool>
certify_dyadic_candidate
(
80
ExactRealAlgebraic
&
value
,
const
DyadicProposal
& proposal,
81
const
BigInt& candidate,
const
BigInt& scale,
82
ComputationContext
&
context
,
const
std::string&
operation
) {
83
const
Rational
lower
= proposal.
base
+ proposal.
span
* Rational(candidate, scale);
84
const
Rational
upper
= proposal.
base
+ proposal.
span
* Rational(candidate + BigInt(1), scale);
85
auto
count =
count_real_roots_exact
(
value
.polynomial,
lower
,
upper
,
context
,
operation
);
86
if
(!count)
return
Result<bool>::failure
(count.error());
87
if
(count.value() != 1)
return
Result<bool>::success
(
false
);
88
value
.lower =
lower
;
89
value
.upper =
upper
;
90
return
Result<bool>::success
(
true
);
91
}
92
93
Result<bool>
search_dyadic_scale
(
94
ExactRealAlgebraic
&
value
,
const
DyadicProposal
& proposal,
int
depth
,
95
ComputationContext
&
context
,
const
std::string&
operation
) {
96
auto
step =
context
.consume_steps(1,
operation
);
97
if
(!step) {
98
return
Result<bool>::failure
(step.error());
99
}
100
auto
bits =
context
.require_integer_bits(
static_cast<
std::size_t
>
(
depth
) + 1,
operation
);
101
if
(!bits) {
102
return
Result<bool>::failure
(bits.error());
103
}
104
const
BigInt scale = BigInt(1) <<
depth
;
105
BigInt center = (proposal.
fraction
.get_numerator() * scale) /
106
proposal.
fraction
.get_denominator();
107
if
(center >= scale) {
108
center = scale - BigInt(1);
109
}
110
for
(
int
radius = 0; radius <= 16; ++radius) {
111
for
(
int
direction
: {radius == 0 ? 0 : -1, radius == 0 ? 0 : 1}) {
112
const
BigInt candidate = center + BigInt(
direction
* radius);
113
if
(candidate.is_negative() || candidate >= scale) {
114
continue
;
115
}
116
auto
certified =
certify_dyadic_candidate
(
117
value
, proposal, candidate, scale,
context
,
operation
);
118
if
(!certified || certified.value()) {
119
return
certified;
120
}
121
if
(radius == 0) {
122
break
;
123
}
124
}
125
}
126
return
Result<bool>::success
(
false
);
127
}
128
129
}
130
131
Result<void>
refine_exact_real_algebraic_to_tolerance
(
132
ExactRealAlgebraic
&
value
,
double
absolute_tolerance
,
double
relative_tolerance
,
133
ComputationContext
&
context
,
const
std::string&
operation
) {
134
if
(!(
absolute_tolerance
> 0.0) || !(
relative_tolerance
> 0.0) ||
135
!std::isfinite(
absolute_tolerance
) || !std::isfinite(
relative_tolerance
)) {
136
return
Result<void>::failure
(
137
CasErrc::InvalidArgument
,
138
"algebraic refinement tolerances must be finite and positive"
,
operation
);
139
}
140
if
(
value
.lower ==
value
.upper) {
141
return
Result<void>::success
();
142
}
143
try
{
144
auto
proposal = propose_dyadic_bracket(
145
value
,
absolute_tolerance
,
relative_tolerance
,
operation
);
146
if
(!proposal) {
147
return
Result<void>::failure
(proposal.error());
148
}
149
for
(
int
depth
= std::max(1, proposal.value().initial_depth);
depth
<= 60; ++
depth
) {
150
auto
certified = search_dyadic_scale(
value
, proposal.value(),
depth
,
context
,
operation
);
151
if
(!certified) {
152
return
Result<void>::failure
(certified.error());
153
}
154
if
(certified.value()) {
155
return
Result<void>::success
();
156
}
157
}
158
return
Result<void>::failure
(
159
CasErrc::InternalInvariant
,
160
"exact projection refinement could not certify the suggested bracket"
,
operation
);
161
}
catch
(
const
std::bad_alloc&) {
162
return
Result<void>::failure
(
163
CasErrc::ResourceLimit
,
"algebraic refinement allocation failed"
,
operation
);
164
}
catch
(
const
std::exception& error) {
165
return
Result<void>::failure
(
CasErrc::InternalInvariant
, error.what(),
operation
);
166
}
167
}
168
169
}
LMCAS::ComputationContext
定义
computation_context.hpp:99
LMCAS::Polynomial
一元多项式模板类
定义
polynomial.hpp:52
LMCAS::Polynomial::coeffs
std::vector< CoeffType > coeffs
系数数组,coeffs[i] 为 x^i 的系数
定义
polynomial.hpp:55
LMCAS::Result
定义
result.hpp:39
LMCAS::Result::failure
static Result failure(CasErrc code, std::string message, std::string operation={})
定义
result.hpp:52
LMCAS::Result::success
static Result success(T value)
定义
result.hpp:48
exact_algebraic.hpp
exact_sturm.hpp
LMCAS::detail::anonymous_namespace{exact_algebraic_refinement.cpp}::search_dyadic_scale
Result< bool > search_dyadic_scale(ExactRealAlgebraic &value, const DyadicProposal &proposal, int depth, ComputationContext &context, const std::string &operation)
定义
exact_algebraic_refinement.cpp:93
LMCAS::detail::anonymous_namespace{exact_algebraic_refinement.cpp}::DyadicProposal::span
Rational span
定义
exact_algebraic_refinement.cpp:13
LMCAS::detail::anonymous_namespace{exact_algebraic_refinement.cpp}::approximate_root
double approximate_root(const ExactRealAlgebraic &value)
定义
exact_algebraic_refinement.cpp:27
LMCAS::detail::anonymous_namespace{exact_algebraic_refinement.cpp}::evaluate_polynomial_double
double evaluate_polynomial_double(const Polynomial< Rational > &polynomial, double point)
定义
exact_algebraic_refinement.cpp:18
LMCAS::detail::anonymous_namespace{exact_algebraic_refinement.cpp}::propose_dyadic_bracket
Result< DyadicProposal > propose_dyadic_bracket(const ExactRealAlgebraic &value, double absolute_tolerance, double relative_tolerance, const std::string &operation)
定义
exact_algebraic_refinement.cpp:49
LMCAS::detail::anonymous_namespace{exact_algebraic_refinement.cpp}::DyadicProposal::initial_depth
int initial_depth
定义
exact_algebraic_refinement.cpp:15
LMCAS::detail::anonymous_namespace{exact_algebraic_refinement.cpp}::DyadicProposal::base
Rational base
定义
exact_algebraic_refinement.cpp:12
LMCAS::detail::anonymous_namespace{exact_algebraic_refinement.cpp}::certify_dyadic_candidate
Result< bool > certify_dyadic_candidate(ExactRealAlgebraic &value, const DyadicProposal &proposal, const BigInt &candidate, const BigInt &scale, ComputationContext &context, const std::string &operation)
定义
exact_algebraic_refinement.cpp:79
LMCAS::detail::anonymous_namespace{exact_algebraic_refinement.cpp}::DyadicProposal::fraction
Rational fraction
定义
exact_algebraic_refinement.cpp:14
LMCAS::detail::anonymous_namespace{exact_algebraic_refinement.cpp}::DyadicProposal
定义
exact_algebraic_refinement.cpp:11
LMCAS::detail
多元 Hensel 提升(单变量步)
定义
assumption_context.hpp:31
LMCAS::detail::refine_exact_real_algebraic_to_tolerance
Result< void > refine_exact_real_algebraic_to_tolerance(ExactRealAlgebraic &value, double absolute_tolerance, double relative_tolerance, ComputationContext &context, const std::string &operation)
定义
exact_algebraic_refinement.cpp:131
LMCAS::detail::absolute_tolerance
double absolute_tolerance
定义
exact_algebraic.hpp:36
LMCAS::detail::count_real_roots_exact
Result< std::size_t > count_real_roots_exact(const Polynomial< Rational > &polynomial, const Rational &lower, const Rational &upper, ComputationContext &context, const std::string &operation)
定义
exact_sturm.cpp:242
LMCAS::detail::operation
ComputationContext const std::string & operation
定义
exact_algebraic.hpp:32
LMCAS::detail::context
std::size_t std::size_t ComputationContext & context
定义
exact_algebraic.hpp:27
LMCAS::detail::relative_tolerance
double double relative_tolerance
定义
exact_algebraic.hpp:37
LMCAS::point
const std::string const LimitExprPtr & point
定义
limit_result.hpp:29
LMCAS::upper
__attribute__((visibility("default"))) ExprResult function(const std __attribute__((visibility("default"))) ExprResult finite_set(std ExprPtr upper
定义
expr.hpp:148
LMCAS::lower
const ExprPtr & lower
定义
expr.hpp:255
LMCAS::direction
const std::string const LimitExprPtr LimitDirection direction
定义
limit_result.hpp:30
LMCAS::CasErrc::InvalidArgument
@ InvalidArgument
定义
result.hpp:13
LMCAS::CasErrc::InternalInvariant
@ InternalInvariant
定义
result.hpp:28
LMCAS::CasErrc::ResourceLimit
@ ResourceLimit
定义
result.hpp:25
LMCAS::CasErrc::NumericFailure
@ NumericFailure
定义
result.hpp:27
LMCAS::depth
std::size_t std::size_t depth
定义
equivalence_options.hpp:44
LMCAS::value
const std::string const ExprPtr & value
定义
expr.hpp:293
LMCAS::detail::ExactRealAlgebraic
定义
exact_algebraic.hpp:11
src
exact_algebraic_refinement.cpp
生成于
, 为 LMCAS使用
1.18.0