00001 /*************************************************************************** 00002 *cr 00003 *cr (C) Copyright 1995-2019 The Board of Trustees of the 00004 *cr University of Illinois 00005 *cr All Rights Reserved 00006 *cr 00007 ***************************************************************************/ 00008 00009 /*************************************************************************** 00010 * RCS INFORMATION: 00011 * 00012 * $RCSfile: SmallRingLinkages.h,v $ 00013 * $Author: johns $ $Locker: $ $State: Exp $ 00014 * $Revision: 1.10 $ $Date: 2020年10月28日 15:09:57 $ 00015 * 00016 *************************************************************************** 00017 * DESCRIPTION: 00018 * A SmallRingLinkages object contains a list of edges which lie on paths 00019 * connecting (orientated) SmallRings. 00020 * 00021 ***************************************************************************/ 00022 #ifndef SMALLRINGLINKAGE_H 00023 #define SMALLRINGLINKAGE_H 00024 00025 #include "SmallRing.h" 00026 #include "ResizeArray.h" 00027 #include "inthash.h" 00028 #include "Inform.h" 00029 00033 class LinkagePath { 00034 public: 00035 SmallRing path; 00036 int start_ring, end_ring; 00037 00038 LinkagePath(void) : path(), start_ring(-1), end_ring(-1) {} 00039 LinkagePath(SmallRing &p_path, int p_start_ring, int p_end_ring) { 00040 path = p_path; 00041 start_ring = p_start_ring; 00042 end_ring = p_end_ring; 00043 } 00044 00045 int num(void) { return path.num(); } 00046 int operator [](int i) { return path[i]; } 00047 void append(int i) { path.append(i); } 00048 void remove_last(void) { path.remove_last(); } 00049 00050 LinkagePath* copy(void) { 00051 LinkagePath *pathcopy; 00052 pathcopy = new LinkagePath(*path.copy(),start_ring,end_ring); 00053 return pathcopy; 00054 } 00055 00056 friend Inform& operator << (Inform &os, LinkagePath &lp) { 00057 os << lp.path << " [" << lp.start_ring << "," << lp.end_ring << "]"; 00058 return os; 00059 } 00060 }; 00061 00065 class LinkageEdge { 00066 public: 00067 int left_atom, right_atom; 00068 ResizeArray<LinkagePath *> paths; 00069 00070 LinkageEdge(int p_atom_left, int p_atom_right) : paths (1) { 00071 left_atom = p_atom_left; 00072 right_atom = p_atom_right; 00073 } 00074 00075 void addPath(LinkagePath &lp) { 00076 paths.append(&lp); 00077 } 00078 00079 friend Inform& operator << (Inform &os, LinkageEdge &le) { 00080 os << "(" << le.left_atom << "," << le.right_atom << ")"; 00081 return os; 00082 } 00083 }; 00084 00087 class SmallRingLinkages { 00088 private: 00089 inthash_t *edges_to_links; 00090 00091 public: 00092 ResizeArray<LinkageEdge *> links; 00093 ResizeArray<LinkagePath *> paths; 00094 00095 SmallRingLinkages(void) : links(1) { 00096 edges_to_links = new inthash_t; 00097 // TODO: Adjust the initial number of hash buckets? 00098 inthash_init(edges_to_links,64); 00099 } 00100 00101 ~SmallRingLinkages(void) { 00102 inthash_destroy(edges_to_links); 00103 delete edges_to_links; 00104 } 00105 00106 void clear(void) { 00107 links.clear(); 00108 paths.clear(); 00109 inthash_destroy(edges_to_links); 00110 // TODO: Adjust the initial number of hash buckets? 00111 inthash_init(edges_to_links,64); 00112 } 00113 00114 void addLinkagePath(LinkagePath &lp) { 00115 int i, atom_left, atom_right; 00116 LinkageEdge *link; 00117 atom_right = lp.path[0]; 00118 00119 for (i=1;i<lp.path.num();i++) { 00120 atom_left = atom_right; 00121 atom_right = lp.path[i]; 00122 link = getLinkageEdge(atom_left,atom_right); 00123 link->addPath(lp); 00124 } 00125 00126 paths.append(&lp); 00127 } 00128 00129 bool sharesLinkageEdges(LinkagePath &lp) { 00130 int i, atom_left, atom_right; 00131 LinkageEdge *link; 00132 atom_right = lp.path[0]; 00133 00134 for (i=1;i<lp.path.num();i++) { 00135 atom_left = atom_right; 00136 atom_right = lp.path[i]; 00137 link = getLinkageEdge(atom_left,atom_right); 00138 if (link->paths.num() > 1) 00139 return true; 00140 } 00141 00142 return false; 00143 } 00144 00145 LinkageEdge* getLinkageEdge(int atom_left, int atom_right) { 00146 int key, link_idx; 00147 LinkageEdge *link; 00148 00149 order_edge_atoms(atom_left,atom_right); 00150 key = get_link_key(atom_left,atom_right); 00151 00152 link_idx = inthash_lookup(edges_to_links, key); 00153 if (link_idx == HASH_FAIL) { 00154 link = new LinkageEdge(atom_left,atom_right); 00155 links.append(link); 00156 link_idx = int(links.num())-1; 00157 inthash_insert(edges_to_links,key,link_idx); 00158 } 00159 00160 return links[link_idx]; 00161 } 00162 00163 void order_edge_atoms(int& atom_left, int& atom_right) { 00164 int t; 00165 if (atom_left > atom_right) { 00166 t = atom_left; 00167 atom_left = atom_right; 00168 atom_right = t; 00169 } 00170 } 00171 00172 int get_link_key(int al, int ar) { 00173 // al - left atom id 00174 // ar - right atom id 00175 // triangular mapping of pairs to single numbers 00176 return 1 + ar*(ar+1)/2 + al*(al+1)/2 + (al+1)*ar; 00177 } 00178 00179 friend Inform& operator << (Inform &os, SmallRingLinkages &srl) { 00180 int i, len; 00181 00182 os << "SmallRingLinkages:\n"; 00183 00184 os << "Links:\n"; 00185 len = int(srl.links.num()); 00186 for (i=0; i < len; i++) 00187 os << "\t" << *(srl.links[i]) << "\n"; 00188 00189 os << "Paths:\n"; 00190 len = int(srl.paths.num()); 00191 for (i=0; i < len; i++) 00192 os << "\t" << *(srl.paths[i]) << "\n"; 00193 00194 return os; 00195 } 00196 }; 00197 00198 #endif