First time here? Check out the FAQ!

Ask Your Question
1

How to inherit from polytopes

asked 0 years ago

JTS gravatar image

updated 0 years ago

FrédéricC gravatar image

Dear all, I want to write a very simple class that inherits from existing polytopes functionality, creates one particular type of polytopes, and adds some functionality which is only relevant for this type of polytopes.

However, I am a python beginner, and am having a hard time navigating the sagemath src directory to find exactly from which class (Polyhedron or Polyhedra) that I should inherit, and how to do this.

Here is a toy example: suppose I want to investigate "depleted cubes", ie polytopes combinatorially equivalent with hypercubes with one corner neatly sliced off. I also want to easily retrieve the cut-off facet.

This works:

def depleted_cube(n: Integer) -> Polyhedron:
       """Returns the n-dimensional hypercube minus one vertex"""
       H = polytopes.hypercube(n)
       Verts = [v for v in H.vertices_list() if add(v) < n]
       C = Polyhedron(vertices=Verts)
       return C

def _strange_facet(P: Polyhedron):
      """Returns the strange facet of P, but only of P depleted cube"""
      n = P.dimension()
      L = [F for F in P.facets() if len(F.vertices()) == n]
      return L[0]

I can now go

sage: _strange_facet(depleted_cube(6)).vertices()
(A vertex at (-1, 1, 1, 1, 1, 1),
A vertex at (1, -1, 1, 1, 1, 1),
A vertex at (1, 1, -1, 1, 1, 1),
A vertex at (1, 1, 1, -1, 1, 1),
A vertex at (1, 1, 1, 1, -1, 1),
A vertex at (1, 1, 1, 1, 1, -1))

but I would like to be able to do

polytopes.depleted_cube(6).strange_facet().vertices()

so as not to dilute the precious namespace! I.e., the function should be a "method" to some "class" that inherits from, either Polyhedron or Polyhedra or polyhedron_base_with_backend_cpp or ... Can someone provide an example, skeleton implementation of a polytope class that inherits from somewhere? As I mentioned, I tried looking at the src directory, but the relevant files are extremely long and littered with docstrings and doctests and cruft; I can make neither head nor tails of them.

Edit: As per the answer by dan_fulea, it is not worthwhile to try to turn the functions into a method. I will undogmatically refrain from doing so, then. Thank you for the tour through the internals of sagemath; I was not aware of the f.?? method of getting the code of a function/object.

Preview: (hide)

Comments

probably using Polyhedra_base

FrédéricC gravatar imageFrédéricC ( 0 years ago )

1 Answer

Sort by » oldest newest most voted
1

answered 0 years ago

dan_fulea gravatar image

For me it is not clear why the simple and direct code that avoids an avatar of a new class is not good enough, so it is hard to design a good class, that makes next steps easy to work. The passage about "diluting a precious namespace" is not really an issue from a pragmatical point of view. The namespace is "something else" while writing code.

The line polytopes.depleted_cube(6).strange_facet().vertices()must be an orientation wish. So let us see what can be realized from it. What is polytopes? I will use p as a short cut.

sage: p = polytopes
sage: print(p)
<sage.geometry.polyhedron.library.Polytopes object at 0x7b0addf97e00>
sage: type(p)
<class 'sage.geometry.polyhedron.library.Polytopes'>

So this is a class. It has many methods. For instance:

sage: p.__init__
<method-wrapper '__init__' of Polytopes object at 0x7b0addf97e00>

And also a lot of other published methods. We avoid the "privat" ones, those starting with an underscore (at least), and pick only the first ten:

sage: [met for met in dir(p) if not met.startswith('_')][:10]
['Birkhoff_polytope',
 'Gosset_3_21',
 'Kirkman_icosahedron',
 'associahedron',
 'bitruncated_six_hundred_cell',
 'buckyball',
 'cantellated_one_hundred_twenty_cell',
 'cantellated_six_hundred_cell',
 'cantitruncated_one_hundred_twenty_cell',
 'cantitruncated_six_hundred_cell']
sage:

(Remove the slicing [:10] to see all of them.) Of course, depleted_cube is not on the list, but we have for instance the h-starting methods:

