CppAD: A C++ Algorithmic Differentiation Package  20171217
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
sparse_list.hpp
Go to the documentation of this file.
1 # ifndef CPPAD_LOCAL_SPARSE_LIST_HPP
2 # define CPPAD_LOCAL_SPARSE_LIST_HPP
3 
4 /* --------------------------------------------------------------------------
5 CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-17 Bradley M. Bell
6 
7 CppAD is distributed under multiple licenses. This distribution is under
8 the terms of the
9  Eclipse Public License Version 1.0.
10 
11 A copy of this license is included in the COPYING file of this distribution.
12 Please visit http://www.coin-or.org/CppAD/ for information on other licenses.
13 -------------------------------------------------------------------------- */
14 # include <cppad/core/define.hpp>
15 # include <cppad/local/is_pod.hpp>
16 # include <list>
17 
18 namespace CppAD { namespace local { // BEGIN_CPPAD_LOCAL_NAMESPACE
19 /*!
20 \file sparse_list.hpp
21 Vector of sets of positive integers stored as singly linked lists
22 with the element values strictly increasing.
23 */
24 class sparse_list_const_iterator;
25 
26 // =========================================================================
27 /*!
28 Vector of sets of positive integers, each set stored as a singly
29 linked list.
30 
31 All the public members for this class are also in the
32 sparse_pack and sparse_vecsize classes.
33 This defines the CppAD vector_of_sets concept.
34 */
35 class sparse_list {
37 private:
38  // -----------------------------------------------------------------
39  /// type used for each entry in a singly linked list.
40  struct pair_size_t {
41  /// For the first entry in each list, this is the reference count.
42  /// For the other entries in the list this is an element of the set.
43  size_t value;
44 
45  /// This is the data index of the next entry in the list.
46  /// If there are no more entries in the list, this value is zero.
47  /// (The first entry in data_ is not used.)
48  size_t next;
49  };
50  friend bool is_pod<pair_size_t>(void);
51  // -----------------------------------------------------------------
52  /// Possible elements in each set are 0, 1, ..., end_ - 1;
53  size_t end_;
54 
55  /// number of elements in data_ that are not being used.
57 
58  /// list of elements of data_ that are not being used.
60 
61  /// The data for all the singly linked lists.
63 
64  /*!
65  Starting point for i-th set is start_[i].
66 
67  \li
68  If the i-th set has no elements, start_[i] is zero.
69  Otherwise the conditions below hold.
70 
71  \li
72  data_[ start_[i] ].value is the reference count for this list.
73  This element is not in the list.
74 
75  \li
76  data_[ start_[i] ].next point the the first element in the list
77  and is not zero because there is at least one entry in this list.
78 
79  \li
80  For all lists, the last pair in the list has data_ index zero,
81  data_[0].value == end_ and data_[0].next = 0, and is not in the set.
82  */
84 
85  /*!
86  Vectors of elements that have not yet been added to corresponding sets.
87 
88  \li
89  If all the post_element calls for the i-th set have been added,
90  post_[i] is zero. Otherwise the conditions below hold.
91 
92  \li
93  data_[ post_[i] ].value is the first element that has been posted,
94  but not yet added, to set i.
95 
96  \li
97  For all lists, the last pair in the list has data_ index zero,
98  data_[0].value == end_ and data_[0].next = 0, and is not in the posted
99  elements.
100  */
102 
103  /*!
104  A temporary vector used by member functions that keeps its capacity.
105  */
107 
108  // -----------------------------------------------------------------
109  /*!
110  Counts references to sets.
111 
112  \param i
113  is the index of the set that we are counting the references to.
114 
115  \return
116  if the set is empty, the return value is zero.
117  Otherwise it is the number of sets that share the same linked list
118  */
119  size_t reference_count(size_t i) const
120  { // start data index
121  size_t start = start_[i];
122  if( start == 0 )
123  return 0;
124  //
125  // reference count
126  return data_[start].value;
127  }
128  // -----------------------------------------------------------------
129  /*!
130  drop a set and its postings (no longer being used).
131 
132  \param i
133  is the index of the set that will be dropped.
134 
135  \par reference_count
136  if the set is non-empty,
137  the reference count data_[ start_[i] ] will be decremented.
138 
139  \par start_
140  The value start_[i] is set to zero.
141 
142  \par post_
143  the value post_[i] will be set to zero.
144 
145  \par data_not_used_
146  the eleemmnts of data_ that are dropped are added to this list.
147 
148  \return
149  is the additional number of elements of data_ that are not used.
150  This is non-zero when the initial reference count is one.
151  */
152  size_t drop(size_t i)
153  { // inialize count of addition elements not being used.
154  size_t number_drop = 0;
155 
156  // the elements in the post list will no longer be used
157  size_t post = post_[i];
158  if( post != 0 )
159  { // drop this posting
160  post_[i] = 0;
161  //
162  // count elements in this posting
163  ++number_drop;
164  size_t previous = post;
165  size_t next = data_[previous].next;
166  while( next != 0 )
167  { previous = next;
168  next = data_[previous].next;
169  ++number_drop;
170  }
171  //
172  // add the posting elements to data_not_used_
173  data_[previous].next = data_not_used_;
174  data_not_used_ = post;
175  }
176 
177  // check for empty set
178  size_t start = start_[i];
179  if( start == 0 )
180  return number_drop;
181 
182  // decrement reference counter
183  CPPAD_ASSERT_UNKNOWN( data_[start].value > 0 );
184  data_[start].value--;
185 
186  // set this set to empty
187  start_[i] = 0;
188 
189  // If new reference count is positive, the list corresponding to
190  // start is still being used.
191  if( data_[start].value > 0 )
192  return number_drop;
193 
194  //
195  // count elements representing this set
196  ++number_drop;
197  size_t previous = start;
198  size_t next = data_[previous].next;
199  while( next != 0 )
200  { previous = next;
201  next = data_[previous].next;
202  ++number_drop;
203  }
204  //
205  // add representing this set to data_not_used_
206  data_[previous].next = data_not_used_;
207  data_not_used_ = start;
208  //
209  return number_drop;
210  }
211  // -----------------------------------------------------------------
212  /*!
213  get a new data_ element for use.
214 
215  \par number_not_used_
216  if this is non-zero, it is decremented by one.
217 
218  \par data_not_used_
219  if this list is non-empty, one element is removed from it.
220 
221  \return
222  is the index in data_ of the new element.
223  */
224  size_t get_data_index(void)
225  { size_t index;
226  if( data_not_used_ > 0 )
229  index = data_not_used_;
230  data_not_used_ = data_[index].next;
231  }
232  else
233  { index = data_.extend(1);
234  }
235  return index;
236  }
237  // -----------------------------------------------------------------
238  /*!
239  Checks data structure
240  (effectively const, but modifies and restores values)
241  */
242 # ifdef NDEBUG
243  void check_data_structure(void)
244  { return; }
245 # else
247  { // number of sets
249  size_t n_set = start_.size();
250  if( n_set == 0 )
251  { CPPAD_ASSERT_UNKNOWN( end_ == 0 );
254  CPPAD_ASSERT_UNKNOWN( data_.size() == 0 );
255  CPPAD_ASSERT_UNKNOWN( start_.size() == 0 );
256  return;
257  }
258  // check data index zero
259  CPPAD_ASSERT_UNKNOWN( data_[0].value == end_ );
260  CPPAD_ASSERT_UNKNOWN( data_[0].next == 0 );
261  // -----------------------------------------------------------
262  // save the reference counters
263  pod_vector<size_t> ref_count(n_set);
264  for(size_t i = 0; i < n_set; i++)
265  ref_count[i] = reference_count(i);
266  // -----------------------------------------------------------
267  // number of entries in data used by sets and posts
268  size_t number_used_by_sets = 1;
269  // -----------------------------------------------------------
270  // count the number of entries in data_ that are used by sets
271  for(size_t i = 0; i < n_set; i++)
272  { size_t start = start_[i];
273  if( start > 0 )
274  { // check structure for this non-empty set
275  size_t reference_count = data_[start].value;
276  size_t next = data_[start].next;
277  CPPAD_ASSERT_UNKNOWN( reference_count > 0 );
278  CPPAD_ASSERT_UNKNOWN( next != 0 );
279  CPPAD_ASSERT_UNKNOWN( data_[next].value < end_ );
280  //
281  // decrement the reference counter
282  data_[start].value--;
283  //
284  // count the entries when find last reference
285  if( data_[start].value == 0 )
286  {
287  // restore reference count
288  data_[start].value = ref_count[i];
289 
290  // number of data entries used for this set
291  number_used_by_sets += number_elements(i) + 1;
292  /*
293  number of elements checks that value < end_
294  each pair in the list except for the start pair
295  and the pair with index zero.
296  */
297  }
298  }
299  }
300  // ------------------------------------------------------------------
301  // count the number of entries in data_ that are used by posts
302  size_t number_used_by_posts = 0;
303  for(size_t i = 0; i < n_set; i++)
304  { size_t post = post_[i];
305  if( post > 0 )
306  { size_t value = data_[post].value;
307  size_t next = data_[post].next;
308  CPPAD_ASSERT_UNKNOWN( value < end_ );
309  //
310  while( value < end_ )
311  { ++number_used_by_posts;
312  value = data_[next].value;
313  next = data_[next].next;
314  }
315  }
316  }
317  // ------------------------------------------------------------------
318  // count number of entries in data_not_used_
319  size_t count = 0;
320  size_t next = data_not_used_;
321  while( next != 0 )
322  { ++count;
323  next = data_[next].next;
324  }
326  // ------------------------------------------------------------------
327  size_t number_used = number_used_by_sets + number_used_by_posts;
329  number_used + number_not_used_ == data_.size()
330  );
331  return;
332  }
333 # endif
334  // -----------------------------------------------------------------
335  /*!
336  Check if one of two sets is a subset of the other set
337 
338  \param one_this
339  is the index in this sparse_sizevec object of the first set.
340 
341  \param two_other
342  is the index in other sparse_sizevec object of the second set.
343 
344  \param other
345  is the other sparse_sizevec object which may be the same as this object.
346 
347  \return
348  If zero, niether set is a subset of the other.
349  If one, then one is a subset of two and they are not equal.
350  If two, then two is a subset of one and they are not equal.
351  If three, then the sets are equal.
352  */
353  size_t is_subset(
354  size_t one_this ,
355  size_t two_other ,
356  const sparse_list& other ) const
357  {
358  CPPAD_ASSERT_UNKNOWN( one_this < start_.size() );
359  CPPAD_ASSERT_UNKNOWN( two_other < other.start_.size() );
360  CPPAD_ASSERT_UNKNOWN( end_ == other.end_ );
361  //
362  // start
363  size_t start_one = start_[one_this];
364  size_t start_two = other.start_[two_other];
365  //
366  if( start_one == 0 )
367  { // set one is empty
368  if( start_two == 0 )
369  { // set two is empty
370  return 3;
371  }
372  return 1;
373  }
374  if( start_two == 0 )
375  { // set two is empty and one is not empty
376  return 2;
377  }
378  //
379  // next
380  size_t next_one = data_[start_one].next;
381  size_t next_two = other.data_[start_two].next;
382  //
383  // value
384  size_t value_one = data_[next_one].value;
385  size_t value_two = other.data_[next_two].value;
386  //
387  bool one_subset = true;
388  bool two_subset = true;
389  //
390  size_t value_union = std::min(value_one, value_two);
391  while( (one_subset | two_subset) & (value_union < end_) )
392  { if( value_one > value_union )
393  two_subset = false;
394  else
395  { next_one = data_[next_one].next;
396  value_one = data_[next_one].value;
397  }
398  if( value_two > value_union )
399  one_subset = false;
400  else
401  { next_two = other.data_[next_two].next;
402  value_two = other.data_[next_two].value;
403  }
404  value_union = std::min(value_one, value_two);
405  }
406  if( one_subset )
407  { if( two_subset )
408  { // sets are equal
409  return 3;
410  }
411  // one is a subset of two
412  return 1;
413  }
414  if( two_subset )
415  { // two is a subset of one
416  return 2;
417  }
418  //
419  // neither is a subset
420  return 0;
421  }
422  // -----------------------------------------------------------------
423  /*!
424  Assign a set equal to the union of a set and a vector;
425 
426  \param target
427  is the index in this sparse_list object of the set being assinged.
428 
429  \param left
430  is the index in this sparse_list object of the
431  left operand for the union operation.
432  It is OK for target and left to be the same value.
433 
434  \param right
435  is a vector of size_t, sorted in accending order.
436  right operand for the union operation.
437  Elements can be repeated in right, but are not be repeated in the
438  resulting set.
439  All of the elements must have value less than end();
440  */
442  size_t target ,
443  size_t left ,
444  const pod_vector<size_t>& right )
445  { CPPAD_ASSERT_UNKNOWN( post_[left] == 0 );
446  //
447  CPPAD_ASSERT_UNKNOWN( target < start_.size() );
448  CPPAD_ASSERT_UNKNOWN( left < start_.size() );
449 
450  // get start indices before drop modifies modify start_ in case target
451  // and left are the same.
452  size_t start_left = start_[left];
453 
454  // -------------------------------------------------------------------
455  // Check if right is a subset of left so that we used reference count
456  // and not copies of identical sets.
457  //
458  // initialize index for left and right sets
459  size_t current_left = start_left;
460  size_t current_right = 0;
461  //
462  // initialize value_left
463  size_t value_left = end_;
464  if( current_left > 0 )
465  { // advance from reference counter to data
466  current_left = data_[current_left].next;
467  CPPAD_ASSERT_UNKNOWN( current_left != 0 )
468  //
469  value_left = data_[current_left].value;
470  CPPAD_ASSERT_UNKNOWN( value_left < end_);
471  }
472  //
473  // initialize value_right
474  size_t value_right = end_;
475  if( right.size() > 0 )
476  value_right = right[current_right];
477  //
478  bool subset = true;
479  while( subset & (value_right < end_) )
480  { while( value_left < value_right )
481  { // advance left
482  current_left = data_[current_left].next;
483  value_left = data_[current_left].value;
484  }
485  if( value_right < value_left )
486  subset = false;
487  else
488  { // advance right
489  ++current_right;
490  if( current_right == right.size() )
491  value_right = end_;
492  else
493  value_right = right[current_right];
494  }
495  }
496  //
497  if( subset )
498  { // target = left will use reference count for identical sets
499  assignment(target, left, *this);
500  return;
501  }
502 
503  // -------------------------------------------------------------------
504 
505  // start new version of target
506  size_t start = get_data_index();
507  data_[start].value = 1; // reference count
508  //
509  // previous index for new set
510  size_t previous_target = start;
511  //
512  // initialize index for left and right sets
513  current_left = start_left;
514  current_right = 0;
515  //
516  // initialize value_left
517  value_left = end_;
518  if( current_left > 0 )
519  { // advance from reference counter to data
520  current_left = data_[current_left].next;
521  CPPAD_ASSERT_UNKNOWN( current_left != 0 )
522  //
523  value_left = data_[current_left].value;
524  CPPAD_ASSERT_UNKNOWN( value_left < end_);
525  }
526  //
527  // initialize value_right
528  value_right = end_;
529  if( right.size() > 0 )
530  value_right = right[current_right];
531  //
532  // merge
533  while( (value_left < end_) | (value_right < end_) )
534  { if( value_left == value_right)
535  { // advance left so left and right are no longer equal
536  current_left = data_[current_left].next;
537  value_left = data_[current_left].value;
538  CPPAD_ASSERT_UNKNOWN( value_right < value_left );
539  }
540  // place to put new element
541  size_t current_target = get_data_index();
542  data_[previous_target].next = current_target;
543  //
544  if( value_left < value_right )
545  { // value_left case
546  CPPAD_ASSERT_UNKNOWN( value_left < end_ );
547  data_[current_target].value = value_left;
548  //
549  // advance left
550  current_left = data_[current_left].next;
551  value_left = data_[current_left].value;
552  }
553  else
554  { CPPAD_ASSERT_UNKNOWN( value_right < value_left )
555  // value_right case
556  CPPAD_ASSERT_UNKNOWN( value_right < end_);
557  data_[current_target].value = value_right;
558  //
559  // advance right (skip values equal to this one)
560  size_t previous_value = value_right;
561  while( value_right == previous_value )
562  { ++current_right;
563  if( current_right == right.size() )
564  value_right = end_;
565  else
566  { value_right = right[current_right];
567  CPPAD_ASSERT_UNKNOWN( value_right < end_ );
568  }
569  }
570  }
571  // done setting current target value
572  previous_target = current_target;
573  }
574  // make end of target list
575  data_[previous_target].next = 0;
576 
577  // adjust number_not_used_
578  size_t number_drop = drop(target);
579  number_not_used_ += number_drop;
580 
581  // set the new start value for target
582  start_[target] = start;
583 
584  return;
585  }
586 // ===========================================================================
587 public:
588  /// declare a const iterator
590  // -----------------------------------------------------------------
591  /*!
592  Default constructor (no sets)
593  */
594  sparse_list(void) :
595  end_(0) ,
596  number_not_used_(0) ,
597  data_not_used_(0) ,
598  data_(0) ,
599  start_(0) ,
600  post_(0)
601  { }
602  // -----------------------------------------------------------------
603  /// Destructor
606  }
607  // -----------------------------------------------------------------
608  /*!
609  Using copy constructor is a programing (not user) error
610 
611  \param v
612  vector of sets that we are attempting to make a copy of.
613  */
615  { // Error: Probably a sparse_list argument has been passed by value
616  CPPAD_ASSERT_UNKNOWN(false);
617  }
618  // -----------------------------------------------------------------
619  /*!
620  Assignement operator.
621 
622  \param other
623  this sparse_list with be set to a deep copy of other.
624 
625  \par vector_of_sets
626  This public member function is not yet part of
627  the vector_of_sets concept.
628  */
629  void operator=(const sparse_list& other)
630  { end_ = other.end_;
633  data_ = other.data_;
634  start_ = other.start_;
635  post_ = other.post_;
636  }
637  // -----------------------------------------------------------------
638  /*!
639  Start a new vector of sets.
640 
641  \param n_set
642  is the number of sets in this vector of sets.
643  \li
644  If n_set is zero, any memory currently allocated for this object
645  is freed.
646  \li
647  If n_set is non-zero, a vector of n_set sets is created and all
648  the sets are initilaized as empty.
649 
650  \param end
651  is the maximum element plus one (the minimum element is 0).
652  If n_set is zero, end must also be zero.
653  */
654  void resize(size_t n_set, size_t end)
656 
657  if( n_set == 0 )
658  { CPPAD_ASSERT_UNKNOWN( end == 0 );
659  //
660  // restore object to start after constructor
661  // (no memory allocated for this object)
662  data_.clear();
663  start_.clear();
664  post_.clear();
665  number_not_used_ = 0;
666  data_not_used_ = 0;
667  end_ = 0;
668  //
669  return;
670  }
671  end_ = end;
672  //
673  start_.resize(n_set);
674  post_.resize(n_set);
675  //
676  for(size_t i = 0; i < n_set; i++)
677  { start_[i] = 0;
678  post_[i] = 0;
679  }
680  //
681  // last element, marks the end for all lists
682  data_.resize(1);
683  data_[0].value = end_;
684  data_[0].next = 0;
685  //
686  number_not_used_ = 0;
687  data_not_used_ = 0;
688  }
689  // -----------------------------------------------------------------
690  /*!
691  Count number of elements in a set.
692 
693  \param i
694  is the index of the set we are counting the elements of.
695 
696  \par
697  number of elements checks that value < end_ for each element of the set.
698  */
699  size_t number_elements(size_t i) const
700  { CPPAD_ASSERT_UNKNOWN( post_[i] == 0 );
701 
702  // check if the set is empty
703  size_t start = start_[i];
704  if( start == 0 )
705  return 0;
706 
707  // initialize counter
708  size_t count = 0;
709 
710  // advance to the first element in the set
711  size_t next = data_[start].next;
712  while( next != 0 )
713  { CPPAD_ASSERT_UNKNOWN( data_[next].value < end_ );
714  count++;
715  next = data_[next].next;
716  }
717  CPPAD_ASSERT_UNKNOWN( count > 0 );
718  return count;
719  }
720  /*!
721  Post an element for delayed addition to a set.
722 
723  \param i
724  is the index for this set in the vector of sets.
725 
726  \param element
727  is the value of the element that we are posting.
728  The same element may be posted multiple times.
729 
730  \par
731  It is faster to post multiple elements to set i and then call
732  process_post(i) then to add each element individually.
733  It is an error to call any member function,
734  that depends on the value of set i,
735  before processing the posts to set i.
736  */
737  void post_element(size_t i, size_t element)
738  { CPPAD_ASSERT_UNKNOWN( i < start_.size() );
739  CPPAD_ASSERT_UNKNOWN( element < end_ );
740 
741  // put element at the front of this list
742  size_t next = post_[i];
743  size_t post = get_data_index();
744  post_[i] = post;
745  data_[post].value = element;
746  data_[post].next = next;
747 
748  return;
749  }
750  // -----------------------------------------------------------------
751  /*!
752  process post entries for a specific set.
753 
754  \param i
755  index of the set for which we are processing the post entries.
756 
757  \par post_
758  Upon call, post_[i] is location in data_ of the elements that get
759  added to the i-th set. Upon return, post_[i] is zero.
760  */
761  void process_post(size_t i)
762  { // post
763  size_t post = post_[i];
764  //
765  // check if there are no elements to process
766  if( post == 0 )
767  return;
768  //
769  // check if there is only one element to process
770  size_t next = data_[post].next;
771  if( next == 0 )
772  { // done with this posting
773  size_t value = data_[post].value;
774  post_[i] = 0;
775  data_[post].next = data_not_used_;
776  data_not_used_ = post;
778  //
779  add_element(i, value);
780  //
781  return;
782  }
783  //
784  // copy the elements that need to be processed into temporary
785  temporary_.resize(0);
786  size_t previous = post;
787  size_t value = data_[previous].value;
788  CPPAD_ASSERT_UNKNOWN( value < end_ );
789  temporary_.push_back(value);
790  while( next != 0 )
791  { previous = next;
792  value = data_[previous].value;
793  CPPAD_ASSERT_UNKNOWN( value < end_ );
794  temporary_.push_back(value);
795  next = data_[previous].next;
796  }
797  size_t number_post = temporary_.size();
798  //
799  // done with this posting
800  post_[i] = 0;
801  data_[previous].next = data_not_used_;
802  data_not_used_ = post;
803  number_not_used_ += number_post;;
804  //
805  // sort temporary_
806  CPPAD_ASSERT_UNKNOWN( number_post > 1 );
807  std::sort( temporary_.data(), temporary_.data() + number_post);
808  //
809  // add the elements to the set
810  binary_union(i, i, temporary_);
811  //
812  return;
813  }
814  // -----------------------------------------------------------------
815  /*!
816  Add one element to a set.
817 
818  \param i
819  is the index for this set in the vector of sets.
820 
821  \param element
822  is the element we are adding to the set.
823  */
824  void add_element(size_t i, size_t element)
825  { CPPAD_ASSERT_UNKNOWN( i < start_.size() );
826  CPPAD_ASSERT_UNKNOWN( element < end_ );
827 
828  // check for case where starting set is empty
829  size_t start = start_[i];
830  if( start == 0 )
831  { start = get_data_index();
832  start_[i] = start;
833  data_[start].value = 1; // reference count
834  //
835  size_t next = get_data_index();
836  data_[start].next = next;
837  //
838  data_[next].value = element;
839  data_[next].next = 0;
840  return;
841  }
842  //
843  // start of set with this index
844  size_t previous = start_[i];
845  //
846  // first entry in this set
847  size_t next = data_[previous].next;
848  size_t value = data_[next].value;
849  //
850  // locate place to insert this element
851  while( value < element )
852  { previous = next;
853  next = data_[next].next;
854  value = data_[next].value;
855  }
856  //
857  // check for case where element is in the set
858  if( value == element )
859  return;
860  //
861  //
862  // check for case where this is the only reference to this set
863  CPPAD_ASSERT_UNKNOWN( element < value );
864  if( data_[start].value == 1 )
865  { size_t insert = get_data_index();
866  data_[insert].next = next;
867  data_[insert].value = element;
868  data_[previous].next = insert;
869  //
870  return;
871  }
872  //
873  // must make a separate copy with new element inserted
874  CPPAD_ASSERT_UNKNOWN( data_[start].value > 1 );
875  data_[start].value--; // reverence counter for old list
876  //
877  size_t start_new = get_data_index();
878  data_[start_new].value = 1; // reference counter for new list
879  size_t previous_new = start_new;
880  //
881  // start of old set with this index
882  previous = start_[i];
883  //
884  // first entry in old set
885  next = data_[previous].next;
886  value = data_[next].value;
887  //
888  // locate place to insert this element
889  while( value < element )
890  { // copy to new list
891  size_t next_new = get_data_index();
892  data_[previous_new].next = next_new;
893  data_[next_new].value = value;
894  previous_new = next_new;
895  //
896  // get next value
897  previous = next;
898  next = data_[next].next;
899  value = data_[next].value;
900  }
901  CPPAD_ASSERT_UNKNOWN( element < value );
902  //
903  // insert the element
904  size_t next_new = get_data_index();
905  data_[previous_new].next = next_new;
906  data_[next_new].value = element;
907  previous_new = next_new;
908  //
909  // copy rest of the old set
910  while( value < end_ )
911  { // copy to new list
912  next_new = get_data_index();
913  data_[previous_new].next = next_new;
914  data_[next_new].value = value;
915  previous_new = next_new;
916  //
917  // get next value
918  previous = next;
919  next = data_[next].next;
920  value = data_[next].value;
921  }
922  CPPAD_ASSERT_UNKNOWN( next == 0 );
923  data_[previous_new].next = 0;
924  //
925  // hook up new list
926  start_[i] = start_new;
927  return;
928  }
929  // -----------------------------------------------------------------
930  /*!
931  check an element is in a set.
932 
933  \param i
934  is the index for this set in the vector of sets.
935 
936  \param element
937  is the element we are checking to see if it is in the set.
938  */
939  bool is_element(size_t i, size_t element) const
940  { CPPAD_ASSERT_UNKNOWN( post_[i] == 0 );
941  CPPAD_ASSERT_UNKNOWN( element < end_ );
942  //
943  size_t start = start_[i];
944  if( start == 0 )
945  return false;
946  //
947  size_t next = data_[start].next;
948  size_t value = data_[next].value;
949  while( value < element )
950  { next = data_[next].next;
951  value = data_[next].value;
952  }
953  return element == value;
954  }
955  // -----------------------------------------------------------------
956  /*!
957  Assign the empty set to one of the sets.
958 
959  \param target
960  is the index of the set we are setting to the empty set.
961 
962  \par number_not_used_
963  increments this value by additional number of data_ elements that are
964  no longer being used.
965  */
966  void clear(size_t target)
967  { CPPAD_ASSERT_UNKNOWN( target < start_.size() );
968 
969  // adjust number_not_used_
970  size_t number_drop = drop(target);
971  number_not_used_ += number_drop;
972 
973  return;
974  }
975  // -----------------------------------------------------------------
976  /*!
977  Assign one set equal to another set.
978 
979  \param this_target
980  is the index in this sparse_list object of the set being assinged.
981 
982  \param other_source
983  is the index in the other \c sparse_list object of the
984  set that we are using as the value to assign to the target set.
985 
986  \param other
987  is the other sparse_list object (which may be the same as this
988  sparse_list object). This must have the same value for end_.
989 
990  \par number_not_used_
991  increments this value by additional number of elements not being used.
992  */
994  size_t this_target ,
995  size_t other_source ,
996  const sparse_list& other )
997  { CPPAD_ASSERT_UNKNOWN( other.post_[ other_source ] == 0 );
998  //
999  CPPAD_ASSERT_UNKNOWN( this_target < start_.size() );
1000  CPPAD_ASSERT_UNKNOWN( other_source < other.start_.size() );
1001  CPPAD_ASSERT_UNKNOWN( end_ == other.end_ );
1002 
1003  // check if we are assigning a set to itself
1004  if( (this == &other) & (this_target == other_source) )
1005  return;
1006 
1007  // set depending on cases below
1008  size_t this_start;
1009 
1010  // If this and other are the same, use another reference to same list
1011  size_t other_start = other.start_[other_source];
1012  if( this == &other )
1013  { this_start = other_start;
1014  if( other_start != 0 )
1015  { data_[other_start].value++; // increment reference count
1016  CPPAD_ASSERT_UNKNOWN( data_[other_start].value > 1 );
1017  }
1018  }
1019  else if( other_start == 0 )
1020  { this_start = 0;
1021  }
1022  else
1023  { // make a copy of the other list in this sparse_list
1024  this_start = get_data_index();
1025  size_t this_next = get_data_index();
1026  data_[this_start].value = 1; // reference count
1027  data_[this_start].next = this_next;
1028  //
1029  size_t next = other.data_[other_start].next;
1030  CPPAD_ASSERT_UNKNOWN( next != 0 );
1031  while( next != 0 )
1032  { data_[this_next].value = other.data_[next].value;
1033  next = other.data_[next].next;
1034  if( next == 0 )
1035  data_[this_next].next = 0;
1036  else
1037  { size_t tmp = get_data_index();
1038  data_[this_next].next = tmp;
1039  this_next = tmp;
1040  }
1041  }
1042  }
1043 
1044  // adjust number_not_used_
1045  size_t number_drop = drop(this_target);
1046  number_not_used_ += number_drop;
1047 
1048  // set the new start value for this_target
1049  start_[this_target] = this_start;
1050 
1051  return;
1052  }
1053  // -----------------------------------------------------------------
1054  /*!
1055  Assign a set equal to the union of two other sets.
1056 
1057  \param this_target
1058  is the index in this sparse_list object of the set being assinged.
1059 
1060  \param this_left
1061  is the index in this sparse_list object of the
1062  left operand for the union operation.
1063  It is OK for this_target and this_left to be the same value.
1064 
1065  \param other_right
1066  is the index in the other sparse_list object of the
1067  right operand for the union operation.
1068  It is OK for this_target and other_right to be the same value.
1069 
1070  \param other
1071  is the other sparse_list object (which may be the same as this
1072  sparse_list object).
1073  */
1075  size_t this_target ,
1076  size_t this_left ,
1077  size_t other_right ,
1078  const sparse_list& other )
1079  { CPPAD_ASSERT_UNKNOWN( post_[this_left] == 0 );
1080  CPPAD_ASSERT_UNKNOWN( other.post_[ other_right ] == 0 );
1081  //
1082  CPPAD_ASSERT_UNKNOWN( this_target < start_.size() );
1083  CPPAD_ASSERT_UNKNOWN( this_left < start_.size() );
1084  CPPAD_ASSERT_UNKNOWN( other_right < other.start_.size() );
1085  CPPAD_ASSERT_UNKNOWN( end_ == other.end_ );
1086 
1087  // check if one of the two operands is a subset of the the other
1088  size_t subset = is_subset(this_left, other_right, other);
1089 
1090  // case where right is a subset of left or right and left are equal
1091  if( subset == 2 || subset == 3 )
1092  { assignment(this_target, this_left, *this);
1093  return;
1094  }
1095  // case where the left is a subset of right and they are not equal
1096  if( subset == 1 )
1097  { assignment(this_target, other_right, other);
1098  return;
1099  }
1100  // if niether case holds, then both left and right are non-empty
1101  CPPAD_ASSERT_UNKNOWN( reference_count(this_left) > 0 );
1102  CPPAD_ASSERT_UNKNOWN( other.reference_count(other_right) > 0 );
1103 
1104  // must get all the start indices before modify start_this
1105  // (incase start_this is the same as start_left or start_right)
1106  size_t start_left = start_[this_left];
1107  size_t start_right = other.start_[other_right];
1108 
1109  // start the new list
1110  size_t start = get_data_index();
1111  size_t next = start;
1112  data_[start].value = 1; // reference count
1113 
1114  // next for left and right lists
1115  size_t next_left = data_[start_left].next;
1116  size_t next_right = other.data_[start_right].next;
1117 
1118  // value for left and right sets
1119  size_t value_left = data_[next_left].value;
1120  size_t value_right = other.data_[next_right].value;
1121 
1122  CPPAD_ASSERT_UNKNOWN( value_left < end_ && value_right < end_ );
1123  while( (value_left < end_) | (value_right < end_) )
1124  { if( value_left == value_right )
1125  { // advance right so left and right are no longer equal
1126  next_right = other.data_[next_right].next;
1127  value_right = other.data_[next_right].value;
1128  }
1129  if( value_left < value_right )
1130  { size_t tmp = get_data_index();
1131  data_[next].next = tmp;
1132  next = tmp;
1133  data_[next].value = value_left;
1134  // advance left to its next element
1135  next_left = data_[next_left].next;
1136  value_left = data_[next_left].value;
1137  }
1138  else
1139  { CPPAD_ASSERT_UNKNOWN( value_right < value_left )
1140  size_t tmp = get_data_index();
1141  data_[next].next = tmp;
1142  next = tmp;
1143  data_[next].value = value_right;
1144  // advance right to its next element
1145  next_right = other.data_[next_right].next;
1146  value_right = other.data_[next_right].value;
1147  }
1148  }
1149  data_[next].next = 0;
1150 
1151  // adjust number_not_used_
1152  size_t number_drop = drop(this_target);
1153  number_not_used_ += number_drop;
1154 
1155  // set the new start value for this_target
1156  start_[this_target] = start;
1157 
1158  return;
1159  }
1160  // -----------------------------------------------------------------
1161  /*!
1162  Assign a set equal to the intersection of two other sets.
1163 
1164  \param this_target
1165  is the index in this sparse_list object of the set being assinged.
1166 
1167  \param this_left
1168  is the index in this sparse_list object of the
1169  left operand for the intersection operation.
1170  It is OK for this_target and this_left to be the same value.
1171 
1172  \param other_right
1173  is the index in the other sparse_list object of the
1174  right operand for the intersection operation.
1175  It is OK for this_target and other_right to be the same value.
1176 
1177  \param other
1178  is the other sparse_list object (which may be the same as this
1179  sparse_list object).
1180  */
1182  size_t this_target ,
1183  size_t this_left ,
1184  size_t other_right ,
1185  const sparse_list& other )
1186  { CPPAD_ASSERT_UNKNOWN( post_[this_left] == 0 );
1187  CPPAD_ASSERT_UNKNOWN( other.post_[ other_right ] == 0 );
1188  //
1189  CPPAD_ASSERT_UNKNOWN( this_target < start_.size() );
1190  CPPAD_ASSERT_UNKNOWN( this_left < start_.size() );
1191  CPPAD_ASSERT_UNKNOWN( other_right < other.start_.size() );
1192  CPPAD_ASSERT_UNKNOWN( end_ == other.end_ );
1193  //
1194  // check if one of the two operands is a subset of the the other
1195  size_t subset = is_subset(this_left, other_right, other);
1196 
1197  // case where left is a subset of right or left and right are equal
1198  if( subset == 1 || subset == 3 )
1199  { assignment(this_target, this_left, *this);
1200  return;
1201  }
1202  // case where the right is a subset of left and they are not equal
1203  if( subset == 2 )
1204  { assignment(this_target, other_right, other);
1205  return;
1206  }
1207  // if niether case holds, then both left and right are non-empty
1208  CPPAD_ASSERT_UNKNOWN( reference_count(this_left) > 0 );
1209  CPPAD_ASSERT_UNKNOWN( other.reference_count(other_right) > 0 );
1210 
1211  // must get all the start indices before modify start_this
1212  // (incase start_this is the same as start_left or start_right)
1213  size_t start_left = start_[this_left];
1214  size_t start_right = other.start_[other_right];
1215 
1216  // start the new list as emptyh
1217  size_t start = 0;
1218  size_t next = start;
1219 
1220  // next for left and right lists
1221  size_t next_left = data_[start_left].next;
1222  size_t next_right = other.data_[start_right].next;
1223 
1224  // value for left and right sets
1225  size_t value_left = data_[next_left].value;
1226  size_t value_right = other.data_[next_right].value;
1227 
1228  CPPAD_ASSERT_UNKNOWN( value_left < end_ && value_right < end_ );
1229  while( (value_left < end_) & (value_right < end_) )
1230  { if( value_left == value_right )
1231  { if( start == 0 )
1232  { // this is the first element in the intersection
1233  start = get_data_index();
1234  next = start;
1235  start_[this_target] = start;
1236  data_[start].value = 1; // reference count
1237  CPPAD_ASSERT_UNKNOWN( start > 0 );
1238  }
1239  size_t tmp = get_data_index();
1240  data_[next].next = tmp;
1241  next = tmp;
1242  data_[next].value = value_left;
1243  //
1244  // advance left
1245  next_left = data_[next_left].next;
1246  value_left = data_[next_left].value;
1247  //
1248  }
1249  if( value_left > value_right )
1250  { // advance right
1251  next_right = other.data_[next_right].next;
1252  value_right = other.data_[next_right].value;
1253  }
1254  if( value_right > value_left )
1255  { // advance left
1256  next_left = data_[next_left].next;
1257  value_left = data_[next_left].value;
1258  }
1259  }
1260  if( start != 0 )
1261  { CPPAD_ASSERT_UNKNOWN( next != 0 );
1262  data_[next].next = 0;
1263  }
1264 
1265  // adjust number_not_used_
1266  size_t number_drop = drop(this_target);
1267  number_not_used_ += number_drop;
1268 
1269  // set new start for this_target
1270  start_[this_target] = start;
1271 
1272  return;
1273  }
1274  // -----------------------------------------------------------------
1275  /*! Fetch n_set for vector of sets object.
1276 
1277  \return
1278  Number of from sets for this vector of sets object
1279  */
1280  size_t n_set(void) const
1281  { return start_.size(); }
1282  // -----------------------------------------------------------------
1283  /*! Fetch end for this vector of sets object.
1284 
1285  \return
1286  is the maximum element value plus one (the minimum element value is 0).
1287  */
1288  size_t end(void) const
1289  { return end_; }
1290  // -----------------------------------------------------------------
1291  /*! Amount of memory used by this vector of sets
1292 
1293  \return
1294  The amount of memory in units of type unsigned char memory.
1295  */
1296  size_t memory(void) const
1297  { return data_.capacity() * sizeof(pair_size_t);
1298  }
1299  /*!
1300  Print the vector of sets (used for debugging)
1301  */
1302  void print(void) const;
1303 };
1304 // =========================================================================
1305 /*!
1306 cons_iterator for one set of positive integers in a sparse_list object.
1307 
1308 All the public members for this class are also in the
1309 sparse_pack_const_iterator and sparse_sizevec_const_iterator classes.
1310 This defines the CppAD vector_of_sets iterator concept.
1311 */
1313 private:
1314  /// type used by sparse_list to represent one element of the list
1316 
1317  /// data for the entire vector of sets
1319 
1320  /// Possible elements in a list are 0, 1, ..., end_ - 1;
1321  const size_t end_;
1322 
1323  /// next element in the singly linked list
1324  /// (next_pair_.value == end_ for past end of list)
1326 public:
1327  /// construct a const_iterator for a list in a sparse_list object
1328  sparse_list_const_iterator (const sparse_list& list, size_t i)
1329  :
1330  data_( list.data_ ) ,
1331  end_ ( list.end_ )
1332  { CPPAD_ASSERT_UNKNOWN( list.post_[i] == 0 );
1333  //
1334  size_t start = list.start_[i];
1335  if( start == 0 )
1336  { next_pair_.next = 0;
1337  next_pair_.value = end_;
1338  }
1339  else
1340  { // value for this entry is reference count for list
1341  CPPAD_ASSERT_UNKNOWN( data_[start].value > 0 );
1342 
1343  // data index where list truely starts
1344  size_t next = data_[start].next;
1345  CPPAD_ASSERT_UNKNOWN( next != 0 );
1346 
1347  // true first entry in the list
1348  next_pair_ = data_[next];
1350  }
1351  }
1352 
1353  /// advance to next element in this list
1356  return *this;
1357  }
1358 
1359  /// obtain value of this element of the set of positive integers
1360  /// (end_ for no such element)
1361  size_t operator*(void)
1362  { return next_pair_.value; }
1363 };
1364 // =========================================================================
1365 /*!
1366 Print the vector of sets (used for debugging)
1367 */
1368 inline void sparse_list::print(void) const
1369 { std::cout << "sparse_list:\n";
1370  for(size_t i = 0; i < n_set(); i++)
1371  { std::cout << "set[" << i << "] = {";
1372  const_iterator itr(*this, i);
1373  while( *itr != end() )
1374  { std::cout << *itr;
1375  if( *(++itr) != end() )
1376  std::cout << ",";
1377  }
1378  std::cout << "}\n";
1379  }
1380  return;
1381 }
1382 // =========================================================================
1383 // Tell pod_vector class that each pair_size_t is plain old data and hence
1384 // the corresponding constructor need not be called.
1385 template <> inline bool is_pod<sparse_list::pair_size_t>(void)
1386 { return true; }
1387 
1388 /*!
1389 Copy a user vector of sets sparsity pattern to an internal sparse_list object.
1390 
1391 \tparam VectorSet
1392 is a simple vector with elements of type std::set<size_t>.
1393 
1394 \param internal
1395 The input value of sparisty does not matter.
1396 Upon return it contains the same sparsity pattern as \c user
1397 (or the transposed sparsity pattern).
1398 
1399 \param user
1400 sparsity pattern that we are placing internal.
1401 
1402 \param n_set
1403 number of sets (rows) in the internal sparsity pattern.
1404 
1405 \param end
1406 end of set value (number of columns) in the interanl sparsity pattern.
1407 
1408 \param transpose
1409 if true, the user sparsity patter is the transposed.
1410 
1411 \param error_msg
1412 is the error message to display if some values in the user sparstiy
1413 pattern are not valid.
1414 */
1415 template<class VectorSet>
1417  sparse_list& internal ,
1418  const VectorSet& user ,
1419  size_t n_set ,
1420  size_t end ,
1421  bool transpose ,
1422  const char* error_msg )
1423 {
1424 # ifndef NDEBUG
1425  if( transpose )
1426  CPPAD_ASSERT_KNOWN( end == size_t( user.size() ), error_msg);
1427  if( ! transpose )
1428  CPPAD_ASSERT_KNOWN( n_set == size_t( user.size() ), error_msg);
1429 # endif
1430 
1431  // iterator for user set
1432  std::set<size_t>::const_iterator itr;
1433 
1434  // size of internal sparsity pattern
1435  internal.resize(n_set, end);
1436 
1437  if( transpose )
1438  { // transposed pattern case
1439  for(size_t j = 0; j < end; j++)
1440  { itr = user[j].begin();
1441  while(itr != user[j].end())
1442  { size_t i = *itr++;
1443  CPPAD_ASSERT_KNOWN(i < n_set, error_msg);
1444  internal.add_element(i, j);
1445  }
1446  }
1447  }
1448  else
1449  { for(size_t i = 0; i < n_set; i++)
1450  { itr = user[i].begin();
1451  while(itr != user[i].end())
1452  { size_t j = *itr++;
1453  CPPAD_ASSERT_KNOWN( j < end, error_msg);
1454  internal.add_element(i, j);
1455  }
1456  }
1457  }
1458  return;
1459 }
1460 
1461 } } // END_CPPAD_LOCAL_NAMESPACE
1462 # endif
void assignment(size_t this_target, size_t other_source, const sparse_list &other)
Assign one set equal to another set.
sparse_list(void)
Default constructor (no sets)
#define CPPAD_ASSERT_KNOWN(exp, msg)
Check that exp is true, if not print msg and terminate execution.
size_t end(void) const
Fetch end for this vector of sets object.
Vector of sets of positive integers, each set stored as a singly linked list.
Definition: sparse_list.hpp:35
Define processor symbols and macros that are used by CppAD.
void resize(size_t n)
resize the vector (existing elements preserved when n &lt;= capacity_).
Definition: pod_vector.hpp:180
void clear(void)
Remove all the elements from this vector and free its memory.
Definition: pod_vector.hpp:246
void push_back(const Type &e)
Add an element to theh back of this vector.
Definition: pod_vector.hpp:312
void add_element(size_t i, size_t element)
Add one element to a set.
size_t end_
Possible elements in each set are 0, 1, ..., end_ - 1;.
Definition: sparse_list.hpp:53
void binary_intersection(size_t this_target, size_t this_left, size_t other_right, const sparse_list &other)
Assign a set equal to the intersection of two other sets.
pod_vector< size_t > post_
Vectors of elements that have not yet been added to corresponding sets.
A vector class with Type element that does not use element constructors or destructors when Type is P...
Definition: pod_vector.hpp:34
void binary_union(size_t target, size_t left, const pod_vector< size_t > &right)
Assign a set equal to the union of a set and a vector;.
size_t next
This is the data index of the next entry in the list. If there are no more entries in the list...
Definition: sparse_list.hpp:48
size_t number_not_used_
number of elements in data_ that are not being used.
Definition: sparse_list.hpp:56
pod_vector< size_t > start_
Starting point for i-th set is start_[i].
Definition: sparse_list.hpp:83
pod_vector< pair_size_t > data_
The data for all the singly linked lists.
Definition: sparse_list.hpp:62
size_t is_subset(size_t one_this, size_t two_other, const sparse_list &other) const
Check if one of two sets is a subset of the other set.
size_t number_elements(size_t i) const
Count number of elements in a set.
sparse_list::pair_size_t pair_size_t
type used by sparse_list to represent one element of the list
size_t drop(size_t i)
drop a set and its postings (no longer being used).
sparse_list_const_iterator & operator++(void)
advance to next element in this list
size_t memory(void) const
Amount of memory used by this vector of sets.
type used for each entry in a singly linked list.
Definition: sparse_list.hpp:40
void print(void) const
Print the vector of sets (used for debugging)
void post_element(size_t i, size_t element)
Post an element for delayed addition to a set.
void binary_union(size_t this_target, size_t this_left, size_t other_right, const sparse_list &other)
Assign a set equal to the union of two other sets.
size_t size(void) const
current number of elements in this vector.
Definition: pod_vector.hpp:79
size_t operator*(void)
obtain value of this element of the set of positive integers (end_ for no such element) ...
~sparse_list(void)
Destructor.
size_t value
For the first entry in each list, this is the reference count. For the other entries in the list this...
Definition: sparse_list.hpp:43
Type * data(void)
current data pointer is no longer valid after any of the following: extend, erase, operator=, and ~pod_vector. Take extreem care when using this function.
Definition: pod_vector.hpp:89
const size_t end_
Possible elements in a list are 0, 1, ..., end_ - 1;.
const pod_vector< pair_size_t > & data_
data for the entire vector of sets
#define CPPAD_ASSERT_UNKNOWN(exp)
Check that exp is true, if not terminate execution.
void clear(size_t target)
Assign the empty set to one of the sets.
size_t data_not_used_
list of elements of data_ that are not being used.
Definition: sparse_list.hpp:59
void resize(size_t n_set, size_t end)
Start a new vector of sets.
size_t reference_count(size_t i) const
Counts references to sets.
size_t get_data_index(void)
get a new data_ element for use.
pair_size_t next_pair_
next element in the singly linked list (next_pair_.value == end_ for past end of list) ...
void process_post(size_t i)
process post entries for a specific set.
size_t n_set(void) const
Fetch n_set for vector of sets object.
void check_data_structure(void)
Checks data structure (effectively const, but modifies and restores values)
bool is_element(size_t i, size_t element) const
check an element is in a set.
pod_vector< size_t > temporary_
A temporary vector used by member functions that keeps its capacity.
sparse_list_const_iterator const_iterator
declare a const iterator
sparse_list_const_iterator(const sparse_list &list, size_t i)
construct a const_iterator for a list in a sparse_list object
void operator=(const sparse_list &other)
Assignement operator.
sparse_list(const sparse_list &v)
Using copy constructor is a programing (not user) error.
cons_iterator for one set of positive integers in a sparse_list object.
void sparsity_user2internal(sparse_list &internal, const VectorSet &user, size_t n_set, size_t end, bool transpose, const char *error_msg)
Copy a user vector of sets sparsity pattern to an internal sparse_list object.