예제 #1
0
    def _test_polymake_pickling(self, tester=None, other=None, **options):
        """
        Run tests to see that our polymake pickling/unpickling works.

        INPUT:

        - ``other`` -- a pickling polytope of ``self`` to be tested against

        TESTS::

            sage: polytopes.cross_polytope(3, backend='polymake')._test_polymake_pickling()  # optional - polymake
        """
        if tester is None:
            tester = self._tester(**options)

        if other is None:
            from sage.misc.persist import loads, dumps
            other = loads(dumps(self))

        tester.assertEqual(self, other)

        if not hasattr(self, '_polymake_polytope'):
            tester.assertFalse(hasattr(other, '_polymake_polytope'))
            return

        P = self._polymake_polytope
        P1 = other._polymake_polytope

        tester.assertEqual(P.F_VECTOR, P1.F_VECTOR)
        tester.assertEqual(P.VERTICES, P1.VERTICES)
        tester.assertEqual(P.LINEALITY_SPACE, P1.LINEALITY_SPACE)
        tester.assertEqual(P.FACETS, P1.FACETS)
        tester.assertEqual(P.AFFINE_HULL, P1.AFFINE_HULL)
예제 #2
0
        def load_element(self, str):
            """
            Create element from its string representation.
            The default implementation uses 'loads' and is very inefficient.
            """
            import base64

            return loads(base64.b64decode(str))
예제 #3
0
    def __init__(self, algebra, gens, subalgebra, unstable, bbox, facade):
        self._algebra = algebra
        self._unstable = unstable
        self._amil = algebra.an_element().change_basis("milnor").parent()
        self._subalg = subalgebra
        self._prime = self._algebra.characteristic()
        self._emask = 0
        self._trunc = bbox
        self._rmask = []
        if facade is None:
            print("WARNING: you should supply a reasonable facade")
            facade = self
        if subalgebra is not None:
            assert subalgebra._truncation_type == 0
            # FIXME
            if not algebra.is_generic():
                e, r = (), subalgebra._profile
            else:
                r, e = subalgebra._profile
            msk = 1
            for i in e:
                if 2 == i:
                    self._emask = self._emask | msk
                msk = msk << 1
            self._rmask = r
        self._gens = gens
        if hasattr(gens, "dump_element"):
            self._dumpfuncs = gens.dump_element, gens.load_element
        else:
            import base64
            from sage.misc.persist import dumps, loads

            self._dumpfuncs = lambda x: base64.b64encode(dumps(
                x)), lambda x: loads(base64.b64decode(x))
        if self.is_finite():
            cat = FiniteEnumeratedSets()
            if not self._algebra.is_generic():
                emax = 0
            else:
                assert self._algebra._has_nontrivial_profile()
                rp, ep = self._profile
                emax = len(k for k in ep if k == 2)
            self._algbox = region(tmin=0,
                                  tmax=self._algebra.top_class().degree(),
                                  emin=0,
                                  emax=emax,
                                  s=0)
        else:
            cat = InfiniteEnumeratedSets()
            self._algbox = region(tmin=0, emin=0, s=0)
        Parent.__init__(self, facade=facade, category=(cat, YacopGradedSets()))
예제 #4
0
    def _test_pickling(self, **options):
        """
        Checks that the instance in self can be pickled and unpickled properly.

        EXAMPLES::

            sage: from sage.misc.sage_unittest import PythonObjectWithTests
            sage: PythonObjectWithTests(int(1))._test_pickling()

        .. SEEALSO::

            :func:`dumps`, :func:`loads`
        """
        tester = instance_tester(self, **options)
        from sage.misc.persist import loads, dumps
        tester.assertEqual(loads(dumps(self._instance)), self._instance)
