Statistiques
| Révision :

root / pobysoPythonSage / src / sageSLZ.sage @ 61

Historique | Voir | Annoter | Télécharger (8,67 ko)

1 61 storres
2 61 storres
def slz_compute_polynomial_and_interval(functionSo, degreeSo, lowerBoundSa,
3 61 storres
                                        upperBoundSa, approxPrecSa,
4 61 storres
                                        sollyaPrecSa=None):
5 61 storres
    """
6 61 storres
    Under the assumptions listed for slz_get_intervals_and_polynomials, compute
7 61 storres
    a polynomial that approximates the function on a an interval starting
8 61 storres
    at lowerBoundSa and finishing at a value that guarantees that the polynomial
9 61 storres
    approximates with the expected precision.
10 61 storres
    The interval upper bound is lowered until the expected approximation
11 61 storres
    precision is reached.
12 61 storres
    The polynomial, the bounds, the center of the interval and the error
13 61 storres
    are returned.
14 61 storres
    """
15 61 storres
    RRR = lowerBoundSa.parent()
16 61 storres
    #goldenRatioSa = RRR(5.sqrt() / 2 - 1/2)
17 61 storres
    #intervalShrinkConstFactorSa = goldenRatioSa
18 61 storres
    intervalShrinkConstFactorSa = RRR('0.5')
19 61 storres
    absoluteErrorTypeSo = pobyso_absolute_so_so()
20 61 storres
    currentRangeSo = pobyso_bounds_to_range_sa_so(lowerBoundSa, upperBoundSa)
21 61 storres
    currentUpperBoundSa = upperBoundSa
22 61 storres
    currentLowerBoundSa = lowerBoundSa
23 61 storres
    # What we want here is the polynomial without the variable change,
24 61 storres
    # since our actual variable will be x-intervalCenter defined over the
25 61 storres
    # domain [lowerBound-intervalCenter , upperBound-intervalCenter].
26 61 storres
    (polySo, intervalCenterSo, maxErrorSo) = \
27 61 storres
        pobyso_taylor_expansion_no_change_var_so_so(functionSo, degreeSo,
28 61 storres
                                                    currentRangeSo,
29 61 storres
                                                    absoluteErrorTypeSo)
30 61 storres
    maxErrorSa = pobyso_get_constant_as_rn_with_rf_so_sa(maxErrorSo)
31 61 storres
    while maxErrorSa > approxPrecSa:
32 61 storres
        sollya_lib_clear_obj(maxErrorSo)
33 61 storres
        errorRatioSa = 1/(maxErrorSa/approxPrecSa).log2()
34 61 storres
        #print "Error ratio: ", errorRatioSa
35 61 storres
        if errorRatioSa < intervalShrinkConstFactorSa:
36 61 storres
            #currentUpperBoundSa = currentLowerBoundSa + (currentUpperBoundSa - currentLowerBoundSa) * errorRatioSa
37 61 storres
            currentUpperBoundSa = currentLowerBoundSa + \
38 61 storres
                                  (currentUpperBoundSa - currentLowerBoundSa) * \
39 61 storres
                                   intervalShrinkConstFactorSa
40 61 storres
        else:
41 61 storres
            currentUpperBoundSa = currentLowerBoundSa + \
42 61 storres
                                  (currentUpperBoundSa - currentLowerBoundSa) * \
43 61 storres
                                  intervalShrinkConstFactorSa
44 61 storres
        #print lowerBoundSa, currentUpperBoundSa
45 61 storres
        sollya_lib_clear_obj(currentRangeSo)
46 61 storres
        sollya_lib_clear_obj(polySo)
47 61 storres
        currentRangeSo = pobyso_bounds_to_range_sa_so(currentLowerBoundSa,
48 61 storres
                                                      currentUpperBoundSa)
49 61 storres
        (polySo, intervalCenterSo, maxErrorSo) = \
50 61 storres
            pobyso_taylor_expansion_no_change_var_so_so(functionSo, degreeSo,
51 61 storres
                                                        currentRangeSo,
52 61 storres
                                                        absoluteErrorTypeSo)
53 61 storres
        #maxErrorSa = pobyso_get_constant_as_rn_with_rf_so_sa(maxErrorSo, RRR)
