| @@ -75,6 +75,17 @@ def cannonical_param(v): | |||
| i = [x != 0 for x in v[0]].index(True) | |||
| return i, v[0, i] | |||
| def xgcd_of_list(a): | |||
| (g, s, t) = xgcd(a[0], a[1]) | |||
| bezouts = [s, t] | |||
| for v in a[2:]: | |||
| (g, s_, t_) = xgcd(g, v) | |||
| bezouts = [b*s_ for b in bezouts] | |||
| bezouts.append(t_) | |||
| return (g, bezouts) | |||
| def remove_linear_dependencies(B, dim=None): | |||
| nrows = B.nrows() | |||
| if dim is None or nrows > dim: | |||
| @@ -85,22 +96,46 @@ def remove_linear_dependencies(B, dim=None): | |||
| r = K.dimensions()[0] | |||
| else: | |||
| r = nrows-dim | |||
| if r == 1: | |||
| if r == 1 and False: | |||
| print("Use Better Algo") | |||
| # Find a linear dependency | |||
| if K is None: | |||
| K = B.left_kernel().basis_matrix() | |||
| assert K.dimensions()[0] == 1 | |||
| combinaison = K[0] | |||
| # Detect the redundant vector | |||
| combinaison *= lcm([v.denominator() for v in combinaison]) | |||
| print(combinaison) | |||
| pivot, pivot_value = None, None | |||
| for ind, value in enumerate(combinaison): | |||
| if abs(value) > 0 and (pivot is None or abs(value)<abs(pivot_value)): | |||
| if abs(value) == 1: | |||
| pivot, pivot_value = ind, value | |||
| break | |||
| if pivot_value is None: | |||
| print('Complex case') | |||
| for ind, value in enumerate(combinaison): | |||
| if abs(value) > 0 and gcd([v for i,v in enumerate(combinaison) if i!=ind]) == 1: | |||
| if pivot is None or abs(value)<abs(pivot_value): | |||
| pivot, pivot_value = ind, value | |||
| if pivot_value < 0: | |||
| combinaison = vector(ZZ, [-v for v in combinaison]) | |||
| _, bezouts = xgcd_of_list([v for i,v in enumerate(combinaison) if i!=pivot]) | |||
| factor = combinaison[pivot]-1 | |||
| for i in range(len(combinaison)): | |||
| ind = i if i < pivot else i-1 | |||
| if i != pivot: | |||
| B[i] += factor*bezouts[ind]*B[pivot] | |||
| combinaison[pivot] += -factor | |||
| assert (combinaison*B).is_zero(), 'It is not a linear dependency anymore !' | |||
| assert abs(combinaison[pivot]) == 1, f'Error abs(combinaison[pivot]) == {abs(combinaison[pivot])} != 1' | |||
| B = B[[i for i in range(B.dimensions()[0]) if i != pivot]] | |||
| else: | |||
| B = B.LLL() | |||
| B = B[r:] | |||
| @@ -129,7 +164,7 @@ def lattice_orthogonal_section(D, V, maintains_basis=True): | |||
| # Eliminate linear dependencies | |||
| if maintains_basis: | |||
| D = remove_linear_dependencies(D) | |||
| # Go back to the primal | |||
| return D | |||
| @@ -137,7 +172,7 @@ def lattice_orthogonal_section(D, V, maintains_basis=True): | |||
| def lattice_project_against(B, V, maintains_basis=True): | |||
| """ | |||
| Compute the projection of the lattice L(B) orthogonally to Span(V). All vectors if V | |||
| (or at least their projection on Span(B)) must belong to L(B). | |||
| (or at least their projection on Span(B)) must belong to L(B). | |||
| Algorithm: | |||
| - project V onto Span(B) | |||
| - project the basis onto orth(V) | |||
| @@ -200,7 +235,7 @@ def is_diagonal(M): | |||
| def logdet(M, exact=False): | |||
| """ | |||
| """ | |||
| Compute the log of the determinant of a large rational matrix, | |||
| tryping to avoid overflows. | |||
| """ | |||
| @@ -221,7 +256,7 @@ def logdet(M, exact=False): | |||
| def degen_inverse(S, B=None): | |||
| """ Compute the inverse of a symmetric matrix restricted | |||
| """ Compute the inverse of a symmetric matrix restricted | |||
| to its span | |||
| """ | |||
| # Get an orthogonal basis for the Span of B | |||
| @@ -294,13 +329,13 @@ def square_root_inverse_degen(S, B=None): | |||
| def build_standard_substitution_matrix(V, pivot=None, data=None, output_data=False): | |||
| _, pivot = V.nonzero_positions()[0] if (pivot is None) else (None, pivot) | |||
| _, pivot = V.nonzero_positions()[0] if (pivot is None) else (None, pivot) | |||
| assert V[0,pivot] != 0, 'The value of the pivot must be non-zero.' | |||
| dim = V.ncols() | |||
| V1 = - V[0,:pivot] / V[0,pivot] | |||
| V2 = - V[0,pivot+1:] / V[0,pivot] | |||
| Gamma = zero_matrix(QQ, dim,dim-1) | |||
| Gamma[:pivot,:pivot] = identity_matrix(pivot) | |||
| Gamma[pivot,:pivot] = V1 | |||
| @@ -315,11 +350,11 @@ def build_standard_substitution_matrix(V, pivot=None, data=None, output_data=Fal | |||
| normalization_matrix[pivot:,pivot:] = identity_matrix(dim-pivot-1) - V2.T*V2 / norm2 | |||
| normalization_matrix[:pivot,pivot:] = - V1.T*V2 / norm2 | |||
| normalization_matrix[pivot:,:pivot] = - V2.T*V1 / norm2 | |||
| data['det'] = norm2 | |||
| data['normalization_matrix'] = normalization_matrix | |||
| if output_data: | |||
| return Gamma, data | |||
| else: | |||
| return Gamma | |||
| return Gamma | |||