/// <summary> /// Tries to saturate a bond by increasing its bond orders by 1.0. /// </summary> /// <returns>true if the bond could be increased</returns> public bool SaturateByIncreasingBondOrder(IBond bond, IAtomContainer atomContainer) { var atoms = BondManipulator.GetAtomArray(bond); var atom = atoms[0]; var partner = atoms[1]; Debug.WriteLine(" saturating bond: ", atom.Symbol, "-", partner.Symbol); var atomTypes1 = structgenATF.GetAtomTypes(atom.Symbol); var atomTypes2 = structgenATF.GetAtomTypes(partner.Symbol); foreach (var aType1 in atomTypes1) { Debug.WriteLine($" considering atom type: {aType1}"); if (CouldMatchAtomType(atomContainer, atom, aType1)) { Debug.WriteLine($" trying atom type: {aType1}"); foreach (var aType2 in atomTypes2) { Debug.WriteLine($" considering partner type: {aType1}"); if (CouldMatchAtomType(atomContainer, partner, aType2)) { Debug.WriteLine($" with atom type: {aType2}"); if (BondManipulator.IsLowerOrder(bond.Order, aType2.MaxBondOrder) && BondManipulator.IsLowerOrder(bond.Order, aType1.MaxBondOrder)) { bond.Order = BondManipulator.IncreaseBondOrder(bond.Order); Debug.WriteLine($"Bond order now {bond.Order}"); return(true); } } } } } return(false); }
/// <summary> /// Saturate atom by adjusting its bond orders. /// This method is known to fail, especially on pyrrole-like compounds. /// Consider using <see cref="Smiles.DeduceBondSystemTool"/>, which should work better /// </summary> public bool NewSaturate(IBond bond, IAtomContainer atomContainer) { var atoms = BondManipulator.GetAtomArray(bond); var atom = atoms[0]; var partner = atoms[1]; Debug.WriteLine($" saturating bond: {atom.Symbol}-{partner.Symbol}"); var atomTypes1 = structgenATF.GetAtomTypes(atom.Symbol); var atomTypes2 = structgenATF.GetAtomTypes(partner.Symbol); bool bondOrderIncreased = true; while (bondOrderIncreased && !IsSaturated(bond, atomContainer)) { Debug.WriteLine("Can increase bond order"); bondOrderIncreased = false; foreach (var aType1 in atomTypes1) { if (bondOrderIncreased) { break; } Debug.WriteLine($" considering atom type: {aType1}"); if (CouldMatchAtomType(atomContainer, atom, aType1)) { Debug.WriteLine($" trying atom type: {aType1}"); foreach (var aType2 in atomTypes2) { if (bondOrderIncreased) { break; } Debug.WriteLine($" considering partner type: {aType1}"); if (CouldMatchAtomType(atomContainer, partner, aType2)) { Debug.WriteLine($" with atom type: {aType2}"); if (!BondManipulator.IsLowerOrder(bond.Order, aType2.MaxBondOrder) || !BondManipulator.IsLowerOrder(bond.Order, aType1.MaxBondOrder)) { Debug.WriteLine("Bond order not increased: atoms has reached (or exceeded) maximum bond order for this atom type"); } else if (BondManipulator.IsLowerOrder(bond.Order, aType2.MaxBondOrder) && BondManipulator.IsLowerOrder(bond.Order, aType1.MaxBondOrder)) { BondManipulator.IncreaseBondOrder(bond); Debug.WriteLine($"Bond order now {bond.Order}"); bondOrderIncreased = true; } } } } } } return(IsSaturated(bond, atomContainer)); }
/// <summary> /// This method decides the highest bond order that the bond can have and set /// it to that. /// </summary> /// <param name="bond">The bond to be investigated</param> /// <param name="atomContainer">The <see cref="IAtomContainer"/> that contains the bond</param> /// <exception cref="CDKException">when the bond cannot be further increased</exception> private void SetMaxBondOrder(IBond bond, IAtomContainer atomContainer) { if (BondOrderCanBeIncreased(bond, atomContainer)) { if (bond.Order != BondOrder.Quadruple) { bond.Order = BondManipulator.IncreaseBondOrder(bond.Order); } else { throw new CDKException("Can't increase a quadruple bond!"); } } }
public virtual void TestGetBondOrderSum() { IChemObject obj = NewChemObject(); IRing r = obj.Builder.NewRing(5, "C"); Assert.AreEqual(5, r.GetBondOrderSum()); BondManipulator.IncreaseBondOrder(r.Bonds[0]); Assert.AreEqual(6, r.GetBondOrderSum()); BondManipulator.IncreaseBondOrder(r.Bonds[0]); Assert.AreEqual(7, r.GetBondOrderSum()); BondManipulator.IncreaseBondOrder(r.Bonds[4]); Assert.AreEqual(8, r.GetBondOrderSum()); }
/// <summary> /// Initiates the process for the given mechanism. The atoms to apply are mapped between /// reactants and products. /// </summary> /// <param name="atomContainerSet"></param> /// <param name="atomList"> /// The list of atoms taking part in the mechanism. Only allowed two atoms. /// The first atom is the atom which contains the ISingleElectron and the second /// third is the atom which will be removed /// the first atom</param> /// <param name="bondList">The list of bonds taking part in the mechanism. Only allowed one bond. /// It is the bond which is moved</param> /// <returns>The Reaction mechanism</returns> public IReaction Initiate(IChemObjectSet <IAtomContainer> atomContainerSet, IList <IAtom> atomList, IList <IBond> bondList) { var atMatcher = CDK.AtomTypeMatcher; if (atomContainerSet.Count != 1) { throw new CDKException("RadicalSiteIonizationMechanism only expects one IAtomContainer"); } if (atomList.Count != 3) { throw new CDKException("RadicalSiteIonizationMechanism expects three atoms in the List"); } if (bondList.Count != 2) { throw new CDKException("RadicalSiteIonizationMechanism only expect one bond in the List"); } IAtomContainer molecule = atomContainerSet[0]; IAtomContainer reactantCloned; reactantCloned = (IAtomContainer)molecule.Clone(); IAtom atom1 = atomList[0]; // Atom containing the ISingleElectron IAtom atom1C = reactantCloned.Atoms[molecule.Atoms.IndexOf(atom1)]; IAtom atom2 = atomList[1]; // Atom IAtom atom2C = reactantCloned.Atoms[molecule.Atoms.IndexOf(atom2)]; IAtom atom3 = atomList[2]; // Atom to be saved IAtom atom3C = reactantCloned.Atoms[molecule.Atoms.IndexOf(atom3)]; IBond bond1 = bondList[0]; // Bond to increase the order int posBond1 = molecule.Bonds.IndexOf(bond1); IBond bond2 = bondList[1]; // Bond to remove int posBond2 = molecule.Bonds.IndexOf(bond2); BondManipulator.IncreaseBondOrder(reactantCloned.Bonds[posBond1]); reactantCloned.Bonds.Remove(reactantCloned.Bonds[posBond2]); var selectron = reactantCloned.GetConnectedSingleElectrons(atom1C); reactantCloned.SingleElectrons.Remove(selectron.Last()); atom1C.Hybridization = Hybridization.Unset; AtomContainerManipulator.PercieveAtomTypesAndConfigureAtoms(reactantCloned); IAtomType type = atMatcher.FindMatchingAtomType(reactantCloned, atom1C); if (type == null || type.AtomTypeName.Equals("X", StringComparison.Ordinal)) { return(null); } atom2C.Hybridization = Hybridization.Unset; AtomContainerManipulator.PercieveAtomTypesAndConfigureAtoms(reactantCloned); type = atMatcher.FindMatchingAtomType(reactantCloned, atom2C); if (type == null || type.AtomTypeName.Equals("X", StringComparison.Ordinal)) { return(null); } reactantCloned.SingleElectrons.Add(atom2C.Builder.NewSingleElectron(atom3C)); atom3C.Hybridization = Hybridization.Unset; AtomContainerManipulator.PercieveAtomTypesAndConfigureAtoms(reactantCloned); type = atMatcher.FindMatchingAtomType(reactantCloned, atom3C); if (type == null || type.AtomTypeName.Equals("X", StringComparison.Ordinal)) { return(null); } IReaction reaction = atom2C.Builder.NewReaction(); reaction.Reactants.Add(molecule); /* mapping */ foreach (var atom in molecule.Atoms) { IMapping mapping = atom2C.Builder.NewMapping(atom, reactantCloned.Atoms[molecule.Atoms.IndexOf(atom)]); reaction.Mappings.Add(mapping); } var moleculeSetP = ConnectivityChecker.PartitionIntoMolecules(reactantCloned); foreach (var moleculeP in moleculeSetP) { reaction.Products.Add(moleculeP); } return(reaction); }
/// <summary> /// Initiates the process for the given mechanism. The atoms to apply are mapped between /// reactants and products. /// </summary> /// <param name="atomContainerSet"></param> /// <param name="atomList"> The list of atoms taking part in the mechanism. Only allowed two atoms</param> /// <param name="bondList">The list of bonds taking part in the mechanism. Only allowed one bond</param> /// <returns>The Reaction mechanism</returns> public IReaction Initiate(IChemObjectSet <IAtomContainer> atomContainerSet, IList <IAtom> atomList, IList <IBond> bondList) { var atMatcher = CDK.AtomTypeMatcher; if (atomContainerSet.Count != 1) { throw new CDKException("SharingElectronMechanism only expects one IAtomContainer"); } if (atomList.Count != 2) { throw new CDKException("SharingElectronMechanism expects two atoms in the List"); } if (bondList.Count != 1) { throw new CDKException("SharingElectronMechanism only expect one bond in the List"); } IAtomContainer molecule = atomContainerSet[0]; IAtomContainer reactantCloned; reactantCloned = (IAtomContainer)molecule.Clone(); IAtom atom1 = atomList[0]; // Atom containing the lone pair to share IAtom atom1C = reactantCloned.Atoms[molecule.Atoms.IndexOf(atom1)]; IAtom atom2 = atomList[1]; // Atom to neutralize the deficiency of charge IAtom atom2C = reactantCloned.Atoms[molecule.Atoms.IndexOf(atom2)]; IBond bond1 = bondList[0]; int posBond1 = molecule.Bonds.IndexOf(bond1); BondManipulator.IncreaseBondOrder(reactantCloned.Bonds[posBond1]); var lonePair = reactantCloned.GetConnectedLonePairs(atom1C); reactantCloned.LonePairs.Remove(lonePair.Last()); int charge = atom1C.FormalCharge.Value; atom1C.FormalCharge = charge + 1; charge = atom2C.FormalCharge.Value; atom2C.FormalCharge = charge - 1; atom1C.Hybridization = Hybridization.Unset; AtomContainerManipulator.PercieveAtomTypesAndConfigureAtoms(reactantCloned); IAtomType type = atMatcher.FindMatchingAtomType(reactantCloned, atom1C); if (type == null || type.AtomTypeName.Equals("X", StringComparison.Ordinal)) { return(null); } atom2C.Hybridization = Hybridization.Unset; AtomContainerManipulator.PercieveAtomTypesAndConfigureAtoms(reactantCloned); type = atMatcher.FindMatchingAtomType(reactantCloned, atom2C); if (type == null || type.AtomTypeName.Equals("X", StringComparison.Ordinal)) { return(null); } IReaction reaction = atom2C.Builder.NewReaction(); reaction.Reactants.Add(molecule); /* mapping */ foreach (var atom in molecule.Atoms) { IMapping mapping = atom2C.Builder.NewMapping(atom, reactantCloned.Atoms[molecule.Atoms.IndexOf(atom)]); reaction.Mappings.Add(mapping); } reaction.Products.Add(reactantCloned); return(reaction); }
/// <summary> /// The method is known to fail for certain compounds. For more information, see /// cdk.test.limitations package. /// This method is known to fail, especially on pyrrole-like compounds. /// Consider using <see cref="Smiles.DeduceBondSystemTool"/>, which should work better /// </summary> public void Saturate(IAtomContainer atomContainer) { for (int i = 1; i < 4; i++) { // handle atoms with degree 1 first and then proceed to higher order for (int f = 0; f < atomContainer.Atoms.Count; f++) { var atom = atomContainer.Atoms[f]; Debug.WriteLine($"symbol: {atom.Symbol}"); var atomTypes1 = structgenATF.GetAtomTypes(atom.Symbol); var atomType1 = atomTypes1.FirstOrDefault(); if (atomType1 != null) { Debug.WriteLine($"first atom type: {atomType1}"); if (atomContainer.GetConnectedBonds(atom).Count() == i) { var hcount = atom.ImplicitHydrogenCount ?? 0; if (atom.IsAromatic && atomContainer.GetBondOrderSum(atom) < atomType1.BondOrderSum - hcount) { var partners = atomContainer.GetConnectedAtoms(atom); foreach (var partner in partners) { Debug.WriteLine($"Atom has {partners.Count()} partners"); var atomType2 = structgenATF.GetAtomTypes(partner.Symbol).FirstOrDefault(); if (atomType2 == null) { return; } hcount = partner.ImplicitHydrogenCount ?? 0; if (atomContainer.GetBond(partner, atom).IsAromatic && atomContainer.GetBondOrderSum(partner) < atomType2.BondOrderSum - hcount) { Debug.WriteLine($"Partner has {atomContainer.GetBondOrderSum(partner)}, may have: {atomType2.BondOrderSum}"); var bond = atomContainer.GetBond(atom, partner); Debug.WriteLine($"Bond order was {bond.Order}"); BondManipulator.IncreaseBondOrder(bond); Debug.WriteLine($"Bond order now {bond.Order}"); break; } } } var bondOrderSum = atomType1.BondOrderSum ?? 0; var hydrogenCount = atom.ImplicitHydrogenCount ?? 0; var atomContainerBondOrderSum = atomContainer.GetBondOrderSum(atom); if (atomContainerBondOrderSum < bondOrderSum - hydrogenCount) { Debug.WriteLine("Atom has " + atomContainerBondOrderSum + ", may have: " + bondOrderSum); var partners = atomContainer.GetConnectedAtoms(atom); foreach (var partner in partners) { Debug.WriteLine("Atom has " + partners.Count() + " partners"); var atomType2 = structgenATF.GetAtomTypes(partner.Symbol).FirstOrDefault(); if (atomType2 == null) { return; } var bos2 = atomType2.BondOrderSum ?? 0; var hc2 = partner.ImplicitHydrogenCount ?? 0; var acbos2 = atomContainer.GetBondOrderSum(partner); if (acbos2 < bos2 - hc2) { Debug.WriteLine($"Partner has {acbos2}, may have: {bos2}"); var bond = atomContainer.GetBond(atom, partner); Debug.WriteLine($"Bond order was {bond.Order}"); BondManipulator.IncreaseBondOrder(bond); Debug.WriteLine($"Bond order now {bond.Order}"); break; } } } } } } } }
/// <summary> /// Initiates the process for the given mechanism. The atoms to apply are mapped between /// reactants and products. /// </summary> /// <param name="atomContainerSet"></param> /// <param name="atomList">The list of atoms taking part in the mechanism. Only allowed two three. /// The first atom is the atom which must contain the charge to be moved, the second /// is the atom which is in the middle and the third is the atom which acquires the new charge /// <param name="bondList">The list of bonds taking part in the mechanism. Only allowed two bond.</param> /// The first bond is the bond to increase the order and the second is the bond /// to decrease the order /// It is the bond which is moved</param> /// <returns>The Reaction mechanism</returns> public IReaction Initiate(IChemObjectSet <IAtomContainer> atomContainerSet, IList <IAtom> atomList, IList <IBond> bondList) { var atMatcher = CDK.AtomTypeMatcher; if (atomContainerSet.Count != 1) { throw new CDKException("RearrangementChargeMechanism only expects one IAtomContainer"); } if (atomList.Count != 3) { throw new CDKException("RearrangementChargeMechanism expects three atoms in the List"); } if (bondList.Count != 2) { throw new CDKException("RearrangementChargeMechanism only expect one bond in the List"); } IAtomContainer molecule = atomContainerSet[0]; IAtomContainer reactantCloned; reactantCloned = (IAtomContainer)molecule.Clone(); IAtom atom1 = atomList[0]; // Atom with the charge IAtom atom1C = reactantCloned.Atoms[molecule.Atoms.IndexOf(atom1)]; IAtom atom3 = atomList[2]; // Atom which acquires the charge IAtom atom3C = reactantCloned.Atoms[molecule.Atoms.IndexOf(atom3)]; IBond bond1 = bondList[0]; // Bond with single bond int posBond1 = molecule.Bonds.IndexOf(bond1); IBond bond2 = bondList[1]; // Bond with double bond int posBond2 = molecule.Bonds.IndexOf(bond2); BondManipulator.IncreaseBondOrder(reactantCloned.Bonds[posBond1]); if (bond2.Order == BondOrder.Single) { reactantCloned.Bonds.Remove(reactantCloned.Bonds[posBond2]); } else { BondManipulator.DecreaseBondOrder(reactantCloned.Bonds[posBond2]); } //Depending of the charge moving (radical, + or -) there is a different situation if (reactantCloned.GetConnectedSingleElectrons(atom1C).Any()) { var selectron = reactantCloned.GetConnectedSingleElectrons(atom1C); reactantCloned.SingleElectrons.Remove(selectron.Last()); reactantCloned.SingleElectrons.Add(bond2.Builder.NewSingleElectron(atom3C)); } else if (atom1C.FormalCharge > 0) { int charge = atom1C.FormalCharge.Value; atom1C.FormalCharge = charge - 1; charge = atom3C.FormalCharge.Value; atom3C.FormalCharge = charge + 1; } else if (atom1C.FormalCharge < 1) { int charge = atom1C.FormalCharge.Value; atom1C.FormalCharge = charge + 1; var ln = reactantCloned.GetConnectedLonePairs(atom1C); reactantCloned.LonePairs.Remove(ln.Last()); atom1C.IsAromatic = false; charge = atom3C.FormalCharge.Value; atom3C.FormalCharge = charge - 1; reactantCloned.LonePairs.Add(bond2.Builder.NewLonePair(atom3C)); atom3C.IsAromatic = false; } else { return(null); } atom1C.Hybridization = Hybridization.Unset; atom3C.Hybridization = Hybridization.Unset; AtomContainerManipulator.PercieveAtomTypesAndConfigureAtoms(reactantCloned); IAtomType type = atMatcher.FindMatchingAtomType(reactantCloned, atom1C); if (type == null || type.AtomTypeName.Equals("X", StringComparison.Ordinal)) { return(null); } type = atMatcher.FindMatchingAtomType(reactantCloned, atom3C); if (type == null || type.AtomTypeName.Equals("X", StringComparison.Ordinal)) { return(null); } IReaction reaction = bond2.Builder.NewReaction(); reaction.Reactants.Add(molecule); /* mapping */ foreach (var atom in molecule.Atoms) { IMapping mapping = bond2.Builder.NewMapping(atom, reactantCloned.Atoms[molecule.Atoms.IndexOf(atom)]); reaction.Mappings.Add(mapping); } if (bond2.Order != BondOrder.Single) { reaction.Products.Add(reactantCloned); } else { IChemObjectSet <IAtomContainer> moleculeSetP = ConnectivityChecker.PartitionIntoMolecules(reactantCloned); for (int z = 0; z < moleculeSetP.Count(); z++) { reaction.Products.Add((IAtomContainer)moleculeSetP[z]); } } return(reaction); }
/// <summary> /// Initiates the process for the given mechanism. The atoms and bonds to apply are mapped between /// reactants and products. /// </summary> /// <param name="atomContainerSet"></param> /// <param name="atomList">The list of atoms taking part in the mechanism. Only allowed fourth atoms.</param> /// <param name="bondList">The list of bonds taking part in the mechanism. Only allowed two bond. /// The first bond is the bond to decrease the order and the second is the bond to increase the order. /// It is the bond which is moved</param> /// <returns>The Reaction mechanism</returns> public IReaction Initiate(IChemObjectSet <IAtomContainer> atomContainerSet, IList <IAtom> atomList, IList <IBond> bondList) { var atMatcher = CDK.AtomTypeMatcher; if (atomContainerSet.Count != 1) { throw new CDKException("TautomerizationMechanism only expects one IAtomContainer"); } if (atomList.Count != 4) { throw new CDKException("TautomerizationMechanism expects four atoms in the List"); } if (bondList.Count != 3) { throw new CDKException("TautomerizationMechanism expects three bonds in the List"); } var molecule = atomContainerSet[0]; IAtomContainer reactantCloned; reactantCloned = (IAtomContainer)molecule.Clone(); IAtom atom1 = atomList[0]; // Atom to be added the hydrogen IAtom atom1C = reactantCloned.Atoms[molecule.Atoms.IndexOf(atom1)]; IAtom atom2 = atomList[1]; // Atom 2 IAtom atom2C = reactantCloned.Atoms[molecule.Atoms.IndexOf(atom2)]; IAtom atom3 = atomList[2]; // Atom 3 IAtom atom3C = reactantCloned.Atoms[molecule.Atoms.IndexOf(atom3)]; IAtom atom4 = atomList[3]; // hydrogen Atom IAtom atom4C = reactantCloned.Atoms[molecule.Atoms.IndexOf(atom4)]; IBond bond1 = bondList[0]; // Bond with double bond int posBond1 = molecule.Bonds.IndexOf(bond1); IBond bond2 = bondList[1]; // Bond with single bond int posBond2 = molecule.Bonds.IndexOf(bond2); IBond bond3 = bondList[2]; // Bond to be removed int posBond3 = molecule.Bonds.IndexOf(bond3); BondManipulator.DecreaseBondOrder(reactantCloned.Bonds[posBond1]); BondManipulator.IncreaseBondOrder(reactantCloned.Bonds[posBond2]); reactantCloned.Bonds.Remove(reactantCloned.Bonds[posBond3]); IBond newBond = molecule.Builder.NewBond(atom1C, atom4C, BondOrder.Single); reactantCloned.Bonds.Add(newBond); atom1C.Hybridization = Hybridization.Unset; AtomContainerManipulator.PercieveAtomTypesAndConfigureAtoms(reactantCloned); IAtomType type = atMatcher.FindMatchingAtomType(reactantCloned, atom1C); if (type == null || type.AtomTypeName.Equals("X", StringComparison.Ordinal)) { return(null); } atom3C.Hybridization = Hybridization.Unset; AtomContainerManipulator.PercieveAtomTypesAndConfigureAtoms(reactantCloned); type = atMatcher.FindMatchingAtomType(reactantCloned, atom3C); if (type == null || type.AtomTypeName.Equals("X", StringComparison.Ordinal)) { return(null); } IReaction reaction = atom2C.Builder.NewReaction(); reaction.Reactants.Add(molecule); /* mapping */ foreach (var atom in molecule.Atoms) { IMapping mapping = atom2C.Builder.NewMapping(atom, reactantCloned.Atoms[molecule.Atoms.IndexOf(atom)]); reaction.Mappings.Add(mapping); } reaction.Products.Add(reactantCloned); return(reaction); }
/// <summary> /// Initiate process. /// It is needed to call the addExplicitHydrogensToSatisfyValency /// from the class tools.HydrogenAdder. /// </summary> /// <exception cref="CDKException"> Description of the Exception</exception> /// <param name="reactants">reactants of the reaction.</param> /// <param name="agents">agents of the reaction (Must be in this case null).</param> public IReactionSet Initiate(IChemObjectSet <IAtomContainer> reactants, IChemObjectSet <IAtomContainer> agents) { CheckInitiateParams(reactants, agents); var setOfReactions = reactants.Builder.NewReactionSet(); var reactant = reactants[0]; AtomContainerManipulator.PercieveAtomTypesAndConfigureAtoms(reactant); // if the parameter hasActiveCenter is not fixed yet, set the active centers var ipr = base.GetParameterClass(typeof(SetReactionCenter)); if (ipr != null && !ipr.IsSetParameter) { SetActiveCenters(reactant); } var arf = new AllRingsFinder(); var ringSet = arf.FindAllRings((IAtomContainer)reactant); for (int ir = 0; ir < ringSet.Count; ir++) { var ring = ringSet[ir]; //only rings with even number of atoms int nrAtoms = ring.Atoms.Count; if (nrAtoms % 2 == 0) { int nrSingleBonds = 0; foreach (var bond in ring.Bonds) { if (bond.Order == BondOrder.Single) { nrSingleBonds++; } } //if exactly half (nrAtoms/2==nrSingleBonds) if (nrSingleBonds != 0 && nrAtoms / 2 == nrSingleBonds) { bool ringCompletActive = false; foreach (var bond in ring.Bonds) { if (bond.IsReactiveCenter) { ringCompletActive = true; } else { ringCompletActive = false; break; } } if (!ringCompletActive) { continue; } IReaction reaction = reactants.Builder.NewReaction(); reaction.Reactants.Add(reactant); IAtomContainer reactantCloned; reactantCloned = (IAtomContainer)reactant.Clone(); foreach (var bondi in ring.Bonds) { int bondiP = reactant.Bonds.IndexOf(bondi); if (bondi.Order == BondOrder.Single) { BondManipulator.IncreaseBondOrder(reactantCloned.Bonds[bondiP]); } else { BondManipulator.DecreaseBondOrder(reactantCloned.Bonds[bondiP]); } } reaction.Products.Add(reactantCloned); setOfReactions.Add(reaction); } } } return(setOfReactions); }