Révision 61 pobysoPythonSage/src/sageSLZ.sage

sageSLZ.sage (revision 61)
1

  
2
def slz_compute_polynomial_and_interval(functionSo, degreeSo, lowerBoundSa, 
3
                                        upperBoundSa, approxPrecSa, 
4
                                        sollyaPrecSa=None):
5
    """
6
    Under the assumptions listed for slz_get_intervals_and_polynomials, compute
7
    a polynomial that approximates the function on a an interval starting
8
    at lowerBoundSa and finishing at a value that guarantees that the polynomial
9
    approximates with the expected precision.
10
    The interval upper bound is lowered until the expected approximation 
11
    precision is reached.
12
    The polynomial, the bounds, the center of the interval and the error
13
    are returned.
14
    """
15
    RRR = lowerBoundSa.parent()
16
    #goldenRatioSa = RRR(5.sqrt() / 2 - 1/2)
17
    #intervalShrinkConstFactorSa = goldenRatioSa
18
    intervalShrinkConstFactorSa = RRR('0.5')
19
    absoluteErrorTypeSo = pobyso_absolute_so_so()
20
    currentRangeSo = pobyso_bounds_to_range_sa_so(lowerBoundSa, upperBoundSa)
21
    currentUpperBoundSa = upperBoundSa
22
    currentLowerBoundSa = lowerBoundSa
23
    # What we want here is the polynomial without the variable change, 
24
    # since our actual variable will be x-intervalCenter defined over the 
25
    # domain [lowerBound-intervalCenter , upperBound-intervalCenter]. 
26
    (polySo, intervalCenterSo, maxErrorSo) = \
27
        pobyso_taylor_expansion_no_change_var_so_so(functionSo, degreeSo, 
28
                                                    currentRangeSo, 
29
                                                    absoluteErrorTypeSo)
30
    maxErrorSa = pobyso_get_constant_as_rn_with_rf_so_sa(maxErrorSo)
31
    while maxErrorSa > approxPrecSa:
32
        sollya_lib_clear_obj(maxErrorSo)
33
        errorRatioSa = 1/(maxErrorSa/approxPrecSa).log2()
34
        #print "Error ratio: ", errorRatioSa
35
        if errorRatioSa < intervalShrinkConstFactorSa:
36
            #currentUpperBoundSa = currentLowerBoundSa + (currentUpperBoundSa - currentLowerBoundSa) * errorRatioSa
37
            currentUpperBoundSa = currentLowerBoundSa + \
38
                                  (currentUpperBoundSa - currentLowerBoundSa) * \
39
                                   intervalShrinkConstFactorSa
40
        else:
41
            currentUpperBoundSa = currentLowerBoundSa + \
42
                                  (currentUpperBoundSa - currentLowerBoundSa) * \
43
                                  intervalShrinkConstFactorSa
44
        #print lowerBoundSa, currentUpperBoundSa
45
        sollya_lib_clear_obj(currentRangeSo)
46
        sollya_lib_clear_obj(polySo)
47
        currentRangeSo = pobyso_bounds_to_range_sa_so(currentLowerBoundSa, 
48
                                                      currentUpperBoundSa)
49
        (polySo, intervalCenterSo, maxErrorSo) = \
50
            pobyso_taylor_expansion_no_change_var_so_so(functionSo, degreeSo, 
51
                                                        currentRangeSo, 
52
                                                        absoluteErrorTypeSo)
53
        #maxErrorSa = pobyso_get_constant_as_rn_with_rf_so_sa(maxErrorSo, RRR)
54
        maxErrorSa = pobyso_get_constant_as_rn_with_rf_so_sa(maxErrorSo)
55
    sollya_lib_clear_obj(absoluteErrorTypeSo)
56
    return((polySo, currentRangeSo, intervalCenterSo, maxErrorSo))
57
    # End slz_compute_polynomial_and_interval
58

  
1 59
def slz_get_intervals_and_polynomials(functionSa, degreeSa, lowerBoundSa, 
2 60
                                      upperBoundSa, floatingPointPrecSa, 
3 61
                                      internalSollyaPrecSa):
......
13 71
    - the internal Sollya precision;
14 72
    compute a list of tuples made of:
15 73
    - a polynomial approximating the function (a Sollya object);
