Skip to content

Add PointCollection #11400

@novoselt

Description

@novoselt

This patch adds support for a PointCollection class, which is not yet used for anything, but I propose switching cones and fans to it and plan to extensively use it in the rewrite of lattice polytopes.

Module level documentation explains the benefits, basically, it is an "enhanced but still fast tuple" which will allow uniform treatment of things like ray generators, lattice points, and normals. Instead of writing

sage: cone.rays()
sage: cone.ray_matrix()
sage: cone.ray_set()
sage: cone.lines()
sage: cone.line_matrix()
sage: cone.line_set()

which requires 6 different methods (and more for facet normals and vertices/points of polytopes), one will be able to use

sage: cone.rays()
sage: cone.rays().matrix()
sage: cone.rays().set()
sage: cone.lines()
sage: cone.lines().matrix()
sage: cone.lines().set()

which uses only special methods for cones (plus 2 for point collections).

Another good point will be elimination of IntegralRayCollection class which is currently the common base of cones and fans, which seemed to be convenient, but is definitely a bit weird.

To make sure that the transition is painless, this ticket will only add the new class, while transition will be done in a consecutive one, with all the proper deprecations etc. The doctests show how cone.rays() will eventually behave.

Regarding speed: there is Sequence class which does a similar thing, "Sagifying" lists and tuples. But it is very slow in construction (1000 times with checks on, 20 times with checks off compared to tuples, my class is only 2 times slower) and two times slower than tuples in access (mine is as fast as tuples):

sage: from sage.geometry.point_collection import PointCollection
sage: f = toric_varieties.dP6xdP6().fan()
sage: timeit("PointCollection(f.rays())", number=1000, repeat=100)
1000 loops, best of 100: 3.59 µs per loop
sage: timeit("tuple(f.rays())", number=1000, repeat=100)
1000 loops, best of 100: 1.62 µs per loop
sage: timeit("seq(f.rays())", number=100, repeat=10)
100 loops, best of 10: 1.49 ms per loop
sage: timeit("seq(f.rays(), f.lattice(), check=False)", number=1000, repeat=100)
1000 loops, best of 100: 39.3 µs per loop
sage: pc = PointCollection(f.rays())
sage: timeit("pc[5]", number=1000, repeat=100)
1000 loops, best of 100: 561 ns per loop
sage: pct = tuple(f.rays())
sage: timeit("pct[5]", number=1000, repeat=100)
1000 loops, best of 100: 547 ns per loop
sage: pcs = seq(f.rays(), f.lattice(), check=False)
sage: timeit("pcs[5]", number=1000, repeat=100)
1000 loops, best of 100: 1.16 µs per loop

While plain tuples are still the fastest, I think that benefits of the proposed class worth the associated penalty (which is not the case for sequences). In fact, I think that overall speed will improve due to better cache sharing.

CC: @vbraun @hivert

Component: geometry

Author: Andrey Novoseltsev

Reviewer: Volker Braun

Merged: sage-5.0.beta6

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

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions