Polaris: SimGraph.cc Source File

SimGraph.cc

Go to the documentation of this file.
00001 ///
00002 /// \file SimGraph.cc
00003 ///
00004 #ifdef POLARIS_GNU_PRAGMAS
00005 #pragma implementation
00006 #endif
00007 ///
00008 #include "SimGraph.h"
00009 #include "UEdge.h"
00010 #include "utilities/access_util.h"
00011 #include "utilities/stmt_util.h"
00012 #include "Range/Relation.h"
00013 #include "Range/RangeAccessor.h"
00014 #include "UBiGraphIterator.h"
00015 
00016 /// Create an empty graph
00017 SimGraph::SimGraph( ) {
00018     #ifdef CLASS_INSTANCE_REGISTRY
00019     register_instance(SIM_GRAPH, sizeof(SimGraph), this);
00020     #endif
00021 
00022     _descr_exists = new Array< bool >;
00023     _ptrs = new Array< RefElement< AbstractAccess > >;
00024     _graph = new Array<Array<SimEdgeKernel> >;
00025     _nodes = 0;
00026     _range_acc = 0;
00027 }
00028 
00029 /// Create a complete graph with given number of nodes
00030 
00031 SimGraph::SimGraph( List<AbstractAccess> & list )
00032 {
00033     #ifdef CLASS_INSTANCE_REGISTRY
00034     register_instance(SIM_GRAPH, sizeof(SimGraph), this);
00035     #endif
00036 
00037     /// ...  Make a complete graph with the proper number of nodes
00038 
00039     _nodes = list.entries();
00040 
00041     if (_nodes < 2) {
00042     _range_acc = 0;
00043     _ptrs = 0;
00044     _descr_exists = 0;
00045     _graph = 0;
00046     return;
00047     }
00048 
00049     _ptrs = new Array< RefElement< AbstractAccess > >;
00050     _graph  = new Array<Array<SimEdgeKernel> >;
00051 
00052     _ptrs->resize(_nodes);
00053     _graph->resize(_nodes);
00054 
00055     _descr_exists = new Array< bool >;
00056     _descr_exists->resize( _nodes );
00057 
00058     /// ...  Mark that all nodes are valid to start with
00059 
00060     for (int i=0; i < _nodes; ++i) {
00061     (*_descr_exists)[i] = true;
00062     }
00063 
00064     Iterator<AbstractAccess> iter = list; 
00065     for (int i = 0;  iter.valid(); ++iter,++i) {
00066 
00067     (*_ptrs)[i] = iter.current();
00068     (*_graph)[i].resize(_nodes);
00069     }
00070 
00071     /// ...  Initialized each edge to SIM_UNKNOWN
00072 
00073     for (int i=0; i<_nodes; ++i) {
00074     for (int j=0; j<_nodes; ++j) {
00075         (((*_graph)[i])[j]).type(SIM_UNKNOWN);
00076     }
00077     }
00078 
00079     Statement * r_stmt = range_stmt(*(list[0]._summarized_to));
00080     String stmt_tag = r_stmt->tag();
00081     _range_acc = new RangeAccessor(list[0]._pgm_summarized_to->range_dict_guarded(), 
00082                    *r_stmt );
00083     
00084     /// ...  Compare each pair of descriptors, building the Similarity graph as we go
00085 
00086     for (int i=0; i<_nodes; ++i) {
00087     if (!(*_descr_exists)[i]) continue;
00088     for (int j=i+1; j<_nodes; ++j) {
00089         if (!(*_descr_exists)[j]) continue;
00090         calc_similarity( i, j );
00091     }
00092     }
00093 }
00094 
00095 void
00096 SimGraph::print_similarities( ) const
00097 {
00098     if (_ar_logging && _ar_logging % 5 == 0) {
00099     for (int i=0; i<_nodes; ++i) {
00100         if (!(*_descr_exists)[i]) continue;
00101         arlog << "[" << i << "]" ;
00102         AbstractAccess & aa = *((*_ptrs)[i]);
00103         int ndims1 = aa.number_of_dimensions();
00104         for (int j=0; j<_nodes; ++j) {
00105         if (!(*_descr_exists)[j]) continue;
00106         AbstractAccess & aa2 = *((*_ptrs)[j]);
00107         SimEdgeKernel & sek = ((*_graph)[i])[j];
00108         int ndims2 = aa2.number_of_dimensions();
00109         arlog << "    " << sek.type_name() << "[" ;
00110         if ((i != j) && (ndims1 == ndims2) && 
00111             (sek.type() != SIM_NOT_SIMILAR)) {
00112             for (int k=0; k<aa.number_of_dimensions(); ++k) {
00113             arlog << (*(sek.stridematch()))[k] << ":" ;
00114             if ((*(sek.spanmatch()))[k]) {
00115                 arlog << "T";
00116             } else {
00117                 arlog << "F";
00118             }
00119             }
00120         }
00121         arlog << "]";
00122         }
00123         arlog << endl;
00124     }
00125     }
00126 }
00127 
00128 
00129 /// Add edges determined by transitivity - Given a matching from new to mid, want to construct a matching from new to old
00130 void
00131 SimGraph::_add_corresp_edge_forward(SimilarityType type, int index_new, int index_mid, int index_old,
00132                       Array<int> * stride_match_new_mid, Array<bool> * span_match_new_mid)
00133 {
00134     /// ...  The stride_match must be the matching from index_new to index_mid
00135 
00136     SimEdgeKernel & kernel_mid_old = ((*_graph)[index_mid])[index_old];
00137     Array<int> * stride_match_mid_old = kernel_mid_old.stridematch( );
00138     Array<bool> * span_match_mid_old = kernel_mid_old.spanmatch( );
00139     
00140     int new_dims = ((*_ptrs)[index_new])->number_of_dimensions();
00141     Array<int> * stride_match_new_old = new Array<int>;
00142     (*stride_match_new_old).resize( new_dims );
00143     Array<bool> * span_match_new_old = new Array<bool>;
00144     (*span_match_new_old).resize( new_dims );
00145 
00146     for (int i=0; i<new_dims; ++i) {
00147     if ( (*stride_match_new_mid)[i] == -1 ) {
00148         (*stride_match_new_old)[i] = -1;
00149         (*span_match_new_old)[i] = false;
00150     } else {
00151         (*stride_match_new_old)[i] = (*stride_match_mid_old)[ (*stride_match_new_mid)[i] ];
00152         (*span_match_new_old)[i]   = (*span_match_new_mid)[i] && 
00153         (*span_match_mid_old)[ (*stride_match_new_mid)[i] ];
00154     }
00155     }
00156     SimEdgeKernel & kernel_new_old = ((*_graph)[index_new])[index_old];
00157     kernel_new_old.dump_in_match( type, stride_match_new_old, span_match_new_old );
00158 }
00159 
00160 /// Given a matching from mid to new, need to construct a matching from old to new
00161 
00162 void
00163 SimGraph::_add_corresp_edge_backward(SimilarityType type, 
00164                        int index_old, int index_mid, int index_new,
00165                        Array<int> * stride_match_mid_new, Array<bool> * span_match_mid_new)
00166 {
00167     /// ...  The stride_match must be the matching from index_mid to index_new
00168 
00169     SimEdgeKernel & kernel_old_mid = ((*_graph)[index_old])[index_mid];
00170     Array<int> * stride_match_old_mid = kernel_old_mid.stridematch( );
00171     Array<bool> * span_match_old_mid = kernel_old_mid.spanmatch( );
00172     int old_dims = ((*_ptrs)[index_old])->number_of_dimensions();
00173     
00174     Array<int> * stride_match_old_new = new Array<int>;
00175     (*stride_match_old_new).resize( old_dims );
00176     Array<bool> * span_match_old_new = new Array<bool>;
00177     (*span_match_old_new).resize( old_dims );
00178 
00179     for (int i=0; i<old_dims; ++i) {
00180     if ( (*stride_match_old_mid)[i] == -1 ) {
00181         (*stride_match_old_new)[i] = -1;
00182         (*span_match_old_new)[i] = false;
00183     } else {
00184         (*stride_match_old_new)[i] = (*stride_match_mid_new)[ (*stride_match_old_mid)[i] ];
00185         (*span_match_old_new)[i]   = (*span_match_old_mid)[i] && 
00186                                  (*span_match_mid_new)[ (*stride_match_old_mid)[i] ];
00187     }
00188     }
00189     SimEdgeKernel & kernel_old_new = ((*_graph)[index_old])[index_new];
00190     kernel_old_new.dump_in_match( type, stride_match_old_new, span_match_old_new );
00191 }
00192     
00193 
00194 /// Create a copy of a given graph
00195 
00196 SimGraph::SimGraph( const SimGraph & other ) {
00197     #ifdef CLASS_INSTANCE_REGISTRY
00198     register_instance(SIM_GRAPH, sizeof(SimGraph), this);
00199     #endif
00200 
00201     _nodes = other._nodes;
00202     _ptrs = new Array< RefElement< AbstractAccess > >;
00203     _descr_exists = new Array< bool >;
00204     _graph  = new Array< Array< SimEdgeKernel > >;
00205 
00206     _ptrs->resize(_nodes);
00207     _descr_exists->resize( _nodes );
00208     _graph->resize(_nodes);
00209 
00210     for (int i = 0; i<_nodes; ++i) {
00211     (*_ptrs)[i] = (*(other._ptrs))[i];
00212     (*_descr_exists)[i] = (*_descr_exists)[i];
00213     (*_graph)[i].resize(_nodes);
00214     }
00215 
00216     for (int i=0; i < _nodes; ++i) {
00217     for (int j=0; j < _nodes; ++j) {
00218         ((*_graph)[i])[j] = ((*(other._graph))[i])[j];
00219     }
00220     }
00221 }
00222 
00223 /// Return the number of nodes in the graph
00224 
00225 int
00226 SimGraph::nodes( )
00227 {
00228     return _nodes;
00229 }
00230 
00231 SimGraph::~SimGraph( )
00232 {
00233     #ifdef CLASS_INSTANCE_REGISTRY
00234     unregister_instance(SIM_GRAPH, this);
00235     #endif
00236 
00237     if (_ptrs) {
00238     delete _ptrs;
00239     }
00240     if (_descr_exists) {
00241     delete _descr_exists;
00242     }
00243     if (_graph) {
00244     delete _graph;
00245     }
00246     if (_range_acc) {
00247     delete _range_acc;
00248     }
00249 }
00250 
00251 /// Calculate the similarity relationship between nodes i and j in the Similarity graph
00252 
00253 void
00254 SimGraph::calc_similarity( int i, int j )
00255 {
00256 
00257     AbstractAccess & descr1 = *((*_ptrs)[ i ]);
00258     int ndims1 = descr1.number_of_dimensions();
00259 
00260     AbstractAccess & descr2 = *((*_ptrs)[ j ]);
00261     int ndims2 = descr2.number_of_dimensions();
00262 
00263     SimEdgeKernel & kernelij = ((*_graph)[i])[j];
00264     SimEdgeKernel & kernelji = ((*_graph)[j])[i];
00265 
00266     SimilarityType orig_ij_type = kernelij.type();
00267     SimilarityType calc_ij_type;
00268 
00269     /// ...  If already filled in, skip it
00270     if ((orig_ij_type != SIM_UNKNOWN ) &&
00271     (orig_ij_type != SIM_DIM_EQUIV_UP ) &&
00272     (orig_ij_type != SIM_STRIDE_EQUIV_UP )) return;
00273     
00274     bool equal_dim_count;
00275 
00276     if (ndims1 == ndims2) {
00277     equal_dim_count = true;
00278     } else {
00279     equal_dim_count = false;
00280     }
00281 
00282     bool matchoff = false;
00283     bool matchstrides, matchspans;
00284 
00285     Array<int> * stride_match1;
00286     Array<int> * stride_match2;
00287     Array<bool> * span_match1;
00288     Array<bool> * span_match2;
00289 
00290     /// ...  Do the offsets match?
00291 
00292     matchoff = ar_offsets_match(descr1, descr2);
00293 
00294     /// ...  If these two descriptors were already found dimension-equivalent,
00295     /// ...  check offsets to see whether they are totally equivalent.  Then we
00296     /// ...  can avoid all the rest of the equivalency checks.
00297 
00298     if (orig_ij_type == SIM_DIM_EQUIV_UP) {
00299     if (matchoff) {
00300         calc_ij_type = SIM_EQUIV;
00301     } else {
00302         calc_ij_type = SIM_DIM_EQUIV;
00303     }
00304     kernelij.type(calc_ij_type);
00305     kernelji.type(calc_ij_type);
00306 
00307     stride_match1 = kernelij.stridematch();
00308     span_match1 = kernelij.spanmatch();
00309     stride_match2 = kernelji.stridematch();
00310     span_match2 = kernelji.spanmatch();
00311 
00312     } else {
00313 
00314     /// ...  Compare one dimension from each descriptor
00315 
00316     stride_match1 = new Array<int>;
00317     stride_match1->resize(ndims1);
00318 
00319     stride_match2 = new Array<int>;
00320     stride_match2->resize(ndims2);
00321 
00322     span_match1 = new Array<bool>;
00323     span_match1->resize(ndims1);
00324 
00325     span_match2 = new Array<bool>;
00326     span_match2->resize(ndims2);
00327 
00328     if (orig_ij_type == SIM_STRIDE_EQUIV_UP) {
00329             
00330         /// ...  Check only for a span match based on the previous stride match
00331 
00332         Array<int> * temp1 = kernelij.stridematch();
00333         for (int ii=0; ii<ndims1; ++ii) {
00334         (*stride_match1)[ii] = (*temp1)[ii];
00335         (*span_match1)[ii] = false;
00336         }
00337         Array<int> * temp2 = kernelji.stridematch();
00338         for (int ii=0; ii<ndims2; ++ii) {
00339         (*stride_match2)[ii] = (*temp2)[ii];
00340         (*span_match2)[ii] = false;
00341         }
00342         
00343     } else {
00344 
00345         calc_stride_span_match(descr1, descr2, *_range_acc,
00346                    *stride_match1, *stride_match2,
00347                    *span_match1, *span_match2);
00348     }
00349 
00350     /// ...  Now, check for a match.
00351 
00352     if (orig_ij_type == SIM_STRIDE_EQUIV_UP) {
00353         matchstrides = true;  /// ...  Already asserted that strides are equiv
00354     } else {
00355         matchstrides = true;
00356 
00357         /// ...  Check whether all dimensions of at least one descriptor 
00358         /// ...  have a matching dimension.
00359 
00360         int count1 = 0;
00361         for (int ii=0; ii<ndims1; ++ii) {
00362         if ((*stride_match1)[ii] != -1) {
00363             count1++;
00364         }
00365         }
00366         int count2 = 0;
00367         for (int ii=0; ii<ndims2; ++ii) {
00368         if ((*stride_match2)[ii] != -1) {
00369             count2++;
00370         }
00371         }
00372 
00373         p_assert(count1 == count2, "Stride-match is not reflexive");
00374 
00375         if ((count1 != ndims1) && (count1 != ndims2)) {
00376         matchstrides = false;
00377         }
00378     }
00379 
00380     matchspans = true;
00381     for (int ii=0; ii<ndims1; ++ii) {
00382         if (((*stride_match1)[ii] != -1) && (! (*span_match1)[ii])) {
00383         matchspans = false;
00384         break;
00385         }
00386     }
00387 
00388     if (matchoff && matchstrides && matchspans && equal_dim_count) {
00389         calc_ij_type = SIM_EQUIV;
00390     } else if (matchoff && matchstrides && matchspans) {
00391         calc_ij_type = SIM_EQUIV_SEMI;
00392     } else if (matchstrides && matchspans && equal_dim_count) {
00393         calc_ij_type = SIM_DIM_EQUIV;
00394     } else if (matchstrides && matchspans) {
00395         calc_ij_type = SIM_DIM_EQUIV_SEMI;
00396     } else if (matchstrides && equal_dim_count) {
00397         calc_ij_type = SIM_STRIDE_EQUIV;
00398     } else if (matchstrides) {
00399         calc_ij_type = SIM_STRIDE_EQUIV_SEMI;
00400     } else {
00401         calc_ij_type = SIM_NOT_SIMILAR;
00402     }
00403 
00404     kernelij.dump_in_match( calc_ij_type, stride_match1, span_match1 );
00405     kernelji.dump_in_match( calc_ij_type, stride_match2, span_match2 );
00406     }
00407 
00408     if (kernelij.type( ) == SIM_NOT_SIMILAR) return;
00409 
00410     /// ...  Now, see if we can fill in any more nodes in the graph
00411     /// ...  The above tested descriptor i against descriptor j
00412     /// ...  Now, we check all other nodes (k) connected to i for a relationship with j
00413 
00414     for (int k=0; k<_nodes; ++k) {
00415     if (!(*_descr_exists)[k]) continue;
00416     if (k == i) continue;  /// ...  The above tested i vs j
00417     if (k == j) continue;  /// ...  This would be testing j vs itself
00418 
00419     SimilarityType ik_type = ((*_graph)[i])[k].type();
00420 
00421     if ((ik_type != SIM_NOT_SIMILAR) &&
00422         (ik_type != SIM_UNKNOWN)) {
00423 
00424         if (calc_ij_type == SIM_EQUIV) {            /// ...  j = i && i ? k => j ? k
00425         _add_corresp_edge_forward ( ik_type, j, i, k, stride_match2, span_match2 );
00426         _add_corresp_edge_backward( ik_type, k, i, j, stride_match1, span_match1 );
00427 
00428         } else if (ik_type == SIM_EQUIV) {     /// ...  j ? i && i = k => j ? k
00429         _add_corresp_edge_forward ( calc_ij_type, j, i, k, stride_match2, span_match2 );
00430         _add_corresp_edge_backward( calc_ij_type, k, i, j, stride_match1, span_match1 );
00431 
00432         } else if ((calc_ij_type == SIM_DIM_EQUIV) &&  /// ...  j =d i && i =d k => j =d^ k
00433                (ik_type == SIM_DIM_EQUIV)) {
00434         _add_corresp_edge_forward ( SIM_DIM_EQUIV_UP, j, i, k, stride_match2, span_match2 );
00435         _add_corresp_edge_backward( SIM_DIM_EQUIV_UP, k, i, j, stride_match1, span_match1 );
00436 
00437         } else if ((calc_ij_type == SIM_STRIDE_EQUIV) && /// ...  j =s i && i =s k => j =s^ k
00438                (ik_type == SIM_STRIDE_EQUIV)) {
00439         _add_corresp_edge_forward ( SIM_STRIDE_EQUIV_UP, j, i, k, stride_match2, span_match2 );
00440         _add_corresp_edge_backward( SIM_STRIDE_EQUIV_UP, k, i, j, stride_match1, span_match1 );
00441 
00442         } else if (((calc_ij_type == SIM_STRIDE_EQUIV) &&  /// ...  j =s i && i =d k => j =s k
00443             (ik_type == SIM_DIM_EQUIV)) ||    /// ...  j =d i && i =s k => j =s k
00444                ((calc_ij_type == SIM_DIM_EQUIV) &&
00445             (ik_type == SIM_STRIDE_EQUIV))) {
00446         _add_corresp_edge_forward ( SIM_STRIDE_EQUIV, j, i, k, stride_match2, span_match2 );
00447         _add_corresp_edge_backward( SIM_STRIDE_EQUIV, k, i, j, stride_match1, span_match1 );
00448 
00449         } else if ((calc_ij_type == SIM_DIM_EQUIV) &&     /// ...  j =d i && i =d^ k => j =d^ k
00450                (ik_type == SIM_DIM_EQUIV_UP)) {
00451         _add_corresp_edge_forward ( SIM_DIM_EQUIV_UP, j, i, k, stride_match2, span_match2 );
00452         _add_corresp_edge_backward( SIM_DIM_EQUIV_UP, k, i, j, stride_match1, span_match1 );
00453 
00454         } else if ((calc_ij_type == SIM_DIM_EQUIV) &&     /// ...  j =d i && i =s^ k => j =s^ k
00455                (ik_type == SIM_STRIDE_EQUIV_UP)) {
00456         _add_corresp_edge_forward ( SIM_STRIDE_EQUIV_UP, j, i, k, stride_match2, span_match2 );
00457         _add_corresp_edge_backward( SIM_STRIDE_EQUIV_UP, k, i, j, stride_match1, span_match1 );
00458 
00459         } else if ((calc_ij_type == SIM_STRIDE_EQUIV) &&  /// ...  j =s i && i =d^ k => j =s k
00460                (ik_type == SIM_DIM_EQUIV_UP)) {
00461         _add_corresp_edge_forward ( SIM_STRIDE_EQUIV, j, i, k, stride_match2, span_match2 );
00462         _add_corresp_edge_backward( SIM_STRIDE_EQUIV, k, i, j, stride_match1, span_match1 );
00463 
00464         } else if ((calc_ij_type == SIM_STRIDE_EQUIV) &&  /// ...  j =s i && i =s^ k => j =s^ k
00465                (ik_type == SIM_STRIDE_EQUIV_UP)) {
00466         _add_corresp_edge_forward ( SIM_STRIDE_EQUIV_UP, j, i, k, stride_match2, span_match2 );
00467         _add_corresp_edge_backward( SIM_STRIDE_EQUIV_UP, k, i, j, stride_match1, span_match1 );
00468 
00469         } else {
00470         continue;
00471         }
00472     }
00473     }
00474 }
00475 
00476 /// Check connections for the node which was in an aggregation.  When a SIM_DIM_EQUIV
00477 /// is found, set the appropriate span-match flag false (since the span is changed
00478 /// by the aggregation.
00479 
00480 void 
00481 SimGraph::redo_spanmatch( SimEdge & edge, int which_node, int which_dim )
00482 {
00483     for (int i=0; i<_nodes; ++i) {
00484     if (!(*_descr_exists)[i]) continue;
00485     if (i==which_node) continue;
00486     SimEdgeKernel & edgek = ((*_graph)[which_node])[i];
00487     if ((edgek.type() == SIM_DIM_EQUIV) || 
00488         (edgek.type() == SIM_DIM_EQUIV_UP)) {
00489        (*(edgek.spanmatch()))[which_dim] = false;
00490        SimEdgeKernel & edgek2 = ((*_graph)[i])[which_node];
00491        (*(edgek2.spanmatch()))[(*(edgek.stridematch()))[which_dim]] = false;
00492        }
00493     }
00494 }
00495 
00496 void 
00497 SimGraph::set_unknown( SimEdge & edge, int which_node)
00498 {
00499     for (int i=0; i<_nodes; ++i) {
00500     if (!(*_descr_exists)[i]) continue;
00501     if (i==which_node) continue;
00502     ((*_graph)[which_node])[i].type(SIM_UNKNOWN);
00503     ((*_graph)[i])[which_node].type(SIM_UNKNOWN);
00504     }
00505 }
00506 
00507 RangeAccessor *
00508 SimGraph::range_acc(  )
00509 {
00510     return _range_acc;
00511 }
00512 
00513 SimGraph *
00514 SimGraph::clone() const
00515 {
00516     return new SimGraph( (SimGraph &)*this );
00517 }
00518 
00519 Listable *
00520 SimGraph::listable_clone() const
00521 {
00522     return (Listable *) clone();
00523 }
00524 
00525 void
00526 SimGraph::print(ostream & o) const 
00527 {
00528     o << "{ Nodes: " << _nodes << "; Ptrs: " << *_ptrs << "; Graph: " << *_graph << "}";
00529 }
00530 
00531 ostream & 
00532 operator << (ostream & o, const SimGraph & graph) 
00533 {
00534     graph.print(o);
00535     return o;
00536 }
00537 
00538 SimEdgeKernel &
00539 SimGraph::kernel(int i, int j)
00540 {
00541     return ((*_graph)[i])[j];
00542 }
00543 
00544 void
00545 SimGraph::set_ptr(int i, AbstractAccess & aa)
00546 {
00547     (*_ptrs)[i] = aa;
00548 }
 © 1995-2005 University of Illinois, Urbana-Champaign. All rights reserved.  Fri Mar 25 23:06:07 2005