54 61 storres
        maxErrorSa = pobyso_get_constant_as_rn_with_rf_so_sa(maxErrorSo)
55 61 storres
    sollya_lib_clear_obj(absoluteErrorTypeSo)
56 61 storres
    return((polySo, currentRangeSo, intervalCenterSo, maxErrorSo))
57 61 storres
    # End slz_compute_polynomial_and_interval
58 61 storres
59 60 storres
def slz_get_intervals_and_polynomials(functionSa, degreeSa, lowerBoundSa,
60 60 storres
                                      upperBoundSa, floatingPointPrecSa,
61 60 storres
                                      internalSollyaPrecSa):
62 60 storres
    """
63 60 storres
    Under the assumption that:
64 60 storres
    - functionSa is monotonic on the [lowerBoundSa, upperBoundSa] interval;
65 60 storres
    - lowerBound and upperBound belong to the same binade.
66 60 storres
    from a:
67 60 storres
    - function;
68 60 storres
    - a degree
69 60 storres
    - a pair of bounds;
70 60 storres
    - the floating-point precision we work on;
71 60 storres
    - the internal Sollya precision;
72 60 storres
    compute a list of tuples made of:
73 60 storres
    - a polynomial approximating the function (a Sollya object);
74 61 storres
    - the range for which the polynomial approximates the function
75 61 storres
      (a Sollya object);
76 61 storres
    - the center of the interval (a Sollya object);
77 60 storres
    - the approximation error (a Sage object).
78 60 storres
      with the error given as the last element (a Sage object);
79 61 storres
    The initial interval is, possibly, splitted into smaller intervals.
80 61 storres
    It return a list of tuples, each made of:
81 61 storres
    - a polynomial;
82 61 storres
    - the approximation interval;
83 61 storres
    - the center, x0,  of the interval (the polynomial is defined as p(x-x0));
84 61 storres
    - the corresponding approximation error.
85 60 storres
    """
86 60 storres
    # Scalling the domain -> [1,2[.
87 60 storres
    # Notice the clumsy notation for log2.
88 60 storres
    domainScalingFactorSa = floor(lowerBound.log2()) + 1
89 60 storres
    print "domainScalingFactor for argument :", domainScalingFactorSa.n()
90 60 storres
    ff(x) = f(x * domainScalingFactorSa)
91 60 storres
    scaledLowerBoundSa = lowerBoundSa/domainScalingFactorSa
92 60 storres
    scaledUpperBoundSa = upperBoundSa/domainScalingFactorSa
93 60 storres
    print 'ff:', ff, "- Domain:", scaledLowerBoundSa, scaledUpperBoundSa
94 60 storres
    #
95 60 storres
    # Scalling the image -> [1,2[.
96 60 storres
    flb = f(lowerBoundSa).n()
97 60 storres
    fub = f(upperBoundSa).n()
98 60 storres
    if flb <= fub: # Increasing
99 60 storres
        imageBinadeBottom = floor(flb.log2())
100 60 storres
    else: # Decreasing
101 60 storres
        imageBinadeBottom = floor(fub.log2())
102 60 storres
    print 'ff:', ff, '- Image:', flb, fub, imageBinadeBottom
103 60 storres
    #
104 60 storres
    resultArray = []
105 60 storres
    #
106 60 storres
    approxPrecSa = 1/(2^(floatingPointPrecSa + 1))
107 60 storres
    print "Approximation precision: ", RR(approxPrecSa)
108 61 storres
    # Prepare the arguments for the Taylor expansion computation with Sollya.
109 60 storres
    functionSo = pobyso_parse_string_sa_so(functionSa._assume_str())
110 60 storres
    degreeSo = pobyso_constant_from_int_sa_so(degreeSa)
111 61 storres
    scaledBoundsSo = pobyso_bounds_to_range_sa_so(scaledLowerBoundSa,
112 61 storres
                                                  scaledUpperBoundSa)
113 60 storres
    absoluteErrorTypeSo = pobyso_absolute_so_so()
114 61 storres
    # Compute the first Taylor expansion.
115 60 storres
    (polySo, boundsSo, intervalCenterSo, maxErrorSo) = \
116 60 storres
        slz_compute_polynomial_and_interval(functionSo, degreeSo,
117 60 storres
                                        scaledLowerBoundSa, scaledUpperBoundSa,
118 60 storres
                                        approxPrecSa, internalSollyaPrecSa)
