CrossoverMachine { public List<IAtomContainer> doCrossover(IAtomContainer dad, IAtomContainer mom) throws CDKException { int tries = 0; while (true) { int dim = dad.getAtomCount(); IAtomContainer[] redChild = new IAtomContainer[2]; IAtomContainer[] blueChild = new IAtomContainer[2]; List<Integer> redAtoms = new ArrayList<Integer>(); List<Integer> blueAtoms = new ArrayList<Integer>(); if (splitMode == SPLIT_MODE_RADNDOM) { for (int i = 0; i < dim; i++) redAtoms.add(Integer.valueOf(i)); for (int i = 0; i < (dim - numatoms); i++) { int ranInt = RandomNumbersTool.randomInt(0, redAtoms.size() - 1); redAtoms.remove(Integer.valueOf(ranInt)); blueAtoms.add(Integer.valueOf(ranInt)); } } else { ChemGraph graph = new ChemGraph(dad); graph.setNumAtoms(numatoms); if (splitMode == SPLIT_MODE_DEPTH_FIRST) { redAtoms = graph.pickDFgraph(); } else { redAtoms = graph.pickBFgraph(); } for (int i = 0; i < dim; i++) { Integer element = Integer.valueOf(i); if (!(redAtoms.contains(element))) { blueAtoms.add(element); } } } redChild[0] = dad.getBuilder().newInstance(IAtomContainer.class, dad); blueChild[0] = dad.getBuilder().newInstance(IAtomContainer.class, dad); redChild[1] = dad.getBuilder().newInstance(IAtomContainer.class, mom); blueChild[1] = dad.getBuilder().newInstance(IAtomContainer.class, mom); List<IAtom> blueAtomsInRedChild0 = new ArrayList<IAtom>(); for (int j = 0; j < blueAtoms.size(); j++) { blueAtomsInRedChild0.add(redChild[0].getAtom((Integer) blueAtoms.get(j))); } for (int j = 0; j < blueAtomsInRedChild0.size(); j++) { redChild[0].removeAtom(blueAtomsInRedChild0.get(j)); } List<IAtom> blueAtomsInRedChild1 = new ArrayList<IAtom>(); for (int j = 0; j < blueAtoms.size(); j++) { blueAtomsInRedChild1.add(redChild[1].getAtom((Integer) blueAtoms.get(j))); } for (int j = 0; j < blueAtomsInRedChild1.size(); j++) { redChild[1].removeAtom(blueAtomsInRedChild1.get(j)); } List<IAtom> redAtomsInBlueChild0 = new ArrayList<IAtom>(); for (int j = 0; j < redAtoms.size(); j++) { redAtomsInBlueChild0.add(blueChild[0].getAtom((Integer) redAtoms.get(j))); } for (int j = 0; j < redAtomsInBlueChild0.size(); j++) { blueChild[0].removeAtom(redAtomsInBlueChild0.get(j)); } List<IAtom> redAtomsInBlueChild1 = new ArrayList<IAtom>(); for (int j = 0; j < redAtoms.size(); j++) { redAtomsInBlueChild1.add(blueChild[1].getAtom((Integer) redAtoms.get(j))); } for (int j = 0; j < redAtomsInBlueChild1.size(); j++) { blueChild[1].removeAtom(redAtomsInBlueChild1.get(j)); } SaturationChecker satCheck = new SaturationChecker(); double red1attachpoints = 0; for (int i = 0; i < redChild[0].getAtomCount(); i++) { red1attachpoints += satCheck.getCurrentMaxBondOrder(redChild[0].getAtom(i), redChild[0]); } double red2attachpoints = 0; for (int i = 0; i < redChild[1].getAtomCount(); i++) { red2attachpoints += satCheck.getCurrentMaxBondOrder(redChild[1].getAtom(i), redChild[1]); } boolean isok = true; if (red1attachpoints % 2 == 1 ^ red2attachpoints % 2 == 1) { isok = false; IAtomContainer firstToBalance = redChild[1]; IAtomContainer secondToBalance = blueChild[0]; if (red1attachpoints % 2 == 1) { firstToBalance = redChild[0]; secondToBalance = blueChild[1]; } for (IAtom atom : firstToBalance.atoms()) { if (satCheck.getCurrentMaxBondOrder(atom, firstToBalance) % 2 == 1 && firstToBalance.getBondOrderSum(atom) % 2 == 0) { firstToBalance.removeAtom(atom); secondToBalance.addAtom(atom); isok = true; break; } } } if (isok) { IAtomContainerSet[] newstrucs = new IAtomContainerSet[2]; newstrucs[0] = dad.getBuilder().newInstance(IAtomContainerSet.class); newstrucs[0].add(ConnectivityChecker.partitionIntoMolecules(redChild[0])); newstrucs[0].add(ConnectivityChecker.partitionIntoMolecules(blueChild[1])); newstrucs[1] = dad.getBuilder().newInstance(IAtomContainerSet.class); newstrucs[1].add(ConnectivityChecker.partitionIntoMolecules(redChild[1])); newstrucs[1].add(ConnectivityChecker.partitionIntoMolecules(blueChild[0])); List<IAtomContainer> children = new ArrayList<IAtomContainer>(2); for (int f = 0; f < 2; f++) { try { children.add(f, pfsm.generate(newstrucs[f])); } catch (Exception ex) { } } if (children.size() == 2 && ConnectivityChecker.isConnected(children.get(0)) && ConnectivityChecker.isConnected(children.get(1))) return children; } tries++; if (tries > 20) throw new CDKException("Could not mate these properly"); } } CrossoverMachine(); List<IAtomContainer> doCrossover(IAtomContainer dad, IAtomContainer mom); static final int SPLIT_MODE_RADNDOM; static final int SPLIT_MODE_DEPTH_FIRST; static final int SPLIT_MODE_BREADTH_FIRST; }
@Test public void testdoCrossover_IAtomContainer() throws Exception { String filename = "data/smiles/c10h16isomers.smi"; InputStream ins = this.getClass().getClassLoader().getResourceAsStream(filename); SMILESReader reader = new SMILESReader(ins); IAtomContainerSet som = reader.read(new AtomContainerSet()); Assert.assertEquals("We must have read 99 structures", 99, som.getAtomContainerCount()); CrossoverMachine cm = new CrossoverMachine(); String correctFormula = "C10H16"; int errorcount = 0; for (int i = 0; i < som.getAtomContainerCount(); i++) { int[] hydrogencount1 = new int[4]; for (IAtom atom : som.getAtomContainer(i).atoms()) { hydrogencount1[atom.getImplicitHydrogenCount()]++; } for (int k = i + 1; k < som.getAtomContainerCount(); k++) { try { List<IAtomContainer> result = cm.doCrossover(som.getAtomContainer(i), som.getAtomContainer(k)); int[] hydrogencount2 = new int[4]; for (IAtom atom : som.getAtomContainer(k).atoms()) { hydrogencount2[atom.getImplicitHydrogenCount()]++; } Assert.assertEquals("Result size must be 2", 2, result.size()); for (int l = 0; l < 2; l++) { IAtomContainer ac = result.get(l); Assert.assertTrue("Result must be connected", ConnectivityChecker.isConnected(ac)); Assert.assertEquals("Molecular formula must be the same as" + "of the input", MolecularFormulaManipulator.getString(MolecularFormulaManipulator .getMolecularFormula(ac)), correctFormula); int[] hydrogencountresult = new int[4]; int hcounttotal = 0; for (IAtom atom : result.get(l).atoms()) { hydrogencountresult[atom.getImplicitHydrogenCount()]++; hcounttotal += atom.getImplicitHydrogenCount(); } if (hydrogencount1[0] == hydrogencount2[0]) Assert.assertEquals("Hydrogen count of the result must" + " be same as of input", hydrogencount1[0], hydrogencountresult[0]); if (hydrogencount1[1] == hydrogencount2[1]) Assert.assertEquals("Hydrogen count of the result must" + " be same as of input", hydrogencount1[1], hydrogencountresult[1]); if (hydrogencount1[2] == hydrogencount2[2]) Assert.assertEquals("Hydrogen count of the result must" + " be same as of input", hydrogencount1[2], hydrogencountresult[2]); if (hydrogencount1[3] == hydrogencount2[3]) Assert.assertEquals("Hydrogen count of the result must" + " be same as of input", hydrogencount1[3], hydrogencountresult[3]); Assert.assertEquals(16, hcounttotal); } } catch (CDKException ex) { errorcount++; } } } Assert.assertTrue("We tolerate up to 300 errors", errorcount < 300); }