def _prec_for_solve_diff_eqn_families(M, p): #UPDATE THIS with valuation of K[0]-1 and K[1] r""" A helper function for determining the (relative) precision of the input to solve_diff_eqn required in order obtain an answer with (relative) precision ``M``. The parameter ``p`` is the prime and ``k`` is the weight. Given input precision `M_\text{in}`, the output has precision .. MATH:: M = M_\text{in} - \lceil\log_p(M_\text{in}) - 3. """ # Do we need the weight? # A good guess to begin: if M < 1: raise ValueError("Desired precision M(=%s) must be at least 1."%(M)) cp = (p - 2) / (p - 1) Min = ZZ(3 + M + ceil(ZZ(M).log(p))) # It looks like usually there are no iterations # For low M, there can be 1 or 2 while M > Min*cp - ceil(log((Min * cp),p)) - 3: #THINK ABOUT THIS MORE Min += 1 #print("An iteration in _prec_solve_diff_eqn") return Min
def lifts_basis(self, k, prec, cusp_forms=True): r""" Compute a basis of the Maass Spezialschar of weight ``k`` up to precision ``prec``. This computes the theta lifts of a basis of cusp forms (or a basis of modular forms, if ``cusp_forms`` is set to False). INPUT: - ``k`` -- the weight - ``prec`` -- the precision of the output - ``cusp_forms`` -- boolean (default True). If True then we output only cusp forms. OUTPUT: list of OrthogonalModularForm's EXAMPLES:: sage: from weilrep import * sage: ParamodularForms(N = 1).spezialschar(10, 5) [(r^-1 - 2 + r)*q*s + (-2*r^-2 - 16*r^-1 + 36 - 16*r - 2*r^2)*q^2*s + (-2*r^-2 - 16*r^-1 + 36 - 16*r - 2*r^2)*q*s^2 + (r^-3 + 36*r^-2 + 99*r^-1 - 272 + 99*r + 36*r^2 + r^3)*q^3*s + (-16*r^-3 + 240*r^-2 - 240*r^-1 + 32 - 240*r + 240*r^2 - 16*r^3)*q^2*s^2 + (r^-3 + 36*r^-2 + 99*r^-1 - 272 + 99*r + 36*r^2 + r^3)*q*s^3 + O(q, s)^5] """ S = self.gram_matrix() w = self.weilrep() if cusp_forms: X = w.cusp_forms_basis(k + self.input_wt(), ceil(prec * prec / 4) + 1) else: X = w.modular_forms_basis(k + self.input_wt(), ceil(prec * prec / 4) + 1) try: return X[0].theta_lift(prec, _L=X) except TypeError: return [x.theta_lift(prec) for x in X]
def __init__(self, n, instance='key', m=None): """ Construct LWE instance parameterised by security parameter ``n`` where all other parameters are chosen as in [CGW13]_. INPUT: - ``n`` - security parameter (integer >= 89) - ``instance`` - one of - "key" - the LWE-instance that hides the secret key is generated - "encrypt" - the LWE-instance that hides the message is generated (default: ``key``) - ``m`` - number of allowed samples or ``None`` in which case ``m`` is chosen as in [CGW13_]. (default: ``None``) EXAMPLES:: sage: from sage.crypto.lwe import UniformNoiseLWE sage: UniformNoiseLWE(89) LWE(89, 154262477, UniformSampler(0, 351), 'noise', 131) sage: UniformNoiseLWE(89, instance='encrypt') LWE(131, 154262477, UniformSampler(0, 497), 'noise', 181) """ if n < 89: raise TypeError("Parameter too small") n2 = n C = 4 / sqrt(2 * pi) kk = floor((n2 - 2 * log(n2, 2)**2) / 5) n1 = floor((3 * n2 - 5 * kk) / 2) ke = floor((n1 - 2 * log(n1, 2)**2) / 5) l = floor((3 * n1 - 5 * ke) / 2) - n2 sk = ceil((C * (n1 + n2))**(3 / 2)) se = ceil((C * (n1 + n2 + l))**(3 / 2)) q = next_prime( max(ceil((4 * sk)**((n1 + n2) / n1)), ceil((4 * se)**((n1 + n2 + l) / (n2 + l))), ceil(4 * (n1 + n2) * se * sk + 4 * se + 1))) if kk <= 0: raise TypeError("Parameter too small") if instance == 'key': D = UniformSampler(0, sk - 1) if m is None: m = n1 LWE.__init__(self, n=n2, q=q, D=D, secret_dist='noise', m=m) elif instance == 'encrypt': D = UniformSampler(0, se - 1) if m is None: m = n2 + l LWE.__init__(self, n=n1, q=q, D=D, secret_dist='noise', m=m) else: raise TypeError("Parameter instance=%s not understood." % (instance))
def __init__(self, n, instance='key', m=None): """ Construct LWE instance parameterised by security parameter ``n`` where all other parameters are chosen as in [CGW2013]_. INPUT: - ``n`` - security parameter (integer >= 89) - ``instance`` - one of - "key" - the LWE-instance that hides the secret key is generated - "encrypt" - the LWE-instance that hides the message is generated (default: ``key``) - ``m`` - number of allowed samples or ``None`` in which case ``m`` is chosen as in [CGW2013]_. (default: ``None``) EXAMPLES:: sage: from sage.crypto.lwe import UniformNoiseLWE sage: UniformNoiseLWE(89) LWE(89, 154262477, UniformSampler(0, 351), 'noise', 131) sage: UniformNoiseLWE(89, instance='encrypt') LWE(131, 154262477, UniformSampler(0, 497), 'noise', 181) """ if n<89: raise TypeError("Parameter too small") n2 = n C = 4/sqrt(2*pi) kk = floor((n2-2*log(n2, 2)**2)/5) n1 = floor((3*n2-5*kk)/2) ke = floor((n1-2*log(n1, 2)**2)/5) l = floor((3*n1-5*ke)/2)-n2 sk = ceil((C*(n1+n2))**(3/2)) se = ceil((C*(n1+n2+l))**(3/2)) q = next_prime(max(ceil((4*sk)**((n1+n2)/n1)), ceil((4*se)**((n1+n2+l)/(n2+l))), ceil(4*(n1+n2)*se*sk+4*se+1))) if kk<=0: raise TypeError("Parameter too small") if instance == 'key': D = UniformSampler(0, sk-1) if m is None: m = n1 LWE.__init__(self, n=n2, q=q, D=D, secret_dist='noise', m=m) elif instance == 'encrypt': D = UniformSampler(0, se-1) if m is None: m = n2+l LWE.__init__(self, n=n1, q=q, D=D, secret_dist='noise', m=m) else: raise TypeError("Parameter instance=%s not understood."%(instance))
def _normalisation_factor_zz(self, tau=3): r""" This function returns an approximation of `∑_{x ∈ \ZZ^n} \exp(-|x|_2^2/(2σ²))`, i.e. the normalisation factor such that the sum over all probabilities is 1 for `\ZZⁿ`. If this ``self.B`` is not an identity matrix over `\ZZ` a ``NotImplementedError`` is raised. INPUT: - ``tau`` -- all vectors `v` with `|v|_∞ ≤ τ·σ` are enumerated (default: ``3``). EXAMPLES:: sage: from sage.stats.distributions.discrete_gaussian_lattice import DiscreteGaussianDistributionLatticeSampler sage: n = 3; sigma = 1.0 sage: D = DiscreteGaussianDistributionLatticeSampler(ZZ^n, sigma) sage: f = D.f sage: c = D._normalisation_factor_zz(); c 15.528... sage: from collections import defaultdict sage: counter = defaultdict(Integer) sage: m = 0 sage: def add_samples(i): ....: global counter, m ....: for _ in range(i): ....: counter[D()] += 1 ....: m += 1 sage: v = vector(ZZ, n, (0, 0, 0)) sage: v.set_immutable() sage: while v not in counter: add_samples(1000) sage: while abs(m*f(v)*1.0/c/counter[v] - 1.0) >= 0.1: add_samples(1000) sage: v = vector(ZZ, n, (-1, 2, 3)) sage: v.set_immutable() sage: while v not in counter: add_samples(1000) sage: while abs(m*f(v)*1.0/c/counter[v] - 1.0) >= 0.2: add_samples(1000) # long time """ if self.B != identity_matrix(ZZ, self.B.nrows()): raise NotImplementedError( "This function is only implemented when B is an identity matrix." ) f = self.f n = self.B.ncols() sigma = self._sigma return sum( f(x) for x in _iter_vectors(n, -ceil(tau * sigma), ceil(tau * sigma)))
def __init__(self, bleachermark, runs): from sage.parallel.decorate import parallel from sage.functions.other import ceil, floor self._benchmarks = bleachermark._benchmarks # profiling we run each benchmark once self._totaltime = reduce( lambda a, b: a + b, [r[0] for bm in self._benchmarks for r in bm.run(runs[0])[1:]]) #divide the runs in chunks self._chunksize = ceil(2.0 / self._totaltime) self._nchunks = floor(len(runs) / self._chunksize) self._chunks = [ runs[i * self._chunksize:(i + 1) * self._chunksize] for i in range(self._nchunks) ] if (self._nchunks) * self._chunksize < len(runs): self._chunks.append(runs[(self._nchunks) * self._chunksize:]) # we define the parallel function @parallel def f(indices): results = [] for frun in indices: for i in range(len(self._benchmarks)): bm = self._benchmarks[i] res = bm.run(frun) results.append((i, res)) return results self._getchunks = f(self._chunks) self._currentchunk = []
def _base(j, k, c): assert k - j == 1 aajk = subbasis(j, k) assert all(a.order() in (1, p) for a in aajk) idxs = [i for i, a in enumerate(aajk) if a.order() == p] rs = [([0], [0]) for i in range(len(aajk))] for i in range(len(idxs)): rs[idxs[i]] = (range(p), [0]) if i % 2 else ([0], range(p)) if len(idxs) % 2: m = ceil(sqrt(p)) rs[idxs[-1]] = range(0, p, m), range(m) tab = {} for x in iproduct(*(r for r, _ in rs)): key = dotprod(x, aajk) if hasattr(key, 'set_immutable'): key.set_immutable() tab[key] = vector(x) for y in iproduct(*(r for _, r in rs)): key = c - dotprod(y, aajk) if hasattr(key, 'set_immutable'): key.set_immutable() if key in tab: return tab[key] + vector(y) raise TypeError('Not in group')
def get_contents_bound_for_semi_definite_forms(self): r""" Return the bound for the contents of a semi positive definite form falling within this precision. EXAMPLES:: sage: from sage.modular.siegel.siegel_modular_form_prec import SiegelModularFormPrecision sage: prec = SiegelModularFormPrecision(7) sage: prec.get_contents_bound_for_semi_definite_forms() 2 sage: prec = SiegelModularFormPrecision(101) sage: prec.get_contents_bound_for_semi_definite_forms() 26 NOTE If (a,b,c) is semi positive definite, then it is GL(2,Z)-equivalent to a the form (0,0,g) where g is the contents (gcd) of a,b,c. I don't know what this does. It seems to only do it for singular forms-- NR """ if self.__type == 'infinity': return infinity elif self.__type == 'disc': return ceil((self.__prec+1)/4) elif self.__type == 'box': return self.__prec[2] else: raise RuntimeError("Unexpected value of self.__type")
def get_contents_bound_for_semi_definite_forms(self): r""" Return the bound for the contents of a semi positive definite form falling within this precision. EXAMPLES:: sage: from sage.modular.siegel.siegel_modular_form_prec import SiegelModularFormPrecision sage: prec = SiegelModularFormPrecision(7) sage: prec.get_contents_bound_for_semi_definite_forms() 2 sage: prec = SiegelModularFormPrecision(101) sage: prec.get_contents_bound_for_semi_definite_forms() 26 NOTE If (a,b,c) is semi positive definite, then it is GL(2,Z)-equivalent to a the form (0,0,g) where g is the contents (gcd) of a,b,c. I don't know what this does. It seems to only do it for singular forms-- NR """ if self.__type == 'infinity': return infinity elif self.__type == 'disc': return ceil((self.__prec+1)/4) elif self.__type == 'box': return self.__prec[2] else: raise RuntimeError, "Unexpected value of self.__type"
def eisenstein_series(self, k, prec): r""" Compute the Hilbert Eisenstein series E_k(tau1, tau2). This is a simple algorithm based on the theta lift. We do not use a closed formula for Eisenstein series coefficients. INPUT: - ``k`` -- the weight (an even integer >= 2) - ``prec`` -- the precision of the output OUTPUT: HilbertModularForm EXAMPLES:: sage: from weilrep import * sage: x = var('x') sage: K.<sqrt5> = NumberField(x^2 - 5) sage: HMF(K).eisenstein_series(2, 6) 1 + 120*q1^(-1/10*sqrt5 + 1/2)*q2^(1/10*sqrt5 + 1/2) + 120*q1^(1/10*sqrt5 + 1/2)*q2^(-1/10*sqrt5 + 1/2) + 120*q1^(-2/5*sqrt5 + 1)*q2^(2/5*sqrt5 + 1) + 600*q1^(-1/5*sqrt5 + 1)*q2^(1/5*sqrt5 + 1) + 720*q1*q2 + 600*q1^(1/5*sqrt5 + 1)*q2^(-1/5*sqrt5 + 1) + 120*q1^(2/5*sqrt5 + 1)*q2^(-2/5*sqrt5 + 1) + 720*q1^(-1/2*sqrt5 + 3/2)*q2^(1/2*sqrt5 + 3/2) + 1200*q1^(-3/10*sqrt5 + 3/2)*q2^(3/10*sqrt5 + 3/2) + 1440*q1^(-1/10*sqrt5 + 3/2)*q2^(1/10*sqrt5 + 3/2) + 1440*q1^(1/10*sqrt5 + 3/2)*q2^(-1/10*sqrt5 + 3/2) + 1200*q1^(3/10*sqrt5 + 3/2)*q2^(-3/10*sqrt5 + 3/2) + 720*q1^(1/2*sqrt5 + 3/2)*q2^(-1/2*sqrt5 + 3/2) + 600*q1^(-4/5*sqrt5 + 2)*q2^(4/5*sqrt5 + 2) + 1440*q1^(-3/5*sqrt5 + 2)*q2^(3/5*sqrt5 + 2) + 2520*q1^(-2/5*sqrt5 + 2)*q2^(2/5*sqrt5 + 2) + 2400*q1^(-1/5*sqrt5 + 2)*q2^(1/5*sqrt5 + 2) + 3600*q1^2*q2^2 + 2400*q1^(1/5*sqrt5 + 2)*q2^(-1/5*sqrt5 + 2) + 2520*q1^(2/5*sqrt5 + 2)*q2^(-2/5*sqrt5 + 2) + 1440*q1^(3/5*sqrt5 + 2)*q2^(-3/5*sqrt5 + 2) + 600*q1^(4/5*sqrt5 + 2)*q2^(-4/5*sqrt5 + 2) + 120*q1^(-11/10*sqrt5 + 5/2)*q2^(11/10*sqrt5 + 5/2) + 1440*q1^(-9/10*sqrt5 + 5/2)*q2^(9/10*sqrt5 + 5/2) + 2400*q1^(-7/10*sqrt5 + 5/2)*q2^(7/10*sqrt5 + 5/2) + 3720*q1^(-1/2*sqrt5 + 5/2)*q2^(1/2*sqrt5 + 5/2) + 3600*q1^(-3/10*sqrt5 + 5/2)*q2^(3/10*sqrt5 + 5/2) + 3840*q1^(-1/10*sqrt5 + 5/2)*q2^(1/10*sqrt5 + 5/2) + 3840*q1^(1/10*sqrt5 + 5/2)*q2^(-1/10*sqrt5 + 5/2) + 3600*q1^(3/10*sqrt5 + 5/2)*q2^(-3/10*sqrt5 + 5/2) + 3720*q1^(1/2*sqrt5 + 5/2)*q2^(-1/2*sqrt5 + 5/2) + 2400*q1^(7/10*sqrt5 + 5/2)*q2^(-7/10*sqrt5 + 5/2) + 1440*q1^(9/10*sqrt5 + 5/2)*q2^(-9/10*sqrt5 + 5/2) + 120*q1^(11/10*sqrt5 + 5/2)*q2^(-11/10*sqrt5 + 5/2) + O(q1, q2)^6 """ w = self.weilrep() try: return (-((k + k) / bernoulli(k)) * w.eisenstein_series( k, ceil(prec * prec / 4) + 1)).theta_lift(prec) except (TypeError, ValueError, ZeroDivisionError): raise ValueError('Invalid weight')
def native_two_isogeny_descent_work(E, two_tor_rk): """ Prepares the output from two-descent by two-isogeny. INPUT: - ``E`` - an elliptic curve - ``two_tor_rk`` - its two-torsion rank OUTPUT: - a lower bound on the rank - an upper bound on the rank - a lower bound on the rank of Sha[2] - an upper bound on the rank of Sha[2] - a list of the generators found (currently None, since we don't store them) EXAMPLES:: sage: from sage.schemes.elliptic_curves.BSD import native_two_isogeny_descent_work sage: E = EllipticCurve('14a') sage: native_two_isogeny_descent_work(E, E.two_torsion_rank()) (0, 0, 0, 0, None) sage: E = EllipticCurve('65a') sage: native_two_isogeny_descent_work(E, E.two_torsion_rank()) (1, 1, 0, 0, None) """ from sage.schemes.elliptic_curves.descent_two_isogeny import two_descent_by_two_isogeny n1, n2, n1p, n2p = two_descent_by_two_isogeny(E) # bring n1 and n1p up to the nearest power of two two = ZZ(2) # otherwise "log" is symbolic >.< e1 = ceil(ZZ(n1).log(two)) e1p = ceil(ZZ(n1p).log(two)) e2 = ZZ(n2).log(two) e2p = ZZ(n2p).log(two) rank_lower_bd = e1 + e1p - 2 rank_upper_bd = e2 + e2p - 2 sha_upper_bd = e2 + e2p - e1 - e1p gens = None # right now, we are not keeping track of them return rank_lower_bd, rank_upper_bd, 0, sha_upper_bd, gens
def _getitem_by_num(self, i): from sage.functions.other import ceil val = self._polygon(i) if val is Infinity: return self._base_exactprec else: return self._baseprec(ceil(val))
def schmidt_t5_eigenvalue_numerical(self, t): (tau1, z, tau2) = t from sage.libs.mpmath import mp from sage.libs.mpmath.mp import exp, pi from sage.libs.mpmath.mp import j as i if not Integer(self.__level()).is_prime(): raise ValueError("T_5 is only unique if the level is a prime") precision = ParamodularFormD2Filter_trace(self.precision()) s = Sequence([tau1, z, tau2]) if not is_ComplexField(s): mp_precision = 30 else: mp_precision = ceil(3.33 * s.universe().precision()) mp.dps = mp_precision p1list = P1List(self.level()) ## Prepare the operation for d_1(N) ## We have to invert the lifts since we will later use apply_GL_to_form d1_matrices = [p1list.lift_to_sl2z(i) for i in range(len(p1list))] d1_matrices = [(a_b_c_d[3], -a_b_c_d[1], -a_b_c_d[2], a_b_c_d[0]) for a_b_c_d in d1_matrices] ## Prepare the evaluation points corresponding to d_02(N) d2_points = list() for i in range(len(p1list())): (a, b, c, d) = p1list.lift_to_sl2z(i) tau1p = (a * tau1 + b) / (c * tau1 + d) zp = z / (c * tau1 + d) tau2p = tau2 - c * z**2 / (c * tau1 + d) (e_tau1p, e_zp, e_tau2p) = (exp(2 * pi * i * tau1p), exp(2 * pi * i * zp), exp(2 * pi * i * tau2p)) d2_points.append((e_tau1p, e_zp, e_tau2p)) (e_tau1, e_z, e_tau2) = (exp(2 * pi * i * tau1), exp(2 * pi * i * z), exp(2 * pi * i * tau2)) self_value = s.universe().zero() trans_value = s.universe().zero() for k in precision: (a, b, c) = apply_GL_to_form(self._P1List()(k[1]), k[0]) self_value = self_value + self[k] * e_tau1**a * e_z**b * e_tau2**c for m in d1_matrices: (ap, bp, cp) = apply_GL_to_form(m, (a, b, c)) for (e_tau1p, e_zp, e_tau2p) in d2_points: trans_value = trans_value + self[(( ap, bp, cp), 0)] * e_tau1p**ap * e_zp**bp * e_tau2p**cp return trans_value / self_value
def eis_F(cv, dv, N, k, Q=None, prec=10, t=1): """ Computes the coefficient of the Eisenstein series for $\Gamma(N)$. Not indented to be called by user. INPUT: - cv - int, the first coordinate of the vector determining the \Gamma(N) Eisenstein series - dv - int, the second coordinate of the vector determining the \Gamma(N) Eisenstein series - N - int, the level of the Eisenstein series to be computed - k - int, the weight of the Eisenstein seriess to be computed - Q - power series ring, the ring containing the q-expansion to be computed - param_level - int, the parameter of the returned series will be q_{param_level} - prec - int, the precision. The series in q_{param_level} will be truncated after prec coefficients OUTPUT: - an element of the ring Q, which is the Fourier expansion of the Eisenstein series """ if Q == None: Q = PowerSeriesRing(CyclotomicField(N), 'q{}'.format(N)) R = Q.base_ring() zetaN = R.zeta(N) q = Q.gen() s = 0 if k == 1: if cv % N == 0 and dv % N != 0: s = QQ(1) / QQ(2) * (1 + zetaN**dv) / (1 - zetaN**dv) elif cv % N != 0: s = QQ(1) / QQ(2) - QQ(cv) / QQ(N) + floor(QQ(cv) / QQ(N)) elif k > 1: s = -ber_pol(QQ(cv) / QQ(N) - floor(QQ(cv) / QQ(N)), k) / QQ(k) for n1 in xrange(1, ceil(prec / QQ(t))): # this is n/m in DS for n2 in xrange(1, ceil(prec / QQ(t) / QQ(n1)) + 1): # this is m in DS if Mod(n1, N) == Mod(cv, N): s += N**(1 - k) * n1**(k - 1) * zetaN**(dv * n2) * q**(t * n1 * n2) if Mod(n1, N) == Mod(-cv, N): s += (-1)**k * N**(1 - k) * n1**(k - 1) * zetaN**( -dv * n2) * q**(t * n1 * n2) return s + O(q**floor(prec))
def griesmer_upper_bound(n,q,d,algorithm=None): r""" Returns the Griesmer upper bound. Returns the Griesmer upper bound for the number of elements in a largest linear code of minimum distance `d` in `\GF{q}^n`, cf. [HP2003]_. If the method is "gap", it wraps GAP's ``UpperBoundGriesmer``. The bound states: .. MATH:: `n\geq \sum_{i=0}^{k-1} \lceil d/q^i \rceil.` EXAMPLES: The bound is reached for the ternary Golay codes:: sage: codes.bounds.griesmer_upper_bound(12,3,6) 729 sage: codes.bounds.griesmer_upper_bound(11,3,5) 729 :: sage: codes.bounds.griesmer_upper_bound(10,2,3) 128 sage: codes.bounds.griesmer_upper_bound(10,2,3,algorithm="gap") # optional - gap_packages (Guava package) 128 TESTS:: sage: codes.bounds.griesmer_upper_bound(11,3,6) 243 sage: codes.bounds.griesmer_upper_bound(11,3,6) 243 """ _check_n_q_d(n, q, d) if algorithm=="gap": gap.load_package("guava") ans=gap.eval("UpperBoundGriesmer(%s,%s,%s)"%(n,d,q)) return QQ(ans) else: #To compute the bound, we keep summing up the terms on the RHS #until we start violating the inequality. from sage.functions.other import ceil den = 1 s = 0 k = 0 while s <= n: s += ceil(d/den) den *= q k = k + 1 return q**(k-1)
def _an_element_3d(self, x=0, y=0): r""" Returns an element in self. EXAMPLES:: sage: from slabbe import DiscreteHyperplane sage: p = DiscreteHyperplane([1,pi,7], 1+pi+7, mu=10) sage: p._an_element_3d() (0, 0, 0) """ a, b, c = self._v x_sqrt3 = ceil(x / sqrt(3)) left = ((a + b) * y + (a - b) * x_sqrt3 - self._mu) / (a + b + c) right = ((a + b) * y + (a - b) * x_sqrt3 - self._mu + self._omega) / (a + b + c) #print "left, right = ", left, right #print "left, right = ", ceil(left), ceil(right)-1 # left <= z <= right znew = ceil(left) xnew = znew - y - x_sqrt3 ynew = znew - y + x_sqrt3 znew = ceil(right) - 1 #print xnew, ynew, znew #print vector((xnew, ynew, znew)) in self #print vector((x,y,ceil(right)-1)) in self v = vector((xnew, ynew, znew)) if v in self: v.set_immutable() return v else: print "%s not in the plane" % v print "trying similar points" v = vector((xnew, ynew, znew - 1)) if v in self: v.set_immutable() return v v = vector((xnew, ynew, znew + 1)) if v in self: v.set_immutable() return v raise ValueError("%s not in the plane" % v)
def gegenbauer_polynomial(N, s): r""" Compute two-variable Gegenbauer polynomials. """ x, y = PolynomialRing(QQ, ['x', 'y']).gens() f = 0 for k in range(N // 2 + 1): j = N - (k + k) f += (-1)**k * QQ(gamma(s + k + j) / gamma(s + ceil(N / 2))) / ( factorial(k) * factorial(j)) * (x**j) * (y**k) return f * factorial(N)
def _compute_eigenvector(s, l, m, gam, verbose=False, min_nmax=8): r""" Compute the eigenvector and the eigenvalue corresponding to (s, l, m, gam) INPUT: - ``s`` -- integer; the spin weight - ``l`` -- non-negative integer; the harmonic degree - ``m`` -- integer within the range ``[-l, l]``; the azimuthal number - ``gam`` -- spheroidicity parameter - ``verbose`` -- (default: ``False``) determines whether some details of the computation are printed out - ``min_nmax`` -- (default: 8) integer; floor for the evaluation of the parameter ``nmax``, which sets the highest degree of the spherical harmonic expansion as ``l+nmax``. """ nmax = ceil(abs(3 * gam / 2 - gam * gam / 250)) + min_nmax # FIXME : improve the estimate of nmax if nmax % 2 == 0: nmax += 1 lmin = max(abs(s), abs(m)) nmin = min(l - lmin, nmax) size = nmax + nmin + 1 mat = matrix(RDF, size, size) for i in range(1, size + 1): mat[i - 1, i - 1] = -kHat(s, l - nmin - 1 + i, m, gam) if i > 2: mat[i - 1, i - 3] = -k2(s, l - nmin - 3 + i, m, gam) if i > 1: mat[i - 1, i - 2] = -kTilde2(s, l - nmin + i - 2, m, gam) if (i < size): mat[i - 1, i] = -kTilde2(s, l - nmin + i - 1, m, gam) if (i < size - 1): mat[i - 1, i + 1] = -k2(s, l - nmin + i + -1, m, gam) if verbose: print("nmax: {}".format(nmax)) print("lmin: {}".format(lmin)) print("nmin: {}".format(nmin)) print("size: {}".format(size)) # show(mat) # Computation of the eigenvalues and eigenvectors: evlist = mat.eigenvectors_right() # list of triples, each triple being # (eigenvalue, [eigenvector], 1) sevlist = sorted(evlist, key=lambda x: x[0], reverse=True) egval, egvec, mult = sevlist[-(nmin + 1)] egvec = egvec[0] # since egvec is the single-element list [eigenvector] if verbose: print("eigenvalue: {}".format(egval)) print("eigenvector: {}".format(egvec)) check = mat * egvec - egval * egvec print("check: {}".format(check)) lamb = egval - s * (s + 1) - 2 * m * gam + gam * gam return lamb, egvec, nmin, nmax, lmin
def _an_element_3d(self, x=0, y=0): r""" Returns an element in self. EXAMPLES:: sage: from slabbe import DiscreteHyperplane sage: p = DiscreteHyperplane([1,pi,7], 1+pi+7, mu=10) sage: p._an_element_3d() (0, 0, 0) """ a,b,c = self._v x_sqrt3 = ceil(x / sqrt(3)) left = ((a+b) * y + (a-b) * x_sqrt3 - self._mu) / (a+b+c) right = ((a+b) * y + (a-b) * x_sqrt3 - self._mu + self._omega) / (a+b+c) #print("left, right = ", left, right) #print("left, right = ", ceil(left), ceil(right)-1) # left <= z <= right znew = ceil(left) xnew = znew - y - x_sqrt3 ynew = znew - y + x_sqrt3 znew = ceil(right)-1 #print(xnew, ynew, znew) #print(vector((xnew, ynew, znew)) in self) #print(vector((x,y,ceil(right)-1)) in self) v = vector((xnew, ynew, znew)) if v in self: v.set_immutable() return v else: print("%s not in the plane" % v) print("trying similar points") v = vector((xnew, ynew, znew-1)) if v in self: v.set_immutable() return v v = vector((xnew, ynew, znew+1)) if v in self: v.set_immutable() return v raise ValueError("%s not in the plane" % v)
def _sympysage_ceiling(self): """ EXAMPLES:: sage: from sympy import Symbol, ceiling sage: assert ceil(x)._sympy_() == ceiling(Symbol('x')) sage: assert ceil(x) == ceiling(Symbol('x'))._sage_() sage: integrate(ceil(x), x, 0, infinity, algorithm='sympy') integrate(ceil(x), x, 0, +Infinity) """ from sage.functions.other import ceil return ceil(self.args[0]._sage_())
def _normalisation_factor_zz(self, tau=3): r""" This function returns an approximation of `∑_{x ∈ \ZZ^n} \exp(-|x|_2^2/(2σ²))`, i.e. the normalisation factor such that the sum over all probabilities is 1 for `\ZZⁿ`. If this ``self.B`` is not an identity matrix over `\ZZ` a ``NotImplementedError`` is raised. INPUT: - ``tau`` -- all vectors `v` with `|v|_∞ ≤ τ·σ` are enumerated (default: ``3``). EXAMPLE:: sage: from sage.stats.distributions.discrete_gaussian_lattice import DiscreteGaussianDistributionLatticeSampler sage: n = 3; sigma = 1.0; m = 1000 sage: D = DiscreteGaussianDistributionLatticeSampler(ZZ^n, sigma) sage: f = D.f sage: c = D._normalisation_factor_zz(); c 15.528... sage: l = [D() for _ in xrange(m)] sage: v = vector(ZZ, n, (0, 0, 0)) sage: l.count(v), ZZ(round(m*f(v)/c)) (57, 64) """ if self.B != identity_matrix(ZZ, self.B.nrows()): raise NotImplementedError( "This function is only implemented when B is an identity matrix." ) f = self.f n = self.B.ncols() sigma = self._sigma return sum( f(x) for x in _iter_vectors(n, -ceil(tau * sigma), ceil(tau * sigma)))
def bench(p, start=2, stop=200, routine=test_irred): l = [] i = ZZ(start) while i < stop: print i, try: l.append((i, routine(p, i, i+1))) except: print "failed" else: print sum(l[-1][1]) i += ceil(i/10) return l
def automorphy_factor_vector(p, a, c, k, chi, p_prec, var_prec, R): """ EXAMPLES:: sage: from sage.modular.pollack_stevens.families_util import automorphy_factor_vector sage: automorphy_factor_vector(3, 1, 3, 0, None, 4, 3, PowerSeriesRing(ZpCA(3), 'w')) [1 + O(3^20), O(3^21) + (3 + 3^2 + 2*3^3 + O(3^21))*w + (3^2 + 2*3^3 + O(3^22))*w^2, O(3^22) + (3^2 + 2*3^3 + O(3^22))*w + (2*3^2 + O(3^22))*w^2, O(3^22) + (3^2 + 3^3 + O(3^22))*w + (2*3^3 + O(3^23))*w^2] sage: automorphy_factor_vector(3, 1, 3, 2, None, 4, 3, PowerSeriesRing(ZpCA(3), 'w')) [1 + O(3^20), O(3^21) + (3 + 3^2 + 2*3^3 + O(3^21))*w + (3^2 + 2*3^3 + O(3^22))*w^2, O(3^22) + (3^2 + 2*3^3 + O(3^22))*w + (2*3^2 + O(3^22))*w^2, O(3^22) + (3^2 + 3^3 + O(3^22))*w + (2*3^3 + O(3^23))*w^2] sage: p, a, c, k, chi, p_prec, var_prec, R = 11, -3, 11, 0, None, 6, 4, PowerSeriesRing(ZpCA(11, 6), 'w') sage: automorphy_factor_vector(p, a, c, k, chi, p_prec, var_prec, R) [1 + O(11^6) + (7*11^2 + 4*11^3 + 11^4 + 9*11^5 + 3*11^6 + 10*11^7 + O(11^8))*w + (2*11^3 + 2*11^5 + 2*11^6 + 6*11^7 + 8*11^8 + O(11^9))*w^2 + (6*11^4 + 4*11^5 + 5*11^6 + 6*11^7 + 4*11^9 + O(11^10))*w^3, O(11^7) + (7*11 + 11^2 + 2*11^3 + 3*11^4 + 4*11^5 + 3*11^6 + O(11^7))*w + (2*11^2 + 4*11^3 + 5*11^4 + 10*11^5 + 10*11^6 + 2*11^7 + O(11^8))*w^2 + (6*11^3 + 6*11^4 + 2*11^5 + 9*11^6 + 9*11^7 + 2*11^8 + O(11^9))*w^3, O(11^8) + (3*11^2 + 4*11^4 + 2*11^5 + 6*11^6 + 10*11^7 + O(11^8))*w + (8*11^2 + 7*11^3 + 8*11^4 + 8*11^5 + 11^6 + O(11^8))*w^2 + (3*11^3 + 9*11^4 + 10*11^5 + 5*11^6 + 10*11^7 + 11^8 + O(11^9))*w^3, O(11^9) + (8*11^3 + 3*11^4 + 3*11^5 + 7*11^6 + 2*11^7 + 6*11^8 + O(11^9))*w + (10*11^3 + 6*11^5 + 7*11^6 + O(11^9))*w^2 + (4*11^3 + 11^4 + 8*11^8 + O(11^9))*w^3, O(11^10) + (2*11^4 + 9*11^5 + 8*11^6 + 5*11^7 + 4*11^8 + 6*11^9 + O(11^10))*w + (6*11^5 + 3*11^6 + 5*11^7 + 7*11^8 + 4*11^9 + O(11^10))*w^2 + (2*11^4 + 8*11^6 + 2*11^7 + 9*11^8 + 7*11^9 + O(11^10))*w^3, O(11^11) + (2*11^5 + 10*11^6 + 10*11^7 + 10*11^8 + 10*11^9 + 10*11^10 + O(11^11))*w + (5*11^5 + 10*11^6 + 10*11^7 + 10*11^8 + 10*11^9 + 10*11^10 + O(11^11))*w^2 + (2*11^5 + 10*11^6 + 10*11^7 + 10*11^8 + 10*11^9 + 10*11^10 + O(11^11))*w^3] sage: k = 2 sage: automorphy_factor_vector(p, a, c, k, chi, p_prec, var_prec, R) [9 + 6*11^2 + 11^3 + 9*11^4 + 8*11^5 + O(11^6) + (8*11^2 + 8*11^3 + 10*11^4 + 6*11^5 + 5*11^7 + O(11^8))*w + (7*11^3 + 11^4 + 8*11^5 + 9*11^7 + 10*11^8 + O(11^9))*w^2 + (10*11^4 + 7*11^5 + 7*11^6 + 3*11^7 + 8*11^8 + 4*11^9 + O(11^10))*w^3, O(11^7) + (8*11 + 3*11^2 + 6*11^3 + 11^4 + 6*11^5 + 11^6 + O(11^7))*w + (7*11^2 + 4*11^3 + 5*11^4 + 10*11^6 + 5*11^7 + O(11^8))*w^2 + (10*11^3 + 3*11^4 + 4*11^5 + 7*11^6 + 10*11^7 + 3*11^8 + O(11^9))*w^3, O(11^8) + (5*11^2 + 2*11^3 + 10*11^4 + 3*11^5 + 8*11^6 + 7*11^7 + O(11^8))*w + (6*11^2 + 3*11^3 + 5*11^4 + 11^5 + 5*11^6 + 9*11^7 + O(11^8))*w^2 + (5*11^3 + 6*11^4 + 5*11^5 + 2*11^6 + 9*11^7 + 6*11^8 + O(11^9))*w^3, O(11^9) + (6*11^3 + 11^5 + 8*11^6 + 9*11^7 + 2*11^8 + O(11^9))*w + (2*11^3 + 8*11^4 + 4*11^5 + 6*11^6 + 11^7 + 8*11^8 + O(11^9))*w^2 + (3*11^3 + 11^4 + 3*11^5 + 11^6 + 5*11^7 + 6*11^8 + O(11^9))*w^3, O(11^10) + (7*11^4 + 5*11^5 + 3*11^6 + 10*11^7 + 10*11^8 + 11^9 + O(11^10))*w + (10*11^5 + 9*11^6 + 6*11^7 + 6*11^8 + 10*11^9 + O(11^10))*w^2 + (7*11^4 + 11^5 + 7*11^6 + 5*11^7 + 6*11^8 + 2*11^9 + O(11^10))*w^3, O(11^11) + (7*11^5 + 3*11^6 + 8*11^8 + 5*11^9 + 8*11^10 + O(11^11))*w + (11^5 + 6*11^6 + 7*11^7 + 11^8 + 2*11^10 + O(11^11))*w^2 + (7*11^5 + 3*11^6 + 8*11^8 + 5*11^9 + 8*11^10 + O(11^11))*w^3] """ S = PolynomialRing(R, 'z') z = S.gens()[0] w = R.gen() aut = S(1) for n in range(1, var_prec): ## RP: I doubled the precision in "z" here to account for the loss of precision from plugging in arg in below ## This should be done better. LB = logpp_binom(n, p, ceil(p_prec * (p - 1) / (p - 2))) ta = ZZ(Qp(p, 2 * max(p_prec, var_prec)).teichmuller(a)) arg = (a / ta - 1) / p + c / (p * ta) * z aut += LB(arg).truncate(p_prec) * (w**n) aut *= (ta**k) #if not (chi is None): # aut *= chi(a) aut = aut.list() len_aut = len(aut) if len_aut == p_prec: return aut elif len_aut > p_prec: return aut[:p_prec] return aut + [R.zero_element()] * (p_prec - len_aut)
def next_height(self, N): """ Return the next permissable height greater than or equal to N for curves in self's family. WARNING: This function my return a height for which only singular curves exist. For example, in the short Weierstrass case height 0 is permissable, as the curve Y^2 = X^3 (uniquely) has height zero. INPUT: - ``N`` -- A non-negative integer OUTPUT: - A tuple consisting of three elements of the form (H, C, I) such that H: The smallest height >= N C: A list of coefficients for curves of this height I: A list of indices indicating which of the above coefficients achieve this height. The remaining values in C indicate the max absolute value those coefficients are allowed to obtain without altering the height. For example, the tuple (4, [1, 2], [1]) for the short Weierstrass case denotes set of curves with height 4; these are all of the form Y^2 = X^3 + A*X + B, where B=2 and A ranges between -1 and 1. EXAMPLES:: sage: from sage.schemes.elliptic_curves.curve_enumerator import * sage: C = CurveEnumerator(family="short_weierstrass") sage: C.next_height(4) (4, [1, 2], [1]) sage: C.next_height(60) (64, [4, 8], [0, 1]) sage: C.next_height(-100) Traceback (most recent call last): ... AssertionError: Input must be non-negative integer. """ assert N >= 0, "Input must be non-negative integer." coeffs = [ceil(N**(1 / n)) - 1 for n in self._pows] height = max( [coeffs[i]**(self._pows[i]) for i in range(self._num_coeffs)]) return self._height_increment(coeffs)
def automorphy_factor_vector(p, a, c, k, chi, p_prec, var_prec, R): """ EXAMPLES:: sage: from sage.modular.pollack_stevens.families_util import automorphy_factor_vector sage: automorphy_factor_vector(3, 1, 3, 0, None, 4, 3, PowerSeriesRing(ZpCA(3), 'w')) [1 + O(3^20), O(3^21) + (3 + 3^2 + 2*3^3 + O(3^21))*w + (3^2 + 2*3^3 + O(3^22))*w^2, O(3^22) + (3^2 + 2*3^3 + O(3^22))*w + (2*3^2 + O(3^22))*w^2, O(3^22) + (3^2 + 3^3 + O(3^22))*w + (2*3^3 + O(3^23))*w^2] sage: automorphy_factor_vector(3, 1, 3, 2, None, 4, 3, PowerSeriesRing(ZpCA(3), 'w')) [1 + O(3^20), O(3^21) + (3 + 3^2 + 2*3^3 + O(3^21))*w + (3^2 + 2*3^3 + O(3^22))*w^2, O(3^22) + (3^2 + 2*3^3 + O(3^22))*w + (2*3^2 + O(3^22))*w^2, O(3^22) + (3^2 + 3^3 + O(3^22))*w + (2*3^3 + O(3^23))*w^2] sage: p, a, c, k, chi, p_prec, var_prec, R = 11, -3, 11, 0, None, 6, 4, PowerSeriesRing(ZpCA(11, 6), 'w') sage: automorphy_factor_vector(p, a, c, k, chi, p_prec, var_prec, R) [1 + O(11^6) + (7*11^2 + 4*11^3 + 11^4 + 9*11^5 + 3*11^6 + 10*11^7 + O(11^8))*w + (2*11^3 + 2*11^5 + 2*11^6 + 6*11^7 + 8*11^8 + O(11^9))*w^2 + (6*11^4 + 4*11^5 + 5*11^6 + 6*11^7 + 4*11^9 + O(11^10))*w^3, O(11^7) + (7*11 + 11^2 + 2*11^3 + 3*11^4 + 4*11^5 + 3*11^6 + O(11^7))*w + (2*11^2 + 4*11^3 + 5*11^4 + 10*11^5 + 10*11^6 + 2*11^7 + O(11^8))*w^2 + (6*11^3 + 6*11^4 + 2*11^5 + 9*11^6 + 9*11^7 + 2*11^8 + O(11^9))*w^3, O(11^8) + (3*11^2 + 4*11^4 + 2*11^5 + 6*11^6 + 10*11^7 + O(11^8))*w + (8*11^2 + 7*11^3 + 8*11^4 + 8*11^5 + 11^6 + O(11^8))*w^2 + (3*11^3 + 9*11^4 + 10*11^5 + 5*11^6 + 10*11^7 + 11^8 + O(11^9))*w^3, O(11^9) + (8*11^3 + 3*11^4 + 3*11^5 + 7*11^6 + 2*11^7 + 6*11^8 + O(11^9))*w + (10*11^3 + 6*11^5 + 7*11^6 + O(11^9))*w^2 + (4*11^3 + 11^4 + 8*11^8 + O(11^9))*w^3, O(11^10) + (2*11^4 + 9*11^5 + 8*11^6 + 5*11^7 + 4*11^8 + 6*11^9 + O(11^10))*w + (6*11^5 + 3*11^6 + 5*11^7 + 7*11^8 + 4*11^9 + O(11^10))*w^2 + (2*11^4 + 8*11^6 + 2*11^7 + 9*11^8 + 7*11^9 + O(11^10))*w^3, O(11^11) + (2*11^5 + 10*11^6 + 10*11^7 + 10*11^8 + 10*11^9 + 10*11^10 + O(11^11))*w + (5*11^5 + 10*11^6 + 10*11^7 + 10*11^8 + 10*11^9 + 10*11^10 + O(11^11))*w^2 + (2*11^5 + 10*11^6 + 10*11^7 + 10*11^8 + 10*11^9 + 10*11^10 + O(11^11))*w^3] sage: k = 2 sage: automorphy_factor_vector(p, a, c, k, chi, p_prec, var_prec, R) [9 + 6*11^2 + 11^3 + 9*11^4 + 8*11^5 + O(11^6) + (8*11^2 + 8*11^3 + 10*11^4 + 6*11^5 + 5*11^7 + O(11^8))*w + (7*11^3 + 11^4 + 8*11^5 + 9*11^7 + 10*11^8 + O(11^9))*w^2 + (10*11^4 + 7*11^5 + 7*11^6 + 3*11^7 + 8*11^8 + 4*11^9 + O(11^10))*w^3, O(11^7) + (8*11 + 3*11^2 + 6*11^3 + 11^4 + 6*11^5 + 11^6 + O(11^7))*w + (7*11^2 + 4*11^3 + 5*11^4 + 10*11^6 + 5*11^7 + O(11^8))*w^2 + (10*11^3 + 3*11^4 + 4*11^5 + 7*11^6 + 10*11^7 + 3*11^8 + O(11^9))*w^3, O(11^8) + (5*11^2 + 2*11^3 + 10*11^4 + 3*11^5 + 8*11^6 + 7*11^7 + O(11^8))*w + (6*11^2 + 3*11^3 + 5*11^4 + 11^5 + 5*11^6 + 9*11^7 + O(11^8))*w^2 + (5*11^3 + 6*11^4 + 5*11^5 + 2*11^6 + 9*11^7 + 6*11^8 + O(11^9))*w^3, O(11^9) + (6*11^3 + 11^5 + 8*11^6 + 9*11^7 + 2*11^8 + O(11^9))*w + (2*11^3 + 8*11^4 + 4*11^5 + 6*11^6 + 11^7 + 8*11^8 + O(11^9))*w^2 + (3*11^3 + 11^4 + 3*11^5 + 11^6 + 5*11^7 + 6*11^8 + O(11^9))*w^3, O(11^10) + (7*11^4 + 5*11^5 + 3*11^6 + 10*11^7 + 10*11^8 + 11^9 + O(11^10))*w + (10*11^5 + 9*11^6 + 6*11^7 + 6*11^8 + 10*11^9 + O(11^10))*w^2 + (7*11^4 + 11^5 + 7*11^6 + 5*11^7 + 6*11^8 + 2*11^9 + O(11^10))*w^3, O(11^11) + (7*11^5 + 3*11^6 + 8*11^8 + 5*11^9 + 8*11^10 + O(11^11))*w + (11^5 + 6*11^6 + 7*11^7 + 11^8 + 2*11^10 + O(11^11))*w^2 + (7*11^5 + 3*11^6 + 8*11^8 + 5*11^9 + 8*11^10 + O(11^11))*w^3] """ S = PolynomialRing(R, 'z') z = S.gens()[0] w = R.gen() aut = S(1) for n in range(1, var_prec): ## RP: I doubled the precision in "z" here to account for the loss of precision from plugging in arg in below ## This should be done better. LB = logpp_binom(n, p, ceil(p_prec * (p-1)/(p-2))) ta = ZZ(Qp(p, 2 * max(p_prec, var_prec)).teichmuller(a)) arg = (a / ta - 1) / p + c / (p * ta) * z aut += LB(arg).truncate(p_prec) * (w ** n) aut *= (ta ** k) #if not (chi is None): # aut *= chi(a) aut = aut.list() len_aut = len(aut) if len_aut == p_prec: return aut elif len_aut > p_prec: return aut[:p_prec] return aut + [R.zero_element()] * (p_prec - len_aut)
def e_string_to_ground_state(self): r""" Returns a string of integers in the index set `(i_1,\ldots,i_k)` such that `e_{i_k} \cdots e_{i_1} self` is the ground state. INPUT: - ``self`` -- an element of a tensor product of Kirillov-Reshetikhin crystals. OUTPUT: a tuple of integers `(i_1,\ldots,i_k)` This method is only defined when ``self`` is an element of a tensor product of affine Kirillov-Reshetikhin crystals. It calculates a path from ``self`` to a ground state path using Demazure arrows as defined in Lemma 7.3 in [SchillingTingley2011]_. EXAMPLES:: sage: K = KirillovReshetikhinCrystal(['A',2,1],1,1) sage: T = TensorProductOfCrystals(K,K) sage: t = T.module_generators[0] sage: t.e_string_to_ground_state() (0, 2) sage: K = KirillovReshetikhinCrystal(['C',2,1],1,1) sage: T = TensorProductOfCrystals(K,K) sage: t = T.module_generators[0]; t [[[1]], [[1]]] sage: t.e_string_to_ground_state() (0,) sage: x=t.e(0) sage: x.e_string_to_ground_state() () sage: y=t.f_string([1,2,1,1,0]); y [[[2]], [[1]]] sage: y.e_string_to_ground_state() () """ assert self.parent().crystals[0].__module__ == 'sage.combinat.crystals.kirillov_reshetikhin', \ "All crystals in the tensor product need to be Kirillov-Reshetikhin crystals" I = self.index_set() I.remove(0) ell = max( ceil(K.s() / K.cartan_type().c()[K.r()]) for K in self.parent().crystals) for i in I: if self.epsilon(i) > 0: return (i, ) + (self.e(i)).e_string_to_ground_state() if self.epsilon(0) > ell: return (0, ) + (self.e(0)).e_string_to_ground_state() return ()
def exp(self,workprec=Infinity): from sage.functions.other import ceil if workprec is Infinity: raise ApproximationError("unable to compute exp to infinite precision") parent = self.parent() pow = parent(1) res = parent(1) val = self.valuation() iter = ceil(workprec / (val - 1/(parent._p-1))) + 1 for i in range(1,iter): pow *= self / parent(i) res += pow res = res.truncate(workprec) return res
def _normalisation_factor_zz(self, tau=3): r""" This function returns an approximation of `∑_{x ∈ \ZZ^n} \exp(-|x|_2^2/(2σ²))`, i.e. the normalisation factor such that the sum over all probabilities is 1 for `\ZZⁿ`. If this ``self.B`` is not an identity matrix over `\ZZ` a ``NotImplementedError`` is raised. INPUT: - ``tau`` -- all vectors `v` with `|v|_∞ ≤ τ·σ` are enumerated (default: ``3``). EXAMPLES:: sage: from sage.stats.distributions.discrete_gaussian_lattice import DiscreteGaussianDistributionLatticeSampler sage: n = 3; sigma = 1.0; m = 1000 sage: D = DiscreteGaussianDistributionLatticeSampler(ZZ^n, sigma) sage: f = D.f sage: c = D._normalisation_factor_zz(); c 15.528... sage: l = [D() for _ in range(m)] sage: v = vector(ZZ, n, (0, 0, 0)) sage: l.count(v), ZZ(round(m*f(v)/c)) (57, 64) """ if self.B != identity_matrix(ZZ, self.B.nrows()): raise NotImplementedError("This function is only implemented when B is an identity matrix.") f = self.f n = self.B.ncols() sigma = self._sigma return sum(f(x) for x in _iter_vectors(n, -ceil(tau * sigma), ceil(tau * sigma)))
def next_height(self,N): """ Return the next permissable height greater than or equal to N for curves in self's family. WARNING: This function my return a height for which only singular curves exist. For example, in the short Weierstrass case height 0 is permissable, as the curve Y^2 = X^3 (uniquely) has height zero. INPUT: - ``N`` -- A non-negative integer OUTPUT: - A tuple consisting of three elements of the form (H, C, I) such that H: The smallest height >= N C: A list of coefficients for curves of this height I: A list of indices indicating which of the above coefficients achieve this height. The remaining values in C indicate the max absolute value those coefficients are allowed to obtain without altering the height. For example, the tuple (4, [1, 2], [1]) for the short Weierstrass case denotes set of curves with height 4; these are all of the form Y^2 = X^3 + A*X + B, where B=2 and A ranges between -1 and 1. EXAMPLES:: sage: from sage.schemes.elliptic_curves.curve_enumerator import * sage: C = CurveEnumerator(family="short_weierstrass") sage: C.next_height(4) (4, [1, 2], [1]) sage: C.next_height(60) (64, [4, 8], [0, 1]) sage: C.next_height(-100) Traceback (most recent call last): ... AssertionError: Input must be non-negative integer. """ assert N>=0, "Input must be non-negative integer." coeffs = [ceil(N**(1/n))-1 for n in self._pows] height = max([coeffs[i]**(self._pows[i]) for i in range(self._num_coeffs)]) return self._height_increment(coeffs)
def e_string_to_ground_state(self): r""" Returns a string of integers in the index set `(i_1,\ldots,i_k)` such that `e_{i_k} \cdots e_{i_1} self` is the ground state. INPUT: - ``self`` -- an element of a tensor product of Kirillov-Reshetikhin crystals. OUTPUT: a tuple of integers `(i_1,\ldots,i_k)` This method is only defined when ``self`` is an element of a tensor product of affine Kirillov-Reshetikhin crystals. It calculates a path from ``self`` to a ground state path using Demazure arrows as defined in Lemma 7.3 in [SchillingTingley2011]_. EXAMPLES:: sage: K = KirillovReshetikhinCrystal(['A',2,1],1,1) sage: T = TensorProductOfCrystals(K,K) sage: t = T.module_generators[0] sage: t.e_string_to_ground_state() (0, 2) sage: K = KirillovReshetikhinCrystal(['C',2,1],1,1) sage: T = TensorProductOfCrystals(K,K) sage: t = T.module_generators[0]; t [[[1]], [[1]]] sage: t.e_string_to_ground_state() (0,) sage: x=t.e(0) sage: x.e_string_to_ground_state() () sage: y=t.f_string([1,2,1,1,0]); y [[[2]], [[1]]] sage: y.e_string_to_ground_state() () """ assert self.parent().crystals[0].__module__ == 'sage.combinat.crystals.kirillov_reshetikhin', \ "All crystals in the tensor product need to be Kirillov-Reshetikhin crystals" I = self.index_set() I.remove(0) ell = max(ceil(K.s()/K.cartan_type().c()[K.r()]) for K in self.parent().crystals) for i in I: if self.epsilon(i) > 0: return (i,) + (self.e(i)).e_string_to_ground_state() if self.epsilon(0) > ell: return (0,) + (self.e(0)).e_string_to_ground_state() return ()
def trunc(i): """ Truncates to the integer closer to zero EXAMPLES:: sage: from sage.combinat.crystals.tensor_product import trunc sage: trunc(-3/2), trunc(-1), trunc(-1/2), trunc(0), trunc(1/2), trunc(1), trunc(3/2) (-1, -1, 0, 0, 0, 1, 1) sage: isinstance(trunc(3/2), Integer) True """ if i >= 0: return floor(i) else: return ceil(i)
def calc_prec(self): if self.prec != None: return self.prec mp0 = MatrixPowerSexp(self.bsym,self.N-1,iprec=self.iprec,x0=self.x0sym) sexp_precision=RR(1)*log(abs(self.sexp_1(0.5)-mp0.sexp_1(0.5)),2.0) self.prec = (-sexp_precision).floor() print "sexp precision: " , self.prec cprec = self.prec+ceil(log(self.N)/log(2.0)) #self.eigenvalues = [ ev.n(cprec) for ev in self.eigenvalues ] #self.IM = self.IM.n(cprec) #self.b = self.bsym.n(cprec) return self
def trunc(i): """ Truncates to the integer closer to zero EXAMPLES:: sage: from sage.combinat.crystals.tensor_product import trunc sage: trunc(-3/2), trunc(-1), trunc(-1/2), trunc(0), trunc(1/2), trunc(1), trunc(3/2) (-1, -1, 0, 0, 0, 1, 1) sage: isinstance(trunc(3/2), Integer) True """ if i>= 0: return floor(i) else: return ceil(i)
def __iter__(self): r""" Iterate over all GL(2,Z)-reduced semi positive forms which are within the bounds of this precision. EXAMPLES:: sage: from sage.modular.siegel.siegel_modular_form_prec import SiegelModularFormPrecision sage: prec = SiegelModularFormPrecision(11) sage: for k in prec.__iter__(): print k (0, 0, 0) (0, 0, 1) (0, 0, 2) (1, 0, 1) (1, 0, 2) (1, 1, 1) (1, 1, 2) NOTE The forms are enumerated in lexicographic order. """ if self.__type == 'disc': bound = self.get_contents_bound_for_semi_definite_forms() for c in range(0, bound): yield (0,0,c) atop = isqrt(self.__prec // 3) if 3*atop*atop == self.__prec: atop -= 1 for a in range(1,atop + 1): for b in range(a+1): for c in range(a, ceil((b**2 + self.__prec)/(4*a))): yield (a,b,c) elif 'box' == self.__type: (am, bm, cm) = self.__prec for a in range(am): for b in range(min(bm,a+1)): for c in range(a, cm): yield (a,b,c) else: raise RuntimeError("Unexpected value of self.__type") raise StopIteration
def __iter__(self): r""" Iterate over all GL(2,Z)-reduced semi positive forms which are within the bounds of this precision. EXAMPLES:: sage: from sage.modular.siegel.siegel_modular_form_prec import SiegelModularFormPrecision sage: prec = SiegelModularFormPrecision(11) sage: for k in prec.__iter__(): print k (0, 0, 0) (0, 0, 1) (0, 0, 2) (1, 0, 1) (1, 0, 2) (1, 1, 1) (1, 1, 2) NOTE The forms are enumerated in lexicographic order. """ if self.__type == 'disc': bound = self.get_contents_bound_for_semi_definite_forms() for c in xrange(0, bound): yield (0,0,c) atop = isqrt(self.__prec // 3) if 3*atop*atop == self.__prec: atop -= 1 for a in xrange(1,atop + 1): for b in xrange(a+1): for c in xrange(a, ceil((b**2 + self.__prec)/(4*a))): yield (a,b,c) elif 'box' == self.__type: (am, bm, cm) = self.__prec for a in xrange(am): for b in xrange( min(bm,a+1)): for c in xrange(a, cm): yield (a,b,c) else: raise RuntimeError, "Unexpected value of self.__type" raise StopIteration
def newton_iteration(G, n): r"""Returns a truncated series `y = y(x)` satisfying .. math:: G(x,y(x)) \equiv 0 \bmod{x^r} where $r = \ceil{\log_2{n}}$. Based on the algorithm in [XXX]. Parameters ---------- G, x, y : polynomial A polynomial in `x` and `y`. n : int Requested degree of the series expansion. Notes ----- This algorithm returns the series up to order :math:`2^r > n`. Any choice of order below :math:`2^r` will return the same series. """ R = G.parent() x,y = R.gens() if n < 0: raise ValueError('Number of terms must be positive. (n=%d'%n) elif n == 0: return R(0) phi = G phiprime = phi.derivative(y) try: pi = R(x).polynomial(x) gi = R(0) si = R(phiprime(x,gi)).polynomial(x).inverse_mod(pi) except NotImplementedError: raise ValueError('Newton iteration for computing regular part of ' 'Puiseux expansion failed. Curve is most likely ' 'not regular at center.') r = ceil(log(n,2)) for i in range(r): gi,si,pi = newton_iteration_step(phi,phiprime,gi,si,pi) return R(gi)
def newton_iteration(G, n): r"""Returns a truncated series `y = y(x)` satisfying .. math:: G(x,y(x)) \equiv 0 \bmod{x^r} where $r = \ceil{\log_2{n}}$. Based on the algorithm in [XXX]. Parameters ---------- G, x, y : polynomial A polynomial in `x` and `y`. n : int Requested degree of the series expansion. Notes ----- This algorithm returns the series up to order :math:`2^r > n`. Any choice of order below :math:`2^r` will return the same series. """ R = G.parent() x, y = R.gens() if n < 0: raise ValueError('Number of terms must be positive. (n=%d' % n) elif n == 0: return R(0) phi = G phiprime = phi.derivative(y) try: pi = R(x).polynomial(x) gi = R(0) si = R(phiprime(x, gi)).polynomial(x).inverse_mod(pi) except NotImplementedError: raise ValueError('Newton iteration for computing regular part of ' 'Puiseux expansion failed. Curve is most likely ' 'not regular at center.') r = ceil(log(n, 2)) for i in range(r): gi, si, pi = newton_iteration_step(phi, phiprime, gi, si, pi) return R(gi)
def atkin_lehner_eigenvalue_numerical(self, t): (tau1, z, tau2) = t from sage.libs.mpmath import mp from sage.libs.mpmath.mp import exp, pi from sage.libs.mpmath.mp import j as i if not Integer(self.__level()).is_prime(): raise ValueError( "The Atkin Lehner involution is only unique if the level is a prime" ) precision = ParamodularFormD2Filter_trace(self.precision()) s = Sequence([tau1, z, tau2]) if not is_ComplexField(s): mp_precision = 30 else: mp_precision = ceil(3.33 * s.universe().precision()) mp.dps = mp_precision (tau1, z, tau2) = tuple(s) (tau1p, zp, tau2p) = (self.level() * tau1, self.level() * z, self.level() * tau2) (e_tau1, e_z, e_tau2) = (exp(2 * pi * i * tau1), exp(2 * pi * i * z), exp(2 * pi * i * tau2)) (e_tau1p, e_zp, e_tau2p) = (exp(2 * pi * i * tau1p), exp(2 * pi * i * zp), exp(2 * pi * i * tau2p)) self_value = s.universe().zero() trans_value = s.universe().zero() for k in precision: (a, b, c) = apply_GL_to_form(self._P1List()(k[1]), k[0]) self_value = self_value + self[k] * (e_tau1**a * e_z**b * e_tau2**c) trans_value = trans_value + self[k] * (e_tau1p**a * e_zp**b * e_tau2p**c) return trans_value / self_value
def split_xor(self, monomial_list, equal_zero): """ Split XOR chains into subchains. INPUT: - ``monomial_list`` - a list of monomials - ``equal_zero`` - is the constant coefficient zero? EXAMPLES:: sage: from sage.sat.converters.polybori import CNFEncoder sage: from sage.sat.solvers.dimacs import DIMACS sage: B.<a,b,c,d,e,f> = BooleanPolynomialRing() sage: ce = CNFEncoder(DIMACS(), B, cutting_number=3) sage: ce.split_xor([1,2,3,4,5,6], False) [[[1, 7], False], [[7, 2, 8], True], [[8, 3, 9], True], [[9, 4, 10], True], [[10, 5, 11], True], [[11, 6], True]] sage: ce = CNFEncoder(DIMACS(), B, cutting_number=4) sage: ce.split_xor([1,2,3,4,5,6], False) [[[1, 2, 7], False], [[7, 3, 4, 8], True], [[8, 5, 6], True]] sage: ce = CNFEncoder(DIMACS(), B, cutting_number=5) sage: ce.split_xor([1,2,3,4,5,6], False) [[[1, 2, 3, 7], False], [[7, 4, 5, 6], True]] """ c = self.cutting_number nm = len(monomial_list) step = ceil((c - 2) / ZZ(nm) * nm) M = [] new_variables = [] for j in range(0, nm, step): m = new_variables + monomial_list[j:j + step] if (j + step) < nm: new_variables = [self.var(None)] m += new_variables M.append([m, equal_zero]) equal_zero = True return M
def split_xor(self, monomial_list, equal_zero): """ Split XOR chains into subchains. INPUT: - ``monomial_list`` - a list of monomials - ``equal_zero`` - is the constant coefficient zero? EXAMPLE:: sage: from sage.sat.converters.polybori import CNFEncoder sage: from sage.sat.solvers.dimacs import DIMACS sage: B.<a,b,c,d,e,f> = BooleanPolynomialRing() sage: ce = CNFEncoder(DIMACS(), B, cutting_number=3) sage: ce.split_xor([1,2,3,4,5,6], False) [[[1, 7], False], [[7, 2, 8], True], [[8, 3, 9], True], [[9, 4, 10], True], [[10, 5, 11], True], [[11, 6], True]] sage: ce = CNFEncoder(DIMACS(), B, cutting_number=4) sage: ce.split_xor([1,2,3,4,5,6], False) [[[1, 2, 7], False], [[7, 3, 4, 8], True], [[8, 5, 6], True]] sage: ce = CNFEncoder(DIMACS(), B, cutting_number=5) sage: ce.split_xor([1,2,3,4,5,6], False) [[[1, 2, 3, 7], False], [[7, 4, 5, 6], True]] """ c = self.cutting_number nm = len(monomial_list) step = ceil((c-2)/ZZ(nm) * nm) M = [] new_variables = [] for j in range(0, nm, step): m = new_variables + monomial_list[j:j+step] if (j + step) < nm: new_variables = [self.var(None)] m += new_variables M.append([m, equal_zero]) equal_zero = True return M
def compute_series_truncations(f, alpha): r"""Computes Puiseux series at :math:`x=\alpha` with necessary terms. The Puiseux series expansions of :math:`f = f(x,y)` centered at :math:`\alpha` are computed up to the number of terms needed for the integral basis algorithm to be successful. The expansion degree bounds are determined by :func:`compute_expansion_bounds`. Parameters ---------- f : polynomial alpha : complex Returns ------- list : PuiseuxXSeries A list of Puiseux series expansions centered at :math:`x = \alpha` with enough terms to compute integral bases as SymPy expressions. """ # compute the parametric Puiseix series with the minimal number of terms # needed to distinguish them. pt = puiseux(f,alpha) px = [p for P in pt for p in P.xseries()] # compute the orders necessary for the integral basis algorithm. the orders # are on the Puiseux x-series (non-parametric) so scale by the ramification # index of each series N = compute_expansion_bounds(px) for i in range(len(N)): e = px[i].ramification_index N[i] = ceil(N[i]*e) order = max(N) + 1 for pti in pt: pti.extend(order=order) # recompute the corresponding x-series with the extened terms px = [p for P in pt for p in P.xseries()] return px
def compute_series_truncations(f, alpha): r"""Computes Puiseux series at :math:`x=\alpha` with necessary terms. The Puiseux series expansions of :math:`f = f(x,y)` centered at :math:`\alpha` are computed up to the number of terms needed for the integral basis algorithm to be successful. The expansion degree bounds are determined by :func:`compute_expansion_bounds`. Parameters ---------- f : polynomial alpha : complex Returns ------- list : PuiseuxXSeries A list of Puiseux series expansions centered at :math:`x = \alpha` with enough terms to compute integral bases as SymPy expressions. """ # compute the parametric Puiseix series with the minimal number of terms # needed to distinguish them. pt = puiseux(f, alpha) px = [p for P in pt for p in P.xseries()] # compute the orders necessary for the integral basis algorithm. the orders # are on the Puiseux x-series (non-parametric) so scale by the ramification # index of each series N = compute_expansion_bounds(px) for i in range(len(N)): e = px[i].ramification_index N[i] = ceil(N[i] * e) order = max(N) + 1 for pti in pt: pti.extend(order=order) # recompute the corresponding x-series with the extened terms px = [p for P in pt for p in P.xseries()] return px
def _N0_nodenominators(p, g, n): """ Return the necessary p-adic precision for the Frobenius matrix to deduce the characteristic polynomial of Frobenius using the Newton identities, using :meth:`charpoly_frobenius`, which assumes that the Frobenius matrix is integral, i.e., has no denominators. INPUT: - `p` - prime - `g` - genus - `n` - degree of residue field TESTS:: sage: sage.schemes.cyclic_covers.cycliccover_finite_field._N0_nodenominators(4999, 4, 5) 11 """ return max( ceil(log(2 * (2 * g) / ZZ(i), p) + (n * i) / ZZ(2)) for i in range(1, g + 1))
def numeric_converter(value, cur=None): """ Used for converting numeric values from Postgres to Python. INPUT: - ``value`` -- a string representing a decimal number. - ``cur`` -- a cursor, unused OUTPUT: - either a sage integer (if there is no decimal point) or a real number whose precision depends on the number of digits in value. """ if value is None: return None if '.' in value: # The following is a good guess for the bit-precision, # but we use LmfdbRealLiterals to ensure that our number # prints the same as we got it. prec = ceil(len(value)*3.322) return LmfdbRealLiteral(RealField(prec), value) else: return Integer(value)
def numeric_converter(value, cur=None): """ Used for converting numeric values from Postgres to Python. INPUT: - ``value`` -- a string representing a decimal number. - ``cur`` -- a cursor, unused OUTPUT: - either a sage integer (if there is no decimal point) or a real number whose precision depends on the number of digits in value. """ if value is None: return None if '.' in value: # The following is a good guess for the bit-precision, # but we use LmfdbRealLiterals to ensure that our number # prints the same as we got it. prec = ceil(len(value) * 3.322) return LmfdbRealLiteral(RealField(prec), value) else: return Integer(value)
def eisenstein_series(self, k, prec, allow_small_weight=False): r""" Compute the Eisenstein series. (i.e. the theta lift of a vector-valued Eisenstein series) INPUT: - ``k`` -- the weight (an even integer) - ``prec`` -- the output precision OUTPUT: OrthogonalModularFormLorentzian EXAMPLES:: sage: from weilrep import * sage: OrthogonalModularForms(diagonal_matrix([-2, 2, 2])).eisenstein_series(4, 5) 1 + 480*t + (240*x^-2 + (2880*r_0^-1 + 7680 + 2880*r_0)*x^-1 + (240*r_0^-2 + 7680*r_0^-1 + 18720 + 7680*r_0 + 240*r_0^2) + (2880*r_0^-1 + 7680 + 2880*r_0)*x + 240*x^2)*t^2 + ((480*r_0^-2 + 15360*r_0^-1 + 28800 + 15360*r_0 + 480*r_0^2)*x^-2 + (15360*r_0^-2 + 76800*r_0^-1 + 92160 + 76800*r_0 + 15360*r_0^2)*x^-1 + (28800*r_0^-2 + 92160*r_0^-1 + 134400 + 92160*r_0 + 28800*r_0^2) + (15360*r_0^-2 + 76800*r_0^-1 + 92160 + 76800*r_0 + 15360*r_0^2)*x + (480*r_0^-2 + 15360*r_0^-1 + 28800 + 15360*r_0 + 480*r_0^2)*x^2)*t^3 + (2160*x^-4 + (7680*r_0^-2 + 44160*r_0^-1 + 61440 + 44160*r_0 + 7680*r_0^2)*x^-3 + (7680*r_0^-3 + 112320*r_0^-2 + 207360*r_0^-1 + 312960 + 207360*r_0 + 112320*r_0^2 + 7680*r_0^3)*x^-2 + (44160*r_0^-3 + 207360*r_0^-2 + 380160*r_0^-1 + 430080 + 380160*r_0 + 207360*r_0^2 + 44160*r_0^3)*x^-1 + (2160*r_0^-4 + 61440*r_0^-3 + 312960*r_0^-2 + 430080*r_0^-1 + 656160 + 430080*r_0 + 312960*r_0^2 + 61440*r_0^3 + 2160*r_0^4) + (44160*r_0^-3 + 207360*r_0^-2 + 380160*r_0^-1 + 430080 + 380160*r_0 + 207360*r_0^2 + 44160*r_0^3)*x + (7680*r_0^-3 + 112320*r_0^-2 + 207360*r_0^-1 + 312960 + 207360*r_0 + 112320*r_0^2 + 7680*r_0^3)*x^2 + (7680*r_0^-2 + 44160*r_0^-1 + 61440 + 44160*r_0 + 7680*r_0^2)*x^3 + 2160*x^4)*t^4 + O(t^5) """ w = self.__weilrep try: return (-((k + k) / bernoulli(k)) * w.eisenstein_series( k + self.input_wt(), ceil(prec * prec / 4) + 1, allow_small_weight=allow_small_weight)).theta_lift(prec) except (TypeError, ValueError, ZeroDivisionError): raise ValueError('Invalid weight') from None
def _monomial_list(maxdeg, l, wy): r""" Returns a list of all non-negative integer pairs `(i,j)` such that ``i + wy * j < maxdeg`` and ``j \geq l``. INPUT: - ``maxdeg``, ``l``, ``wy`` -- integers. OUTPUT: - a list of pairs of integers. EXAMPLES:: sage: from sage.coding.guruswami_sudan.interpolation import _monomial_list sage: _monomial_list(8, 1, 3) [(0, 0), (1, 0), (2, 0), (3, 0), (4, 0), (5, 0), (6, 0), (7, 0), (0, 1), (1, 1), (2, 1), (3, 1), (4, 1)] """ monomials = [] for y in range(0, l+1): for x in range(0, ceil(maxdeg - y*wy)): monomials.append((x, y)) return monomials
def _monomial_list(maxdeg, l, wy): r""" Returns a list of all non-negative integer pairs `(i,j)` such that ``i + wy * j < maxdeg`` and ``j \geq l``. INPUT: - ``maxdeg``, ``l``, ``wy`` -- integers. OUTPUT: - a list of pairs of integers. EXAMPLES:: sage: from sage.coding.guruswami_sudan.interpolation import _monomial_list sage: _monomial_list(8, 1, 3) [(0, 0), (1, 0), (2, 0), (3, 0), (4, 0), (5, 0), (6, 0), (7, 0), (0, 1), (1, 1), (2, 1), (3, 1), (4, 1)] """ monomials = [] for y in range(0, l + 1): for x in range(0, ceil(maxdeg - y * wy)): monomials.append((x, y)) return monomials
def binpacking(items,maximum=1,k=None): r""" Solves the bin packing problem. The Bin Packing problem is the following : Given a list of items of weights `p_i` and a real value `K`, what is the least number of bins such that all the items can be put in the bins, while keeping sure that each bin contains a weight of at most `K` ? For more informations : http://en.wikipedia.org/wiki/Bin_packing_problem Two version of this problem are solved by this algorithm : * Is it possible to put the given items in `L` bins ? * What is the assignment of items using the least number of bins with the given list of items ? INPUT: - ``items`` -- A list of real values (the items' weight) - ``maximum`` -- The maximal size of a bin - ``k`` -- Number of bins - When set to an integer value, the function returns a partition of the items into `k` bins if possible, and raises an exception otherwise. - When set to ``None``, the function returns a partition of the items using the least number possible of bins. OUTPUT: A list of lists, each member corresponding to a box and containing the list of the weights inside it. If there is no solution, an exception is raised (this can only happen when ``k`` is specified or if ``maximum`` is less that the size of one item). EXAMPLES: Trying to find the minimum amount of boxes for 5 items of weights `1/5, 1/4, 2/3, 3/4, 5/7`:: sage: from sage.numerical.optimize import binpacking sage: values = [1/5, 1/3, 2/3, 3/4, 5/7] sage: bins = binpacking(values) sage: len(bins) 3 Checking the bins are of correct size :: sage: all([ sum(b)<= 1 for b in bins ]) True Checking every item is in a bin :: sage: b1, b2, b3 = bins sage: all([ (v in b1 or v in b2 or v in b3) for v in values ]) True One way to use only three boxes (which is best possible) is to put `1/5 + 3/4` together in a box, `1/3+2/3` in another, and `5/7` by itself in the third one. Of course, we can also check that there is no solution using only two boxes :: sage: from sage.numerical.optimize import binpacking sage: binpacking([0.2,0.3,0.8,0.9], k=2) Traceback (most recent call last): ... ValueError: This problem has no solution ! """ if max(items) > maximum: raise ValueError("This problem has no solution !") if k==None: from sage.functions.other import ceil k=ceil(sum(items)/maximum) while True: from sage.numerical.mip import MIPSolverException try: return binpacking(items,k=k,maximum=maximum) except MIPSolverException: k = k + 1 from sage.numerical.mip import MixedIntegerLinearProgram, MIPSolverException p=MixedIntegerLinearProgram() # Boolean variable indicating whether # the i th element belongs to box b box=p.new_variable(dim=2) # Each bin contains at most max for b in range(k): p.add_constraint(p.sum([items[i]*box[i][b] for i in range(len(items))]),max=maximum) # Each item is assigned exactly one bin for i in range(len(items)): p.add_constraint(p.sum([box[i][b] for b in range(k)]),min=1,max=1) p.set_objective(None) p.set_binary(box) try: p.solve() except MIPSolverException: raise ValueError("This problem has no solution !") box=p.get_values(box) boxes=[[] for i in range(k)] for b in range(k): boxes[b].extend([items[i] for i in range(len(items)) if round(box[i][b])==1]) return boxes
def f(x): if x == Infinity: return Infinity else: return max(x - workprec_shift, ceil(x/exp))
def sqrt(self,exp=2): from sage.functions.other import ceil precision = ceil(self._precision / exp) return ValuationBigOh(self.parent(), precision)
def heights(self,lowerbound,upperbound): """ Return a list of permissable curve heights in the specified range (bounds inclusive), and for each height the equation coefficients that produce curves of that height. WARNING: This function my return heights for which only singular curves exist. For example, in the short Weierstrass case height 0 is permissable, as the curve Y^2 = X^3 (uniquely) has height zero. INPUT: - ``lowerbound`` -- Lower bound for the height range; - ``upperbound`` -- Upper bound for the height range. Heights returned are up to and including both bounds. OUTPUT: - A list of tuples, each consisting of three elements of the form (H, C, I) such that H: The smallest height >= N C: A list of coefficients for curves of this height I: A list of indices indicating which of the above coefficients achieve this height. The remaining values in C indicate the max absolute value those coefficients are allowed to obtain without altering the height. For example, the tuple (4, [1, 2], [1]) for the short Weierstrass case denotes set of curves with height 4; these are all of the form Y^2 = X^3 + A*X + B, where B=2 and A ranges between -1 and 1. EXAMPLES:: sage: from sage.schemes.elliptic_curves.curve_enumerator import * sage: C = CurveEnumerator(family="short_weierstrass") sage: C.heights(100,150) [(100, [4, 10], [1]), (121, [4, 11], [1]), (125, [5, 11], [0]), (144, [5, 12], [1])] sage: C.heights(150,100) Traceback (most recent call last): ... AssertionError: Height upper bound must be greater than or equal to lower bound. sage: C.heights(-100,100) Traceback (most recent call last): ... AssertionError: Height lower bound must be non-negative. """ assert lowerbound>=0, "Height lower bound must be non-negative." assert upperbound>=lowerbound, "Height upper bound must be greater "\ +"than or equal to lower bound." coeffs = [ceil(lowerbound**(1/n))-1 for n in self._pows] height = max([coeffs[i]**(self._pows[i]) for i in range(self._num_coeffs)]) L = [] while height <= upperbound: C = self._height_increment(coeffs) if C[0]>upperbound: break else: height = C[0] coeffs = C[1] L.append(C) return L
def binpacking(items, maximum=1, k=None, solver=None, verbose=0): r""" Solve the bin packing problem. The Bin Packing problem is the following : Given a list of items of weights `p_i` and a real value `k`, what is the least number of bins such that all the items can be packed in the bins, while ensuring that the sum of the weights of the items packed in each bin is at most `k` ? For more informations, see :wikipedia:`Bin_packing_problem`. Two versions of this problem are solved by this algorithm : - Is it possible to put the given items in `k` bins ? - What is the assignment of items using the least number of bins with the given list of items ? INPUT: - ``items`` -- list or dict; either a list of real values (the items' weight), or a dictionary associating to each item its weight. - ``maximum`` -- (default: 1); the maximal size of a bin - ``k`` -- integer (default: ``None``); Number of bins - When set to an integer value, the function returns a partition of the items into `k` bins if possible, and raises an exception otherwise. - When set to ``None``, the function returns a partition of the items using the least possible number of bins. - ``solver`` -- (default: ``None``); Specify a Linear Program (LP) solver to be used. If set to ``None``, the default one is used. For more information on LP solvers and which default solver is used, see the method :meth:`~sage.numerical.mip.MixedIntegerLinearProgram.solve` of the class :class:`~sage.numerical.mip.MixedIntegerLinearProgram`. - ``verbose`` -- integer (default: ``0``); sets the level of verbosity. Set to 0 by default, which means quiet. OUTPUT: A list of lists, each member corresponding to a bin and containing either the list of the weights inside it when ``items`` is a list of items' weight, or the list of items inside it when ``items`` is a dictionary. If there is no solution, an exception is raised (this can only happen when ``k`` is specified or if ``maximum`` is less than the weight of one item). EXAMPLES: Trying to find the minimum amount of boxes for 5 items of weights `1/5, 1/4, 2/3, 3/4, 5/7`:: sage: from sage.numerical.optimize import binpacking sage: values = [1/5, 1/3, 2/3, 3/4, 5/7] sage: bins = binpacking(values) sage: len(bins) 3 Checking the bins are of correct size :: sage: all(sum(b) <= 1 for b in bins) True Checking every item is in a bin :: sage: b1, b2, b3 = bins sage: all((v in b1 or v in b2 or v in b3) for v in values) True And only in one bin :: sage: sum(len(b) for b in bins) == len(values) True One way to use only three boxes (which is best possible) is to put `1/5 + 3/4` together in a box, `1/3+2/3` in another, and `5/7` by itself in the third one. Of course, we can also check that there is no solution using only two boxes :: sage: from sage.numerical.optimize import binpacking sage: binpacking([0.2,0.3,0.8,0.9], k=2) Traceback (most recent call last): ... ValueError: this problem has no solution ! We can also provide a dictionary keyed by items and associating to each item its weight. Then, the bins contain the name of the items inside it :: sage: values = {'a':1/5, 'b':1/3, 'c':2/3, 'd':3/4, 'e':5/7} sage: bins = binpacking(values) sage: set(flatten(bins)) == set(values.keys()) True TESTS: Wrong type for parameter items:: sage: binpacking(set()) Traceback (most recent call last): ... TypeError: parameter items must be a list or a dictionary. """ if isinstance(items, list): weight = {i:w for i,w in enumerate(items)} elif isinstance(items, dict): weight = items else: raise TypeError("parameter items must be a list or a dictionary.") if max(weight.values()) > maximum: raise ValueError("this problem has no solution !") if k is None: from sage.functions.other import ceil k = ceil(sum(weight.values())/maximum) while True: from sage.numerical.mip import MIPSolverException try: return binpacking(items, k=k, maximum=maximum, solver=solver, verbose=verbose) except MIPSolverException: k = k + 1 from sage.numerical.mip import MixedIntegerLinearProgram, MIPSolverException p = MixedIntegerLinearProgram(solver=solver) # Boolean variable indicating whether the ith element belongs to box b box = p.new_variable(binary=True) # Capacity constraint of each bin for b in range(k): p.add_constraint(p.sum(weight[i]*box[i,b] for i in weight) <= maximum) # Each item is assigned exactly one bin for i in weight: p.add_constraint(p.sum(box[i,b] for b in range(k)) == 1) try: p.solve(log=verbose) except MIPSolverException: raise ValueError("this problem has no solution !") box = p.get_values(box) boxes = [[] for i in range(k)] for i,b in box: if box[i,b] == 1: boxes[b].append(weight[i] if isinstance(items, list) else i) return boxes
def genfiles_mpfr(integrator, driver, f, ics, initial, final, delta, parameters = None , parameter_values = None, dig = 20, tolrel=1e-16, tolabs=1e-16, output = ''): r""" Generate the needed files for the mpfr module of the tides library. INPUT: - ``integrator`` -- the name of the integrator file. - ``driver`` -- the name of the driver file. - ``f`` -- the function that determines the differential equation. - ``ics`` -- a list or tuple with the initial conditions. - ``initial`` -- the initial time for the integration. - ``final`` -- the final time for the integration. - ``delta`` -- the step of the output. - ``parameters`` -- the variables inside the function that should be treated as parameters. - ``parameter_values`` -- the values of the parameters for the particular initial value problem. - ``dig`` -- the number of digits of precission that will be used in the integration - ``tolrel`` -- the relative tolerance. - ``tolabs`` -- the absolute tolerance. - ``output`` -- the name of the file that the compiled integrator will write to This function creates two files, integrator and driver, that can be used later with the tides library ([TI]_). TESTS:: sage: from tempfile import mkdtemp sage: from sage.interfaces.tides import genfiles_mpfr sage: import os sage: import shutil sage: from sage.misc.temporary_file import tmp_dir sage: tempdir = tmp_dir() sage: intfile = os.path.join(tempdir, 'integrator.c') sage: drfile = os.path.join(tempdir ,'driver.c') sage: var('t,x,y,X,Y') (t, x, y, X, Y) sage: f(t,x,y,X,Y)=[X, Y, -x/(x^2+y^2)^(3/2), -y/(x^2+y^2)^(3/2)] sage: genfiles_mpfr(intfile, drfile, f, [1,0, 0, 0.2], 0, 10, 0.1, output = 'out', dig = 50) sage: fileint = open(intfile) sage: l = fileint.readlines() sage: fileint.close() sage: l[5] ' #include "mp_tides.h"\n' sage: l[15] '\tstatic int PARAMETERS = 0;\n' sage: l[25] '\t\tmpfrts_var_t(itd, link[5], var[3], i);\n' sage: l[30] '\t\tmpfrts_pow_t_c(itd, link[2], "-1.500000000000000000000000000000000000000000000000000", link[3], i);\n' sage: l[35] '\n' sage: l[36] ' }\n' sage: l[37] ' write_mp_solution();\n' sage: filedr = open(drfile) sage: l = filedr.readlines() sage: filedr.close() sage: l[6] ' #include "mpfr.h"\n' sage: l[16] ' int nfun = 0;\n' sage: l[26] '\tmpfr_set_str(v[2], "0.0000000000000000000000000000000000000000000000000000", 10, TIDES_RND);\n' sage: l[30] '\tmpfr_init2(tolabs, TIDES_PREC); \n' sage: l[34] '\tmpfr_init2(tini, TIDES_PREC); \n' sage: l[40] '\tmp_tides_delta(function_iteration, NULL, nvar, npar, nfun, v, p, tini, dt, nipt, tolrel, tolabs, NULL, fd);\n' sage: shutil.rmtree(tempdir) Check that ticket :trac:`17179` is fixed (handle expressions like `\\pi`):: sage: from sage.interfaces.tides import genfiles_mpfr sage: import os sage: import shutil sage: from sage.misc.temporary_file import tmp_dir sage: tempdir = tmp_dir() sage: intfile = os.path.join(tempdir, 'integrator.c') sage: drfile = os.path.join(tempdir ,'driver.c') sage: var('t,x,y,X,Y') (t, x, y, X, Y) sage: f(t,x,y,X,Y)=[X, Y, -x/(x^2+y^2)^(3/2), -y/(x^2+y^2)^(3/2)] sage: genfiles_mpfr(intfile, drfile, f, [pi, 0, 0, 0.2], 0, 10, 0.1, output = 'out', dig = 50) sage: fileint = open(intfile) sage: l = fileint.readlines() sage: fileint.close() sage: l[30] '\t\tmpfrts_pow_t_c(itd, link[2], "-1.500000000000000000000000000000000000000000000000000", link[3], i);\n' sage: filedr = open(drfile) sage: l = filedr.readlines() sage: filedr.close() sage: l[24] '\tmpfr_set_str(v[0], "3.141592653589793238462643383279502884197169399375101", 10, TIDES_RND);\n' sage: shutil.rmtree(tempdir) """ if parameters == None: parameters = [] if parameter_values == None: parameter_values = [] RR = RealField(ceil(dig * 3.3219)) l1, l2 = subexpressions_list(f, parameters) remove_repeated(l1, l2) remove_constants(l1, l2) l3=[] var = f[0].arguments() l0 = map(str, l1) lv = map(str, var) lp = map(str, parameters) for i in l2: oper = i[0] if oper in ["log", "exp", "sin", "cos", "atan", "asin", "acos"]: a = i[1] if str(a) in lv: l3.append((oper, 'var[{}]'.format(lv.index(str(a))))) elif str(a) in lp: l3.append((oper, 'par[{}]'.format(lp.index(str(a))))) else: l3.append((oper, 'link[{}]'.format(l0.index(str(a))))) else: a=i[1] b=i[2] sa = str(a) sb = str(b) consta=False constb=False if sa in lv: aa = 'var[{}]'.format(lv.index(sa)) elif sa in l0: aa = 'link[{}]'.format(l0.index(sa)) elif sa in lp: aa = 'par[{}]'.format(lp.index(sa)) else: consta=True aa = RR(a).str(truncate=False) if sb in lv: bb = 'var[{}]'.format(lv.index(sb)) elif sb in l0: bb = 'link[{}]'.format(l0.index(sb)) elif sb in lp: bb = 'par[{}]'.format(lp.index(sb)) else: constb=True bb = RR(b).str(truncate=False) if consta: oper += '_c' if not oper=='div': bb, aa = aa,bb elif constb: oper += '_c' l3.append((oper, aa, bb)) n = len(var) code = [] l0 = lv + l0 indices = [l0.index(str(i(*var)))+n for i in f] for i in range (1, n): aux = indices[i-1]-n if aux < n: code.append('mpfrts_var_t(itd, var[{}], var[{}], i);'.format(aux, i)) else: code.append('mpfrts_var_t(itd, link[{}], var[{}], i);'.format(aux-n, i)) for i in range(len(l3)): el = l3[i] string = "mpfrts_" if el[0] == 'add': string += 'add_t(itd, ' + el[1] + ', ' + el[2] + ', link[{}], i);'.format(i) elif el[0] == 'add_c': string += 'add_t_c(itd, "' + el[2] + '", ' + el[1] + ', link[{}], i);'.format(i) elif el[0] == 'mul': string += 'mul_t(itd, ' + el[1] + ', ' + el[2] + ', link[{}], i);'.format(i) elif el[0] == 'mul_c': string += 'mul_t_c(itd, "' + el[2] + '", ' + el[1] + ', link[{}], i);'.format(i) elif el[0] == 'pow_c': string += 'pow_t_c(itd, ' + el[1] + ', "' + el[2] + '", link[{}], i);'.format(i) elif el[0] == 'div': string += 'div_t(itd, ' + el[2] + ', ' + el[1] + ', link[{}], i);'.format(i) elif el[0] == 'div_c': string += 'div_t_cv(itd, "' + el[2] + '", ' + el[1] + ', link[{}], i);'.format(i) elif el[0] == 'log': string += 'log_t(itd, ' + el[1] + ', link[{}], i);'.format(i) elif el[0] == 'exp': string += 'exp_t(itd, ' + el[1] + ', link[{}], i);'.format(i) elif el[0] == 'sin': string += 'sin_t(itd, ' + el[1] + ', link[{}], link[{}], i);'.format(i+1, i) elif el[0] == 'cos': string += 'cos_t(itd, ' + el[1] + ', link[{}], link[{}], i);'.format(i-1, i) elif el[0] == 'atan': indarg = l0.index(str(1+l2[i][1]**2))-n string += 'atan_t(itd, ' + el[1] + ', link[{}], link[{}], i);'.format(indarg, i) elif el[0] == 'asin': indarg = l0.index(str(sqrt(1-l2[i][1]**2)))-n string += 'asin_t(itd, ' + el[1] + ', link[{}], link[{}], i);'.format(indarg, i) elif el[0] == 'acos': indarg = l0.index(str(-sqrt(1-l2[i][1]**2)))-n string += 'acos_t(itd, ' + el[1] + ', link[{}], link[{}], i);'.format(indarg, i) code.append(string) VAR = n-1 PAR = len(parameters) TT = len(code)+1-VAR outfile = open(integrator, 'a') auxstring = """ /**************************************************************************** This file has been created by Sage for its use with TIDES *****************************************************************************/ #include "mp_tides.h" long function_iteration(iteration_data *itd, mpfr_t t, mpfr_t v[], mpfr_t p[], int ORDER, mpfr_t *cvfd) { int i; int NCONST = 0; mpfr_t ct[0]; """ outfile.write(auxstring) outfile.write("\n\tstatic int VARIABLES = {};\n".format(VAR)) outfile.write("\tstatic int PARAMETERS = {};\n".format(PAR)) outfile.write("\tstatic int LINKS = {};\n".format(TT)) outfile.write('\tstatic int FUNCTIONS = 0;\n') outfile.write('\tstatic int POS_FUNCTIONS[1] = {0};\n') outfile.write('\n\tinitialize_mp_case();\n') outfile.write('\n\tfor(i=0; i<=ORDER; i++) {\n') for i in code: outfile.write('\t\t'+i+'\n') auxstring = """ } write_mp_solution(); clear_vpl(); clear_cts(); return NUM_COLUMNS; } """ outfile.write(auxstring) outfile.close() npar = len(parameter_values) outfile = open(driver, 'a') auxstring = """ /**************************************************************************** Driver file of the mp_tides program This file has been created automatically by Sage *****************************************************************************/ #include "mpfr.h" #include "mp_tides.h" long function_iteration(iteration_data *itd, mpfr_t t, mpfr_t v[], mpfr_t p[], int ORDER, mpfr_t *cvfd); int main() { int i; int nfun = 0; """ outfile.write(auxstring) outfile.write('\tset_precision_digits({});'.format(dig)) outfile.write('\n\tint npar = {};\n'.format(npar)) outfile.write('\tmpfr_t p[npar];\n') outfile.write('\tfor(i=0; i<npar; i++) mpfr_init2(p[i], TIDES_PREC);\n') for i in range(npar): outfile.write('\tmpfr_set_str(p[{}], "{}", 10, TIDES_RND);\n'.format(i,RR(parameter_values[i]).str(truncate=False))) outfile.write('\tint nvar = {};\n\tmpfr_t v[nvar];\n'.format(VAR)) outfile.write('\tfor(i=0; i<nvar; i++) mpfr_init2(v[i], TIDES_PREC);\n') for i in range(len(ics)): outfile.write('\tmpfr_set_str(v[{}], "{}", 10, TIDES_RND);\n'.format(i,RR(ics[i]).str(truncate=False))) outfile.write('\tmpfr_t tolrel, tolabs;\n') outfile.write('\tmpfr_init2(tolrel, TIDES_PREC); \n') outfile.write('\tmpfr_init2(tolabs, TIDES_PREC); \n') outfile.write('\tmpfr_set_str(tolrel, "{}", 10, TIDES_RND);\n'.format(RR(tolrel).str(truncate=False))) outfile.write('\tmpfr_set_str(tolabs, "{}", 10, TIDES_RND);\n'.format(RR(tolabs).str(truncate=False))) outfile.write('\tmpfr_t tini, dt; \n') outfile.write('\tmpfr_init2(tini, TIDES_PREC); \n') outfile.write('\tmpfr_init2(dt, TIDES_PREC); \n') outfile.write('\tmpfr_set_str(tini, "{}", 10, TIDES_RND);;\n'.format(RR(initial).str(truncate=False))) outfile.write('\tmpfr_set_str(dt, "{}", 10, TIDES_RND);\n'.format(RR(delta).str(truncate=False))) outfile.write('\tint nipt = {};\n'.format(floor((final-initial)/delta))) outfile.write('\tFILE* fd = fopen("' + output + '", "w");\n') outfile.write('\tmp_tides_delta(function_iteration, NULL, nvar, npar, nfun, v, p, tini, dt, nipt, tolrel, tolabs, NULL, fd);\n') outfile.write('\tfclose(fd);\n\treturn 0;\n}') outfile.close()
def plot(self, **kwds): r""" Plot the initial triangulation associated to ``self``. INPUT: - ``radius`` - the radius of the disk; by default the length of the circle is the number of vertices - ``points_color`` - the color of the vertices; default 'black' - ``points_size`` - the size of the vertices; default 7 - ``triangulation_color`` - the color of the arcs; default 'black' - ``triangulation_thickness`` - the thickness of the arcs; default 0.5 - ``shading_color`` - the color of the shading used on neuter intervals; default 'lightgray' - ``reflections_color`` - the color of the reflection axes; default 'blue' - ``reflections_thickness`` - the thickness of the reflection axes; default 1 EXAMPLES:: sage: Y = SineGordonYsystem('A',(6,4,3)) sage: Y.plot() # long time 2s Graphics object consisting of 219 graphics primitives """ # Set up plotting options if 'radius' in kwds: radius = kwds['radius'] else: radius = ceil(self.r() / (2 * pi)) points_opts = {} if 'points_color' in kwds: points_opts['color'] = kwds['points_color'] else: points_opts['color'] = 'black' if 'points_size' in kwds: points_opts['size'] = kwds['points_size'] else: points_opts['size'] = 7 triangulation_opts = {} if 'triangulation_color' in kwds: triangulation_opts['color'] = kwds['triangulation_color'] else: triangulation_opts['color'] = 'black' if 'triangulation_thickness' in kwds: triangulation_opts['thickness'] = kwds['triangulation_thickness'] else: triangulation_opts['thickness'] = 0.5 shading_opts = {} if 'shading_color' in kwds: shading_opts['color'] = kwds['shading_color'] else: shading_opts['color'] = 'lightgray' reflections_opts = {} if 'reflections_color' in kwds: reflections_opts['color'] = kwds['reflections_color'] else: reflections_opts['color'] = 'blue' if 'reflections_thickness' in kwds: reflections_opts['thickness'] = kwds['reflections_thickness'] else: reflections_opts['thickness'] = 1 # Helper functions def triangle(x): (a, b) = sorted(x[:2]) for p in self.vertices(): if (p, a) in self.triangulation() or (a, p) in self.triangulation(): if (p, b) in self.triangulation() or (b, p) in self.triangulation(): if p < a or p > b: return sorted((a, b, p)) def plot_arc(radius, p, q, **opts): # TODO: THIS SHOULD USE THE EXISTING PLOT OF ARCS! # plot the arc from p to q differently depending on the type of self p = ZZ(p) q = ZZ(q) t = var('t') if p - q in [1, -1]: def f(t): return (radius * cos(t), radius * sin(t)) (p, q) = sorted([p, q]) angle_p = vertex_to_angle(p) angle_q = vertex_to_angle(q) return parametric_plot(f(t), (t, angle_q, angle_p), **opts) if self.type() == 'A': angle_p = vertex_to_angle(p) angle_q = vertex_to_angle(q) if angle_p < angle_q: angle_p += 2 * pi internal_angle = angle_p - angle_q if internal_angle > pi: (angle_p, angle_q) = (angle_q + 2 * pi, angle_p) internal_angle = angle_p - angle_q angle_center = (angle_p+angle_q) / 2 hypotenuse = radius / cos(internal_angle / 2) radius_arc = hypotenuse * sin(internal_angle / 2) center = (hypotenuse * cos(angle_center), hypotenuse * sin(angle_center)) center_angle_p = angle_p + pi / 2 center_angle_q = angle_q + 3 * pi / 2 def f(t): return (radius_arc * cos(t) + center[0], radius_arc * sin(t) + center[1]) return parametric_plot(f(t), (t, center_angle_p, center_angle_q), **opts) elif self.type() == 'D': if p >= q: q += self.r() px = -2 * pi * p / self.r() + pi / 2 qx = -2 * pi * q / self.r() + pi / 2 arc_radius = (px - qx) / 2 arc_center = qx + arc_radius def f(t): return exp(I * ((cos(t) + I * sin(t)) * arc_radius + arc_center)) * radius return parametric_plot((real_part(f(t)), imag_part(f(t))), (t, 0, pi), **opts) def vertex_to_angle(v): # v==0 corresponds to pi/2 return -2 * pi * RR(v) / self.r() + 5 * pi / 2 # Begin plotting P = Graphics() # Shade neuter intervals neuter_intervals = [x for x in flatten(self.intervals()[:-1], max_level=1) if x[2] in ["NR", "NL"]] shaded_triangles = map(triangle, neuter_intervals) for (p, q, r) in shaded_triangles: points = list(plot_arc(radius, p, q)[0]) points += list(plot_arc(radius, q, r)[0]) points += list(reversed(plot_arc(radius, p, r)[0])) P += polygon2d(points, **shading_opts) # Disk boundary P += circle((0, 0), radius, **triangulation_opts) # Triangulation for (p, q) in self.triangulation(): P += plot_arc(radius, p, q, **triangulation_opts) if self.type() == 'D': s = radius / 50.0 P += polygon2d([(s, 5 * s), (s, 7 * s), (3 * s, 5 * s), (3 * s, 7 * s)], color=triangulation_opts['color']) P += bezier_path([[(0, 0), (2 * s, 1 * s), (2 * s, 6 * s)], [(2 * s, 10 * s), (s, 20 * s)], [(0, 30 * s), (0, radius)]], **triangulation_opts) P += bezier_path([[(0, 0), (-2 * s, 1 * s), (-2 * s, 6 * s)], [(-2 * s, 10 * s), (-s, 20 * s)], [(0, 30 * s), (0, radius)]], **triangulation_opts) P += point((0, 0), zorder=len(P), **points_opts) # Vertices v_points = {x: (radius * cos(vertex_to_angle(x)), radius * sin(vertex_to_angle(x))) for x in self.vertices()} for v in v_points: P += point(v_points[v], zorder=len(P), **points_opts) # Reflection axes P += line([(0, 1.1 * radius), (0, -1.1 * radius)], zorder=len(P), **reflections_opts) axis_angle = vertex_to_angle(-0.5 * (self.rk() + (1, 1))[1]) (a, b) = (1.1 * radius * cos(axis_angle), 1.1 * radius * sin(axis_angle)) P += line([(a, b), (-a, -b)], zorder=len(P), **reflections_opts) # Wrap up P.set_aspect_ratio(1) P.axes(False) return P
def energy_function(self): r""" Returns the energy function of `self`. INPUT: - ``self`` -- an element of a tensor product of perfect Kirillov-Reshetkhin crystals of the same level. OUTPUT: an integer The energy is only defined when ``self`` is an element of a tensor product of affine Kirillov-Reshetikhin crystals. In this implementation, it is assumed that ``self`` is an element of a tensor product of perfect crystals of the same level, see Theorem 7.5 in [SchillingTingley2011]_. REFERENCES: .. [SchillingTingley2011] A. Schilling, P. Tingley. Demazure crystals, Kirillov-Reshetikhin crystals, and the energy function. preprint arXiv:1104.2359 EXAMPLES:: sage: K = KirillovReshetikhinCrystal(['A',2,1],1,1) sage: T = TensorProductOfCrystals(K,K,K) sage: hw = [b for b in T if all(b.epsilon(i)==0 for i in [1,2])] sage: for b in hw: ... print b, b.energy_function() ... [[[1]], [[1]], [[1]]] 0 [[[1]], [[2]], [[1]]] 2 [[[2]], [[1]], [[1]]] 1 [[[3]], [[2]], [[1]]] 3 sage: K = KirillovReshetikhinCrystal(['C',2,1],1,2) sage: T = TensorProductOfCrystals(K,K) sage: hw = [b for b in T if all(b.epsilon(i)==0 for i in [1,2])] sage: for b in hw: # long time (5s on sage.math, 2011) ... print b, b.energy_function() ... [[], []] 4 [[], [[1, 1]]] 1 [[[1, 1]], []] 3 [[[1, 1]], [[1, 1]]] 0 [[[1, 2]], [[1, 1]]] 1 [[[2, 2]], [[1, 1]]] 2 [[[-1, -1]], [[1, 1]]] 2 [[[1, -1]], [[1, 1]]] 2 [[[2, -1]], [[1, 1]]] 2 sage: K = KirillovReshetikhinCrystal(['C',2,1],1,1) sage: T = TensorProductOfCrystals(K) sage: t = T.module_generators[0] sage: t.energy_function() Traceback (most recent call last): ... AssertionError: All crystals in the tensor product need to be perfect of the same level """ C = self.parent().crystals[0] ell = ceil(C.s()/C.cartan_type().c()[C.r()]) assert all(ell == K.s()/K.cartan_type().c()[K.r()] for K in self.parent().crystals), \ "All crystals in the tensor product need to be perfect of the same level" t = self.parent()(*[K.module_generator() for K in self.parent().crystals]) d = t.affine_grading() return d - self.affine_grading()
def guess(self, sequence, algorithm="sage"): """ Return the minimal CFiniteSequence that generates the sequence. Assume the first value has index 0. INPUT: - ``sequence`` -- list of integers - ``algorithm`` -- string - 'sage' - the default is to use Sage's matrix kernel function - 'pari' - use Pari's implementation of LLL - 'bm' - use Sage's Berlekamp-Massey algorithm OUTPUT: - a CFiniteSequence, or 0 if none could be found With the default kernel method, trailing zeroes are chopped off before a guessing attempt. This may reduce the data below the accepted length of six values. EXAMPLES:: sage: C.<x> = CFiniteSequences(QQ) sage: C.guess([1,2,4,8,16,32]) C-finite sequence, generated by 1/(-2*x + 1) sage: r = C.guess([1,2,3,4,5]) Traceback (most recent call last): ... ValueError: Sequence too short for guessing. With Berlekamp-Massey, if an odd number of values is given, the last one is dropped. So with an odd number of values the result may not generate the last value:: sage: r = C.guess([1,2,4,8,9], algorithm='bm'); r C-finite sequence, generated by 1/(-2*x + 1) sage: r[0:5] [1, 2, 4, 8, 16] """ S = self.polynomial_ring() if algorithm == "bm": from sage.matrix.berlekamp_massey import berlekamp_massey if len(sequence) < 2: raise ValueError("Sequence too short for guessing.") R = PowerSeriesRing(QQ, "x") if len(sequence) % 2 == 1: sequence = sequence[:-1] l = len(sequence) - 1 denominator = S(berlekamp_massey(sequence).list()[::-1]) numerator = R(S(sequence) * denominator, prec=l).truncate() return CFiniteSequence(numerator / denominator) elif algorithm == "pari": global _gp if len(sequence) < 6: raise ValueError("Sequence too short for guessing.") if _gp is None: _gp = Gp() _gp( "ggf(v)=local(l,m,p,q,B);l=length(v);B=floor(l/2);\ if(B<3,return(0));m=matrix(B,B,x,y,v[x-y+B+1]);\ q=qflll(m,4)[1];if(length(q)==0,return(0));\ p=sum(k=1,B,x^(k-1)*q[k,1]);\ q=Pol(Pol(vector(l,n,v[l-n+1]))*p+O(x^(B+1)));\ if(polcoeff(p,0)<0,q=-q;p=-p);q=q/p;p=Ser(q+O(x^(l+1)));\ for(m=1,l,if(polcoeff(p,m-1)!=v[m],return(0)));q" ) _gp.set("gf", sequence) _gp("gf=ggf(gf)") num = S(sage_eval(_gp.eval("Vec(numerator(gf))"))[::-1]) den = S(sage_eval(_gp.eval("Vec(denominator(gf))"))[::-1]) if num == 0: return 0 else: return CFiniteSequence(num / den) else: from sage.matrix.constructor import matrix from sage.functions.other import floor, ceil from numpy import trim_zeros l = len(sequence) while l > 0 and sequence[l - 1] == 0: l -= 1 sequence = sequence[:l] if l == 0: return 0 if l < 6: raise ValueError("Sequence too short for guessing.") hl = ceil(ZZ(l) / 2) A = matrix([sequence[k : k + hl] for k in range(hl)]) K = A.kernel() if K.dimension() == 0: return 0 R = PolynomialRing(QQ, "x") den = R(trim_zeros(K.basis()[-1].list()[::-1])) if den == 1: return 0 offset = next((i for i, x in enumerate(sequence) if x != 0), None) S = PowerSeriesRing(QQ, "x", default_prec=l - offset) num = S(R(sequence) * den).add_bigoh(floor(ZZ(l) / 2 + 1)).truncate() if num == 0 or sequence != S(num / den).list(): return 0 else: return CFiniteSequence(num / den)