Révision 9cf1fb38

b/src/functions_for_cvp.sage
1
"""@package functions_for_cvp
1
"""
2
@file functions_for_cvp.sage
3
@package functions_for_cvp
2 4
Auxiliary functions used for CVP.
5

  
6
@author S.T.
3 7
"""
4 8
print "Functions for CVP loading..."
5 9
#
......
7 11
    """
8 12
    Compute the affine parameters to map [-1, 1] to the interval given
9 13
    as argument.
10
    @param lowerBound (of the target interval)
11
    @param upperBound (of the target interval)
14
    @param: lowerBound (of the target interval)
15
    @param: upperBound (of the target interval)
12 16
    @return the (scalingCoefficient, offset) tuple.
13 17
    """
14 18
    ## Check bounds consistency. Bounds must differ.
......
71 75
    return fplllIntBasis._sage_()
72 76
# End cvp_hkz_reduce.
73 77
#
78
def cvp_candidate_vectors(intVect, diffsList):
79
    """
80
    Computes a list of best approximation vectors based on the CVP
81
    computed vector using the differences between this vector and the 
82
    target function vector.
83
    @param intVect the vector from which candidates are built
84
    @param diffsList the list of the values that will be appended to the
85
           initial vector to form the candidates
86
    @return A matrix made of candidates rows or None if there is some invalid
87
            argument.
88
    @par How it works
89
    The idea is to create all the possible vectors based on the computed CVP
90
    vector and its differences to the target. Those are collected in 
91
    diffsList.@n
92
    From the vector we create all the possible combinations between the original
93
    value and the differences in diffsList. Some of those can be equal to 0.
94
    They are not taken into account. If nonZeroDiffsCount is the number of 
95
    diffsList element different from 0, there are 2^nonZeroDiffsCount 
96
    possible variants.@n
97
    To compute those, we build a 2^nonZeroDiffsCount rows matrix. For the
98
    first element in the vector corresponding to a non-zero in diffsList, we
99
    switch values in the matrix at every row.@n
100
    For the second such element (non-zero corresponding diffsList element), we
101
    switch values in the matrix at every second row for a string of two similar 
102
    values.@n
103
    For the third such element, change happens at every fourth row, for a 
104
    string of four similar values. And so on...
105
    @par Example
106
    @verbatim
107
    vect        =  [10, 20, 30, 40, 50]
108
    diffsList   =  [ 1,  0, -1,  0,  1]
109
    vectCandMat = [[10, 20, 30, 40, 50],
110
                   [11, 20, 30, 40, 50],
111
                   [10, 20, 29, 40, 50],
112
                   [11, 20, 29, 40, 50],
113
                   [10, 20, 30, 40, 51],
114
                   [11, 20, 30, 40, 51],
115
                   [10, 20, 29, 40, 51],
116
                   [11, 20, 29, 40, 51]]
117
    @endverbatim
118
"""
119
    ## Arguments check.
120
    vectLen = len(intVect)
121
    if vectLen != len(diffsList):
122
        return None
123
    #
124
    ## Compute the number of diffsList elements different from 0.
125
    nonZeroDiffsCount = 0
126
    for elem in diffsList:
127
        if elem != 0:
128
            nonZeroDiffsCount += 1
129
    if nonZeroDiffsCount == 0:
130
        return matrix(ZZ, 0, vectLen)
131
    numRows = 2^nonZeroDiffsCount
132
    vectMat = matrix(ZZ, numRows, vectLen)
133
    for rowIndex in xrange(0,numRows):
134
        effColIndex = 0
135
        for colIndex in xrange(0,vectLen):
136
            vectMat[rowIndex, colIndex] = intVect[colIndex]
137
            if diffsList[colIndex] != 0:
138
                if (rowIndex % 2^(effColIndex + 1)) >= 2^effColIndex:
139
                    vectMat[rowIndex, colIndex] += diffsList[colIndex]
140
                effColIndex += 1
141
    return vectMat
142
# End cvp_candidate_vectors
143
#
74 144
def cvp_coefficients_bounds_projection(executablePath, arguments):
75 145
    """
76 146
    Compute the min and max of the coefficients with linear
......
258 328
# End cvp_evaluation_points_list.
259 329
#
260 330
def cvp_extra_basis_scaling_exps(precsList, minExponentsList):
331
    """
332
    Computes the exponents for the extra scaling down of the elements of the
333
    basis.
334
    This extra scaling down is necessary when there are elements of the 
335
    basis that have negative exponents.
336
    """
261 337
    extraScalingExpsList = []
262 338
    for minExp, prec in zip(minExponentsList, precsList):
263 339
        if minExp - prec < 0:
......
396 472
# End cvp_monomials_list.
397 473
#
398 474
def cvp_polynomial_coeffs_from_vect(cvpVectInBasis,
399
                                   coeffsPrecList, 
400
                                   minCoeffsExpList,
401
                                   extraFuncScalingExp):
