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

Add sage.geometry.abc; remove uses of is_Polyhedron, is_LatticePolytope, is_Cone outside of sage.geometry #32637

Closed
mkoeppe opened this issue Oct 5, 2021 · 29 comments

Comments

@mkoeppe
Copy link
Contributor

mkoeppe commented Oct 5, 2021

$ git grep 'def is_[A-Z]' src/sage/geometry/
src/sage/geometry/cone.py:def is_Cone(x):
src/sage/geometry/fan.py:def is_Fan(x):
src/sage/geometry/lattice_polytope.py:def is_LatticePolytope(x):
src/sage/geometry/lattice_polytope.py:def is_NefPartition(x):
src/sage/geometry/point_collection.pyx:def is_PointCollection(x):
src/sage/geometry/polyhedron/base.py:def is_Polyhedron(X):
src/sage/geometry/toric_lattice.py:def is_ToricLattice(x):
src/sage/geometry/toric_lattice.py:def is_ToricLatticeQuotient(x):
src/sage/geometry/toric_lattice_element.pyx:def is_ToricLatticeElement(x):

In this ticket, we add ABCs LatticePolytope, ConvexRationalPolyhedralCone, Polyhedron.

A small number of uses outside of sage.geometry will need updating. $ git grep 'geometry.*import.*is_[A-Z]' src/sage/

(Part of meta-ticket #32414)

Depends on #32614
Depends on #32649

CC: @kliem @orlitzky @egourgoulhon

Component: refactoring

Author: Matthias Koeppe

Branch/Commit: 44540f5

Reviewer: Michael Orlitzky

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

@mkoeppe mkoeppe added this to the sage-9.5 milestone Oct 5, 2021
@mkoeppe mkoeppe changed the title Add sage.geometry.abc; deprecate is_Polyhedron, is_LatticePolytope, is_Cone, ... Add sage.geometry.abc; remove uses of is_Polyhedron, is_LatticePolytope, is_Cone outside of sage.geometry Oct 17, 2021
@mkoeppe
Copy link
Contributor Author

mkoeppe commented Oct 17, 2021

@mkoeppe
Copy link
Contributor Author

mkoeppe commented Oct 17, 2021

Author: Matthias Koeppe

@mkoeppe
Copy link
Contributor Author

mkoeppe commented Oct 17, 2021

New commits:

502546bsrc/sage/geometry/abc.pyx: New
79a8ba4sage.schemes.toric: Remove use of is_Cone
6e32262src/sage/matrix/matrix2.pyx: Remove use of is_Cone
19aee74src/sage/groups/affine_gps/group_element.py: Remove use of is_Polyhedron
87ad226src/sage/manifolds/subsets/pullback.py: Remove use of is_Polyhedron

@mkoeppe
Copy link
Contributor Author

mkoeppe commented Oct 17, 2021

Commit: 87ad226

@mkoeppe

This comment has been minimized.

@orlitzky
Copy link
Contributor

comment:5

I worry that we're changing is_Foo() to mean "does this object provide the interface defined by abc.Foo?" But then abc.Foo doesn't declare any methods, properties, or data.

On the other hand, you don't want to put the implementation into the base class, because the whole point is to avoid importing the implementations to perform a typecheck. Nor does it make much sense to blindly add a million @abstractmethod def foo(...): pass lines to each ABC. I guess in lieu of an alternative, it has to be OK.

I wonder if something ridiculous like this wouldn't also work as an interim hack:

sage: def is_Polyhedron(C):
....:     return "Polyhedron_base" in [c.__name__ for c in C.__class__.__mro__]

You can also check the (string) module name with c.__module__ to avoid name clashes. But chances are, it's slower at runtime.

@mkoeppe
Copy link
Contributor Author

mkoeppe commented Oct 18, 2021

comment:6

Replying to @orlitzky:

I worry that we're changing is_Foo() to mean "does this object provide the interface defined by abc.Foo?" But then abc.Foo doesn't declare any methods, properties, or data.

As explained in #32414, "each of the new abstract base classes is intended to have a unique direct implementation subclass. Attempting to define new hierarchies of abstract base classes is beyond the scope of this ticket. Also, the new classes do not define any methods.".

@mkoeppe
Copy link
Contributor Author

mkoeppe commented Oct 18, 2021

comment:7

Replying to @orlitzky:

I wonder if something ridiculous like this wouldn't also work as an interim hack:

sage: def is_Polyhedron(C):
....:     return "Polyhedron_base" in [c.__name__ for c in C.__class__.__mro__]

Yeah, I'm not interested in a solution that looks like this

@orlitzky
Copy link
Contributor

comment:8

Replying to @mkoeppe:

As explained in #32414, "each of the new abstract base classes is intended to have a unique direct implementation subclass. Attempting to define new hierarchies of abstract base classes is beyond the scope of this ticket. Also, the new classes do not define any methods.".

I saw that, but unless you plan to live forever and spend most of it monitoring trac, there's no technical means to enforce that restriction.

@mkoeppe
Copy link
Contributor Author

mkoeppe commented Oct 18, 2021

comment:9

Sounds like someone wants to write a decorator for these types of classes

@sagetrac-git
Copy link
Mannequin

sagetrac-git mannequin commented Oct 18, 2021

Branch pushed to git repo; I updated commit sha1. New commits:

8b9839asrc/sage/manifolds/subsets/pullback.py: Remove more uses of is_Polyhedron

@sagetrac-git
Copy link
Mannequin

sagetrac-git mannequin commented Oct 18, 2021

Changed commit from 87ad226 to 8b9839a

@orlitzky
Copy link
Contributor

comment:11

Replying to @mkoeppe:

Sounds like someone wants to write a decorator for these types of classes

I don't know how to do it with a decorator, but I think a metaclass can ensure that a given class is only subclassed once. As an added bonus, the metaclass can explain why these exist and how they should be used (i.e. that they aren't really abstract base classes).