예제 #5
0
    def __call__(self, f, inputs):
        """
        Parallel iterator using ``fork()``.

        INPUT:

        - ``f`` -- a function (or more general, any callable)

        - ``inputs`` -- a list of pairs ``(args, kwds)`` to be used as
          arguments to ``f``, where ``args`` is a tuple and ``kwds`` is
          a dictionary.

        OUTPUT:

        EXAMPLES::

            sage: F = sage.parallel.use_fork.p_iter_fork(2,3)
            sage: sorted(list( F( (lambda x: x^2), [([10],{}), ([20],{})])))
            [(([10], {}), 100), (([20], {}), 400)]
            sage: sorted(list( F( (lambda x, y: x^2+y), [([10],{'y':1}), ([20],{'y':2})])))
            [(([10], {'y': 1}), 101), (([20], {'y': 2}), 402)]

        TESTS:

        The output of functions decorated with :func:`parallel` is read
        as a pickle by the parent process. We intentionally break the
        unpickling and demonstrate that this failure is handled
        gracefully (the exception is put in the list instead of the
        answer)::

            sage: Polygen = parallel(polygen)
            sage: list(Polygen([QQ]))
            [(((Rational Field,), {}), x)]
            sage: from sage.misc.persist import unpickle_override, register_unpickle_override
            sage: register_unpickle_override('sage.rings.polynomial.polynomial_rational_flint', 'Polynomial_rational_flint', Integer)
            sage: L = list(Polygen([QQ]))
            sage: L
            [(((Rational Field,), {}),
              'INVALID DATA __init__() takes at most 2 positional arguments (4 given)')]

        Fix the unpickling::

            sage: del unpickle_override[('sage.rings.polynomial.polynomial_rational_flint', 'Polynomial_rational_flint')]
            sage: list(Polygen([QQ,QQ]))
            [(((Rational Field,), {}), x), (((Rational Field,), {}), x)]
        """
        n = self.ncpus
        v = list(inputs)
        import os
        import sys
        import signal
        from sage.misc.persist import loads
        from sage.misc.temporary_file import tmp_dir
        dir = tmp_dir()
        timeout = self.timeout

        workers = {}
        try:
            while v or workers:
                # Spawn up to n subprocesses
                while v and len(workers) < n:
                    v0 = v.pop(0)  # Input value for the next subprocess
                    with ContainChildren():
                        pid = os.fork()
                        # The way fork works is that pid returns the
                        # nonzero pid of the subprocess for the master
                        # process and returns 0 for the subprocess.
                        if not pid:
                            # This is the subprocess.
                            self._subprocess(f, dir, *v0)

                    workers[pid] = WorkerData(v0)

                if len(workers) > 0:
                    # Now wait for one subprocess to finish and report the result.
                    # However, wait at most the time since the oldest process started.
                    T = walltime()
                    if timeout:
                        oldest = min(W.starttime for W in workers.values())
                        alarm(max(timeout - (T - oldest), 0.1))

                    try:
                        pid = os.wait()[0]
                        cancel_alarm()
                        W = workers.pop(pid)
                    except AlarmInterrupt:
                        # Kill workers that are too old
                        for pid, W in workers.items():
                            if T - W.starttime > timeout:
                                if self.verbose:
                                    print(
                                        "Killing subprocess %s with input %s which took too long"
                                        % (pid, W.input))
                                os.kill(pid, signal.SIGKILL)
                                W.failure = " (timed out)"
                    except KeyError:
                        # Some other process exited, not our problem...
                        pass
                    else:
                        # collect data from process that successfully terminated
                        sobj = os.path.join(dir, '%s.sobj' % pid)
                        try:
                            with open(sobj, "rb") as file:
                                data = file.read()
                        except IOError:
                            answer = "NO DATA" + W.failure
                        else:
                            os.unlink(sobj)
                            try:
                                answer = loads(data, compress=False)
                            except Exception as E:
                                answer = "INVALID DATA {}".format(E)

                        out = os.path.join(dir, '%s.out' % pid)
                        try:
                            with open(out) as file:
                                sys.stdout.write(file.read())
                            os.unlink(out)
                        except IOError:
                            pass

                        yield (W.input, answer)
        finally:
            # Send SIGKILL signal to workers that are left.
            if workers:
                if self.verbose:
                    print("Killing any remaining workers...")
                sys.stdout.flush()
                for pid in workers:
                    try:
                        os.kill(pid, signal.SIGKILL)
                    except OSError:
                        # If kill() failed, it is most likely because
                        # the process already exited.
                        pass
                    else:
                        try:
                            os.waitpid(pid, 0)
                        except OSError as msg:
                            if self.verbose:
                                print(msg)

            # Clean up all temporary files.
            rmtree(dir)