119 60 storres
    resultArray.append((polySo, boundsSo, intervalCenterSo, maxErrorSo))
120 60 storres
    realIntervalField = RealIntervalField(max(lowerBoundSa.parent().precision(),
121 60 storres
                                              upperBoundSa.parent().precision()))
122 61 storres
    boundsSa = pobyso_range_to_interval_so_sa(boundsSo, realIntervalField)
123 61 storres
    # Compute the other expansions.
124 60 storres
    while boundsSa.endpoints()[1] < scaledUpperBoundSa:
125 60 storres
        currentScaledLowerBoundSa = boundsSa.endpoints()[1]
126 60 storres
        (polySo, boundsSo, intervalCenterSo, maxErrorSo) = \
127 60 storres
            slz_compute_polynomial_and_interval(functionSo, degreeSo,
128 60 storres
                                            currentScaledLowerBoundSa,
129 60 storres
                                            scaledUpperBoundSa, approxPrecSa,
130 60 storres
                                            internalSollyaPrecSa)
131 60 storres
        resultArray.append((polySo, boundsSo, intervalCenterSo, maxErrorSo))
132 61 storres
        boundsSa = pobyso_range_to_interval_so_sa(boundsSo, realIntervalField)
133 60 storres
    sollya_lib_clear_obj(functionSo)
134 60 storres
    sollya_lib_clear_obj(degreeSo)
135 60 storres
    sollya_lib_clear_obj(scaledBoundsSo)
136 60 storres
    sollya_lib_clear_obj(absoluteErrorTypeSo)
137 60 storres
    return(resultArray)
138 60 storres
    # End slz_get_intervals_and_polynomials
139 60 storres
140 61 storres
def slz_interval_scaling_expression(boundsInterval, varName):
141 61 storres
    """
142 61 storres
    Compute the scaling expression to map an interval that span only
143 61 storres
    a binade to [1, 2)
144 61 storres
    """
145 61 storres
    if abs(boundsInterval.endpoints()[0]) < 1:
146 61 storres
        if boundsInterval.endpoints()[0] >= 0:
147 61 storres
            scalingCoeff = 2^(-floor(boundsInterval.endpoints()[0].log2()))
148 61 storres
            return(scalingCoeff * eval(varName))
149 60 storres
        else:
150 61 storres
            scalingCoeff = 2^(-floor((-boundsInterval.endpoints()[1]).log2()))
151 61 storres
            scalingOffset = -ceil(scalingCoeff * boundsInterval.endpoints()[0])
152 61 storres
            return(scalingCoeff * eval(varName) + scalingOffset)
153 61 storres
    else:
154 61 storres
        if boundsInterval.endpoints()[0] >= 0:
155 61 storres
            scalingCoeff = 2^(-floor(boundsInterval.endpoints()[0].log2()))
156 61 storres
            scalingOffset = 0
157 61 storres
            return(scalingCoeff * eval(varName))
158 61 storres
        else:
159 61 storres
            scalingCoeff = 2^(-floor((-boundsInterval.endpoints()[1]).log2()))
160 61 storres
            scalingOffset = floor(-(scalingCoeff * boundsInterval.endpoints()[1]) + 2)
161 61 storres
            return(scalingCoeff * eval(varName) + scalingOffset)
162 61 storres
163 61 storres
164 60 storres
def slz_polynomial_and_interval_to_sage(polyRangeCenterErrorSo):
165 60 storres
    polynomialSa = pobyso_get_poly_so_sa(polyRangeCenterErrorSo[0])
166 60 storres
    intervalSa = \
167 60 storres
            pobyso_get_interval_from_range_so_sa(polyRangeCenterErrorSo[1])
168 60 storres
    centerSa = \
169 60 storres
            pobyso_get_constant_as_rn_with_rf_so_sa(polyRangeCenterErrorSo[2])
170 60 storres
    errorSa = \
171 60 storres
            pobyso_get_constant_as_rn_with_rf_so_sa(polyRangeCenterErrorSo[3])
172 60 storres
    return((polynomialSa, intervalSa, centerSa, errorSa))
173 60 storres
    # End slz_polynomial_and_interval_to_sage