Esempio n. 1
0
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)
Esempio n. 2
0
 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
Esempio n. 3
0
    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
Esempio n. 4
0
    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