def dual_cone_as_polyhedron(rays, strict=False): """ Compute the polyhedron consisting of all y such that r * y >= 0 (or r * y > 0 if strict=True) for r in rays. """ if not rays: raise TypeError('Need at least one ray') c = Integer(-1) if strict else ZZ.zero() return Polyhedron(ieqs=[[c] + list(v) for v in rays], base_ring=QQ)
def __init__(self, E, a=None): self._resolution_graph = E n = E.number_of_components() if a is None: # Z is initialized as the zero cycle a = [ZZ.zero() for i in range(n)] else: assert len(a) == n, "length of a must match number of components" self._multiplicities = a
def degree(self, D): r""" Return the degree of the divisor ``D``. Note that the degree of `D` is defined relative to the field of constants of the curve. """ deg = ZZ.zero() for P, m in D: deg += m*P.degree() return deg
def simplify(self): """ Simplify a toric datum. We do the following: (1) Move pseudo-monomial divisibility conditions into the polyhedron. (2) Perform support reduction using the polyhedron. (3) Scan for divisibility relations. """ try: if self._is_simple: return self except AttributeError: pass # T is the current toric datum T = self cnt = 0 while True: cnt += 1 if cnt > 2: logger.info('Simplification entered round %d' % cnt) # e.g. triggered for Perm(123) logger.debug('Looping. Current datum:\n%s' % T) # T = T.divide_out_variables() changed = False polyhedron = T.polyhedron new_cc, new_initials = [], [] # Step 1: Move pseudo-monomial conditions into the polyhedron. # We say that a condition is pseudo-monomial if it's initial form is monomial. idx_mon = [ i for i in range(len(T.cc)) if (T.initials[i] is not None) and T.initials[i].is_monomial() ] idx_nonmon = [i for i in range(len(T.cc)) if i not in idx_mon] logger.debug('Number of conditions: %d (pseudo-monomials: %d)' % (len(T.cc), len(idx_mon))) if len(idx_mon): logger.debug('Shrinking polyhedron.') polyhedron &= dual_cone_as_polyhedron([ monomial_log(T.initials[i]) - monomial_log(T.lhs[i]) for i in idx_mon ]) # NOTE: we don't set 'changed = True' at this point. No need. # Step 2: # For each non-monomial condition, remove terms divisible by the # LHS within the polyhedron cone = conify_polyhedron(polyhedron) for i in idx_nonmon: # or 'range(len(T.cc))', to be safe lhs, rhs = T.cc[i] init = T.initials[i] g = gcd(lhs, rhs) lhs, rhs = lhs // g, rhs // g if init is not None: init //= g # Find redundant terms of 'rhs'. mon, coeff = rhs.monomials(), rhs.coefficients() idx_red = [ j for j in range(len(mon)) if is_contained_in_dual( Cone([monomial_log(mon[j]) - monomial_log(lhs)], lattice=ZZ**T.ambient_dim), cone) ] # Case a: No term of 'rhs' is redundant if not idx_red: new_cc.append((lhs, rhs)) new_initials.append(init) continue changed = True # Case b: (lhs || rhs) follows from the monomial conditions. if len(idx_red) == len(mon): logger.debug('Redundant condition: %s || %s' % (lhs, rhs)) continue # Case c: lhs || rhs can be simplified but not removed. logger.debug('Condition %s || %s becomes...') red = sum(coeff[k] * mon[k] for k in idx_red) # = redundant form of 'rhs' rhs -= red g = gcd(lhs, rhs) lhs, rhs = lhs // g, rhs // g if not (init is None): # NOTE: # If init != None and some term of init is redundant, then the # entire condition 'lhs || rhs' has to be redundant. if subpolynomial_meet(init, red) != Integer(0): raise RuntimeError( 'Impossible redundancy. This should never happen.') init = (init - subpolynomial_meet(init, red)) // g init = None if init == ZZ.zero() else init # Sanity check. if not (is_subpolynomial(rhs, init)): raise RuntimeError('I messed up an initial form') logger.debug('... %s || %s' % (lhs, rhs)) new_cc.append((lhs, rhs)) new_initials.append(init) T = ToricDatum(ring=T.ring, integrand=T.integrand, cc=new_cc, initials=new_initials, polyhedron=polyhedron, depth=self._depth) if not changed: break T = T._purge_multiples() T._is_simple = True return T