The bliss C++ API
partition.hh
1 #pragma once
2 
3 /*
4  Copyright (c) 2003-2021 Tommi Junttila
5  Released under the GNU Lesser General Public License version 3.
6 
7  This file is part of bliss.
8 
9  bliss is free software: you can redistribute it and/or modify
10  it under the terms of the GNU Lesser General Public License as published by
11  the Free Software Foundation, version 3 of the License.
12 
13  bliss is distributed in the hope that it will be useful,
14  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  GNU Lesser General Public License for more details.
17 
18  You should have received a copy of the GNU Lesser General Public License
19  along with bliss. If not, see <http://www.gnu.org/licenses/>.
20 */
21 
22 namespace bliss {
23  class Partition;
24 }
25 
26 #include <vector>
27 #include <climits>
28 #include "kqueue.hh"
29 #include "abstractgraph.hh"
30 
31 
32 namespace bliss {
33 
44 class Partition
45 {
46 public:
50  class Cell
51  {
52  friend class Partition;
53  public:
54  unsigned int length;
55  /* Index of the first element of the cell in
56  the Partition::elements array */
57  unsigned int first;
58  unsigned int max_ival;
59  unsigned int max_ival_count;
60  private:
61  bool in_splitting_queue;
62  public:
63  bool in_neighbour_heap;
64  /* Pointer to the next cell, null if this is the last one. */
65  Cell* next;
66  Cell* prev;
67  Cell* next_nonsingleton;
68  Cell* prev_nonsingleton;
69  unsigned int split_level;
71  bool is_unit() const {return(length == 1); }
73  bool is_in_splitting_queue() const {return(in_splitting_queue); }
74  };
75 
76 
77 private:
78 
83  class RefInfo {
84  public:
85  unsigned int split_cell_first;
86  int prev_nonsingleton_first;
87  int next_nonsingleton_first;
88  };
92  std::vector<RefInfo> refinement_stack;
93 
94  class BacktrackInfo {
95  public:
96  unsigned int refinement_stack_size;
97  unsigned int cr_backtrack_point;
98  };
99 
103  std::vector<BacktrackInfo> bt_stack;
104 
105 public:
106  AbstractGraph* graph;
107 
108  /* Used during equitable partition refinement */
109  KQueue<Cell*> splitting_queue;
110  void splitting_queue_add(Cell* const cell);
111  Cell* splitting_queue_pop();
112  bool splitting_queue_is_empty() const;
113  void splitting_queue_clear();
114 
115 
117  typedef unsigned int BacktrackPoint;
118 
122  BacktrackPoint set_backtrack_point();
123 
127  void goto_backtrack_point(BacktrackPoint p);
128 
137  Cell* individualize(Cell* const cell,
138  const unsigned int element);
139 
140  Cell* aux_split_in_two(Cell* const cell,
141  const unsigned int first_half_size);
142 
143 
144 private:
145  unsigned int N;
146  Cell* cells;
147  Cell* free_cells;
148  unsigned int discrete_cell_count;
149 public:
150  Cell* first_cell;
151  Cell* first_nonsingleton_cell;
152  unsigned int *elements;
153  /* invariant_values[e] gives the invariant value of the element e */
154  unsigned int *invariant_values;
155  /* element_to_cell_map[e] gives the cell of the element e */
156  Cell **element_to_cell_map;
158  Cell* get_cell(const unsigned int e) const {
159  assert(e < N);
160  return element_to_cell_map[e];
161  }
162  /* in_pos[e] points to the elements array s.t. *in_pos[e] = e */
163  unsigned int **in_pos;
164 
165  Partition();
166  ~Partition();
167 
172  void init(const unsigned int N);
173 
178  bool is_discrete() const {return(free_cells == 0); }
179 
180  unsigned int nof_discrete_cells() const {return(discrete_cell_count); }
181 
185  size_t print(FILE* const fp, const bool add_newline = true) const;
186 
190  size_t print_signature(FILE* const fp, const bool add_newline = true) const;
191 
192  /*
193  * Splits the Cell \a cell into [cell_1,...,cell_n]
194  * according to the invariant_values of the elements in \a cell.
195  * After splitting, cell_1 == \a cell.
196  * Returns the pointer to the Cell cell_n;
197  * cell_n != cell iff the Cell \a cell was actually splitted.
198  * The flag \a max_ival_info_ok indicates whether the max_ival and
199  * max_ival_count fields of the Cell \a cell have consistent values
200  * when the method is called.
201  * Clears the invariant values of the elements in the Cell \a cell as well as
202  * the max_ival and max_ival_count fields of the Cell \a cell.
203  */
204  Cell *zplit_cell(Cell * const cell, const bool max_ival_info_ok);
205 
206  /*
207  * Routines for component recursion
208  */
209  void cr_init();
210  void cr_free();
211  unsigned int cr_get_level(const unsigned int cell_index) const;
212  unsigned int cr_split_level(const unsigned int level,
213  const std::vector<unsigned int>& cells);
214 
216  void clear_ivs(Cell* const cell);
217 
218 private:
219  /*
220  * Component recursion data structures
221  */
222 
223  /* Is component recursion support in use? */
224  bool cr_enabled;
225 
226  class CRCell {
227  public:
228  unsigned int level;
229  CRCell* next;
230  CRCell** prev_next_ptr;
231  void detach() {
232  if(next)
233  next->prev_next_ptr = prev_next_ptr;
234  *(prev_next_ptr) = next;
235  level = UINT_MAX;
236  next = nullptr;
237  prev_next_ptr = nullptr;
238  }
239  };
240  CRCell* cr_cells;
241  CRCell** cr_levels;
242  class CR_BTInfo {
243  public:
244  unsigned int created_trail_index;
245  unsigned int splitted_level_trail_index;
246  };
247  std::vector<unsigned int> cr_created_trail;
248  std::vector<unsigned int> cr_splitted_level_trail;
249  std::vector<CR_BTInfo> cr_bt_info;
250  unsigned int cr_max_level;
251  void cr_create_at_level(const unsigned int cell_index, unsigned int level);
252  void cr_create_at_level_trailed(const unsigned int cell_index, unsigned int level);
253  unsigned int cr_get_backtrack_point();
254  void cr_goto_backtrack_point(const unsigned int btpoint);
255 
256 
257  /*
258  *
259  * Auxiliary routines for sorting and splitting cells
260  *
261  */
262  Cell* sort_and_split_cell1(Cell* cell);
263  Cell* sort_and_split_cell255(Cell* const cell, const unsigned int max_ival);
264  bool shellsort_cell(Cell* cell);
265  Cell* split_cell(Cell* const cell);
266 
267  /*
268  * Some auxiliary stuff needed for distribution count sorting.
269  * To make the code thread-safe (modulo the requirement that each graph is
270  * only accessed in one thread at a time), the arrays are owned by
271  * the partition instance, not statically defined.
272  */
273  unsigned int dcs_count[256];
274  unsigned int dcs_start[256];
275  void dcs_cumulate_count(const unsigned int max);
276 };
277 
278 
279 inline Partition::Cell*
280 Partition::splitting_queue_pop()
281 {
282  assert(!splitting_queue.is_empty());
283  Cell* const cell = splitting_queue.pop_front();
284  assert(cell->in_splitting_queue);
285  cell->in_splitting_queue = false;
286  return cell;
287 }
288 
289 inline bool
290 Partition::splitting_queue_is_empty() const
291 {
292  return splitting_queue.is_empty();
293 }
294 
295 
296 inline unsigned int
297 Partition::cr_get_level(const unsigned int cell_index) const
298 {
299  assert(cr_enabled);
300  assert(cell_index < N);
301  assert(cr_cells[cell_index].level != UINT_MAX);
302  return(cr_cells[cell_index].level);
303 }
304 
305 } // namespace bliss
Definition: abstractgraph.cc:35
A simple implementation of queues with fixed maximum capacity.
Definition: kqueue.hh:31
Cell * individualize(Cell *const cell, const unsigned int element)
Definition: partition.cc:254
size_t print(FILE *const fp, const bool add_newline=true) const
Definition: partition.cc:353
BacktrackPoint set_backtrack_point()
Definition: partition.cc:147
void clear_ivs(Cell *const cell)
Definition: partition.cc:822
size_t print_signature(FILE *const fp, const bool add_newline=true) const
Definition: partition.cc:379
bool is_unit() const
Definition: partition.hh:71
unsigned int BacktrackPoint
Definition: partition.hh:117
Data structure for holding information about a cell in a Partition.
Definition: partition.hh:50
bool is_in_splitting_queue() const
Definition: partition.hh:73
bool is_discrete() const
Definition: partition.hh:178
void init(const unsigned int N)
Definition: partition.cc:64
An abstract base class for different types of graphs.
Definition: abstractgraph.hh:47
Cell * get_cell(const unsigned int e) const
Definition: partition.hh:158
A class for refinable, backtrackable ordered partitions.
Definition: partition.hh:44
void goto_backtrack_point(BacktrackPoint p)
Definition: partition.cc:161