Quetzal-CoaTL
The Coalescence Template Library
Loading...
Searching...
No Matches
Partitioner.hpp
1// Copyright 2021 Arnaud Becheler <abechele@umich.edu>
2
3/*********************************************************************** * This program is free software; you can
4 *redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free
5 *Software Foundation; either version 2 of the License, or * (at your option) any later version. *
6 * *
7 ***************************************************************************/
8
9#ifndef __PARTITIONER_H_INCLUDED__
10#define __PARTITIONER_H_INCLUDED__
11
12#include "assert.h"
13#include <list>
14#include <numeric> //iota
15#include <string>
16#include <vector>
17
18#include "RestrictedGrowthString.hpp"
19
21{
22namespace fuzzy_transfer_distance
23{
25{
26
27 using id_type = unsigned int;
28 using set_type = std::vector<id_type>;
29
30 public:
31 using RGS_type = std::vector<unsigned int>; // Restricted Growth String
32
33 template <typename T> Partitioner(T const &set) : m_set(enumerate_elements(set))
34 {
35 }
36
37 // http://www.computing-wisdom.com/computingreadings/fasc3b.pdf : response to exercice 17, page 68, 7.2.1.5
38 std::vector<RestrictedGrowthString> construct_all_m_blocks_partitions_of_the_set_by_algorithm_u(
39 unsigned int nb_blocks)
40 {
41
42 std::vector<RestrictedGrowthString> result;
43
44 if (nb_blocks == 1)
45 {
46
47 result.emplace_back(RGS_type(m_set.size(), 0));
48 }
49 else if (nb_blocks == m_set.size())
50 {
51 RGS_type v(m_set.size());
52 std::iota(std::begin(v), std::end(v), 0);
53 result.emplace_back(v);
54 }
55 else
56 {
57 assert((1 < nb_blocks) && (nb_blocks < m_set.size()));
58 auto n = m_set.size();
59 a = RGS_type(n + 1, 0);
60 for (unsigned int j = 1; j <= nb_blocks; ++j)
61 {
62 a[n - nb_blocks + j] = j - 1;
63 }
64
65 f(nb_blocks, n, 0);
66
67 for (auto &it : m_partitions)
68 {
69 it.erase(it.begin());
70 result.emplace_back(it);
71 }
72
73 m_partitions.clear();
74 }
75
76 return result;
77 }
78
79 private:
80 RGS_type a;
81 std::vector<RGS_type> m_partitions;
82 set_type m_set;
83
84 void visit()
85 {
86 m_partitions.push_back(a);
87 }
88
89 void f(unsigned int mu, unsigned int nu, unsigned int sigma)
90 {
91 if (mu == 2)
92 {
93 visit();
94 }
95 else
96 {
97 f(mu - 1, nu - 1, (mu + sigma) % 2);
98 }
99
100 if (nu == mu + 1)
101 {
102 a[mu] = mu - 1;
103 visit();
104 while (a[nu] > 0)
105 {
106 a[nu] = a[nu] - 1;
107 visit();
108 }
109 }
110 else if (nu > mu + 1)
111 {
112 if ((mu + sigma) % 2 == 1)
113 {
114 a[nu - 1] = mu - 1;
115 }
116 else
117 {
118 a[mu] = mu - 1;
119 }
120
121 if ((a[nu] + sigma) % 2 == 1)
122 {
123 b(mu, nu - 1, 0);
124 }
125 else
126 {
127 f(mu, nu - 1, 0);
128 }
129
130 while (a[nu] > 0)
131 {
132 a[nu] = a[nu] - 1;
133 if ((a[nu] + sigma) % 2 == 1)
134 {
135 b(mu, nu - 1, 0);
136 }
137 else
138 {
139 f(mu, nu - 1, 0);
140 }
141 }
142 }
143 }
144
145 void b(unsigned int mu, unsigned int nu, unsigned int sigma)
146 {
147 if (nu == mu + 1)
148 {
149 while (a[nu] < mu - 1)
150 {
151 visit();
152 a[nu] = a[nu] + 1;
153 }
154 visit();
155 a[mu] = 0;
156 }
157 else if (nu > mu + 1)
158 {
159 if ((a[nu] + sigma) % 2 == 1)
160 {
161 f(mu, nu - 1, 0);
162 }
163 else
164 {
165 b(mu, nu - 1, 0);
166 }
167
168 while (a[nu] < mu - 1)
169 {
170 a[nu] = a[nu] + 1;
171 if ((a[nu] + sigma) % 2 == 1)
172 {
173 f(mu, nu - 1, 0);
174 }
175 else
176 {
177 b(mu, nu - 1, 0);
178 }
179 }
180
181 if ((mu + sigma) % 2 == 1)
182 {
183 a[nu - 1] = 0;
184 }
185 else
186 {
187 a[mu] = 0;
188 }
189 }
190
191 if (mu == 2)
192 {
193 visit();
194 }
195 else
196 {
197 b(mu - 1, nu - 1, (mu + sigma) % 2);
198 }
199 }
200
201 template <typename T> set_type enumerate_elements(T const &set) const
202 {
203 std::vector<id_type> v(set.size());
204 std::iota(v.begin(), v.end(), 1);
205 return v;
206 }
207};
208} // end namespace fuzzy_transfer_distance
209} // namespace quetzal::polymorphism
210
211#endif
Generic components for polymorphism analysis.
Definition polymorphism.hpp:16