| 1 | initial version |
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.)
Copyright Sage, 2010. Some rights reserved under creative commons license. Content on this site is licensed under a Creative Commons Attribution Share Alike 3.0 license.