This example fails (as intended) the second time we subclass:

class TypeCheckWrapper(type):
    _subclasses = 0

    def __init__(cls, name, bases, clsdict):
        if len(cls.mro()) > 2:
            TypeCheckWrapper._subclasses += 1
            if TypeCheckWrapper._subclasses > 1:
                raise TypeError("TypeCheckWrapper with multiple subclasses")
        super(TypeCheckWrapper, cls).__init__(name, bases, clsdict)

class Polyhedron(metaclass=TypeCheckWrapper):
    pass

print("Defined base class Polyhedron")

class Cone(Polyhedron):
    pass

print("Defined class Cone(Polyhedron)")

class Polytope(Polyhedron):
    pass

print("Defined class Polytope(Polyhedron)")

@mkoeppe
Copy link
Contributor Author

mkoeppe commented Oct 18, 2021

comment:12

I think this discussion should go to a separate ticket. Note also that some of the ABCs added in other tickets of #32414 are actually extension classes, and using a metaclass there is probably tricky.

@mkoeppe
Copy link
Contributor Author

mkoeppe commented Oct 18, 2021

comment:13

A simple solution could be to just add a doctest for the MRO length. We enforce pretty much everything else with doctests as well.

@mkoeppe
Copy link
Contributor Author

mkoeppe commented Oct 18, 2021

comment:14
    TESTS::

        sage: import sage.geometry.abc
        sage: len(sage.geometry.abc.Polyhedron.__subclasses__()) <= 1
        True

@mkoeppe
Copy link
Contributor Author

mkoeppe commented Oct 18, 2021

Dependencies: #32614

@sagetrac-git
Copy link
Mannequin

sagetrac-git mannequin commented Oct 18, 2021

Changed commit from 8b9839a to ceff8dc

@sagetrac-git
Copy link
Mannequin

sagetrac-git mannequin commented Oct 18, 2021

Branch pushed to git repo; I updated commit sha1. Last 10 new commits:

14fd1e5src/doc/en/developer/coding_basics.rst: Update discussion of feature tags
27c53acsrc/sage/features/sagemath.py: Add 'sage.plot'
180e31dMerge #30887
10e8d63sage.features.sagemath: Use JoinFeature when tag is different from the actually tested module
654d09csage.features.sagemath: Change sage_optional_tags to sage_features
f63a7d0src/sage/features/: Move features depending on optional packages to separate files
4558791Merge tag '9.5.beta3' into t/32614/features_and_optional_tags_for_sage_subset_distributions
f68e511Merge #32614
18aa26fsrc/sage/features/sagemath.py: Add sage.geometry.polyhedron
ceff8dcsrc/sage/geometry/abc.pyx: Add doctests

@mkoeppe
Copy link
Contributor Author

mkoeppe commented Oct 18, 2021

comment:17

How's this?

@sagetrac-git
Copy link
Mannequin

sagetrac-git mannequin commented Oct 18, 2021

Changed commit from ceff8dc to 9471570

@sagetrac-git
Copy link
Mannequin

sagetrac-git mannequin commented Oct 18, 2021

Branch pushed to git repo; I updated commit sha1. This was a forced push. New commits:

9471570src/sage/geometry/abc.pyx: Add doctests

@mkoeppe
Copy link
Contributor Author

mkoeppe commented Oct 18, 2021

Changed dependencies from #32614 to #32614, #32649

@sagetrac-git
Copy link
Mannequin

sagetrac-git mannequin commented Oct 18, 2021

Changed commit from 9471570 to 44540f5

@sagetrac-git
Copy link
Mannequin

sagetrac-git mannequin commented Oct 18, 2021

Branch pushed to git repo; I updated commit sha1. Last 10 new commits:

9358502Merge #32614
6457ee9src/sage/features/mip_backends.py: Fixup
eeaa722Merge #32614
c872d69Add description to features
08248a1Fix for doctest failures
759c88bsage.doctest, sage.control: Remove unused imports
15729dcsrc/sage/features/mcqd.py: Add doctests
1d02bd0More doctests for coverage
58572e1Merge #32649
44540f5src/sage/features/sagemath.py: Add doctests

@orlitzky
Copy link
Contributor

comment:21

We actually have a module (sage.cpython.cython_metaclass) that hacks metaclasses into cython using undocumented internals. What could possibly go wrong?

Using doctests is good enough.

@orlitzky
Copy link
Contributor

Reviewer: Michael Orlitzky

@mkoeppe
Copy link
Contributor Author

mkoeppe commented Oct 19, 2021

comment:22

Thanks!

@vbraun
Copy link
Member

vbraun commented Oct 20, 2021

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

3 participants