16
    - the bounds for which the polynomial approximates the function 
17
      (a Sage object);
18
    - the center of the interval;
74
    - the range for which the polynomial approximates the function 
75
      (a Sollya object);
76
    - the center of the interval (a Sollya object);
19 77
    - the approximation error (a Sage object). 
20 78
      with the error given as the last element (a Sage object);
21
    The initial interval is, possibly, splitted into a list of smaller interval
22
    each associated to an approximation polynomial and a the corresponding 
23
    approximation error.
79
    The initial interval is, possibly, splitted into smaller intervals.
80
    It return a list of tuples, each made of:
81
    - a polynomial;
82
    - the approximation interval;
83
    - the center, x0,  of the interval (the polynomial is defined as p(x-x0));
84
    - the corresponding approximation error.
24 85
    """
25 86
    # Scalling the domain -> [1,2[.
26 87
    # Notice the clumsy notation for log2.
......
44 105
    #
45 106
    approxPrecSa = 1/(2^(floatingPointPrecSa + 1))
46 107
    print "Approximation precision: ", RR(approxPrecSa)
47
    # Prepare the arguments for the Taylor expansion computation.
108
    # Prepare the arguments for the Taylor expansion computation with Sollya.
48 109
    functionSo = pobyso_parse_string_sa_so(functionSa._assume_str())
49 110
    degreeSo = pobyso_constant_from_int_sa_so(degreeSa)
50
    scaledBoundsSo = pobyso_range_sa_so(scaledLowerBoundSa, scaledUpperBoundSa)
111
    scaledBoundsSo = pobyso_bounds_to_range_sa_so(scaledLowerBoundSa, 
112
                                                  scaledUpperBoundSa)
51 113
    absoluteErrorTypeSo = pobyso_absolute_so_so()
52
    #Compute the first Taylor expansion.
114
    # Compute the first Taylor expansion.
53 115
    (polySo, boundsSo, intervalCenterSo, maxErrorSo) = \
54 116
        slz_compute_polynomial_and_interval(functionSo, degreeSo,
55 117
                                        scaledLowerBoundSa, scaledUpperBoundSa,
......
57 119
    resultArray.append((polySo, boundsSo, intervalCenterSo, maxErrorSo))
58 120
    realIntervalField = RealIntervalField(max(lowerBoundSa.parent().precision(),
59 121
                                              upperBoundSa.parent().precision()))
60
    boundsSa = pobyso_range_so_sa(boundsSo, realIntervalField)
122
    boundsSa = pobyso_range_to_interval_so_sa(boundsSo, realIntervalField)
123
    # Compute the other expansions.
61 124
    while boundsSa.endpoints()[1] < scaledUpperBoundSa:
62 125
        currentScaledLowerBoundSa = boundsSa.endpoints()[1]
63 126
        (polySo, boundsSo, intervalCenterSo, maxErrorSo) = \
......
66 129
                                            scaledUpperBoundSa, approxPrecSa, 
67 130
                                            internalSollyaPrecSa)
68 131
        resultArray.append((polySo, boundsSo, intervalCenterSo, maxErrorSo))
69
        boundsSa = pobyso_range_so_sa(boundsSo, realIntervalField)
132
        boundsSa = pobyso_range_to_interval_so_sa(boundsSo, realIntervalField)
70 133
    sollya_lib_clear_obj(functionSo)
71 134
    sollya_lib_clear_obj(degreeSo)
72 135
    sollya_lib_clear_obj(scaledBoundsSo)
......
74 137
    return(resultArray)
75 138
    # End slz_get_intervals_and_polynomials
76 139

  
77
def slz_compute_polynomial_and_interval(functionSo, degreeSo, lowerBoundSa, 
78
                                        upperBoundSa, approxPrecSa, 
79
                                        sollyaPrecSa=None):
80
    RRR = lowerBoundSa.parent()
81
    goldenRatioSa = RRR(5.sqrt() / 2 - 1/2)
82
    #intervalShrinkConstFactorSa = goldenRatioSa
83
    intervalShrinkConstFactorSa = RRR('0.5')
84
    absoluteErrorTypeSo = pobyso_absolute_so_so()
85
    currentRangeSo = pobyso_range_sa_so(lowerBoundSa, upperBoundSa)
86
    currentUpperBoundSa = upperBoundSa
87
    currentLowerBoundSa = lowerBoundSa
88
    # What we want here is the polynomial without the variable change, 
89
    # since our actual variable will be x-intervalCenter defined over the 
90
    # domain [lowerBound-intervalCenter , upperBound-intervalCenter]. 
91
    (polySo, intervalCenterSo, maxErrorSo) = \
92
        pobyso_taylor_expansion_no_change_var_so_so(functionSo, degreeSo, 
93
                                                    currentRangeSo, 
94
                                                    absoluteErrorTypeSo)
95
    maxErrorSa = pobyso_get_constant_as_rn_with_rf_so_sa(maxErrorSo)
96
    while maxErrorSa > approxPrecSa:
97
        sollya_lib_clear_obj(maxErrorSo)
98
        errorRatioSa = 1/(maxErrorSa/approxPrecSa).log2()
99
        #print "Error ratio: ", errorRatioSa
100
        if errorRatioSa < intervalShrinkConstFactorSa:
101
            #currentUpperBoundSa = currentLowerBoundSa + (currentUpperBoundSa - currentLowerBoundSa) * errorRatioSa
102
            currentUpperBoundSa = currentLowerBoundSa + \
103
                                  (currentUpperBoundSa - currentLowerBoundSa) * \
104
                                   intervalShrinkConstFactorSa
140
def slz_interval_scaling_expression(boundsInterval, varName):
141
    """
