public void ShortestPathFoundForGraphWithMultipleEdgesBetweenTwoVertices() { var vertices = new List <Vertex <object> > { new Vertex <object>(0), new Vertex <object>(1), new Vertex <object>(2), new Vertex <object>(3), new Vertex <object>(4) }; var edges = new List <Edge <object> > { new Edge <object>(0, 0, 1), new Edge <object>(1, 1, 2), new Edge <object>(2, 1, 2), // Double edge new Edge <object>(3, 2, 3), new Edge <object>(4, 1, 4), new Edge <object>(5, 2, 4) }; var graph = new Graph <object, object>(vertices, edges); Assert.That(() => GraphAlgorithms.ShortestPaths(graph, 0), Throws.Nothing); var shortestPathLookup = GraphAlgorithms.ShortestPaths(graph, 0); var pathToV3 = shortestPathLookup.PathTo(vertices.Single(v => v.Id == 3)); Assert.That(pathToV3.PathLength, Is.EqualTo(3)); }
public void ShortestPathThrowsExceptionIfAnyEdgeHasNegativeWeight() { // Remove this test if an algorithm with support for // negative weights has been implemented. var graph = CreateTestGraph(); graph.Edges.First().Weight = -1; Assert.Throws <NotImplementedException>(() => GraphAlgorithms.ShortestPaths(graph, graph.GetVertexFromId(0))); }
public static void MarkBackbone(this Molecule molecule, MoleculeReference moleculeReference) { var pathsFromFirstAtom = GraphAlgorithms.ShortestPaths(molecule.MoleculeStructure, moleculeReference.FirstAtomId); var pathToLastAtom = pathsFromFirstAtom.PathTo(molecule.MoleculeStructure.GetVertexFromId(moleculeReference.LastAtomId)); var pathVertices = pathToLastAtom.Path .SelectMany(edge => new[] { edge.Vertex1Id, edge.Vertex2Id }) .Distinct() .Select(vId => molecule.MoleculeStructure.GetVertexFromId(vId)) .Select(v => v.Object); pathVertices.ForEach(atom => atom.IsBackbone = true); }
public void ShortestPathFindsExpectedPathLengts() { var graph = CreateTestGraph(); graph.Edges.Single(e => e.Vertex1Id == 1 && e.Vertex2Id == 3).Weight = 0.5; var shortestPathLookup = GraphAlgorithms.ShortestPaths(graph, graph.GetVertexFromId(0)); Assert.That(shortestPathLookup.PathLengthTo(graph.GetVertexFromId(0)), Is.EqualTo(0)); Assert.That(shortestPathLookup.PathLengthTo(graph.GetVertexFromId(1)), Is.EqualTo(1)); Assert.That(shortestPathLookup.PathLengthTo(graph.GetVertexFromId(2)), Is.EqualTo(2)); Assert.That(shortestPathLookup.PathLengthTo(graph.GetVertexFromId(3)), Is.EqualTo(1.5)); }
public void ShortestPathFinishesWithinTimespan() { // This test is testing for possible deadlocks or inefficiencies // in the shortest path algorithm. var graph = CreateTestGraph(); var timeout = TimeSpan.FromMilliseconds(3000); ShortestPathLookup distanceDictionary = null; var thread = new Thread(() => { distanceDictionary = GraphAlgorithms.ShortestPaths(graph, graph.GetVertexFromId(0)); }); thread.Start(); thread.Join(timeout); Assert.That(distanceDictionary, Is.Not.Null); }
public void ShortestPathDoesntThrowIfGraphNotConnected() { var graph = CreateTestGraph(); var v1v2Edge = graph.Edges.Single(e => e.Vertex1Id == 0 && e.Vertex2Id == 1); graph.RemoveEdge(v1v2Edge); Assume.That(graph.GetVertexFromId(0).EdgeIds, Is.Empty); ShortestPathLookup shortestPathLookup = null; try { shortestPathLookup = GraphAlgorithms.ShortestPaths(graph, graph.GetVertexFromId(0)); } catch (Exception) { Assert.Fail("GraphAlgorithm.ShortestPath should not throw exception for not connected test graph"); } Assert.That(shortestPathLookup.PathLengthTo(graph.GetVertexFromId(1)), Is.EqualTo(double.PositiveInfinity)); }
public static void PositionAtoms(Molecule molecule, uint firstAtomId = uint.MaxValue, uint lastAtomId = uint.MaxValue) { // Remove position information molecule.MoleculeStructure.Vertices .Select(v => v.Object) .ForEach(atom => atom.IsPositioned = false); var positionableVertices = new Queue <IVertex <Atom> >(); // If first and last atom is specified, position atoms between those two first // Usually the case when a peptide is positioned, in which case the backbone // is oriented along the X-axis if (firstAtomId != uint.MaxValue && lastAtomId != uint.MaxValue) { // Position first atom var firstVertex = molecule.MoleculeStructure.GetVertexFromId(firstAtomId); var firstAtom = firstVertex.Object; if (firstAtom.Position == null) { firstAtom.Position = new UnitPoint3D(Unit.Meter, 0, 0, 0); } firstAtom.IsPositioned = true; positionableVertices.Enqueue(firstVertex); // Trace through molecule to last atom var lastVertex = molecule.MoleculeStructure.GetVertexFromId(lastAtomId); var pathFromFirstVertex = GraphAlgorithms.ShortestPaths(molecule.MoleculeStructure, firstVertex); var pathToLastVertex = pathFromFirstVertex.PathTo(lastVertex); // Position atoms between first and last along X-axis var currentEdge = pathToLastVertex.Path.First; var currentVertex = firstVertex; while (currentEdge != null) { var neighborId = currentEdge.Value.Vertex1Id == currentVertex.Id ? currentEdge.Value.Vertex2Id : currentEdge.Value.Vertex1Id; var neighborVertex = molecule.MoleculeStructure.GetVertexFromId(neighborId); PositionSpecificNeighborAlongXAxis(molecule, currentVertex, neighborVertex); positionableVertices.Enqueue(neighborVertex); currentEdge = currentEdge.Next; currentVertex = neighborVertex; } } else { var startVertex = firstAtomId != uint.MaxValue ? molecule.MoleculeStructure.GetVertexFromId(firstAtomId) : molecule.MoleculeStructure.Vertices.First(); positionableVertices.Enqueue(startVertex); var startAtom = startVertex.Object; if (startAtom.Position == null) { startAtom.Position = new UnitPoint3D(Unit.Meter, 0, 0, 0); } startAtom.IsPositioned = true; } while (positionableVertices.Any()) { var vertex = positionableVertices.Dequeue(); var positionableNeighbors = PositionNeighborsAndLonePairs(molecule, vertex); positionableNeighbors.ForEach(neighbor => positionableVertices.Enqueue(neighbor)); } }