475
                                    coeffsPrecList, 
476
                                    minCoeffsExpList,
477
                                    extraFuncScalingExp):
478
    """
479
    Computes polynomial coefficients out of the elements of the CVP vector.
480
    @todo
481
    Rewrite the code with a single exponentiation, at the very end.
482
    """
402 483
    numElements = len(cvpVectInBasis)
403 484
    ## Arguments check.
404 485
    if numElements != len(minCoeffsExpList) or \
......
452 533
    return poly
453 534
# End cvp_polynomial_from_coeffs_and_exps.
454 535
#
455
def cvp_remez_all_poly_error_func_maxi(funct, 
536
def cvp_remez_all_poly_error_func_maxis(funct, 
456 537
                                        maxDegree, 
457 538
                                        lowerBound, 
458 539
                                        upperBound,
459 540
                                        precsList, 
460 541
                                        realField = None,
461 542
                                        contFracMaxErr = None):
462
    pass
463 543
    """
464 544
    For a given function f, a degree and an interval, compute the 
465 545
    maxima of the (f-remez_d(f)) function and those of the (f-truncRemez_d(f)) 
466 546
    function over the interval.
467 547
    """
468
# End cvp_remez_all_poly_error_func_maxi.
548
    ## If no realField argument is given try to retrieve it from the 
549
    #  bounds. If impossible (e.g. rational bound), fall back on RR. 
550
    if realField is None:
551
        try:
552
            ### Force failure if parent does not have prec() member.
553
            lowerBound.parent().prec()
554
            ### If no exception is thrown, set realField.
555
            realField = lowerBound.parent()
556
        except:
557
            realField = RR
558
    #print "Real field:", realField
559
    funcSa         = func
560
    funcAsStringSa = func._assume_str().replace("_SAGE_VAR_","",100)
561
    print "Function as a string:", funcAsStringSa
562
    ## Create the Sollya version of the function and compute the
563
    #  Remez approximant
564
    funcSo  = pobyso_parse_string(funcAsStringSa)
565
    pStarSo = pobyso_remez_canonical_sa_so(funcAsStringSa, 
566
                                           maxDegree, 
567
                                           lowerBound,
568
                                           upperBound)
569
    ## Compute the error function and its derivative
570
    ### First create the error function with copies since they are needed later.
571
    errorFuncSo = sollya_lib_build_function_sub(sollya_lib_copy_obj(pStarSo), 
572
                                                sollya_lib_copy_obj(funcSo))
573
    intervalSo = pobyso_range_from_bounds_sa_so(lowerBound, upperBound)
574
    diffErrorFuncSo = pobyso_diff_so_so(errorFuncSo)
575
    pobyso_clear_obj(errorFuncSo)
576
    ## Compute the zeros of the derivative.
577
    errorFuncZerosSo = pobyso_dirty_find_zeros_so_so(diffErrorFuncSo, intervalSo)
578
    pobyso_clear_obj(diffErrorFuncSo)
579
    errorFuncZerosSa = pobyso_float_list_so_sa(errorFuncZerosSo)
580
    pobyso_clear_obj(errorFuncZerosSo)
581
    ## Compute the truncated Remez polynomial and the error function.
582
    truncFormatListSo = pobyso_build_list_of_ints_sa_so(*precsList)
583
    pTruncSo = pobyso_round_coefficients_so_so(pStarSo, truncFormatListSo)
584
    pobyso_clear_obj(pStarSo)
585
    ### Compute the error function. This time we consume both the function
586
    #   and the polynomial.
587
    errorFuncSo = sollya_lib_build_function_sub(pTruncSo, funcSo)
588
    ## Compute the derivative.
589
    diffErrorFuncSo = pobyso_diff_so_so(errorFuncSo)
590
    pobyso_clear_obj(errorFuncSo)
591
    ## Compute the zeros of the derivative.
592
    errorFuncZerosSo = pobyso_dirty_find_zeros_so_so(diffErrorFuncSo, intervalSo)
593
    pobyso_clear_obj(diffErrorFuncSo)
594
    pobyso_clear_obj(intervalSo)
595
    errorFuncTruncZerosSa = pobyso_float_list_so_sa(errorFuncZerosSo)
596
    pobyso_clear_obj(errorFuncZerosSo)
597
    errorFuncZerosSa += errorFuncTruncZerosSa
598
    errorFuncZerosSa.sort()
599
    ## If required, convert the numbers to rational numbers.
600
    if not contFracMaxErr is None:
601
        for index in xrange(0, len(errorFuncZerosSa)):
602
            errorFuncZerosSa[index] = \
603
                errorFuncZerosSa[index].nearby_rational(contFracMaxErr)
604
    return errorFuncZerosSa
605
# End cvp_remez_all_poly_error_func_maxis.
469 606
#
470 607
def cvp_remez_all_poly_error_func_zeros(funct, 
471 608
                                        maxDegree, 
......
477 614
    """
478 615
    For a given function f, a degree and an interval, compute the 
479 616
    zeros of the (f-remez_d(f)) function and those of the (f-truncRemez_d(f)) 
480
    function over the interval. If the (f-truncRemez_d(f)) function has very 
481
    few zeros, compute the zeros of the derivative instead.
482
    TODO: change the final behaviour! Now!
617
    function over the interval.
483 618
    """
484 619
    ## If no realField argument is given try to retrieve it from the 
485 620
    #  bounds. If impossible (e.g. rational bound), fall back on RR. 
......
520 655
    ### Create the formats list. Notice the "*" before the list variable name.
521 656
    truncFormatListSo = pobyso_build_list_of_ints_sa_so(*precsList)
522 657
    #print "Precisions list as Sollya object:", 
523
    pobyso_autoprint(truncFormatListSo)
658
    #pobyso_autoprint(truncFormatListSo)
524 659
    pTruncSo = pobyso_round_coefficients_so_so(pStarSo, truncFormatListSo)
525 660
    #print "Truncated polynomial:", ; pobyso_autoprint(pTruncSo)
526 661
    ### Compute the error function. This time we consume both the function
......
530 665
    errorFuncZerosSo = pobyso_dirty_find_zeros_so_so(errorFuncSo, intervalSo)
531 666
    pobyso_clear_obj(pStarSo)
532 667
    #print "Zeroes of the error function for the truncated polynomial from Sollya:"
533
    pobyso_autoprint(errorFuncZerosSo)
668
    #pobyso_autoprint(errorFuncZerosSo)
534 669
    errorFuncTruncZerosSa = pobyso_float_list_so_sa(errorFuncZerosSo)
535 670
    pobyso_clear_obj(errorFuncZerosSo)
536
    ## It may happen that the error function has only one or two zeros.
537
    #  In this case, we are interested in the variations and we consider the
538
    #  derivative
539
    if maxDegree > 3:
540
        if len(errorFuncTruncZerosSa) <= (maxDegree / 2):
541
            errorFuncDiffSo = pobyso_diff_so_so(errorFuncSo)
542
            errorFuncZerosSo = pobyso_dirty_find_zeros_so_so(errorFuncDiffSo,
543
                                                             intervalSo)
544
            errorFuncTruncZerosSa = pobyso_float_list_so_sa(errorFuncZerosSo)
545
            pobyso_clear_obj(errorFuncZerosSo)
546
            pobyso_clear_obj(errorFuncDiffSo) # Clears funcSo and pTruncSo as well.
547
    pobyso_clear_obj(errorFuncSo) # Clears funcSo and pTruncSo as well.
548 671
    ## Sollya objects clean up.
549 672
    pobyso_clear_obj(intervalSo)
550 673
    errorFuncZerosSa += errorFuncTruncZerosSa
......
641 764
    """
642 765
    Compute the coordinates of "vect" in "basis" by
643 766
    solving a linear system.
644
    @param vect : the vector we want to compute the coordinates of
767
    @param vect  the vector we want to compute the coordinates of
645 768
                  in coordinates of the ambient space;
646
    @param basis: the basis we want to compute the coordinates in
769
    @param basis the basis we want to compute the coordinates in
647 770
                  as a matrix relative to the ambient space.
648 771
    """
649 772
    ## Create the variables for the linear equations.
......
670 793
            equationString += str(varsList[bIndex]) + "*" + str(basis[bIndex,vIndex])
671 794
        equationString += " == " + str(vect[vIndex])
672 795
        equationsList.append(sage_eval(equationString))
673
    ## Solve the equations system. The solution dictionnary is needed
796
    ## Solve the equations system. The solution dictionary is needed
674 797
    #  to recover the values of the solutions.
675 798
    solutions = solve(equationsList,varsList, solution_dict=True)
799
    ## This code is deactivated: did not solve the problem.
800
    """
801
    if len(solutions) == 0:
802
        print "Trying Maxima to_poly_sove."
803
        solutions = solve(equationsList,varsList, solution_dict=True, to_poly_solve = 'force')
804
    """
676 805
    #print "Solutions:", s
677 806
    ## Recover solutions in rational components vector.
678 807
    vectInBasis = vector(QQ, basis.nrows())
679 808
    ### There can be several solution, in the general case.
680
    #   Here, there is only one. For each solution, each 
809
    #   Here, there is only one (or none). For each solution, each 
681 810
    #   variable has to be searched for.
682 811
    for sol in solutions:
683 812
        for bIndex in basisIterationsRange:

Formats disponibles : Unified diff