18 #include <boost/foreach.hpp>
19 #include <boost/dynamic_bitset.hpp>
38 : bondType(
Bond::UNSPECIFIED),
39 bondStereo(static_cast<unsigned int>(
Bond::STEREONONE)),
45 bondStereo(static_cast<unsigned int>(bs)),
50 : bondType(bt), bondStereo(bs), nbrSymClass(nsc), nbrIdx(ni){};
64 unsigned int div = 1) {
97 isRingStereoAtom(false),
105 canon_atom *atoms, std::vector<bondholder> &nbrs);
108 canon_atom *atoms, std::vector<bondholder> &nbrs,
unsigned int atomIdx,
109 std::vector<std::pair<unsigned int, unsigned int>> &result);
131 dp_atomsInPlay(NULL),
132 dp_bondsInPlay(NULL){};
135 const boost::dynamic_bitset<> *atomsInPlay = NULL,
136 const boost::dynamic_bitset<> *bondsInPlay = NULL)
139 dp_atomsInPlay(atomsInPlay),
140 dp_bondsInPlay(bondsInPlay){};
145 if (dp_atomsInPlay && !((*dp_atomsInPlay)[i] || (*dp_atomsInPlay)[j])) {
149 if (!dp_atomsInPlay || (*dp_atomsInPlay)[i]) {
152 if (!dp_atomsInPlay || (*dp_atomsInPlay)[j]) {
155 for (
unsigned int ii = 0;
156 ii < dp_atoms[i].
bonds.size() && ii < dp_atoms[j].bonds.size(); ++ii) {
162 std::vector<std::pair<unsigned int, unsigned int>> swapsi;
163 std::vector<std::pair<unsigned int, unsigned int>> swapsj;
164 if (!dp_atomsInPlay || (*dp_atomsInPlay)[i]) {
167 if (!dp_atomsInPlay || (*dp_atomsInPlay)[j]) {
170 for (
unsigned int ii = 0; ii < swapsi.size() && ii < swapsj.size(); ++ii) {
171 int cmp = swapsi[ii].second - swapsj[ii].second;
187 dp_atomsInPlay(NULL),
188 dp_bondsInPlay(NULL){};
191 const boost::dynamic_bitset<> *atomsInPlay = NULL,
192 const boost::dynamic_bitset<> *bondsInPlay = NULL)
195 dp_atomsInPlay(atomsInPlay),
196 dp_bondsInPlay(bondsInPlay){};
201 if (dp_atomsInPlay && !((*dp_atomsInPlay)[i] || (*dp_atomsInPlay)[j])) {
205 if (dp_atoms[i].neighborNum < dp_atoms[j].neighborNum) {
207 }
else if (dp_atoms[i].neighborNum > dp_atoms[j].neighborNum) {
211 if (dp_atoms[i].revistedNeighbors < dp_atoms[j].revistedNeighbors) {
213 }
else if (dp_atoms[i].revistedNeighbors > dp_atoms[j].revistedNeighbors) {
217 if (!dp_atomsInPlay || (*dp_atomsInPlay)[i]) {
220 if (!dp_atomsInPlay || (*dp_atomsInPlay)[j]) {
223 for (
unsigned int ii = 0;
224 ii < dp_atoms[i].
bonds.size() && ii < dp_atoms[j].bonds.size(); ++ii) {
230 if (dp_atoms[i].bonds.size() < dp_atoms[j].
bonds.size()) {
232 }
else if (dp_atoms[i].bonds.size() > dp_atoms[j].
bonds.size()) {
240 unsigned int getAtomRingNbrCode(
unsigned int i)
const {
241 if (!dp_atoms[i].hasRingNbr)
return 0;
243 int *nbrs = dp_atoms[i].nbrIds;
244 unsigned int code = 0;
245 for (
unsigned j = 0; j < dp_atoms[i].degree; ++j) {
246 if (dp_atoms[nbrs[j]].isRingStereoAtom) {
247 code += dp_atoms[nbrs[j]].index * 10000 + 1;
253 int basecomp(
int i,
int j)
const {
255 unsigned int ivi, ivj;
258 ivi = dp_atoms[i].index;
259 ivj = dp_atoms[j].index;
270 int molAtomMapNumber_i = 0;
271 int molAtomMapNumber_j = 0;
276 if (molAtomMapNumber_i < molAtomMapNumber_j)
278 else if (molAtomMapNumber_i > molAtomMapNumber_j)
282 ivi = dp_atoms[i].degree;
283 ivj = dp_atoms[j].degree;
289 if (dp_atoms[i].p_symbol && dp_atoms[j].p_symbol) {
290 if (*(dp_atoms[i].p_symbol) < *(dp_atoms[j].p_symbol))
292 else if (*(dp_atoms[i].p_symbol) > *(dp_atoms[j].p_symbol))
299 ivi = dp_atoms[i].atom->getAtomicNum();
300 ivj = dp_atoms[j].atom->getAtomicNum();
307 if (df_useIsotopes) {
308 ivi = dp_atoms[i].atom->getIsotope();
309 ivj = dp_atoms[j].atom->getIsotope();
317 ivi = dp_atoms[i].totalNumHs;
318 ivj = dp_atoms[j].totalNumHs;
325 ivi = dp_atoms[i].atom->getFormalCharge();
326 ivj = dp_atoms[j].atom->getFormalCharge();
333 if (df_useChirality) {
340 ivi = cipCode ==
"R" ? 2 : 1;
344 ivj = cipCode ==
"R" ? 2 : 1;
352 ivi = dp_atoms[i].atom->getChiralTag() != 0;
353 ivj = dp_atoms[j].atom->getChiralTag() != 0;
360 if (df_useChiralityRings) {
362 ivi = getAtomRingNbrCode(i);
363 ivj = getAtomRingNbrCode(j);
385 dp_atomsInPlay(NULL),
386 dp_bondsInPlay(NULL),
388 df_useIsotopes(true),
389 df_useChirality(true),
390 df_useChiralityRings(true){};
392 const boost::dynamic_bitset<> *atomsInPlay = NULL,
393 const boost::dynamic_bitset<> *bondsInPlay = NULL)
396 dp_atomsInPlay(atomsInPlay),
397 dp_bondsInPlay(bondsInPlay),
399 df_useIsotopes(true),
400 df_useChirality(true),
401 df_useChiralityRings(true){};
406 if (dp_atomsInPlay && !((*dp_atomsInPlay)[i] || (*dp_atomsInPlay)[j])) {
410 int v = basecomp(i, j);
416 if (!dp_atomsInPlay || (*dp_atomsInPlay)[i]) {
419 if (!dp_atomsInPlay || (*dp_atomsInPlay)[j]) {
423 for (
unsigned int ii = 0;
424 ii < dp_atoms[i].
bonds.size() && ii < dp_atoms[j].bonds.size();
431 if (dp_atoms[i].bonds.size() < dp_atoms[j].
bonds.size()) {
433 }
else if (dp_atoms[i].bonds.size() > dp_atoms[j].
bonds.size()) {
448 void getAtomNeighborhood(std::vector<bondholder> &nbrs)
const {
449 for (
unsigned j = 0; j < nbrs.size(); ++j) {
450 unsigned int nbrIdx = nbrs[j].nbrIdx;
455 const Atom *nbr = dp_atoms[nbrIdx].atom;
456 nbrs[j].nbrSymClass =
463 int basecomp(
int i,
int j)
const {
465 unsigned int ivi, ivj;
468 ivi = dp_atoms[i].index;
469 ivj = dp_atoms[j].index;
476 ivi = dp_atoms[i].atom->getAtomicNum();
477 ivj = dp_atoms[j].atom->getAtomicNum();
484 ivi = dp_atoms[i].atom->getIsotope();
485 ivj = dp_atoms[j].atom->getIsotope();
497 ivi = cipCode ==
"R" ? 2 : 1;
501 ivj = cipCode ==
"R" ? 2 : 1;
517 : dp_atoms(NULL), dp_mol(NULL), df_useNbrs(false){};
519 : dp_atoms(atoms), dp_mol(&m), df_useNbrs(false){};
524 int v = basecomp(i, j);
528 getAtomNeighborhood(dp_atoms[i].bonds);
529 getAtomNeighborhood(dp_atoms[j].bonds);
534 for (
unsigned int ii = 0;
535 ii < dp_atoms[i].
bonds.size() && ii < dp_atoms[j].bonds.size();
541 for (
unsigned int ii = 0;
542 ii < dp_atoms[i].
bonds.size() && ii < dp_atoms[j].bonds.size();
548 if (dp_atoms[i].bonds.size() < dp_atoms[j].
bonds.size()) {
550 }
else if (dp_atoms[i].bonds.size() > dp_atoms[j].
bonds.size()) {
563 template <
typename CompareFunc>
565 int mode,
int *order,
int *count,
int &activeset,
566 int *next,
int *changed,
char *touchedPartitions) {
578 while (activeset != -1) {
590 partition = activeset;
591 activeset = next[partition];
592 next[partition] = -2;
594 len = count[partition];
595 offset = atoms[partition].
index;
596 start = order + offset;
607 hanoisort(start, len, count, changed, compar);
614 for (
int k = 0; k < len; ++k) {
615 changed[start[k]] = 0;
621 for (i = count[index]; i < len; i++) {
623 if (count[index]) symclass = offset + i;
624 atoms[index].
index = symclass;
629 for (
unsigned j = 0; j < atoms[index].
degree; ++j) {
630 changed[atoms[index].
nbrIds[j]] = 1;
637 for (i = count[index]; i < len; i++) {
639 for (
unsigned j = 0; j < atoms[index].
degree; ++j) {
640 unsigned int nbor = atoms[index].
nbrIds[j];
641 touchedPartitions[atoms[nbor].
index] = 1;
644 for (
unsigned int ii = 0; ii < nAtoms; ++ii) {
645 if (touchedPartitions[ii]) {
646 partition = order[ii];
647 if ((count[partition] > 1) && (next[partition] == -2)) {
648 next[partition] = activeset;
649 activeset = partition;
651 touchedPartitions[ii] = 0;
658 template <
typename CompareFunc>
660 int mode,
int *order,
int *count,
int &activeset,
int *next,
661 int *changed,
char *touchedPartitions) {
669 for (
unsigned int i = 0; i < nAtoms; i++) {
670 partition = order[i];
671 oldPart = atoms[partition].
index;
672 while (count[partition] > 1) {
673 len = count[partition];
674 offset = atoms[partition].
index + len - 1;
675 index = order[offset];
676 atoms[index].
index = offset;
677 count[partition] = len - 1;
681 if (atoms[index].degree < 1) {
684 for (
unsigned j = 0; j < atoms[index].
degree; ++j) {
685 unsigned int nbor = atoms[index].
nbrIds[j];
686 touchedPartitions[atoms[nbor].
index] = 1;
690 for (
unsigned int ii = 0; ii < nAtoms; ++ii) {
691 if (touchedPartitions[ii]) {
692 int npart = order[ii];
693 if ((count[npart] > 1) && (next[npart] == -2)) {
694 next[npart] = activeset;
697 touchedPartitions[ii] = 0;
701 changed, touchedPartitions);
704 if (atoms[partition].index != oldPart) {
711 int *order,
int *count,
715 int *count,
int &activeset,
716 int *next,
int *changed);
719 std::vector<unsigned int> &res,
720 bool breakTies =
true,
721 bool includeChirality =
true,
722 bool includeIsotopes =
true);
725 const ROMol &mol, std::vector<unsigned int> &res,
726 const boost::dynamic_bitset<> &atomsInPlay,
727 const boost::dynamic_bitset<> &bondsInPlay,
728 const std::vector<std::string> *atomSymbols = NULL,
bool breakTies =
true,
729 bool includeChirality =
true,
bool includeIsotopes =
true);
732 std::vector<unsigned int> &res);
735 std::vector<Canon::canon_atom> &atoms,
736 bool includeChirality =
true);