/// <summary> Construct the vertex short cycles for the given initial cycles.</summary> public VertexShortCycles(InitialCycles initialCycles) { int[][] graph = initialCycles.Graph; int[] sizeOf = new int[graph.Length]; this.paths = new List <int[]>(initialCycles.GetNumberOfCycles()); // cycles are returned ordered by length foreach (var cycle in initialCycles.GetCycles()) { int length = cycle.Length; int[] path = cycle.Path; bool found = false; // check if any vertex is the shortest through a vertex in the path foreach (var v in path) { if (sizeOf[v] < 1 || length <= sizeOf[v]) { found = true; sizeOf[v] = length; } } if (found) { foreach (var p in cycle.GetFamily()) { paths.Add(p); } } } }
/// <inheritdoc/> public override int[][] Apply(int[][] graph, int length) { InitialCycles ic = InitialCycles.OfBiconnectedComponent(graph, length); RelevantCycles rc = new RelevantCycles(ic); return(new EssentialCycles(rc, ic).GetPaths()); }
public virtual void Cycles_cyclophane_odd_limit_5() { InitialCycles initial = new InitialCycles(CyclophaneOdd, 5); var cycles = initial.GetCycles(); Assert.AreEqual(0, cycles.Count()); }
public EvenCycle(InitialCycles parent, ShortestPaths paths, int[] pathToP, int y, int[] pathToQ) : base(parent, paths, Join(pathToP, y, pathToQ)) { this.p = pathToP[pathToP.Length - 1]; this.q = pathToQ[pathToQ.Length - 1]; this.Y = y; }
public Cycle(InitialCycles parent, ShortestPaths paths, int[] path) { this.parent = parent; this.path = path; this.paths = paths; }
/// <summary> Construct the edge short cycles for the /// given initial cycles. </summary> public EdgeShortCycles(InitialCycles initialCycles) { int[][] graph = initialCycles.Graph; int[] sizeOf = new int[initialCycles.GetNumberOfEdges()]; this.paths = new List <int[]>(initialCycles.GetNumberOfCycles()); // cycles are returned ordered by length foreach (var cycle in initialCycles.GetCycles()) { int length = cycle.Length; int[] path = cycle.Path; bool found = false; // check if any vertex is the shortest through a vertex in the path for (int i = 1; i < path.Length; i++) { int idx = initialCycles.IndexOfEdge(path[i - 1], path[i]); if (sizeOf[idx] < 1 || length <= sizeOf[idx]) { found = true; sizeOf[idx] = length; } } if (found) { foreach (var p in cycle.GetFamily()) { paths.Add(p); } } } }
public virtual void JoinWith() { int[] a = new int[] { 0, 1, 2 }; int[] b = new int[] { 0, 3, 4 }; var expected = new int[] { 0, 1, 2, 5, 4, 3, 0 }; Assert.IsTrue(Compares.AreDeepEqual(expected, InitialCycles.Join(a, 5, b))); }
public virtual void Cycles_K4() { InitialCycles initial = new InitialCycles(K4); // todo replace with hasSize (hamcrest) Assert.AreEqual(4, initial.GetCycles().Count()); Assert.AreEqual(4, initial.GetCyclesOfLength(3).Count()); }
public OddCycle(InitialCycles parent, ShortestPaths paths, int[] pathToY, int[] pathToZ) : base(parent, paths, Join(pathToY, pathToZ)) { this.parent = parent; y = pathToY[pathToY.Length - 1]; z = pathToZ[pathToY.Length - 1]; }
public virtual void Lengths_cyclophane() { InitialCycles initial = new InitialCycles(CyclophaneOdd); foreach (var i in new int[] { 6, 9 }) { Assert.IsTrue(initial.Lengths.Contains(i)); } Assert.AreEqual(2, initial.Lengths.Count()); }
public virtual void Cycles_cyclophane_odd_limit_7() { InitialCycles initial = new InitialCycles(CyclophaneOdd, 7); var cycles = initial.GetCycles(); Assert.AreEqual(1, cycles.Count()); int[][] expecteds = new int[][] { new int[] { 3, 2, 1, 0, 5, 4, 3 }, }; AssertInitialCycles(expecteds, cycles); }
public virtual void Edge_K4() { InitialCycles initial = new InitialCycles(K4); Assert.AreEqual(initial.GetEdge(0), new InitialCycles.Cycle.Edge(0, 1)); Assert.AreEqual(initial.GetEdge(1), new InitialCycles.Cycle.Edge(0, 2)); Assert.AreEqual(initial.GetEdge(2), new InitialCycles.Cycle.Edge(0, 3)); Assert.AreEqual(initial.GetEdge(3), new InitialCycles.Cycle.Edge(1, 2)); Assert.AreEqual(initial.GetEdge(4), new InitialCycles.Cycle.Edge(1, 3)); Assert.AreEqual(initial.GetEdge(5), new InitialCycles.Cycle.Edge(2, 3)); }
public virtual void Cycles_naphthalene() { InitialCycles initial = new InitialCycles(Naphthalene); var cycles = initial.GetCycles(); Assert.AreEqual(2, cycles.Count()); int[][] expecteds = new int[][] { new int[] { 5, 0, 1, 2, 3, 4, 5 }, new int[] { 5, 4, 7, 8, 9, 6, 5 }, }; AssertInitialCycles(expecteds, cycles); }
/// <summary> /// Generate the relevant cycle basis from a precomputed set of initial /// cycles. /// </summary> /// <param name="initial">set of initial cycles.</param> /// <exception cref="System.ArgumentNullException">null InitialCycles provided</exception> internal RelevantCycles(InitialCycles initial) { CheckNotNull(initial, nameof(initial), "No InitialCycles provided"); this.basis = new GreedyBasis(initial.GetNumberOfCycles(), initial.GetNumberOfEdges()); // processing by size add cycles which are independent of smaller cycles foreach (var length in initial.Lengths) { basis.AddAll(Independent(initial.GetCyclesOfLength(length))); } }
public virtual void Cycles_cyclophane() { InitialCycles initial = new InitialCycles(CyclophaneOdd); var cycles = initial.GetCycles(); Assert.AreEqual(2, cycles.Count()); int[][] expecteds = new int[][] { new int[] { 3, 2, 1, 0, 5, 4, 3 }, new int[] { 3, 2, 1, 0, 10, 9, 8, 7, 6, 3 }, }; AssertInitialCycles(expecteds, cycles); }
public virtual void ToEdgeVector_K4() { InitialCycles initial = new InitialCycles(K4); BitArray expected, actual; expected = new BitArray(new bool[] { true, false, true, true, false, true }); actual = initial.ToEdgeVector(new int[] { 0, 1, 2, 3, 0 }); Assert.IsTrue(Compares.AreDeepEqual(expected, actual)); expected = new BitArray(new bool[] { true, true, false, true, false, false }); actual = initial.ToEdgeVector(new int[] { 0, 1, 2, 0 }); Assert.IsTrue(Compares.AreDeepEqual(expected, actual)); }
public virtual void Cycles_bicyclo() { InitialCycles initial = new InitialCycles(Bicyclo); var cycles = initial.GetCycles(); Assert.AreEqual(3, cycles.Count()); int[][] expecteds = new int[][] { new int[] { 5, 0, 1, 2, 3, 4, 5 }, new int[] { 5, 0, 1, 2, 7, 6, 5 }, new int[] { 5, 4, 3, 2, 7, 6, 5 }, }; AssertInitialCycles(expecteds, cycles); }
public virtual void Cycles_anthracene() { InitialCycles initial = new InitialCycles(Anthracene); var cycles = initial.GetCycles(); Assert.AreEqual(3, cycles.Count()); int[][] expecteds = new int[][] { new int[] { 5, 0, 1, 2, 3, 4, 5 }, new int[] { 9, 6, 5, 4, 7, 8, 9 }, new int[] { 9, 8, 10, 11, 12, 13, 9 }, }; AssertInitialCycles(expecteds, cycles); }
public virtual void IndexOfEdge_K4() { InitialCycles initial = new InitialCycles(K4); Assert.AreEqual(0, initial.IndexOfEdge(0, 1)); Assert.AreEqual(0, initial.IndexOfEdge(1, 0)); Assert.AreEqual(1, initial.IndexOfEdge(0, 2)); Assert.AreEqual(1, initial.IndexOfEdge(2, 0));; Assert.AreEqual(2, initial.IndexOfEdge(0, 3)); Assert.AreEqual(2, initial.IndexOfEdge(3, 0)); Assert.AreEqual(3, initial.IndexOfEdge(1, 2)); Assert.AreEqual(3, initial.IndexOfEdge(1, 2)); Assert.AreEqual(4, initial.IndexOfEdge(1, 3)); Assert.AreEqual(4, initial.IndexOfEdge(1, 3)); Assert.AreEqual(5, initial.IndexOfEdge(2, 3)); Assert.AreEqual(5, initial.IndexOfEdge(2, 3)); }
/// <inheritdoc/> public override int[][] Apply(int[][] graph, int length) { InitialCycles ic = InitialCycles.OfBiconnectedComponent(graph, length); MinimumCycleBasis mcb = new MinimumCycleBasis(ic, true); // As per the old aromaticity detector if the MCB/SSSR is made // of 2 or 3 rings we check all rings for aromaticity - otherwise // we just check the MCB/SSSR if (mcb.Count > 3) { return(mcb.GetPaths()); } else { return(All.Apply(graph, length)); } }
/// <summary> /// Determine the essential cycles from a precomputed set of initial cycles /// and relevant cycles. /// </summary> /// <param name="relevant"></param> /// <param name="initial">a molecule graph</param> internal EssentialCycles(RelevantCycles relevant, InitialCycles initial) { CheckNotNull(relevant, nameof(relevant), "No RelevantCycles provided"); this.initial = CheckNotNull(initial, nameof(initial), "No InitialCycles provided"); this.basis = new GreedyBasis(initial.GetNumberOfCycles(), initial.GetNumberOfEdges()); this.essential = new List <Cycle>(); // for each cycle added to the basis, if it can be // replaced with one of equal size it is non-essential foreach (var cycles in GroupByLength(relevant)) { foreach (var c in GetMembersOfBasis(cycles)) { if (IsEssential(c, cycles)) { essential.Add(c); } } } }
public virtual void Cycles_family_even() { InitialCycles initial = new InitialCycles(CyclophaneEven); var cycles = initial.GetCycles(); int[] expected = new int[] { 3, 6, 7, 8, 9, 10, 11, 0, 1, 2, 3 }; var cycle = cycles.FirstOrDefault(n => Compares.AreDeepEqual(expected, n.Path)); Assert.IsNotNull(cycle); int[][] family = cycle.GetFamily(); Assert.AreEqual(2, family.Length); int[][] expecteds = new int[][] { expected, new int[] { 3, 6, 7, 8, 9, 10, 11, 0, 5, 4, 3 }, }; foreach (var f in family) { Assert.IsTrue(expecteds.Any(n => Compares.AreDeepEqual(n, f))); } }
/// <summary> /// Generate the minimum cycle basis from a precomputed set of initial /// cycles. This constructor allows on to specify that the graph is /// connected which allows an optimisation to be used. /// </summary> /// <param name="initial">set of initial cycles.</param> /// <param name="connected">the graph is known to be connected</param> /// <exception cref="System.ArgumentNullException">null InitialCycles provided</exception> internal MinimumCycleBasis(InitialCycles initial, bool connected) { CheckNotNull(initial, nameof(initial), "No InitialCycles provided"); this.graph = initial.Graph; this.basis = new GreedyBasis(initial.GetNumberOfCycles(), initial.GetNumberOfEdges()); // a undirected unweighted connected graph there are |E| - (|V| + 1) // cycles in the minimum basis int lim = connected ? initial.GetNumberOfEdges() - graph.Length + 1 : int.MaxValue; // processing by size add cycles which are independent of smaller cycles foreach (var cycle in initial.GetCycles()) { if (basis.Count < lim && basis.IsIndependent(cycle)) { basis.Add(cycle); } } }
public virtual void EndOverlap() { int[] a = new int[] { 0, 1, 3, 5, 7, 9, 10 }; int[] b = new int[] { 0, 2, 4, 6, 8, 9, 10 }; Assert.IsFalse(InitialCycles.GetSingletonIntersect(a, b)); }
/// <inheritdoc/> public override int[][] Apply(int[][] graph, int length) { InitialCycles ic = InitialCycles.OfBiconnectedComponent(graph, length); return(new EdgeShortCycles(ic).GetPaths()); }
/// <inheritdoc/> public override int[][] Apply(int[][] graph, int length) { InitialCycles ic = InitialCycles.OfBiconnectedComponent(graph, length); return(new TripletShortCycles(new MinimumCycleBasis(ic, true), false).GetPaths()); }
public virtual void StartOverlap() { int[] a = new int[] { 0, 1, 2, 3, 4, 6 }; int[] b = new int[] { 0, 1, 2, 3, 5, 7 }; Assert.IsFalse(InitialCycles.GetSingletonIntersect(a, b)); }
/// <summary> /// Determine the essential cycles from a precomputed set of initial cycles. /// </summary> /// <param name="initial">a molecule graph</param> internal EssentialCycles(InitialCycles initial) : this(new RelevantCycles(initial), initial) { }
public virtual void Cycles_K1() { InitialCycles initial = new InitialCycles(K1); Assert.AreEqual(0, initial.GetCycles().Count()); }
/// <summary> /// Generate the minimum cycle basis from a precomputed set of initial cycles. /// </summary> /// <param name="initial">set of initial cycles.</param> /// <exception cref="System.ArgumentNullException">null InitialCycles provided</exception> internal MinimumCycleBasis(InitialCycles initial) : this(initial, false) { }