142
    Compute the scaling expression to map an interval that span only
143
    a binade to [1, 2)
144
    """
145
    if abs(boundsInterval.endpoints()[0]) < 1:
146
        if boundsInterval.endpoints()[0] >= 0:
147
            scalingCoeff = 2^(-floor(boundsInterval.endpoints()[0].log2()))
148
            return(scalingCoeff * eval(varName))
105 149
        else:
106
            currentUpperBoundSa = currentLowerBoundSa + \
107
                                  (currentUpperBoundSa - currentLowerBoundSa) * \
108
                                  intervalShrinkConstFactorSa
109
        #print lowerBoundSa, currentUpperBoundSa
110
        sollya_lib_clear_obj(currentRangeSo)
111
        sollya_lib_clear_obj(polySo)
112
        currentRangeSo = pobyso_range_sa_so(currentLowerBoundSa, 
113
                                            currentUpperBoundSa)
114
        (polySo, intervalCenterSo, maxErrorSo) = \
115
            pobyso_taylor_expansion_no_change_var_so_so(functionSo, degreeSo, 
116
                                                        currentRangeSo, 
117
                                                        absoluteErrorTypeSo)
118
        #maxErrorSa = pobyso_get_constant_as_rn_with_rf_so_sa(maxErrorSo, RRR)
119
        maxErrorSa = pobyso_get_constant_as_rn_with_rf_so_sa(maxErrorSo)
120
    sollya_lib_clear_obj(absoluteErrorTypeSo)
121
    return((polySo, currentRangeSo, intervalCenterSo, maxErrorSo))
122
    # End slz_compute_polynomial_and_interval
123
    
150
            scalingCoeff = 2^(-floor((-boundsInterval.endpoints()[1]).log2()))
151
            scalingOffset = -ceil(scalingCoeff * boundsInterval.endpoints()[0])
152
            return(scalingCoeff * eval(varName) + scalingOffset)
153
    else: 
154
        if boundsInterval.endpoints()[0] >= 0:
155
            scalingCoeff = 2^(-floor(boundsInterval.endpoints()[0].log2()))
156
            scalingOffset = 0
157
            return(scalingCoeff * eval(varName))
158
        else:
159
            scalingCoeff = 2^(-floor((-boundsInterval.endpoints()[1]).log2()))
160
            scalingOffset = floor(-(scalingCoeff * boundsInterval.endpoints()[1]) + 2)
161
            return(scalingCoeff * eval(varName) + scalingOffset)
162

  
163
   
124 164
def slz_polynomial_and_interval_to_sage(polyRangeCenterErrorSo):
125 165
    polynomialSa = pobyso_get_poly_so_sa(polyRangeCenterErrorSo[0])
126 166
    intervalSa = \

Formats disponibles : Unified diff