private static bool MoleculeMatchesRecursive(AtomDefinition atomDefinition1, AtomDefinition atomDefinition2, List <AtomDefinition> undoStack) { // Make sure we don't match an atom that's already matched with something else. This check also prevents infinite // recursion when an atom is revisited by one of its neighbors. if (atomDefinition1.proposedCounterpart != null || atomDefinition2.proposedCounterpart != null) { return(atomDefinition1.proposedCounterpart == atomDefinition2 && atomDefinition2.proposedCounterpart == atomDefinition1); } if (atomDefinition1.atom == atomDefinition2.atom && IdenticalBonds(atomDefinition1, atomDefinition2)) { int undoStackTop = undoStack.Count; // undoStack contains all atoms that have a proposed counterpart. It's used to clean up counterparts if a full match cannot be made. // Indexes smaller than undoStackTop represent assumptions made by callers in higher levels. At this level, we treat them as // absolute fact. Indexes larger or equal to undoStackTop represent assumptions made in this call, or lower callers. We must undo // these assumptions if we can't make a full match. atomDefinition1.proposedCounterpart = atomDefinition2; atomDefinition2.proposedCounterpart = atomDefinition1; undoStack.Add(atomDefinition1); undoStack.Add(atomDefinition2); bool flag1 = true; foreach (BondDefinition bond in atomDefinition1.bonds) { AtomDefinition subAtom1 = (bond.atom1 == atomDefinition1 ? bond.atom2 : bond.atom1); bool flag2 = false; foreach (AtomDefinition subAtom2 in atomDefinition2.GetBondedAtoms(bond.bondCount)) { if (MoleculeMatchesRecursive(subAtom1, subAtom2, undoStack)) { flag2 = true; break; } // It's an invariant that whenever MoleculeMatchesRecursive retuns false, it restores undoStack // to the state it was on method entry, so no need to touch undoStack here. } if (!flag2) // Found no match for subAtomDefinition1, molecule mismatch { flag1 = false; break; // Return false through the recursion } } if (flag1) { return(true); } // clean up the assumptions while (undoStack.Count > undoStackTop) { undoStack[undoStack.Count - 1].proposedCounterpart = null; undoStack.RemoveAt(undoStack.Count - 1); } } return(false); }
public Atom(Molecule molecule, AtomDefinition definition) { this.Molecule = molecule; this.MolecularPosition = definition.Position; this.Element = definition.Element; }
private static bool IdenticalBonds(AtomDefinition atom1, AtomDefinition atom2) { return(false); }