Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bug when converting a Sage polyhedron into Polymake pexpect #24152

Closed
simon-king-jena opened this issue Nov 3, 2017 · 20 comments
Closed

Bug when converting a Sage polyhedron into Polymake pexpect #24152

simon-king-jena opened this issue Nov 3, 2017 · 20 comments

Comments

@simon-king-jena
Copy link
Member

Conversion of a Sage polyhedron into Polymake fails in the first attempt, but succeeds in the second attempt. I've put the example into the first comment rather than in the ticket description.

The fix is to install the File::Slurp module into perl5. This ticket updates the information about prerequisites (and how to install them) in build/pkg/polymake/SPKG.txt.

CC: @videlec @mkoeppe @jplab

Component: interfaces: optional

Keywords: polymake, IMA-PolyGeom

Author: Matthias Koeppe

Branch/Commit: a924632

Reviewer: Jean-Philippe Labbé

Issue created by migration from https://trac.sagemath.org/ticket/24152

@simon-king-jena
Copy link
Member Author

comment:1
sage: eqns = [
....: [-100, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
....: [0, -1, 0, 0, 0, 0, -1, 1, 1, 0, 0, 0, 0],
....: [0, 0, 0, 0, 0, -1, 0, 0, 1, 1, -1, 0, 0],
....: [0, 0, 0, 0, -1, 0, -1, 1, 0, 1, 0, 0, 0],
....: [0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 1, 1, -1],
....: [0, 0, -1, -1, 0, 1, 0, 0, 0, 0, 0, 1, 0],
....: [0, -1, 1, 0, -1, 0, 0, 0, 0, 0, 0, 0, 1],
....: [0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0],
....: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0]
....: ]
sage: ieqs = [
....: [-1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
....: [-1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
....: [-1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
....: [-1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0],
....: [-1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0],
....: [-1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0],
....: [-1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0],
....: [0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0],
....: [-1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0],
....: [-1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0],
....: [-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0],
....: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0],
....: [-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]
....: ]
sage: P = Polyhedron(eqns = eqns, ieqs=ieqs)
sage: PP = polymake(P)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-4-a1de8e99de0e> in <module>()
----> 1 PP = polymake(P)

/home/king/Sage/git/sage/local/lib/python2.7/site-packages/sage/interfaces/interface.pyc in __call__(self, x, name)
    282             return cls(self, x, name=name)
    283         try:
--> 284             return self._coerce_from_special_method(x)
    285         except TypeError:
    286             raise

/home/king/Sage/git/sage/local/lib/python2.7/site-packages/sage/interfaces/interface.pyc in _coerce_from_special_method(self, x)
    308             s = '_gp_'
    309         try:
--> 310             return (x.__getattribute__(s))(self)
    311         except AttributeError:
    312             return self(x._interface_init_())

/home/king/Sage/git/sage/src/sage/structure/sage_object.pyx in sage.structure.sage_object.SageObject._polymake_ (build/cythonized/sage/structure/sage_object.c:11355)()
    937             import sage.interfaces.polymake
    938             G = sage.interfaces.polymake.polymake
--> 939         return self._interface_(G)
    940 
    941     def _polymake_init_(self):

/home/king/Sage/git/sage/src/sage/structure/sage_object.pyx in sage.structure.sage_object.SageObject._interface_ (build/cythonized/sage/structure/sage_object.c:6528)()
    735         init_func = getattr(self, '_%s_init_' % nm, None)
    736         if init_func is not None:
--> 737             s = init_func()
    738         else:
    739             try:

/home/king/Sage/git/sage/local/lib/python2.7/site-packages/sage/geometry/polyhedron/base.pyc in _polymake_init_(self)
   6204         """
   6205         from sage.interfaces.polymake import polymake
-> 6206         polymake_field = polymake(self.base_ring().fraction_field())
   6207         polymake_class = "Polytope<{}>".format(polymake_field)
   6208         if self.is_empty():

/home/king/Sage/git/sage/local/lib/python2.7/site-packages/sage/interfaces/interface.pyc in __call__(self, x, name)
    282             return cls(self, x, name=name)
    283         try:
--> 284             return self._coerce_from_special_method(x)
    285         except TypeError:
    286             raise

/home/king/Sage/git/sage/local/lib/python2.7/site-packages/sage/interfaces/interface.pyc in _coerce_from_special_method(self, x)
    308             s = '_gp_'
    309         try:
--> 310             return (x.__getattribute__(s))(self)
    311         except AttributeError:
    312             return self(x._interface_init_())

/home/king/Sage/git/sage/src/sage/structure/sage_object.pyx in sage.structure.sage_object.SageObject._polymake_ (build/cythonized/sage/structure/sage_object.c:11355)()
    937             import sage.interfaces.polymake
    938             G = sage.interfaces.polymake.polymake
--> 939         return self._interface_(G)
    940 
    941     def _polymake_init_(self):

/home/king/Sage/git/sage/src/sage/structure/sage_object.pyx in sage.structure.sage_object.SageObject._interface_ (build/cythonized/sage/structure/sage_object.c:6726)()
    741             except Exception:
    742                 raise NotImplementedError("coercion of object %s to %s not implemented:\n%s\n%s" % (repr(self), I))
--> 743         X = I(s)
    744         if c:
    745             try:

/home/king/Sage/git/sage/local/lib/python2.7/site-packages/sage/interfaces/interface.pyc in __call__(self, x, name)
    280 
    281         if isinstance(x, string_types):
--> 282             return cls(self, x, name=name)
    283         try:
    284             return self._coerce_from_special_method(x)

/home/king/Sage/git/sage/local/lib/python2.7/site-packages/sage/interfaces/expect.pyc in __init__(self, parent, value, is_name, name)
   1389             except (RuntimeError, ValueError) as x:
   1390                 self._session_number = -1
-> 1391                 raise_(TypeError, x, sys.exc_info()[2])
   1392             except BaseException:
   1393                 self._session_number = -1

/home/king/Sage/git/sage/local/lib/python2.7/site-packages/sage/interfaces/expect.pyc in __init__(self, parent, value, is_name, name)
   1384         else:
   1385             try:
-> 1386                 self._name = parent._create(value, name=name)
   1387             # Convert ValueError and RuntimeError to TypeError for
   1388             # coercion to work properly.

/home/king/Sage/git/sage/local/lib/python2.7/site-packages/sage/interfaces/polymake.pyc in _create(self, value, name)
    617         """
    618         name = self._next_var_name() if name is None else name
--> 619         self.set(name, value)
    620         # If value is a list, then @name is now equal to that list.
    621         # Otherwise, value is obtained by $name[0]. So, we modify

/home/king/Sage/git/sage/local/lib/python2.7/site-packages/sage/interfaces/polymake.pyc in set(self, var, value)
    706             value = value.strip().rstrip(';').strip()
    707         cmd = '@%s%s(%s);'%(var,self._assign_symbol(), value)
--> 708         self.eval(cmd)
    709 
    710     def get(self, cmd):

/home/king/Sage/git/sage/local/lib/python2.7/site-packages/sage/interfaces/expect.pyc in eval(self, code, strip, synchronize, locals, allow_use_file, split_lines, **kwds)
   1298                 elif split_lines:
   1299                     return '\n'.join([self._eval_line(L, allow_use_file=allow_use_file, **kwds)
-> 1300                                         for L in code.split('\n') if L != ''])
   1301                 else:
   1302                     return self._eval_line(code, allow_use_file=allow_use_file, **kwds)

/home/king/Sage/git/sage/local/lib/python2.7/site-packages/sage/interfaces/polymake.pyc in _eval_line(self, line, allow_use_file, wait_for_prompt, restart_if_needed, **kwds)
    891         try:
    892             if not self.is_running():
--> 893                 self._start()
    894             E = self._expect
    895             try:

/home/king/Sage/git/sage/local/lib/python2.7/site-packages/sage/interfaces/polymake.pyc in _start(self, alt_message)
    357         self.eval('use Scalar::Util qw(reftype);')
    358         self.eval('use Scalar::Util qw(blessed);')
--> 359         self.eval('use File::Slurp;')
    360 
    361     def _quit_string(self):

/home/king/Sage/git/sage/local/lib/python2.7/site-packages/sage/interfaces/expect.pyc in eval(self, code, strip, synchronize, locals, allow_use_file, split_lines, **kwds)
   1298                 elif split_lines:
   1299                     return '\n'.join([self._eval_line(L, allow_use_file=allow_use_file, **kwds)
-> 1300                                         for L in code.split('\n') if L != ''])
   1301                 else:
   1302                     return self._eval_line(code, allow_use_file=allow_use_file, **kwds)

/home/king/Sage/git/sage/local/lib/python2.7/site-packages/sage/interfaces/polymake.pyc in _eval_line(self, line, allow_use_file, wait_for_prompt, restart_if_needed, **kwds)
   1057             warnings.warn(w, RuntimeWarning)
   1058         for e in p_errors:
-> 1059             raise PolymakeError(e)
   1060         return out
   1061 

TypeError: Can't locate File/Slurp.pm in @INC (you may need to install the File::Slurp module) (@INC contains: CODE(0x316ca38) /home/king/Sage/git/sage/local/share/polymake/perllib /home/king/Sage/git/sage/local/lib/polymake/perlx/5.22.1/x86_64-linux-gnu-thread-multi /home/king/Sage/git/sage/local/lib/polymake/perlx/5.22.1 /home/king/Sage/git/sage/local/lib/polymake/perlx /home/king/Sage/git/sage/local/lib/perl5/x86_64-linux-gnu-thread-multi /home/king/Sage/git/sage/local/lib/perl5 /etc/perl /usr/local/lib/x86_64-linux-gnu/perl/5.22.1 /usr/local/share/perl/5.22.1 /usr/lib/x86_64-linux-gnu/perl5/5.22 /usr/share/perl5 /usr/lib/x86_64-linux-gnu/perl/5.22 /usr/share/perl/5.22 /usr/local/lib/site_perl /usr/lib/x86_64-linux-gnu/perl-base .) at input line 1.
BEGIN failed--compilation aborted at input line 1.
sage: PP = polymake(P)
sage: PP.VERTICES
1 1 1 46/3 1 49/3 46/3 0 49/3 49/3 49/3 0 1
1 45/2 45/2 1 1 47/2 1 0 47/2 2 2 0 1
1 45/2 1 1 1 2 1 0 47/2 2 47/2 0 45/2
1 1 1 1 45/2 2 1 0 2 47/2 47/2 0 45/2
1 1 45/2 1 45/2 47/2 1 0 2 47/2 2 0 1
sage: P.vertices_list()
[[1, 1, 46/3, 1, 49/3, 46/3, 0, 49/3, 49/3, 49/3, 0, 1],
 [45/2, 45/2, 1, 1, 47/2, 1, 0, 47/2, 2, 2, 0, 1],
 [45/2, 1, 1, 1, 2, 1, 0, 47/2, 2, 47/2, 0, 45/2],
 [1, 1, 1, 45/2, 2, 1, 0, 2, 47/2, 47/2, 0, 45/2],
 [1, 45/2, 1, 45/2, 47/2, 1, 0, 2, 47/2, 2, 0, 1]]
sage: PP.N_LATTICE_POINTS
1260
sage: P.integral_points_count()
1260

Note that a user reported that the above point count is incorrect in Sage, that's why I tested what polymake has to say (and find that it agrees with Sage).

So, the bug is that the first attempt of converting P fails, while the second attempt succeeds.

@simon-king-jena
Copy link
Member Author

comment:2

What does self.eval('use File::Slurp;') mean?

git blame tells me that the line was introduced by Matthias, so CCing him.

@mkoeppe
Copy link
Contributor

mkoeppe commented Nov 4, 2017

comment:3

It's loading a Perl package. http://search.cpan.org/~uri/File-Slurp-9999.19/lib/File/Slurp.pm

We need it for stuff passed by file.

Sage does not control the Perl installation.
Should perhaps add a line to the polymake SPKG.txt to alert the user that this package needs to be installed (in addition to a few others that are already listed).

@simon-king-jena
Copy link
Member Author

comment:4

Replying to @mkoeppe:

Sage does not control the Perl installation.
Should perhaps add a line to the polymake SPKG.txt to alert the user that this package needs to be installed (in addition to a few others that are already listed).

... and HOW it can be installed. The search "perl install slurp" doesn't give me immediate answer.

@simon-king-jena
Copy link
Member Author

comment:5
  1. I did sudo apt-get install libperl6-slurp-perl which I think is supposed to install the slurp module on ubuntu.
  2. The example from comment:1 doesn't work after installing slurp: Polymake still cannot find slurp.
  3. So, we should tell the user how to install slurp AND how to make polymake aware of it.
  4. All that still doesn't explain why the example fails once and then just works. Apparently the interface can do without slurp, but doesn't.

@mkoeppe
Copy link
Contributor

mkoeppe commented Nov 4, 2017

comment:6

Polymake uses Perl5, not 6.

@simon-king-jena
Copy link
Member Author

comment:7

Replying to @mkoeppe:

Polymake uses Perl5, not 6.

Which makes me repeat the question: How to install the slurp module?

$ apt-cache search perl slurp
hobbit-plugins - plugins for the Xymon network monitor
libdbix-simple-perl - Perl module implementing an simpler interface to DBI
libfile-policy-perl - Simple policy for file I/O functions
libfile-read-perl - interface for reading one or more files
libfile-slurp-perl - single call read & write file routines
libfile-slurp-tiny-perl - simple, sane and efficient file slurper
libfile-slurp-unicode-perl - Perl module to add Unicode support for the File::Slurp package
libfile-slurper-perl - simple, sane and efficient module to slurp a file
libperl6-slurp-perl - module implementing the Perl 6 'slurp' built-in
libtext-clip-perl - module to clip and extract text in clipboard-like way

Which of the above do I need to install? Hint: It isn't libfile-slurper-perl either.

@simon-king-jena
Copy link
Member Author

comment:8

sudo apt-get install libfile-read-perl seems to do the trick. Afterwards, I get

sage: polymake(Polyhedron(eqns = eqns, ieqs=ieqs))
Polytope<Rational>[SAGE271]
sage: _.N_INTERIOR_LATTICE_POINTS
952
sage: __.N_LATTICE_POINTS
1260

Anyway.

I find it not good that the polymake interface depends on a specific perl module upon which polymake itself does not depend.

Is it really not possible to provide the same functionality (perhaps slower) if slurp is not installed? If there is a way around slurp then that should be used as a fallback.

And if there is no way around slurp, then the polymake interface should complain about it right in the beginning, giving specific advice on how to install slurp, alerting the user that (s)he has to take care about perl5, not perl6, and so on.

@simon-king-jena

This comment has been minimized.

@mkoeppe
Copy link
Contributor

mkoeppe commented Nov 5, 2017

comment:10

I'd guess (but haven't tested because I am not on Ubuntu) that it would simply be libfile-slurp-perl. The one that you picked probably installs it as a dependency.

The distribution-independent way of installing Perl packages, of course, is using CPAN.

Specific error handling for failure to load File::Slurp is a good idea.

One could, of course, provide a simplified version of read_file directly, instead of requiring File::Slurp. But I don't think it's worth it.

@mkoeppe
Copy link
Contributor

mkoeppe commented Mar 24, 2018

@mkoeppe

This comment has been minimized.

@mkoeppe
Copy link
Contributor

mkoeppe commented Mar 24, 2018

Commit: a924632

@mkoeppe
Copy link
Contributor

mkoeppe commented Mar 24, 2018

Author: Matthias Koeppe

@mkoeppe
Copy link
Contributor

mkoeppe commented Mar 24, 2018

New commits:

a924632polymake SPKG.txt: Mention File::Slurp and CPAN

@mkoeppe mkoeppe modified the milestones: sage-8.1, sage-8.2 Mar 24, 2018
@mkoeppe
Copy link
Contributor

mkoeppe commented Apr 8, 2018

comment:13

Needs review and fixes the problem reported by jipilab on #24905.

@jplab
Copy link
Contributor

jplab commented Apr 8, 2018

Reviewer: Jean-Philippe Labbé

@jplab
Copy link
Contributor

jplab commented Apr 8, 2018

comment:14

This solved the problem raised in #24905 and the above failing example works as well on my computer. This looks good to go.

@mkoeppe
Copy link
Contributor

mkoeppe commented Apr 8, 2018

Changed keywords from polymake to polymake, IMA-PolyGeom

@vbraun
Copy link
Member

vbraun commented May 8, 2018

@vbraun vbraun closed this as completed in 14669b2 May 8, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants