SheafSystem  0.0.0.0
poset_joiner.cc
1 
2 //
3 // Copyright (c) 2014 Limit Point Systems, Inc.
4 
5 // Licensed under the Apache License, Version 2.0 (the "License");
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 
9 // http://www.apache.org/licenses/LICENSE-2.0
10 
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 
17 //
18 
19 
20 
21 // Implementation for class POSET_JOINER
22 
23 #include "SheafSystem/poset_joiner.h"
24 #include "SheafSystem/assert_contract.h"
25 
26 #include "SheafSystem/abstract_poset_member.h"
27 #include "SheafSystem/error_message.h"
28 #include "SheafSystem/unordered_set_filter.h"
29 #include "SheafSystem/total_poset_member.h"
30 #include "SheafSystem/poset_state_handle.h"
31 #include "SheafSystem/scoped_index.h"
32 #include "SheafSystem/set_filter.h"
33 #include "SheafSystem/std_algorithm.h"
34 #include "SheafSystem/std_unordered_set.h"
35 #include "SheafSystem/std_set.h"
36 #include "SheafSystem/tern.h"
37 #include "SheafSystem/triorder_itr.h"
38 
39 using namespace sheaf;
40 using namespace std;
41 using namespace unordered;
42 
43 //#define DIAGNOSTIC_OUTPUT
44 
53 
54 #undef USE_IS_IMPLICIT
55 
56 // ===========================================================
57 // UNNAMED NAMESPACE
58 // ===========================================================
59 
60 namespace
61 {
65 typedef unordered_set<pod_index_type> uset_type;
66 
70 typedef set<pod_index_type> oset_type;
71 
75 typedef unordered_set_triorder_itr crg_itr_type;
76 
80 bool is_singleton(const uset_type& xset)
81 {
82  return (++xset.begin() == xset.end());
83 }
84 
88 void
89 compute_atoms(const scoped_index& xindex,
90  uset_type& xgdown,
91  uset_type& xatoms,
92  crg_itr_type& xdown_itr)
93 {
94  // Preconditions:
95 
96  require(xdown_itr.is_initialized());
97 
98  // Body:
99 
100  poset_state_handle* lhost = xdown_itr.anchor().host();
101 
102  xdown_itr.put_anchor(xindex);
103  xdown_itr.reset(sheaf::NO_RESET);
104 
105  while(!xdown_itr.is_done())
106  {
107  if(xdown_itr.action() == crg_itr_type::POSTVISIT_ACTION)
108  {
109  xgdown.insert(xdown_itr.index().hub_pod());
110  if(lhost->is_atom(xdown_itr.index()))
111  {
112  xatoms.insert(xdown_itr.index().hub_pod());
113  }
114  }
115 
116  xdown_itr.next();
117  }
118 
119  // Postconditions:
120 
121  // Exit:
122 
123  return;
124 }
125 
130 void
131 compute_atoms(const scoped_index& xindex,
132  uset_type& xgdown,
133  uset_type& xatoms,
134  crg_itr_type& xdown_itr,
135  bool& xall_implicit)
136 {
137  // Preconditions:
138 
139  require(xdown_itr.is_initialized());
140 
141  // Body:
142 
143 #ifdef USE_IS_IMPLICIT
144 
145  poset_state_handle* lhost = xdown_itr.anchor().host();
146 
147  xdown_itr.put_anchor(xindex);
148  xdown_itr.reset(sheaf::NO_RESET);
149 
150  while(!xdown_itr.is_done())
151  {
152  switch(xdown_itr.action())
153  {
154  case crg_itr_type::LINK_ACTION:
155 
156  xall_implicit = xall_implicit && xdown_itr.link_is_implicit();
157  break;
158 
159  case crg_itr_type::POSTVISIT_ACTION:
160 
161  xgdown.insert(xdown_itr.index().hub_pod());
162  if(lhost->is_atom(xdown_itr.index()))
163  {
164  xatoms.insert(xdown_itr.index().hub_pod());
165  }
166  break;
167 
168  default:
169 
170  // Just to prevent complier warnings; do nothing.
171 
172  break;
173  }
174 
175  xdown_itr.next();
176  }
177 
178 #endif
179 
180  // Postconditions:
181 
182  // Exit:
183 
184  return;
185 }
186 
191 void
192 compute_atoms(const scoped_index* xexpansion,
193  int xexpansion_ct,
194  uset_type& xgdown,
195  uset_type& xatoms,
196  crg_itr_type& xdown_itr)
197 {
198  // post_information_message("Entering compute_atoms");
199 
200  // Preconditions:
201 
202  require(xgdown.empty());
203  require(xatoms.empty());
204  require(xdown_itr.is_initialized());
205 
206  // Body:
207 
208  // Initialize the downset of g to the downset of xexpansion. Compute
209  // the atoms in the downset of g.
210 
211  // Make sure the has_visited markers are all cleared, since
212  // we won't be resetting them during traversal. Can't use
213  // reset() because it calls first(), which marks the first member.
214 
215  xdown_itr.clear_has_visited();
216 
217  for(int i = 0; i < xexpansion_ct; i++)
218  {
219  compute_atoms(xexpansion[i], xgdown, xatoms, xdown_itr);
220  }
221 
222 #ifdef DIAGNOSTIC_OUTPUT
223  cout << "compute_atoms(): " << endl;
224  cout << "joinands: ";
225 
226  for(int i = 0; i < xexpansion_ct; i++)
227  {
228  cout << xexpansion[i];
229  }
230  cout << endl;
231 
232  cout << "xgdown: ";
233  for(uset_type::iterator i=xgdown.begin(); i!=xgdown.end(); ++i)
234  {
235  cout << setw(6) << *i;
236  }
237  cout << endl;
238 
239  cout << "xatoms: ";
240  for(uset_type::iterator i=xatoms.begin(); i!=xatoms.end(); ++i)
241  {
242  cout << setw(6) << *i;
243  }
244  cout << endl;
245 #endif
246 
247  // Postconditions:
248 
249  ensure(unexecutable("xgdown contains the downset of xexpansion"));
250  ensure(unexecutable("xatoms contains the atoms in the downset of xexpansion"));
251 
252  // Use of down itr in update_gdown(...) called from compute_mlb requires
253  // down_itr has already visited the down set of the operands.
254 
255  require(unexecutable("for all m in down set of xexpansion: xdown_itr.has_visited(m)"));
256 
257 
258  // Exit:
259 
260  // post_information_message("Leaving compute_atoms");
261  return;
262 }
263 
269 void
270 compute_atoms(const scoped_index* xexpansion,
271  int xexpansion_ct,
272  uset_type& xgdown,
273  uset_type& xatoms,
274  crg_itr_type& xdown_itr,
275  bool& xall_implicit)
276 {
277  // post_information_message("Entering compute_atoms");
278 
279  // Preconditions:
280 
281  require(xgdown.empty());
282  require(xatoms.empty());
283  require(xdown_itr.is_initialized());
284 
285  // Body:
286 
287  // Initialize the downset of g to the downset of xexpansion. Compute
288  // the atoms in the downset of g.
289 
290  // Make sure the has_visited markers are all cleared, since
291  // we won't be resetting them during traversal. Can't use
292  // reset() because it calls first(), which marks the first member.
293 
294  xdown_itr.clear_has_visited();
295 
296  for(int i = 0; i < xexpansion_ct; i++)
297  {
298  compute_atoms(xexpansion[i], xgdown, xatoms, xdown_itr, xall_implicit);
299  }
300 
301 #ifdef DIAGNOSTIC_OUTPUT
302  cout << "compute_atoms(): " << endl;
303  cout << "joinands: ";
304 
305  for(int i = 0; i < xexpansion_ct; i++)
306  {
307  cout << xexpansion[i];
308  }
309  cout << endl;
310 
311  cout << "xgdown: ";
312  for(uset_type::iterator i=xgdown.begin(); i!=xgdown.end(); ++i)
313  {
314  cout << setw(6) << *i;
315  }
316  cout << endl;
317 
318  cout << "xatoms: ";
319  for(uset_type::iterator i=xatoms.begin(); i!=xatoms.end(); ++i)
320  {
321  cout << setw(6) << *i;
322  }
323  cout << endl;
324 #endif
325 
326  // Postconditions:
327 
328  ensure(unexecutable("xgdown contains the downset of xexpansion"));
329  ensure(unexecutable("xatoms contains the atoms in the downset of xexpansion"));
330 
331  // Use of down itr in update_gdown(...) called from compute_mlb requires
332  // down_itr has already visited the down set of the operands.
333 
334  require(unexecutable("for all m in down set of xexpansion: xdown_itr.has_visited(m)"));
335 
336 
337  // Exit:
338 
339  // post_information_message("Leaving compute_atoms");
340  return;
341 }
342 
347 void
348 compute_atoms(subposet* xexpansion,
349  uset_type& xgdown,
350  uset_type& xatoms,
351  crg_itr_type& xdown_itr)
352 {
353  // post_information_message("Entering compute_atoms");
354 
355  // Preconditions:
356 
357  require(xgdown.empty());
358  require(xatoms.empty());
359  require(xdown_itr.is_initialized());
360 
361  // Body:
362 
363  // Initialize the downset of g to the downset of xexpansion and
364  // compute the atoms in the downset of g.
365 
366  // Make sure the has_visited markers are all cleared, since
367  // we won't be resetting them during traversal. Can't use
368  // reset() because it calls first(), which marks the first member.
369 
370  xdown_itr.clear_has_visited();
371 
372  index_iterator litr = xexpansion->indexed_member_iterator();
373  while(!litr.is_done())
374  {
375  compute_atoms(litr.index(), xgdown, xatoms, xdown_itr);
376  litr.next();
377  }
378 
379 #ifdef DIAGNOSTIC_OUTPUT
380  cout << "compute_atoms(): " << endl;
381  cout << "joinands: ";
382 
383  litr.reset();
384  while(!litr.is_done())
385  {
386  cout << litr.index();
387  litr.next();
388  }
389  cout << endl;
390 
391  cout << "xgdown: ";
392  for(uset_type::iterator i=xgdown.begin(); i!=xgdown.end(); ++i)
393  {
394  cout << setw(6) << *i;
395  }
396  cout << endl;
397 
398  cout << "xatoms: ";
399  for(uset_type::iterator i=xatoms.begin(); i!=xatoms.end(); ++i)
400  {
401  cout << setw(6) << *i;
402  }
403  cout << endl;
404 #endif
405 
406 
407  // Postconditions:
408 
409  ensure(unexecutable("gdown() contains the downset of xexpansion"));
410  ensure(unexecutable("atoms() contains the atoms in the downset of xexpansion"));
411 
412  // Use of down itr in update_gdown(...) called from compute_mlb requires
413  // down_itr has already visited the down set of the operands.
414 
415  require(unexecutable("for all m in down set of xexpansion: xdown_itr.has_visited(m)"));
416 
417  // Exit:
418 
419  // post_information_message("Leaving compute_atoms");
420  return;
421 }
422 
428 void
429 compute_atoms(subposet* xexpansion,
430  uset_type& xgdown,
431  uset_type& xatoms,
432  crg_itr_type& xdown_itr,
433  bool& xall_implicit)
434 {
435  // post_information_message("Entering compute_atoms");
436 
437  // Preconditions:
438 
439  require(xgdown.empty());
440  require(xatoms.empty());
441  require(xdown_itr.is_initialized());
442 
443  // Body:
444 
445  // Initialize the downset of g to the downset of xexpansion and
446  // compute the atoms in the downset of g.
447 
448  // Make sure the has_visited markers are all cleared, since
449  // we won't be resetting them during traversal. Can't use
450  // reset() because it calls first(), which marks the first member.
451 
452  xdown_itr.clear_has_visited();
453 
454  index_iterator litr = xexpansion->indexed_member_iterator();
455  while(!litr.is_done())
456  {
457  compute_atoms(litr.index(), xgdown, xatoms, xdown_itr, xall_implicit);
458  litr.next();
459  }
460 
461 #ifdef DIAGNOSTIC_OUTPUT
462  cout << "compute_atoms(): " << endl;
463  cout << "joinands: ";
464 
465  litr.reset();
466  while(!litr.is_done())
467  {
468  cout << litr.index();
469  litr.next();
470  }
471  cout << endl;
472 
473  cout << "xgdown: ";
474  for(uset_type::iterator i=xgdown.begin(); i!=xgdown.end(); ++i)
475  {
476  cout << setw(6) << *i;
477  }
478  cout << endl;
479 
480  cout << "xatoms: ";
481  for(uset_type::iterator i=xatoms.begin(); i!=xatoms.end(); ++i)
482  {
483  cout << setw(6) << *i;
484  }
485  cout << endl;
486 #endif
487 
488 
489  // Postconditions:
490 
491  ensure(unexecutable("gdown() contains the downset of xexpansion"));
492  ensure(unexecutable("atoms() contains the atoms in the downset of xexpansion"));
493 
494  // Use of down itr in update_gdown(...) called from compute_mlb requires
495  // down_itr has already visited the down set of the operands.
496 
497  require(unexecutable("for all m in down set of xexpansion: xdown_itr.has_visited(m)"));
498 
499  // Exit:
500 
501  // post_information_message("Leaving compute_atoms");
502  return;
503 }
504 
512 bool
513 update_gdown(const scoped_index& xindex, uset_type& xgdown, crg_itr_type& xdown_itr)
514 {
515  bool result;
516 
517  // Preconditions:
518 
519  // Body:
520 
521  poset_state_handle* lhost = xdown_itr.anchor().host();
522 
523  result = (xgdown.find(xindex.hub_pod()) != xgdown.end());
524 
525  if(!result && !lhost->is_jim(xindex) && !xdown_itr.has_visited(xindex))
526  {
527  // Xindex is not in gdown and is a jrm
528  // and has not been evaluated;
529  // determine if it should be in gdown.
530 
531  stack<bool> ladd_to_gdown;
532 
533  xdown_itr.put_anchor(xindex);
534  xdown_itr.reset(sheaf::NO_RESET);
535 
536  while(!xdown_itr.is_done())
537  {
538  bool lforce_is_done = false;
539  bool ltruncate = false;
540 
541  switch(xdown_itr.action())
542  {
543  case crg_itr_type::PREVISIT_ACTION:
544 
545  { // just to silence compiler warnings
546 
547  // The down set iterator has reached a member that has
548  // not been evaluated. If the member is a jrm, we
549  // assume that the member will be added to gdown;
550  // the link action will determine if the jrm should not
551  // be added. Only jims that are in the down set
552  // of the joinands belong in gdown, so if the member
553  // is a jim its either already there or doesn't
554  // belong. Either way, the down iteration should be truncated.
555 
556  bool lis_jim = lhost->is_jim(xdown_itr.index());
557 
558  ladd_to_gdown.push(!lis_jim);
559  ltruncate = lis_jim;
560  }
561  break;
562 
563  case crg_itr_type::LINK_ACTION:
564 
565  // Only add to gdown if the lower cover of the member is in gdown.
566 
567  ladd_to_gdown.top() =
568  ladd_to_gdown.top() &&
569  (xgdown.find(xdown_itr.lesser_index().hub_pod()) != xgdown.end());
570 
571  break;
572 
573  case crg_itr_type::POSTVISIT_ACTION:
574 
575  if(ladd_to_gdown.top())
576  {
577  // Add the member to gdown.
578 
579  xgdown.insert(xdown_itr.index().hub_pod());
580  result = true;
581  }
582  else
583  {
584  // The member is not in gdown, so no
585  // member in its upset is in gdown.
586 
587  result = false;
588  lforce_is_done = true;
589  }
590 
591  ladd_to_gdown.pop();
592  break;
593 
594  default:
595  break;
596  }
597 
598  if(lforce_is_done)
599  {
600  xdown_itr.force_is_done();
601  }
602  else
603  {
604  xdown_itr.next(ltruncate);
605  }
606  }
607  }
608 
609  // Postconditions:
610 
611  // Exit:
612 
613  return result;
614 }
615 
619 void
620 compute_mlb(uset_type& xgdown,
621  uset_type& xatoms,
622  crg_itr_type& xdown_itr,
623  crg_itr_type& xup_itr,
624  uset_type& xmlb)
625 {
626  // post_information_message("Entering compute_mlb");
627 
628  // Preconditions:
629 
630  require(xdown_itr.is_initialized());
631 
632  // Use of down itr in update_gdown(...) requires down_itr has
633  // already visited the down set of the operands.
634 
635  require(unexecutable("for all m in down set of joinands: xdown_itr.has_visited(m)"));
636 
637  require(xup_itr.is_initialized());
638  require(xmlb.empty());
639 
640  // Body:
641 
642  stack<bool> lis_maximal;
643  scoped_index litem(xdown_itr.anchor().hub_id());
644 
645  // Iterate over the upset of the atoms computing the maximal lower bound.
646  // Clear up_itr has visited, but not down itr has visited (see precondition).
647 
648  xup_itr.clear_has_visited();
649 
650  for(uset_type::iterator itr = xatoms.begin(); itr != xatoms.end(); itr++)
651  {
652  litem = *itr;
653  xup_itr.put_anchor(litem);
654  xup_itr.reset(sheaf::NO_RESET);
655 
656  while(!xup_itr.is_done())
657  {
658  bool ltruncate = false;
659 
660  switch(xup_itr.action())
661  {
662  case crg_itr_type::PREVISIT_ACTION:
663 
664  { // just to silence compiler warning
665 
666  // Add the member to gdown if it should be there.
667 
668  bool lis_in_gdown = update_gdown(xup_itr.index(), xgdown, xdown_itr);
669 
670  // Member is only maximal if it is in gdown
671  // and none of the members above it are in gdown.
672  // Initialize top of is_maximal stack to is_in_gdown,
673  // the link action will test members above.
674 
675  lis_maximal.push(lis_in_gdown);
676 
677  // If the member is not in gdown, no members of
678  // its upset will be in gdown; truncate.
679 
680  ltruncate = !lis_in_gdown;
681  }
682 
683  break;
684 
685  case crg_itr_type::LINK_ACTION:
686 
687  // Memebr is only maximal if it is in gdown
688  // and none of the members above it are in gdown.
689  // Test and accumulate gdown status of members above.
690 
691  lis_maximal.top() =
692  lis_maximal.top() &&
693  (xgdown.find(xup_itr.lesser_index().hub_pod()) == xgdown.end());
694 
695  break;
696 
697  case crg_itr_type::POSTVISIT_ACTION:
698 
699  if(lis_maximal.top())
700  {
701  // Member is a maximal, add to maximal lower bound.
702 
703  xmlb.insert(xup_itr.index().hub_pod());
704  }
705 
706  lis_maximal.pop();
707 
708  break;
709 
710  default:
711  break;
712  }
713 
714  xup_itr.next(ltruncate);
715  }
716  }
717 
718 #ifdef DIAGNOSTIC_OUTPUT
719  cout << "compute_mlb:" << endl;
720  cout << "xgdown: ";
721  for(uset_type::iterator i=xgdown.begin(); i!=xgdown.end(); ++i)
722  {
723  cout << setw(6) << *i;
724  }
725  cout << endl;
726 
727  cout << "xmlb: ";
728  for(uset_type::iterator i=xmlb.begin(); i!=xmlb.end(); ++i)
729  {
730  cout << setw(6) << *i;
731  }
732  cout << endl;
733 #endif
734 
735  // Postconditions:
736 
737  ensure(unexecutable("result contains mlb(g) in internal scope"));
738 
739  // Exit
740 
741  // post_information_message("Leaving compute_mlb");
742  return;
743 }
744 
748 void
749 compute_minimals(crg_itr_type& xup_itr, oset_type& xmub)
750 {
751  // Preconditions:
752 
753  require(unexecutable("xmub is in internal scope"));
754 
755  // Body:
756 
757  // Reset the upset iterator.
758 
759  xup_itr.put_visit_once(true);
760  xup_itr.put_strict(true);
761  xup_itr.clear_has_visited();
762 
763  scoped_index litem(xup_itr.anchor().hub_id());
764 
765  for(oset_type::iterator litr = xmub.begin(); litr != xmub.end(); litr++)
766  {
767  litem = *litr;
768 
769  // Anchor the up itr at the current litr item.
770 
771  xup_itr.put_anchor(litem);
772  xup_itr.reset(sheaf::NO_RESET);
773 
774  // Remove the upset of the anchor from xmub.
775 
776  while(!xup_itr.is_done())
777  {
778  if(xup_itr.action() == crg_itr_type::POSTVISIT_ACTION)
779  {
780  // Since up itr is strict, current member can not be litr current item
781  // and hence we can erase current member without affecting litr.
782 
783  assertion(xup_itr.index().hub_pod() != *litr);
784 
785  xmub.erase(xup_itr.index().hub_pod()); // Internal scope.
786  }
787  xup_itr.next();
788  }
789 
790  // Mark the current anchor as not been visited. This allows an upset
791  // traversal for a member with the anchor in its upset to visit and
792  // remove the anchor.
793 
794  xup_itr.put_has_visited(litem, false);
795  }
796 
797  // Postconditions:
798 
799  // Exit
800 
801  return;
802 }
803 
808 void
809 intersect(const oset_type& xset, oset_type& xresult)
810 {
811 
812  // Preconditions:
813 
814 
815  // Body:
816 
817  oset_type::iterator ritr = xresult.begin();
818  oset_type::const_iterator sitr = xset.begin();
819  oset_type::iterator tmp;
820 
821 
822  oset_type::value_type rmbr, smbr;
823 
824  while(ritr != xresult.end() && sitr != xset.end())
825  {
826  rmbr = *ritr;
827  smbr = *sitr;
828 
829  if( rmbr < smbr )
830  {
831  // Current result member isn't in xset,
832  // erase it from result.
833 
834  // Erasing member that iterator points to
835  // invalidates iterator; increment past it first.
836 
837  tmp = ritr;
838  ritr++;
839  xresult.erase(tmp);
840  }
841  else if( rmbr == smbr )
842  {
843  // Current result member is in xset;
844  // leave it there and move on.
845 
846  ritr++;
847  sitr++;
848  }
849  else
850  {
851  // Current xset member isn't in result;
852  // just move on.
853 
854  sitr++;
855  }
856 
857  }
858 
859  // None of the remaining members (if any) in result
860  // were in xset, remove them from result.
861 
862  if(ritr != xresult.end())
863  {
864  xresult.erase(ritr, xresult.end());
865  }
866 
867 
868  // Postconditions:
869 
870  // Exit
871 
872  return;
873 }
874 
878 void
879 compute_mub(uset_type& xmlb, crg_itr_type& xup_itr, oset_type& xmub)
880 {
881  // post_information_message("Entering compute_mub");
882 
883  // Preconditions:
884 
885  require(xup_itr.is_initialized());
886  require(xmub.empty());
887 
888  // Body:
889 
890  // Compute the common upper bound; the intersection of all
891  // the members of the strict upset of xmlb.
892 
893  xup_itr.put_strict(true);
894  xup_itr.put_visit_once(false);
895  xup_itr.clear_has_visited();
896 
897  scoped_index litem(xup_itr.anchor().hub_id());
898  for(uset_type::iterator itr = xmlb.begin(); itr != xmlb.end(); ++itr)
899  {
900  litem = *itr;
901 
902  xup_itr.put_anchor(litem);
903  xup_itr.reset(sheaf::NO_RESET);
904 
905  if(xmub.empty())
906  {
907  // First upset found, initialize xmub.
908 
909  while(!xup_itr.is_done())
910  {
911  if(xup_itr.action() == crg_itr_type::POSTVISIT_ACTION)
912  {
913  xmub.insert(xup_itr.index().hub_pod());
914  }
915 
916  xup_itr.next();
917  }
918  }
919  else
920  {
921  // Compute the intersection of the upper cover of the
922  // current member of xmlb with the common upper bound.
923 
924  oset_type ltmp_set;
925  while(!xup_itr.is_done())
926  {
927  if(xup_itr.action() == crg_itr_type::POSTVISIT_ACTION)
928  {
929  ltmp_set.insert(xup_itr.index().hub_pod());
930  }
931  xup_itr.next();
932  }
933 
934  intersect(ltmp_set, xmub);
935  }
936  }
937 
938 #ifdef DIAGNOSTIC_OUTPUT
939  cout << "compute_mub:" << endl;
940  cout << "xmub: ";
941  for(oset_type::iterator i=xmub.begin(); i!=xmub.end(); ++i)
942  {
943  cout << setw(6) << *i;
944  }
945  cout << endl;
946 #endif
947 
948  // Compute the minimals of common upper bound.
949 
950  compute_minimals(xup_itr, xmub);
951 
952 #ifdef DIAGNOSTIC_OUTPUT
953  cout << "xmub after compute_minimals: ";
954  for(oset_type::iterator i=xmub.begin(); i!=xmub.end(); ++i)
955  {
956  cout << setw(6) << *i;
957  }
958  cout << endl;
959 #endif
960 
961  // Postconditions:
962 
963  ensure(unexecutable("result contains mub(g) in internal scope"));
964 
965  // Exit
966 
967  // post_information_message("Leaving compute_mub");
968  return;
969 }
970 
971 
976 void
977 link_result(const uset_type& xresult_lc, const oset_type& xresult_uc, abstract_poset_member& xresult)
978 {
979  // Preconditions:
980 
981  require(xresult.state_is_read_write_accessible());
982 
983  // Body:
984 
985 #ifdef DIAGNOSTIC_OUTPUT
986  cout << "link_result:" << endl;
987  cout << "xresult_lc: ";
988  for(uset_type::iterator i=xresult_lc.begin(); i!=xresult_lc.end(); ++i)
989  {
990  cout << setw(6) << *i;
991  }
992  cout << endl;
993 
994  cout << "xresult_uc: ";
995  for(oset_type::iterator i=xresult_uc.begin(); i!=xresult_uc.end(); ++i)
996  {
997  cout << setw(6) << *i;
998  }
999  cout << endl;
1000 #endif
1001 
1002  poset_state_handle* lhost = xresult.host();
1003 
1004  // Get an index in internal scope.
1005 
1006  scoped_index litem(lhost->member_id(false));
1007 
1008  // Link the upper cover.
1009 
1010  for(oset_type::const_iterator litr = xresult_uc.begin(); litr != xresult_uc.end(); ++litr)
1011  {
1012  litem = *litr;
1013 
1014  // Remove all members of result_lc from
1015  // the lower cover of the current upper cover member
1016 
1017  lhost->remove_cover_members(unordered_set_filter(xresult_lc), LOWER, litem);
1018 
1019  // Insert result in the lower cover
1020  // of the current upper cover member.
1021 
1022  lhost->insert_cover_member(xresult.index(), LOWER, litem);
1023 
1024  // Insert the current member of the upper cover
1025  // in the upper cover of result.
1026 
1027  xresult.insert_cover_member(litem, UPPER);
1028  }
1029 
1030  // Link the lower cover.
1031 
1032  for(uset_type::const_iterator litr = xresult_lc.begin(); litr != xresult_lc.end(); ++litr)
1033  {
1034  litem = *litr;
1035 
1036  // Remove all members of result_uc from
1037  // the upper cover of the current lower cover member
1038 
1039  lhost->remove_cover_members(set_filter(xresult_uc), UPPER, litem);
1040 
1041  // Insert result in the upper cover
1042  // of the current lower cover member.
1043 
1044  lhost->insert_cover_member(xresult.index(), UPPER, litem);
1045 
1046  // Insert the current member of the lower cover
1047  // in the lower cover of result.
1048 
1049  xresult.insert_cover_member(litem, LOWER);
1050  }
1051 
1052  // Postconditions:
1053 
1054 
1055  // Exit:
1056 
1057  return;
1058 }
1059 
1064 void
1065 attach_result(poset_state_handle* xhost, const tern& xgreatest, abstract_poset_member& xresult)
1066 {
1067  // post_information_message("Entering attach_result");
1068 
1069  // Preconditions:
1070 
1071  require(xhost->state_is_read_write_accessible());
1072 
1073  // Body:
1074 
1075  // Lower cover is empty; join is bottom.
1076 
1077  scoped_index lindex = xhost->bottom().index();
1078 
1079  if(xgreatest.is_true())
1080  {
1081  // New greatest join equivalent member requested, make it.
1082 
1083  xresult.new_jem_state(xhost, lindex, true, false);
1084  }
1085  else
1086  {
1087  // Attach result to bottom.
1088 
1089  xresult.attach_to_state(xhost, lindex);
1090  }
1091 
1092  // Postconditions:
1093 
1094  ensure(xresult.is_attached());
1095 
1096  // Exit:
1097 
1098  // post_information_message("Leaving attach_result");
1099  return;
1100 }
1101 
1106 void
1107 attach_result(poset_state_handle* xhost,
1108  const uset_type& xmlb,
1109  const tern& xgreatest,
1110  abstract_poset_member& xresult)
1111 {
1112  // post_information_message("Entering attach_result");
1113 
1114  // Preconditions:
1115 
1116  require(xhost->state_is_read_write_accessible());
1117  require(is_singleton(xmlb));
1118 
1119  // Body:
1120 
1121  // Mlb contains a single member, it must be the join.
1122 
1123  scoped_index lindex = xhost->member_id(*(xmlb.begin()), false);
1124 
1125  if(xgreatest.is_true())
1126  {
1127  // New greatest join equivalent member requested, make it.
1128 
1129  xresult.new_jem_state(xhost, lindex, true, false);
1130  }
1131  else if(xgreatest.is_false())
1132  {
1133  // New least join equivalent member requested, make it.
1134 
1135  xresult.new_jem_state(xhost, lindex, false, false);
1136  }
1137  else
1138  {
1139  // New jem not requested,
1140  // attach result to existing member.
1141 
1142  xresult.attach_to_state(xhost, lindex);
1143  }
1144 
1145  // Postconditions:
1146 
1147  ensure(xresult.is_attached());
1148 
1149  // Exit:
1150 
1151  // post_information_message("Leaving attach_result");
1152  return;
1153 }
1154 
1159 void
1160 attach_result(poset_state_handle* xhost,
1161  const uset_type& xmlb,
1162  const oset_type& xmub,
1163  const tern& xgreatest,
1164  abstract_poset_member& xresult)
1165 {
1166  // post_information_message("Entering attach_result");
1167 
1168  // Preconditions:
1169 
1170  require(xhost->state_is_read_write_accessible());
1171  require(!xmlb.empty());
1172  require(!is_singleton(xmlb));
1173  require(!xmub.empty());
1174 
1175  // Body:
1176 
1177  // Join has not been instantiated;
1178  // upper and lower cover are strict bounds.
1179 
1180  // Make a new member state and attach result to it
1181 
1182  pod_index_type lindex = xhost->new_member(false);
1183 
1184  xresult.attach_to_state(xhost, lindex);
1185 
1186  link_result(xmlb, xmub, xresult);
1187 
1188  // Postconditions:
1189 
1190  ensure(xresult.is_attached());
1191 
1192  // Exit:
1193 
1194  // post_information_message("Leaving attach_result");
1195  return;
1196 }
1197 
1198 } // End unnamed namespace.
1199 
1200 
1201 // ===========================================================
1202 // PUBLIC MEMBER FUNCTIONS
1203 // ===========================================================
1204 
1207 {
1208 
1209  // Preconditions:
1210 
1211  require(xhost != 0);
1212  require(xhost->state_is_read_accessible());
1213 
1214  // Body:
1215 
1216  _host = const_cast<poset_state_handle*>(xhost);
1217 
1218  // Postconditions:
1219 
1220  ensure(host() == xhost);
1221 }
1222 
1225 {
1226  // Preconditions:
1227 
1228  // Body:
1229 
1230  // Postconditions:
1231 }
1232 
1233 void
1235 join(const scoped_index* xexpansion,
1236  int xexpansion_ct,
1237  const tern& xgreatest,
1238  abstract_poset_member& xresult)
1239 {
1240 
1241  // Preconditions:
1242 
1243  // Body:
1244 
1245  // Computing the join g of a set S of members of a lattice L
1246  // requires placing g in the order relation, that is, finding
1247  // the upper and lower cover for g. To do this, we compute two
1248  // sets, the maximal lower bound of g, mlb(g), and the
1249  // minimal upper bound of g, mub(g).
1250  //
1251  // Mlb(g) contains the largest (maximal) members that are
1252  // less than or equal to g. A member m is less than or equal
1253  // to g if J(m) is included in J(g). We can discover all such
1254  // members by searching the CRG upward from the bottom,
1255  // see compute_mlb. If the join g already exists,
1256  // the mlb will contain a single member, g. Conversely,
1257  // if the mlb contains a single member then it must be g.
1258  // Otherwise, the mlb is the lower cover of g.
1259  //
1260  // Mub(g) contains the smallest (minimal) members of L which
1261  // are strictly greater than every member of mlb(g). We can
1262  // discover such members by searching the CRG upwards from mlb(g),
1263  // see compute_mub. The strictly greater conditions implies
1264  // mlb(g) and mub(g) are disjoint. Since every member m of mub
1265  // is greater than every member m' of mlb, J(m) contains every
1266  // member of J(g) and furthermore, since it is strictly greater
1267  // than every m', J(m) must contain at least one jim j that is not
1268  // contained in J(g). Hence J(m) includes J(g) as a strict subset,
1269  // which means g is strictly less than m.
1270  // Since mub(g) are the minimal members that satisfy this condition,
1271  // mub(g) is the upper cover of g.
1272  //
1273  // Note that if g is the top, then mlb(g) == {g} and mub(g) == {}.
1274 
1275  // The is_implicit option attempts to optimize computation of
1276  // the maximal lower bound using the fact that if the entire
1277  // down set of the expansion is implicit, then the expansion
1278  // must be its own maximal lower bound. Experiment shows this
1279  // option works just fine, but further study is required to
1280  // determine whether it actually improves performance much.
1281 
1282  uset_type latoms;
1283  uset_type lgdown;
1284  uset_type lmax_gdown;
1285 
1286  crg_itr_type ldown_itr(host()->top(), DOWN, NOT_STRICT);
1287  crg_itr_type lup_itr(host()->top(), UP, NOT_STRICT);
1288 
1289  uset_type lmlb;
1290  oset_type lmub;
1291 
1292 #ifdef USE_IS_IMPLICIT
1293 
1294  bool lall_implicit = true;
1295 
1296  // Gather the down set of g and the atoms in it.
1297 
1298  compute_atoms(xexpansion, xexpansion_ct, lgdown, latoms, ldown_itr, lall_implicit);
1299 
1300  // cout << "all implicit: " << boolalpha << lall_implicit << noboolalpha << endl;
1301 
1302  // Get the maximal lower bound.
1303 
1304  if(lall_implicit)
1305  {
1306  // Downset of expansion was all implicit,
1307  // expansion is its own maximal lower bound.
1308 
1309  for(int i=0; i<xexpansion_ct; ++i)
1310  {
1311  lmlb.insert(xexpansion[i].hub_pod());
1312  }
1313  }
1314  else
1315  {
1316  // Have to compute maximal lower bound.
1317 
1318  compute_mlb(lgdown, latoms, ldown_itr, lup_itr, lmlb);
1319  }
1320 
1321 #else
1322 
1323  // Gather the down set of g and the atoms in it.
1324 
1325  compute_atoms(xexpansion, xexpansion_ct, lgdown, latoms, ldown_itr);
1326 
1327  // Have to compute maximal lower bound.
1328 
1329  compute_mlb(lgdown, latoms, ldown_itr, lup_itr, lmlb);
1330 
1331 #endif
1332 
1333  if(lmlb.empty())
1334  {
1335  // Lower cover is empty;
1336  // result is bottom or equivalent.
1337 
1338  attach_result(host(), xgreatest, xresult);
1339  }
1340  else if(is_singleton(lmlb))
1341  {
1342  // Join is already instantiated,
1343  // don't need to compute mub,
1344  // just attach result.
1345 
1346  attach_result(host(), lmlb, xgreatest, xresult);
1347  }
1348  else
1349  {
1350  // Join is not already instantiated,
1351  // compute the minimal upper bound.
1352 
1353  compute_mub(lmlb, lup_itr, lmub);
1354 
1355  // Create the join member and attach result.
1356 
1357  attach_result(host(), lmlb, lmub, xgreatest, xresult);
1358  }
1359 
1360 
1361  // Postconditions:
1362 
1363  ensure(unexecutable("result is join of xexpansion"));
1364 
1365  // Exit
1366 
1367  return;
1368 }
1369 
1370 void
1372 join(subposet* xexpansion, const tern& xgreatest, abstract_poset_member& xresult)
1373 {
1374 
1375  // Preconditions:
1376 
1377  // Body:
1378 
1379  // See comments in the other join signature.
1380 
1381  uset_type latoms;
1382  uset_type lgdown;
1383  uset_type lmax_gdown;
1384 
1385  crg_itr_type ldown_itr(host()->top(), DOWN, NOT_STRICT);
1386  crg_itr_type lup_itr(host()->top(), UP, NOT_STRICT);
1387 
1388  uset_type lmlb;
1389  oset_type lmub;
1390 
1391 #ifdef USE_IS_IMPLICIT
1392 
1393  bool lall_implicit = true;
1394 
1395  // Gather the down set of xexpansion and the atoms in it.
1396 
1397  compute_atoms(xexpansion, lgdown, latoms, ldown_itr, lall_implicit);
1398 
1399  // cout << "all implicit: " << boolalpha << lall_implicit << noboolalpha << endl;
1400 
1401  // Get the maximal lower bound.
1402 
1403  if(lall_implicit)
1404  {
1405  // Downset of expansion was all implicit,
1406  // expansion is its own maximal lower bound.
1407 
1408  index_iterator litr = xexpansion->indexed_member_iterator();
1409  while(!litr.is_done())
1410  {
1411  lmlb.insert(litr.index());
1412  litr.next();
1413  }
1414  }
1415  else
1416  {
1417  // Have to compute maximal lower bound.
1418 
1419  compute_mlb(lgdown, latoms, ldown_itr, lup_itr, lmlb);
1420  }
1421 
1422 #else
1423 
1424  // Gather the down set of xexpansion and the atoms in it.
1425 
1426  compute_atoms(xexpansion, lgdown, latoms, ldown_itr);
1427 
1428  // Compute maximal lower bound.
1429 
1430  compute_mlb(lgdown, latoms, ldown_itr, lup_itr, lmlb);
1431 
1432 #endif
1433 
1434  if(lmlb.empty())
1435  {
1436  // Lower cover is empty;
1437  // result is bottom or equivalent.
1438 
1439  attach_result(host(), xgreatest, xresult);
1440  }
1441  else if(is_singleton(lmlb))
1442  {
1443  // Join is already instantiated,
1444  // don't need to compute mub,
1445  // just attach result.
1446 
1447  attach_result(host(), lmlb, xgreatest, xresult);
1448  }
1449  else
1450  {
1451  // Join is not already instantiated,
1452  // compute the minimal upper bound.
1453 
1454  compute_mub(lmlb, lup_itr, lmub);
1455 
1456  // Create the join member and attach result.
1457 
1458  attach_result(host(), lmlb, lmub, xgreatest, xresult);
1459  }
1460 
1461  // Postconditions:
1462 
1463  ensure(unexecutable("result is join of xexpansion"));
1464 
1465  // Exit
1466 
1467  return;
1468 }
1469 
1470 
1471 
1474 host() const
1475 {
1476  return _host;
1477 }
poset_state_handle * host() const
The poset which this is a handle to a component of.
void remove_cover_members(const filter_type &xfilter, bool xlower, pod_index_type xmbr_hub_id)
Removes all members for which functor xfilter(xmbr.index().hub_pod()) is true from the lower (xlower ...
A client handle for a subposet.
Definition: subposet.h:86
void insert_cover_member(pod_index_type xother_mbr_hub_id, bool xlower, pod_index_type xmbr_hub_id)
Inserts hub id xother_mbr_hub id in the lower (xlower true) or upper (xlower false) cover set of the ...
bool state_is_read_accessible() const
True if this is attached and if the state is accessible for read or access control is disabled...
bool is_true() const
True if thi has value true.
Definition: tern.cc:186
A three state "bool". Does not provide the operations of ternary logic and is intended for use mostly...
Definition: tern.h:45
A client handle for a general, abstract partially order set.
void insert_cover_member(pod_index_type xother_mbr_index, bool xlower)
Inserts xother_mbr_index in the lower (xlower true) or upper (xlower false) cover set of this...
const scoped_index & index() const
The current item in the subset.
Set implementation of filter concept.
Definition: set_filter.h:38
STL namespace.
const scoped_index & index() const
The index of the component state this handle is attached to.
abstract_poset_member & bottom()
The bottom member of the poset (mutable version)
namespace_poset * host() const
The namespace this poset resides in. Obsolete; use name_space() instead.
virtual pod_index_type new_member(bool xis_jim, pod_index_type xtuple_hub_id)
Create a disconnected member with is_jim == xis_jim and the dof tuple identified by hub id xtuple_hub...
void next()
Makes item the next member of the subset.
~poset_joiner()
Destructor; not virtual, can not be base class.
Hash set implementation of filter concept.
const bool NOT_STRICT
Iteration strictness control.
Definition: sheaf.h:102
const bool DOWN
Iteration directions.
Definition: sheaf.h:77
Specialization of the filtered depth-first iterator which exposes all three actions to the client; th...
Definition: triorder_itr.h:42
bool state_is_read_write_accessible() const
True if this is attached and if the state is accessible for read and write or access control is disab...
poset_state_handle * host() const
The host poset.
poset_joiner(const poset_state_handle *xhost)
Creates a joiner for poset xhost.
An index within the external ("client") scope of a given id space.
Definition: scoped_index.h:116
virtual bool is_attached() const
True if this handle is attached to a non-void state.
void join(const scoped_index *xexpansion, int xexpansion_ct, const tern &xgreatest, abstract_poset_member &xresult)
The join of the members of xexpansion.
const bool UPPER
Selector for upper cover.
Definition: sheaf.h:72
const bool UP
Iteration directions.
Definition: sheaf.h:82
const bool NO_RESET
Iteration marker reset control.
Definition: sheaf.h:92
Iterates over the subset of Zn defined by the characteristic function host().
const bool LOWER
Selector for lower cover.
Definition: sheaf.h:67
bool is_false() const
True if this has value false.
Definition: tern.cc:194
int_type pod_index_type
The plain old data index type.
Definition: pod_types.h:49
bool is_done() const
True if iteration finished.
Namespace for the sheaves component of the sheaf system.
virtual bool is_jim(pod_index_type xmbr_hub_id, bool xin_current_version=true) const
True if the member with hub id xmbr_hub_id is a jim in the current version (xin_current_version == tr...
void attach_to_state(const namespace_poset *xns, const poset_path &xpath, bool xauto_access=true)
Attach to the state specified by path xpath in the namespace xns.
An abstract client handle for a member of a poset.
virtual void new_jem_state(abstract_poset_member *xother, bool xgreatest, bool xauto_access)
Creates a new jrm state in host() which is the greatest jem (xgreatest true) or least jem (xgreatest ...
void reset()
Restarts the iteration, makes item the first member of the subset.
virtual index_iterator indexed_member_iterator() const
An iterator for members of this poset; index version.
Definition: subposet.cc:934
virtual const scoped_index & member_id(bool xauto_access) const
An id in the member hub id space; intended for copying to initialize ids to the member id space...
pod_type hub_pod() const
The pod value of this mapped to the unglued hub id space.
Definition: scoped_index.h:710