sage: [met for met in dir(p) if met.startswith('h')]
['hypercube', 'hypersimplex']

So what is polytopes.hypercube?

sage: type(p.hypercube)
<class 'method'>

It is a method. This method returns an object of an other class. So we jump from place to place. What does it return? To get the related code of the method we type:

sage: p.hypercube??

and scroll down. The last lines are:

        return parent([cp, [], []], [ieqs, []], convert=convert, Vrep_minimal=True, Hrep_minimal=True, pref_rep='Hrep')
File:      /usr/lib/python3.13/site-packages/sage/geometry/polyhedron/library.py
Type:      method

We see where the code lives, and what it returns (in some if-case). The involved variables are defined in advance, for instance:

        parent = Polyhedra(ZZ, dim, backend=backend)

But this "thing", parent, is what kind of an object? We must know where we are, when using it, and how to make from a file path the right python object:

sage: my_parent = sage.geometry.polyhedron.library
sage: my_parent.Polyhedra
<function Polyhedra at 0x7b0ade0ca480>

So Polyhedra is a function published in the same py-module. It is not a class, it returns an object, and this object is used in the next construction. (So trying to do "the same" means to define a function - not a class - depleted_cube in the same framework. Why should we inherit a "kind-of-a-factory" class, to have an other such class with a new function, when we can define this function in a direct manner?) Then for instance p.hypercube(3) returns an object.

An object of which class?

sage: C = p.hypercube(3)
sage: type(C)
<class 'sage.geometry.polyhedron.parent.Polyhedra_ZZ_ppl_with_category.element_class'>

Do we really want to inherit from such a "thing". To better get the story of the thing, let us ask:

sage: type(sage)
<class 'module'>
sage: type(sage.geometry)
<class 'module'>
sage: type(sage.geometry.polyhedron)
<class 'module'>
sage: type(sage.geometry.polyhedron.parent)
<class 'module'>
sage: type(sage.geometry.polyhedron.parent.Polyhedra_ZZ_ppl_with_category)
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
Cell In[82], line 1
----> 1 type(sage.geometry.polyhedron.parent.Polyhedra_ZZ_ppl_with_category)

AttributeError: module 'sage.geometry.polyhedron.parent' has no attribute 'Polyhedra_ZZ_ppl_with_category'
sage:

At this point my wish to trace back the places finally and inherit a class is vanishing. There is no reason to search for such a hidden class or function. In fact, a doc string tells us:

def Polyhedra(ambient_space_or_base_ring=None, ambient_dim=None, backend=None, *,
              ambient_space=None, base_ring=None):
    r"""
    Construct a suitable parent class for polyhedra.

    INPUT:

    - ``base_ring`` -- a ring; currently there are backends for `\ZZ`,
      `\QQ`, and `\RDF`

    - ``ambient_dim`` -- integer; the ambient space dimension

    - ``ambient_space`` -- a free module

    - ``backend`` -- string. The name of the backend for computations. There are
      several backends implemented:

        * ``backend="ppl"`` uses the Parma Polyhedra Library

        * ``backend="cdd"`` uses CDD

        * ``backend="normaliz"`` uses normaliz

        * ``backend="polymake"`` uses polymake

        * ``backend="field"`` a generic Sage implementation

    OUTPUT:

    A parent class for polyhedra over the given base ring if the
    backend supports it. If not, the parent base ring can be larger
    (for example, `\QQ` instead of `\ZZ`). If there is no
    implementation at all, a :exc:`ValueError` is raised.

So Polyhedra is a function returning a class. (Which has its constructor, some methods, and so on.) In other words, the libraries are constructing first a dual, advanced world, then from this world the final geometric objects in suitable dimensions over suitable rings. As an user of the library, it is not easy and/or it does not make sense to extend a package outside of the package. (Since it may change, thus thing stop to work or to be maintainable.)

Preview: (hide)
link

Your Answer

Please start posting anonymously - your entry will be published after you log in or create a new account.

Add Answer

Question Tools

1 follower

Stats

Asked: 0 years ago

Seen: 129 times

Last updated: Feb 17