@@ -278,20 +278,31 @@ def gale_transform_to_polytope(vectors, base_ring=None, backend=None):
278278 'cdd'
279279
280280 A gale transform corresponds to a polytope if and only if
281- every (linear) hyperplane not containing any vector
281+ every oriented (linear) hyperplane
282282 has at least two vectors on each side.
283+ See Theorem 6.19 of [Zie2007]_.
284+ If this is not the case, one of two errors is raised.
283285
284- If this is not the case, an error is raised::
286+ If there is such a hyperplane with no vector on one side,
287+ the vectors are not totally cyclic::
285288
286- sage: gale_transform_to_polytope([(0,1), (1,1), (1,0), (-1,-1 )])
289+ sage: gale_transform_to_polytope([(0,1), (1,1), (1,0), (-1,0 )])
287290 Traceback (most recent call last):
288291 ...
289- ValueError: the gale transform does not correspond to a polytope
292+ ValueError: input vectors not totally cyclic
290293
291- sage: gale_transform_to_polytope([(0,1), (1,1), (1,0), (-1,0)])
294+ If every hyperplane has at least one vector on each side, then the gale
295+ transform corresponds to a point configuration.
296+ It corresponds to a polytope if and only if this point configuration is
297+ convex if and only if every hyperplane contains at least two vectors of
298+ the gale transform on each side.
299+
300+ If this is not the case, an error is raised::
301+
302+ sage: gale_transform_to_polytope([(0,1), (1,1), (1,0), (-1,-1)])
292303 Traceback (most recent call last):
293304 ...
294- ValueError: input vectors not totally cyclic
305+ ValueError: the gale transform does not correspond to a polytope
295306
296307 TESTS::
297308
@@ -309,8 +320,16 @@ def gale_transform_to_polytope(vectors, base_ring=None, backend=None):
309320 """
310321 vertices = gale_transform_to_primal (vectors , base_ring , backend )
311322 P = Polyhedron (vertices = vertices , base_ring = base_ring , backend = backend )
323+
312324 if not P .n_vertices () == len (vertices ):
325+ # If the input vectors are not totally cyclic, ``gale_transform_to_primal``
326+ # raises an error.
327+ # As no error was raised so far, the gale transform corresponds to
328+ # to a point configuration.
329+ # It corresponds to a polytope if and only if
330+ # ``vertices`` are in convex position.
313331 raise ValueError ("the gale transform does not correspond to a polytope" )
332+
314333 return P
315334
316335def gale_transform_to_primal (vectors , base_ring = None , backend = None ):
@@ -346,22 +365,23 @@ def gale_transform_to_primal(vectors, base_ring=None, backend=None):
346365
347366 ALGORITHM:
348367
349- We assume the centroid of the (input) vectors to be the origin.
350- We stack ``Matrix(vectors)`` by a row of ones.
351- The right kernel of this is the dual point configuration.
368+ Step 1: If the centroid of the (input) vectors is not the origin,
369+ we do an appropriate transformation to make it so.
352370
353- More concretely, the dual vector configuration is obtained by
354- taking a basis of the right kernel of ``Matrix(vectors)``.
371+ Step 2: We add a row of ones on top of ``Matrix(vectors)``.
372+ The right kernel of this larger matrix is the dual configuration space,
373+ and a basis of this space provides the dual point configuration.
355374
375+ More concretely, the dual vector configuration (inhomogeneous)
376+ is obtained by taking a basis of the right kernel of ``Matrix(vectors)``.
356377 If the centroid of the (input) vectors is the origin,
357- we can extend the all-ones vector to a basis of the right kernel.
358- In this case the dual vector configuration can be taken to be
359- the columns of ``[[1], [V]]``, where ``[1]`` represents
360- a row of all-ones. Clearly, ``V`` is a dehomogenization.
378+ there exists a basis of the right kernel of the form
379+ ``[[1], [V]]``, where ``[1]`` represents a row of ones.
380+ Then, ``V`` is a dehomogenization and thus the dual point configuration.
361381
362- Extending the all-ones vector to a basis of the right kernel is
363- done by stacking a row of ones on ``Matrix(vectors)`` and then
364- taking the right kernel .
382+ To extend ``[1]`` to a basis of ``Matrix(vectors)``, we add
383+ a row of ones to ``Matrix(vectors)`` and calculate a basis of the
384+ right kernel of the obtained matrix .
365385
366386 REFERENCES:
367387
@@ -426,6 +446,13 @@ def gale_transform_to_primal(vectors, base_ring=None, backend=None):
426446 Traceback (most recent call last):
427447 ...
428448 ValueError: input vectors not totally cyclic
449+
450+ sage: gale_transform_to_primal(
451+ ....: [(1,1,0), (-1,-1,0), (1,0,0),
452+ ....: (-1,0,0), (1,-1,0), (-2,1,0)], backend='field')
453+ Traceback (most recent call last):
454+ ...
455+ ValueError: input vectors not totally cyclic
429456 """
430457 from sage .modules .free_module_element import vector
431458 from sage .matrix .all import Matrix
@@ -473,6 +500,12 @@ def gale_transform_to_primal(vectors, base_ring=None, backend=None):
473500 m = Matrix (base_ring , vectors ).transpose ().stack (Matrix (base_ring , [[1 ]* len (vectors )]))
474501 else :
475502 m = Matrix (vectors ).transpose ().stack (Matrix ([[1 ]* len (vectors )]))
503+
504+ if m .rank () != len (vectors [0 ]) + 1 :
505+ # The given vectors do not span the ambient space,
506+ # then there exists a nonnegative value vector.
507+ raise ValueError ("input vectors not totally cyclic" )
508+
476509 return m .right_kernel_matrix (basis = 'computed' ).columns ()
477510
478511
0 commit comments