MLIR 24.0.0git
GeneratingFunction.h
Go to the documentation of this file.
1//===- GeneratingFunction.h - Generating Functions over Q^d -----*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// Definition of the GeneratingFunction class for Barvinok's algorithm,
10// which represents a function over Q^n, parameterized by d parameters.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef MLIR_ANALYSIS_PRESBURGER_GENERATINGFUNCTION_H
15#define MLIR_ANALYSIS_PRESBURGER_GENERATINGFUNCTION_H
16
19
20#include <utility>
21
22namespace mlir {
23namespace presburger {
24namespace detail {
25
26// A parametric point is a vector, each of whose elements
27// is an affine function of n parameters. Each column
28// in the matrix represents the affine function and
29// has n+1 elements.
31
32// A point is simply a vector.
34
35// A class to describe the type of generating function
36// used to enumerate the integer points in a polytope.
37// Consists of a set of terms, where the ith term has
38// * a sign, ±1, stored in `signs[i]`
39// * a numerator, of the form x^{n},
40// where n, stored in `numerators[i]`,
41// is a parametric point.
42// * a denominator, of the form (1 - x^{d1})...(1 - x^{dn}),
43// where each dj, stored in `denominators[i][j]`,
44// is a vector.
45//
46// Represents functions f_p : Q^n -> Q of the form
47//
48// f_p(x) = \sum_i s_i * (x^n_i(p)) / (\prod_j (1 - x^d_{ij})
49//
50// where s_i is ±1,
51// n_i \in Q^d -> Q^n is an n-vector of affine functions on d parameters, and
52// g_{ij} \in Q^n are vectors.
54public:
55 GeneratingFunction(unsigned numParam, SmallVector<int> signs,
56 std::vector<ParamPoint> nums,
57 std::vector<std::vector<Point>> dens)
58 : numParam(numParam), signs(std::move(signs)),
59 numerators(std::move(nums)), denominators(std::move(dens)) {
60#ifndef NDEBUG
61 for (const ParamPoint &term : numerators)
62 assert(term.getNumRows() == numParam + 1 &&
63 "dimensionality of numerator exponents does not match number of "
64 "parameters!");
65#endif // NDEBUG
66 }
67
68 unsigned getNumParams() const { return numParam; }
69
70 const SmallVector<int> &getSigns() const & { return signs; }
71 SmallVector<int> getSigns() && { return std::move(signs); }
72 SmallVector<int> getSigns() const && { return signs; }
73
74 const std::vector<ParamPoint> &getNumerators() const & { return numerators; }
75 std::vector<ParamPoint> getNumerators() && { return std::move(numerators); }
76 std::vector<ParamPoint> getNumerators() const && { return numerators; }
77
78 const std::vector<std::vector<Point>> &getDenominators() const & {
79 return denominators;
80 }
81 std::vector<std::vector<Point>> getDenominators() && {
82 return std::move(denominators);
83 }
84 std::vector<std::vector<Point>> getDenominators() const && {
85 return denominators;
86 }
87
89 assert(numParam == gf.getNumParams() &&
90 "two generating functions with different numbers of parameters "
91 "cannot be added!");
92 SmallVector<int> sumSigns = signs;
93 sumSigns.append(gf.signs);
94
95 std::vector<ParamPoint> sumNumerators = numerators;
96 llvm::append_range(sumNumerators, gf.numerators);
97
98 std::vector<std::vector<Point>> sumDenominators = denominators;
99 llvm::append_range(sumDenominators, gf.denominators);
100 return GeneratingFunction(numParam, std::move(sumSigns),
101 std::move(sumNumerators),
102 std::move(sumDenominators));
103 }
104
105 llvm::raw_ostream &print(llvm::raw_ostream &os) const {
106 for (unsigned i = 0, e = signs.size(); i < e; i++) {
107 if (i == 0) {
108 if (signs[i] == -1)
109 os << "- ";
110 } else {
111 if (signs[i] == 1)
112 os << " + ";
113 else
114 os << " - ";
115 }
116
117 os << "x^[";
118 unsigned r = numerators[i].getNumRows();
119 for (unsigned j = 0; j < r - 1; j++) {
120 os << "[";
121 for (unsigned k = 0, c = numerators[i].getNumColumns(); k < c - 1; k++)
122 os << numerators[i].at(j, k) << ",";
123 os << numerators[i].getRow(j).back() << "],";
124 }
125 os << "[";
126 for (unsigned k = 0, c = numerators[i].getNumColumns(); k < c - 1; k++)
127 os << numerators[i].at(r - 1, k) << ",";
128 os << numerators[i].getRow(r - 1).back() << "]]/";
129
130 for (const Point &den : denominators[i]) {
131 os << "(x^[";
132 for (unsigned j = 0, e = den.size(); j < e - 1; j++)
133 os << den[j] << ",";
134 os << den.back() << "])";
135 }
136 }
137 return os;
138 }
139
140private:
141 unsigned numParam;
142 SmallVector<int> signs;
143 std::vector<ParamPoint> numerators;
144 std::vector<std::vector<Point>> denominators;
145};
146
147} // namespace detail
148} // namespace presburger
149} // namespace mlir
150
151#endif // MLIR_ANALYSIS_PRESBURGER_GENERATINGFUNCTION_H
const std::vector< std::vector< Point > > & getDenominators() const &
const SmallVector< int > & getSigns() const &
GeneratingFunction operator+(const GeneratingFunction &gf) const
const std::vector< ParamPoint > & getNumerators() const &
std::vector< ParamPoint > getNumerators() &&
llvm::raw_ostream & print(llvm::raw_ostream &os) const
std::vector< std::vector< Point > > getDenominators() &&
std::vector< std::vector< Point > > getDenominators() const &&
GeneratingFunction(unsigned numParam, SmallVector< int > signs, std::vector< ParamPoint > nums, std::vector< std::vector< Point > > dens)
std::vector< ParamPoint > getNumerators() const &&
SmallVector< Fraction > Point
Include the generated interface declarations.
Eliminates variable at the specified position using Fourier-Motzkin variable elimination.