Skip to content

Commit

Permalink
UIT timeout fix
Browse files Browse the repository at this point in the history
It is now possible to set a timeout which stops the current search progress if the timeout is reached.
All results gathered up to the break will be returned as results and will not get lost.

Signed-off-by: Egon Willighagen <egonw@users.sourceforge.net>
  • Loading branch information
Andreas Truszkowski authored and egonw committed Aug 1, 2010
1 parent e1df763 commit 5a329d4
Show file tree
Hide file tree
Showing 4 changed files with 150 additions and 9 deletions.
Expand Up @@ -112,7 +112,7 @@ public class UniversalIsomorphismTester {
final static int ID1 = 0;
final static int ID2 = 1;
private static long start;
public static long timeout=-1;
private static long timeout=-1;

///////////////////////////////////////////////////////////////////////////
// Query Methods
Expand Down Expand Up @@ -440,7 +440,9 @@ public static RGraph buildRGraph(IAtomContainer g1, IAtomContainer g2) throws C
*/
public static List<List<RMap>> search(IAtomContainer g1, IAtomContainer g2, BitSet c1,
BitSet c2, boolean findAllStructure, boolean findAllMap) throws CDKException{

// remember start time
start = System.currentTimeMillis();

// handle single query atom case separately
if (g2.getAtomCount() == 1) {
List<List<RMap>> matches = new ArrayList<List<RMap>>();
Expand Down Expand Up @@ -472,7 +474,10 @@ public static List<List<RMap>> search(IAtomContainer g1, IAtomContainer g2, BitS
List<List<RMap>> rMapsList = new ArrayList<List<RMap>>();

// build the RGraph corresponding to this problem
RGraph rGraph = buildRGraph(g1, g2);
RGraph rGraph = buildRGraph(g1, g2);
// Set time data
rGraph.setTimeout(UniversalIsomorphismTester.timeout);
rGraph.setStart(UniversalIsomorphismTester.start);
// parse the RGraph with the given constrains and options
rGraph.parse(c1, c2, findAllStructure, findAllMap);
List<BitSet> solutionList = rGraph.getSolutions();
Expand Down Expand Up @@ -750,8 +755,6 @@ private static void nodeConstructor(RGraph gr, IAtomContainer ac1, IAtomContaine
// compares each bond of G1 to each bond of G2
for (int i = 0; i < ac1.getBondCount(); i++) {
for (int j = 0; j < ac2.getBondCount(); j++) {
if(timeout>-1 && (System.currentTimeMillis()-start)>timeout)
throw new CDKException("Timeout exceeded in getOverlaps");
IBond bondA2 = ac2.getBond(j);
if (bondA2 instanceof IQueryBond) {
IQueryBond queryBond = (IQueryBond)bondA2;
Expand Down Expand Up @@ -836,8 +839,6 @@ private static void arcConstructor(RGraph gr, IAtomContainer ac1, IAtomContainer
// relationship in are equivalent in G1 and G2
// else they are incompatible.
for (int j = i + 1; j < gr.getGraph().size(); j++) {
if(timeout>-1 && (System.currentTimeMillis()-start)>timeout)
throw new CDKException("Timeout exceeded in getOverlaps");
RNode y = gr.getGraph().get(j);

a1 = ac1.getBond(gr.getGraph().get(i).getRMap().getId1());
Expand Down Expand Up @@ -1078,7 +1079,15 @@ private static boolean testSubgraphHeuristics(IAtomContainer ac1, IAtomContainer
if (ac1ICount < ac2ICount) return false;
return ac1CCount >= ac2CCount;


}

/**
* Sets the time in milliseconds until the substructure search will be breaked.
* @param timeout
* Time in milliseconds. -1 to ignore the timeout.
*/
public static void setTimeout(long timeout) {
UniversalIsomorphismTester.timeout = timeout;
}

}
Expand Down
27 changes: 26 additions & 1 deletion src/main/org/openscience/cdk/isomorphism/mcss/RGraph.java
Expand Up @@ -127,6 +127,9 @@ public class RGraph
int nbIteration = 0;
BitSet graphBitSet = null;

private long timeout = -1;
private long start;

/**
* Constructor for the RGraph object and creates an empty RGraph.
*/
Expand Down Expand Up @@ -253,6 +256,11 @@ private void parseRec(BitSet traversed, BitSet extension, BitSet forbidden)
BitSet newExtension = null;
BitSet newForbidden = null;
BitSet potentialNode = null;

// Test whether the timeout is reached. Stop searching.
if(this.timeout > -1 && (System.currentTimeMillis() - this.start) > this.timeout) {
stop = true;
}

// if there is no more extension possible we
// have reached a potential new solution
Expand Down Expand Up @@ -617,6 +625,23 @@ private boolean isContainedIn(BitSet A, BitSet B)
}

return result;
}
}

/**
* Sets the time in milliseconds until the substructure search will be breaked.
* @param timeout
* Time in milliseconds. -1 to ignore the timeout.
*/
public void setTimeout(long timeout) {
this.timeout = timeout;
}

/**
* @param start
* The start time in milliseconds.
*/
public void setStart(long start) {
this.start = start;
}
}

65 changes: 65 additions & 0 deletions src/test/data/mdl/UITTimeout.sdf
@@ -0,0 +1,65 @@
UITTimeout.sdf
ChemDraw12090921122D

16 17 0 0 0 0 0 0 0 0999 V2000
-2.4235 1.2468 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
-1.7244 1.6397 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
-2.4235 0.4223 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
-0.9994 1.2468 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
-1.7044 2.4644 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
-1.7244 0.0017 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
-1.0304 0.4223 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
-0.3270 0.0183 0.0000 B 0 0 0 0 0 0 0 0 0 0 0 0
0.4556 0.2357 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0
-0.3380 -0.7936 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0
1.1514 -0.1647 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
0.3487 -1.1942 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
1.5320 1.2594 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
2.4235 -0.9022 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
-0.3906 -2.4644 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
1.6188 -1.9317 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
1 2 1 0
1 3 2 0
2 4 2 0
2 5 1 0
3 6 1 0
4 7 1 0
7 8 1 0
8 9 1 0
8 10 1 0
9 11 1 0
10 12 1 0
11 13 1 0
11 14 1 0
12 15 1 0
12 16 1 0
6 7 2 0
11 12 1 0
M END
$$$$
UITTimeout.sdf
ChemDraw12090921122D

10 10 0 0 0 0 0 0 0 0999 V2000
-0.6086 0.4449 0.0000 B 0 0 0 0 0 0 0 0 0 0 0 0
0.0984 0.8738 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0
0.8938 0.6549 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
0.3891 -0.5411 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
-0.4024 -0.3312 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0
0.9499 -0.8489 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
0.1362 -1.4632 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
1.3541 0.3432 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
1.2133 1.4632 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
-1.3541 0.7463 0.0000 R1 0 0 0 0 0 0 0 0 0 0 0 0
1 2 1 0
2 3 1 0
3 4 1 0
5 4 1 0
1 5 1 0
4 6 1 0
4 7 1 0
3 8 1 0
3 9 1 0
1 10 1 0
M END
$$$$
Expand Up @@ -38,16 +38,20 @@
import org.openscience.cdk.AtomContainer;
import org.openscience.cdk.Bond;
import org.openscience.cdk.CDKTestCase;
import org.openscience.cdk.ChemFile;
import org.openscience.cdk.Molecule;
import org.openscience.cdk.DefaultChemObjectBuilder;
import org.openscience.cdk.aromaticity.CDKHueckelAromaticityDetector;
import org.openscience.cdk.atomtype.CDKAtomTypeMatcher;
import org.openscience.cdk.exception.CDKException;
import org.openscience.cdk.graph.AtomContainerAtomPermutor;
import org.openscience.cdk.interfaces.IAtom;
import org.openscience.cdk.interfaces.IAtomContainer;
import org.openscience.cdk.interfaces.IAtomType;
import org.openscience.cdk.interfaces.IBond;
import org.openscience.cdk.interfaces.IMolecule;
import org.openscience.cdk.interfaces.IChemObjectBuilder;
import org.openscience.cdk.io.ISimpleChemObjectReader;
import org.openscience.cdk.io.MDLV2000Reader;
import org.openscience.cdk.io.IChemObjectReader.Mode;
import org.openscience.cdk.isomorphism.matchers.IQueryAtom;
Expand All @@ -60,7 +64,10 @@
import org.openscience.cdk.isomorphism.mcss.RMap;
import org.openscience.cdk.smiles.SmilesParser;
import org.openscience.cdk.templates.MoleculeFactory;
import org.openscience.cdk.tools.CDKHydrogenAdder;
import org.openscience.cdk.tools.manipulator.AtomContainerManipulator;
import org.openscience.cdk.tools.manipulator.AtomTypeManipulator;
import org.openscience.cdk.tools.manipulator.ChemFileManipulator;

import java.util.BitSet;
/**
Expand Down Expand Up @@ -557,6 +564,41 @@ public void testSingleAtomMatching3() throws CDKException {
List<List<RMap>> atomMappings = UniversalIsomorphismTester.makeAtomsMapsOfBondsMaps(matches, target, queryac);
Assert.assertEquals(matches, atomMappings);
}

@Test
public void testUITTimeoutFix() throws Exception {
// Load molecules
String filename = "data/mdl/UITTimeout.sdf";
InputStream ins = this.getClass().getClassLoader().getResourceAsStream(
filename);
ISimpleChemObjectReader reader = new MDLV2000Reader(ins);
ChemFile content = (ChemFile) reader.read(new ChemFile());
List cList = ChemFileManipulator.getAllAtomContainers(content);
IAtomContainer[] molecules = new IAtomContainer[2];
for (int j = 0; j < 2; j++) {
IAtomContainer aAtomContainer = (IAtomContainer) cList.get(j);
CDKAtomTypeMatcher tmpMatcher = CDKAtomTypeMatcher.getInstance(aAtomContainer.getBuilder());
CDKHydrogenAdder tmpAdder = CDKHydrogenAdder.getInstance(aAtomContainer.getBuilder());
for (int i = 0; i < aAtomContainer.getAtomCount(); i++) {
IAtom tmpAtom = aAtomContainer.getAtom(i);
IAtomType tmpType = tmpMatcher.findMatchingAtomType(aAtomContainer, tmpAtom);
AtomTypeManipulator.configure(tmpAtom, tmpType);
tmpAdder.addImplicitHydrogens(aAtomContainer, tmpAtom);
}
AtomContainerManipulator
.convertImplicitToExplicitHydrogens(aAtomContainer);
molecules[j] = aAtomContainer;
}
QueryAtomContainer query = QueryAtomContainerCreator.createAnyAtomForPseudoAtomQueryContainer(molecules[1]);
// test
long starttime = System.currentTimeMillis();
UniversalIsomorphismTester.setTimeout(200);
UniversalIsomorphismTester.getSubgraphAtomsMaps(molecules[0], query);
long duration = System.currentTimeMillis() - starttime;
// The search must last much longer then two seconds if the timeout not works
Assert.assertTrue(duration < 2000);
}


}

0 comments on commit 5a329d4

Please sign in to comment.