Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

The number of essential/relevant cycles can be exponential for some m… #1052

Merged
merged 1 commit into from Mar 9, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
35 changes: 31 additions & 4 deletions base/core/src/main/java/org/openscience/cdk/graph/Cycles.java
Expand Up @@ -32,6 +32,7 @@
import org.openscience.cdk.interfaces.IRing;
import org.openscience.cdk.interfaces.IRingSet;
import org.openscience.cdk.ringsearch.RingSearch;
import org.openscience.cdk.tools.LoggingToolFactory;

import java.util.ArrayDeque;
import java.util.ArrayList;
Expand Down Expand Up @@ -90,6 +91,22 @@
*/
public final class Cycles {

private static final String CDK_MAX_RELEVANT_CYCLES_KEY = "cdk.maxRelevantCycles";
private static final long MAX_RELEVANT_CYCLES = getSystemInteger(CDK_MAX_RELEVANT_CYCLES_KEY, 512000);

private static long getSystemInteger(String key, long val) {
String prop = System.getProperty(key);
if (prop == null)
return val;
try {
return Long.parseLong(prop);
} catch (NumberFormatException ex) {
LoggingToolFactory.createLoggingTool(Cycles.class)
.error("Error - Invalid number for system property=" + key);
}
return val;
}

/** Vertex paths for each cycle. */
private final int[][] paths;

Expand Down Expand Up @@ -861,19 +878,23 @@ int[][] apply(int[][] graph, int length) {

/** {@inheritDoc} */
@Override
int[][] apply(int[][] graph, int length) {
int[][] apply(int[][] graph, int length) throws Intractable {
InitialCycles ic = InitialCycles.ofBiconnectedComponent(graph, length);
RelevantCycles rc = new RelevantCycles(ic);
return new EssentialCycles(rc, ic).paths();
numberOfCyclesCheck(rc);
EssentialCycles essentialCycles = new EssentialCycles(rc, ic);
return essentialCycles.paths();
}
},
RELEVANT {

/** {@inheritDoc} */
@Override
int[][] apply(int[][] graph, int length) {
int[][] apply(int[][] graph, int length) throws Intractable {
InitialCycles ic = InitialCycles.ofBiconnectedComponent(graph, length);
return new RelevantCycles(ic).paths();
RelevantCycles rc = new RelevantCycles(ic);
numberOfCyclesCheck(rc);
return rc.paths();
}
},
ALL {
Expand Down Expand Up @@ -1024,6 +1045,12 @@ public Cycles find(IAtomContainer molecule, int[][] graph, int length) throws In
}
}

private static void numberOfCyclesCheck(RelevantCycles rc) throws Intractable {
if (rc.size() > MAX_RELEVANT_CYCLES)
throw new Intractable("Too many relevant cycles cycles! max=" + MAX_RELEVANT_CYCLES + " was=" + rc.size() + "." +
" Increase this limit with System property -D" + CDK_MAX_RELEVANT_CYCLES_KEY + "=<num>");
}

/**
* Internal - lifts a path in a subgraph back to the original graph.
*
Expand Down