@@ -675,3 +675,132 @@ def random_integral_point(self, **kwds):
675
675
raise EmptySetError ('polyhedron does not contain any integral points' )
676
676
677
677
return self .get_integral_point (current_randstate ().python_random ().randint (0 , count - 1 ), ** kwds )
678
+
679
+ def generating_function_of_integral_points (self , ** kwds ):
680
+ r"""
681
+ Return the multivariate generating function of the
682
+ integral points of this polyhedron.
683
+
684
+ To be precise, this returns
685
+
686
+ .. MATH::
687
+
688
+ \sum_{(r_0,\dots,r_{d-1}) \in \mathit{polyhedron}\cap \ZZ^d}
689
+ y_0^{r_0} \dots y_{d-1}^{r_{d-1}}.
690
+
691
+ This calls
692
+ :func:`~sage.geometry.polyhedron.generating_function.generating_function_of_integral_points`,
693
+ so have a look at the documentation and examples there.
694
+
695
+ INPUT:
696
+
697
+ The following keyword arguments are passed to
698
+ :func:`~sage.geometry.polyhedron.generating_function.generating_function_of_integral_points`:
699
+
700
+ - ``split`` -- (default: ``False``) a boolean or list
701
+
702
+ - ``split=False`` computes the generating function directly,
703
+ without any splitting.
704
+
705
+ - When ``split`` is a list of disjoint polyhedra, then
706
+ for each of these polyhedra, this polyhedron is intersected with it,
707
+ its generating function computed and all these generating functions
708
+ are summed up.
709
+
710
+ - ``split=True`` splits into `d!` disjoint polyhedra.
711
+
712
+ - ``result_as_tuple`` -- (default: ``None``) a boolean or ``None``
713
+
714
+ This specifies whether the output is a (partial) factorization
715
+ (``result_as_tuple=False``) or a sum of such (partial)
716
+ factorizations (``result_as_tuple=True``). By default
717
+ (``result_as_tuple=None``), this is automatically determined.
718
+ If the output is a sum, it is represented as a tuple whose
719
+ entries are the summands.
720
+
721
+ - ``indices`` -- (default: ``None``) a list or tuple
722
+
723
+ If this
724
+ is ``None``, this is automatically determined.
725
+
726
+ - ``name`` -- (default: ``'y'``) a string
727
+
728
+ The variable names of the Laurent polynomial ring of the output
729
+ are this string followed by an integer.
730
+
731
+ - ``names`` -- a list or tuple of names (strings), or a comma separated string
732
+
733
+ ``name`` is extracted from ``names``, therefore ``names`` has to contain
734
+ exactly one variable name, and ``name`` and``names`` cannot be specified
735
+ both at the same time.
736
+
737
+ - ``Factorization_sort`` (default: ``False``) and
738
+ ``Factorization_simplify`` (default: ``True``) -- booleans
739
+
740
+ These are passed on to
741
+ :class:`sage.structure.factorization.Factorization` when creating
742
+ the result.
743
+
744
+ - ``sort_factors`` -- (default: ``False``) a boolean
745
+
746
+ If set, then
747
+ the factors of the output are sorted such that the numerator is
748
+ first and only then all factors of the denominator. It is ensured
749
+ that the sorting is always the same; use this for doctesting.
750
+
751
+ OUTPUT:
752
+
753
+ The generating function as a (partial)
754
+ :class:`~sage.structure.factorization.Factorization`
755
+ of the result whose factors are Laurent polynomials
756
+
757
+ The result might be a tuple of such factorizations
758
+ (depending on the parameter ``result_as_tuple``) as well.
759
+
760
+ .. NOTE::
761
+
762
+ At the moment, only polyhedra with nonnegative coordinates
763
+ (i.e. a polyhedron in the nonnegative orthant) are handled.
764
+
765
+ EXAMPLES::
766
+
767
+ sage: P2 = (
768
+ ....: Polyhedron(ieqs=[(0, 0, 0, 1), (0, 0, 1, 0), (0, 1, 0, -1)]),
769
+ ....: Polyhedron(ieqs=[(0, -1, 0, 1), (0, 1, 0, 0), (0, 0, 1, 0)]))
770
+ sage: P2[0].generating_function_of_integral_points(sort_factors=True)
771
+ 1 * (-y0 + 1)^-1 * (-y1 + 1)^-1 * (-y0*y2 + 1)^-1
772
+ sage: P2[1].generating_function_of_integral_points(sort_factors=True)
773
+ 1 * (-y1 + 1)^-1 * (-y2 + 1)^-1 * (-y0*y2 + 1)^-1
774
+ sage: (P2[0] & P2[1]).Hrepresentation()
775
+ (An equation (1, 0, -1) x + 0 == 0,
776
+ An inequality (1, 0, 0) x + 0 >= 0,
777
+ An inequality (0, 1, 0) x + 0 >= 0)
778
+ sage: (P2[0] & P2[1]).generating_function_of_integral_points(sort_factors=True)
779
+ 1 * (-y1 + 1)^-1 * (-y0*y2 + 1)^-1
780
+
781
+ The number of integer partitions
782
+ `1 \leq r_0 \leq r_1 \leq r_2 \leq r_3 \leq r_4`::
783
+
784
+ sage: P = Polyhedron(ieqs=[(-1, 1, 0, 0, 0, 0), (0, -1, 1, 0, 0, 0),
785
+ ....: (0, 0, -1, 1, 0, 0), (0, 0, 0, -1, 1, 0),
786
+ ....: (0, 0, 0, 0, -1, 1)])
787
+ sage: f = P.generating_function_of_integral_points(sort_factors=True); f
788
+ y0*y1*y2*y3*y4 * (-y4 + 1)^-1 * (-y3*y4 + 1)^-1 * (-y2*y3*y4 + 1)^-1 *
789
+ (-y1*y2*y3*y4 + 1)^-1 * (-y0*y1*y2*y3*y4 + 1)^-1
790
+ sage: f = f.value()
791
+ sage: P.<z> = PowerSeriesRing(ZZ)
792
+ sage: c = f.subs({y: z for y in f.parent().gens()}); c
793
+ z^5 + z^6 + 2*z^7 + 3*z^8 + 5*z^9 + 7*z^10 + 10*z^11 + 13*z^12 + 18*z^13 +
794
+ 23*z^14 + 30*z^15 + 37*z^16 + 47*z^17 + 57*z^18 + 70*z^19 + 84*z^20 +
795
+ 101*z^21 + 119*z^22 + 141*z^23 + 164*z^24 + O(z^25)
796
+ sage: [Partitions(k, length=5).cardinality() for k in range(5,20)] == \
797
+ ....: c.truncate().coefficients(sparse=False)[5:20]
798
+ True
799
+
800
+ .. SEEALSO::
801
+
802
+ More examples can be found at
803
+ :func:`~sage.geometry.polyhedron.generating_function.generating_function_of_integral_points`.
804
+ """
805
+ from .generating_function import generating_function_of_integral_points
806
+ return generating_function_of_integral_points (self , ** kwds )
0 commit comments