Statistiques
| Révision :

root / pobysoPythonSage / src / sageSLZ.sage @ 60

Historique | Voir | Annoter | Télécharger (6,84 ko)

1
def slz_get_intervals_and_polynomials(functionSa, degreeSa, lowerBoundSa, 
2
                                      upperBoundSa, floatingPointPrecSa, 
3
                                      internalSollyaPrecSa):
4
    """
5
    Under the assumption that:
6
    - functionSa is monotonic on the [lowerBoundSa, upperBoundSa] interval;
7
    - lowerBound and upperBound belong to the same binade.
8
    from a:
9
    - function;
10
    - a degree
11
    - a pair of bounds;
12
    - the floating-point precision we work on;
13
    - the internal Sollya precision;
14
    compute a list of tuples made of:
15
    - 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;
19
    - the approximation error (a Sage object). 
20
      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.
24
    """
25
    # Scalling the domain -> [1,2[.
26
    # Notice the clumsy notation for log2.
27
    domainScalingFactorSa = floor(lowerBound.log2()) + 1
28
    print "domainScalingFactor for argument :", domainScalingFactorSa.n()
29
    ff(x) = f(x * domainScalingFactorSa)
30
    scaledLowerBoundSa = lowerBoundSa/domainScalingFactorSa
31
    scaledUpperBoundSa = upperBoundSa/domainScalingFactorSa
32
    print 'ff:', ff, "- Domain:", scaledLowerBoundSa, scaledUpperBoundSa
33
    #
34
    # Scalling the image -> [1,2[.
35
    flb = f(lowerBoundSa).n()
36
    fub = f(upperBoundSa).n()
37
    if flb <= fub: # Increasing
38
        imageBinadeBottom = floor(flb.log2())
39
    else: # Decreasing
40
        imageBinadeBottom = floor(fub.log2())
41
    print 'ff:', ff, '- Image:', flb, fub, imageBinadeBottom
42
    #
43
    resultArray = []
44
    #
45
    approxPrecSa = 1/(2^(floatingPointPrecSa + 1))
46
    print "Approximation precision: ", RR(approxPrecSa)
47
    # Prepare the arguments for the Taylor expansion computation.
48
    functionSo = pobyso_parse_string_sa_so(functionSa._assume_str())
49
    degreeSo = pobyso_constant_from_int_sa_so(degreeSa)
50
    scaledBoundsSo = pobyso_range_sa_so(scaledLowerBoundSa, scaledUpperBoundSa)
51
    absoluteErrorTypeSo = pobyso_absolute_so_so()
52
    #Compute the first Taylor expansion.
53
    (polySo, boundsSo, intervalCenterSo, maxErrorSo) = \
54
        slz_compute_polynomial_and_interval(functionSo, degreeSo,
55
                                        scaledLowerBoundSa, scaledUpperBoundSa,
56
                                        approxPrecSa, internalSollyaPrecSa)
57
    resultArray.append((polySo, boundsSo, intervalCenterSo, maxErrorSo))
58
    realIntervalField = RealIntervalField(max(lowerBoundSa.parent().precision(),
59
                                              upperBoundSa.parent().precision()))
60
    boundsSa = pobyso_range_so_sa(boundsSo, realIntervalField)
61
    while boundsSa.endpoints()[1] < scaledUpperBoundSa:
62
        currentScaledLowerBoundSa = boundsSa.endpoints()[1]
63
        (polySo, boundsSo, intervalCenterSo, maxErrorSo) = \
64
            slz_compute_polynomial_and_interval(functionSo, degreeSo,
65
                                            currentScaledLowerBoundSa, 
66
                                            scaledUpperBoundSa, approxPrecSa, 
67
                                            internalSollyaPrecSa)
68
        resultArray.append((polySo, boundsSo, intervalCenterSo, maxErrorSo))
69
        boundsSa = pobyso_range_so_sa(boundsSo, realIntervalField)
70
    sollya_lib_clear_obj(functionSo)
71
    sollya_lib_clear_obj(degreeSo)
72
    sollya_lib_clear_obj(scaledBoundsSo)
73
    sollya_lib_clear_obj(absoluteErrorTypeSo)
74
    return(resultArray)
75
    # End slz_get_intervals_and_polynomials
76

    
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
105
        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
    
124
def slz_polynomial_and_interval_to_sage(polyRangeCenterErrorSo):
125
    polynomialSa = pobyso_get_poly_so_sa(polyRangeCenterErrorSo[0])
126
    intervalSa = \
127
            pobyso_get_interval_from_range_so_sa(polyRangeCenterErrorSo[1])
128
    centerSa = \
129
            pobyso_get_constant_as_rn_with_rf_so_sa(polyRangeCenterErrorSo[2])
130
    errorSa = \
131
            pobyso_get_constant_as_rn_with_rf_so_sa(polyRangeCenterErrorSo[3])
132
    return((polynomialSa, intervalSa, centerSa, errorSa))
133
    # End slz_polynomial_and_interval_to_sage