diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..95c4320 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +.DS_Store +/.build +/Packages +/*.xcodeproj +xcuserdata/ diff --git a/Graphs/Johnson's algorithm - Swift/readme.rtf b/Graphs/Johnson's algorithm - Swift/readme.rtf deleted file mode 100644 index 80a8ebf..0000000 --- a/Graphs/Johnson's algorithm - Swift/readme.rtf +++ /dev/null @@ -1,6 +0,0 @@ - -Swift library that implements the Jonhson Cycle algorithm to find circuits in a directed graph - -Original Author : Frank Meyer (Java implementation) - -Wikipedia: "https://en.wikipedia.org/wiki/Johnson's_algorithm" diff --git a/Package.swift b/Package.swift new file mode 100644 index 0000000..ec04e3b --- /dev/null +++ b/Package.swift @@ -0,0 +1,28 @@ +// swift-tools-version:5.1 +// The swift-tools-version declares the minimum version of Swift required to build this package. + +import PackageDescription + +let package = Package( + name: "JohnsonsAlgo", + products: [ + // Products define the executables and libraries produced by a package, and make them visible to other packages. + .library( + name: "JohnsonsAlgo", + targets: ["JohnsonsAlgo"]), + ], + dependencies: [ + // Dependencies declare other packages that this package depends on. + // .package(url: /* package url */, from: "1.0.0"), + ], + targets: [ + // Targets are the basic building blocks of a package. A target can define a module or a test suite. + // Targets can depend on other targets in this package, and on products in packages which this package depends on. + .target( + name: "JohnsonsAlgo", + dependencies: []), + .testTarget( + name: "JohnsonsAlgoTests", + dependencies: ["JohnsonsAlgo"]), + ] +) diff --git a/README.md b/README.md new file mode 100644 index 0000000..73aa984 --- /dev/null +++ b/README.md @@ -0,0 +1,12 @@ +# JohnsonsAlgo + +Swift library that implements the Jonhson Cycle algorithm to find circuits in a directed graph +Wikipedia: "https://en.wikipedia.org/wiki/Johnson's_algorithm" + +Original Author: Frank Meyer (Java implementation) +Swift Adaption: Marc Matta +Swift Package Manager Adaption: Klaus Kneupner + +Known issues: sometimes the algo will end in a recursive loop, depending on the sequence of nodes provided. Details yet unknown. + + diff --git a/Graphs/Johnson's algorithm - Swift/AdjacencyList.swift b/Sources/JohnsonsAlgo/AdjacencyList.swift similarity index 74% rename from Graphs/Johnson's algorithm - Swift/AdjacencyList.swift rename to Sources/JohnsonsAlgo/AdjacencyList.swift index 7d5a612..0abcdd6 100644 --- a/Graphs/Johnson's algorithm - Swift/AdjacencyList.swift +++ b/Sources/JohnsonsAlgo/AdjacencyList.swift @@ -8,6 +8,9 @@ import Foundation +public typealias AdjacencyMatrix = Array> +//public typealias AdjacencyList = Array> + /** * Calculates the adjacency-list for a given adjacency-matrix. * @@ -16,7 +19,7 @@ import Foundation * @version 1.0, 26.08.2006 * */ -@objc public class AdjacencyList : NSObject { +public class AdjacencyList { /** * Calculates a adjacency-list for a given array of an adjacency-matrix. * @@ -28,18 +31,18 @@ import Foundation * that are direct successornodes of the node. */ class func getAdjacencyList( adjacencyMatrix: Array>) -> Array> { - var list = [Array](count: adjacencyMatrix.count, repeatedValue: []) + var list = [Array](repeating: [], count: adjacencyMatrix.count) - for var i = 0; i < adjacencyMatrix.count; ++i { + for i in 0.. = Array> + +public enum GraphErrors: Error { + case algoIssue + case missingObject +} + /** * Searchs all elementary cycles in a given directed graph. The implementation * is independent from the concrete objects that represent the graphnodes, it @@ -33,15 +40,15 @@ import Foundation * */ -@objc public class ElementaryCyclesSearch : NSObject { +open class ElementaryCyclesSearch { /** List of cycles */ - private var cycles : Array>? + private var cycles : Array>? /** Adjacency-list of graph */ private var adjList : Array> /** Graphnodes */ - private var graphNodes : Array + private var graphNodes : Array /** Blocked nodes, used by the algorithm of Johnson */ private var blocked : Array? @@ -60,9 +67,9 @@ import Foundation * build sets of the elementary cycles containing the objects of the original * graph-representation */ - init(matrix: Array>, graphNodes: Array) { + public init(matrix: Array>, graphNodes: Array) { self.graphNodes = graphNodes; - self.adjList = AdjacencyList.getAdjacencyList(matrix); + self.adjList = AdjacencyList.getAdjacencyList(adjacencyMatrix: matrix); } /** @@ -71,27 +78,30 @@ import Foundation * * @return List::List::Object with the Lists of the elementary cycles. */ - func getElementaryCycles() -> Array> { - self.cycles = Array>() - self.blocked = [Bool](count:self.adjList.count, repeatedValue:false) - self.B = [Array](count: self.adjList.count, repeatedValue: []) + open func getElementaryCycles() throws -> Array> { + if let result = cycles { + return result + } + self.cycles = Array>() + self.blocked = [Bool](repeating:false, count:self.adjList.count) + self.B = [Array](repeating: [], count: self.adjList.count) self.stack = [Int]() let sccs = StrongConnectedComponents(adjList: self.adjList) var s = 0 while(true) { - let sccResult = sccs.getAdjacencyList(s) + let sccResult = sccs.getAdjacencyList(node: s) if let result = sccResult { let scc = result.adjList s = result.lowestNodeId - for var j = 0; j> ) -> Bool { + func findCycles(v: Int, s: Int, adjList:Array> ) throws -> Bool { var f = false; + + + if stack?.contains(v) ?? false { + self.cycles = Array>() + throw GraphErrors.algoIssue + } self.stack?.append(v) self.blocked![v] = true; - for var i = 0; i < adjList[v].count; ++i { + for i in 0..() - for var j = 0; j < self.stack!.count; ++j { + var cycle = Array() + for j in 0.. 0) { let w = Bnode.first! - Bnode.removeAtIndex(0) + Bnode.remove(at:0) if (self.blocked![w]) { - self.unblock(w) + self.unblock(node: w) } } } -} \ No newline at end of file +} diff --git a/Graphs/Johnson's algorithm - Swift/SCCResult.swift b/Sources/JohnsonsAlgo/SCCResult.swift similarity index 83% rename from Graphs/Johnson's algorithm - Swift/SCCResult.swift rename to Sources/JohnsonsAlgo/SCCResult.swift index 871c6ac..74a9d2f 100644 --- a/Graphs/Johnson's algorithm - Swift/SCCResult.swift +++ b/Sources/JohnsonsAlgo/SCCResult.swift @@ -8,7 +8,7 @@ import Foundation -@objc public class SCCResult : NSObject{ +public class SCCResult { var nodeIDsOfSCC : Set var adjList : Array> var lowestNodeId : Int @@ -17,10 +17,10 @@ import Foundation self.adjList = adjList self.lowestNodeId = lowestNodeId nodeIDsOfSCC = [] - for var index = lowestNodeId; index < adjList.count; ++index { + for index in lowestNodeId.. 0) { self.nodeIDsOfSCC.insert(index) } } } -} \ No newline at end of file +} diff --git a/Graphs/Johnson's algorithm - Swift/StrongConnectedComponents.swift b/Sources/JohnsonsAlgo/StrongConnectedComponents.swift similarity index 78% rename from Graphs/Johnson's algorithm - Swift/StrongConnectedComponents.swift rename to Sources/JohnsonsAlgo/StrongConnectedComponents.swift index ddeca83..4ba9600 100644 --- a/Graphs/Johnson's algorithm - Swift/StrongConnectedComponents.swift +++ b/Sources/JohnsonsAlgo/StrongConnectedComponents.swift @@ -32,7 +32,7 @@ import Foundation * @version 1.1, 22.03.2009 * */ -@objc public class StrongConnectedComponents :NSObject { +public class StrongConnectedComponents { /** Adjacency-list of original graph */ private var adjListOriginal : Array> @@ -78,25 +78,25 @@ import Foundation * connected component; null, if no such component exists */ func getAdjacencyList(node:Int) -> SCCResult? { - self.visited = [Bool](count: self.adjListOriginal.count, repeatedValue: false) - self.lowlink = [Int](count: self.adjListOriginal.count, repeatedValue: 0) - self.number = [Int](count: self.adjListOriginal.count, repeatedValue: 0) + self.visited = [Bool](repeating: false, count: self.adjListOriginal.count) + self.lowlink = [Int](repeating: 0, count: self.adjListOriginal.count) + self.number = [Int](repeating: 0, count: self.adjListOriginal.count) self.stack = Array() self.currentSCCs = Array>() - makeAdjListSubgraph(node) + makeAdjListSubgraph(node: node) - for var i = node; i 0){ return SCCResult(adjList: ad, lowestNodeId: j) } @@ -117,19 +117,19 @@ import Foundation * @param node Node with lowest index in the subgraph */ func makeAdjListSubgraph(node: Int) { - self.adjList = Array>(count:self.adjListOriginal.count, repeatedValue:[]) + self.adjList = Array>(repeating:[], count:self.adjListOriginal.count) - for var i = node; i < self.adjList?.count; ++i { + for i in node..() - for var j = 0; j < self.adjListOriginal[i].count; ++j { + for j in 0..= node { successors.append(self.adjListOriginal[i][j]); } } if (successors.count > 0) { - self.adjList![i] = [Int](count:successors.count, repeatedValue:0) - for var j = 0; j < successors.count; ++j { + self.adjList![i] = [Int](repeating:0, count:successors.count) + for j in 0.. Array? { - var min = self.adjList?.count + var min = self.adjList!.count var currScc : Array?; - for var i = 0; i < self.currentSCCs?.count; ++i { + for i in 0..?) -> Array>?{ var lowestIdAdjacencyList : Array>? if let n = nodes { - lowestIdAdjacencyList = [Array](count: self.adjList!.count, repeatedValue: []) - for var i = 0; i < lowestIdAdjacencyList!.count; ++i { + lowestIdAdjacencyList = [Array](repeating: [], count: self.adjList!.count) + for i in 0.. self.number![root]) // simple scc's with just one node will not be added @@ -224,11 +224,11 @@ import Foundation } } - class func test() { - var nodes = [String](count: 10, repeatedValue: "") - var adjMatrix = [[Bool]](count: 10, repeatedValue: [Bool](count: 10, repeatedValue: false)); + class func test() throws { + var nodes = [String](repeating: "", count: 10) + var adjMatrix = [[Bool]](repeating: [Bool](repeating: false, count: 10), count: 10); - for var i = 0; i < 10; ++i { + for i in 0..<10 { nodes[i] = "Node " + String(i); } @@ -245,12 +245,12 @@ import Foundation adjMatrix[8][6] = true; adjMatrix[6][1] = true; - let ecs = ElementaryCyclesSearch(matrix: adjMatrix, graphNodes: nodes) - let cycles = ecs.getElementaryCycles() - for var i = 0; i) + let cycles = try ecs.getElementaryCycles() + for i in 0.. " @@ -261,4 +261,4 @@ import Foundation print(representation + "\n") } } -} \ No newline at end of file +} diff --git a/Tests/JohnsonsAlgoTests/JohnsonsAlgoTests.swift b/Tests/JohnsonsAlgoTests/JohnsonsAlgoTests.swift new file mode 100644 index 0000000..0c862b1 --- /dev/null +++ b/Tests/JohnsonsAlgoTests/JohnsonsAlgoTests.swift @@ -0,0 +1,27 @@ +import XCTest +@testable import JohnsonsAlgo + +final class JohnsonsAlgoTests: XCTestCase { + func testBigExampleFromVithanco() throws { + // This is an example of a functional test case. + // Use XCTAssert and related functions to verify your tests produce the correct + // results. + // XCTAssertEqual(JohnsonsAlgo.text, "Hello, World!") + + let bigMatrix = [[false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false], [false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, false, false, false], [false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false], [false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false], [false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false], [false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false], [false, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false], [false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, false, false, true, false], [false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false], [false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false], [false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false], [false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false], [false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false], [false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false], [false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, false], [false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false], [false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false], [false, false, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false], [false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false], [false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false], [false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, false, false, false], [false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false], [false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false], [false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false], [false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false], [false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, true, false, false], [false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false], [false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false], [false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false], [false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false], [false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false], [true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false], [false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, false, true, false, false, false, false, false, false, true, true, false, false, false, false, false, false, false, false], [false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false], [false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false], [false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false], [false, false, false, false, false, true, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false], [false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false], [false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false], [false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false], [false, false, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false], [false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false], [false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false], [false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false], [false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false], [false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false], [false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false], [false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false], [false, true, false, false, false, false, false, false, false, true, true, false, false, false, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false], [false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, false, false], [false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false], [false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false], [false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, false], [false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false], [false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, false], [false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false], [false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false], [false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false], [false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false], [false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false], [false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false], [false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false], [false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false], [false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false], [false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, false, false], [false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, false], [false, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false], [false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false], [false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false], [false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false], [false, false, false, true, false, false, false, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, false, false, false, true, false, false, false, false, false, true, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, false, false, true], [false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false], [false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, true, false, false, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false], [false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false]] + let elements = Array(1...74) + let ecs = ElementaryCyclesSearch(matrix: bigMatrix, graphNodes: elements) + let result = try ecs.getElementaryCycles() + XCTAssertEqual(result.count, 1000) + + } + + func testSmall() throws { + let matrix = [[false, false, false, false, false, false, false, false, false, false], [false, false, false, true, false, false, false, false, false, false], [false, false, false, false, false, true, true, false, false, false], [false, false, false, false, false, false, false, false, true, false], [false, false, true, false, false, false, false, true, false, false], [false, false, false, false, false, false, false, false, false, false], [false, false, false, false, false, false, false, false, false, false], [false, false, false, false, false, false, false, false, true, false], [false, false, false, false, false, false, false, false, false, true], [true, false, false, false, true, false, false, false, false, false]] + let elements = Array(1...10) + let ecs = ElementaryCyclesSearch(matrix: matrix, graphNodes: elements) + let result = try ecs.getElementaryCycles() + XCTAssertEqual(result.count, 1) + } + +} diff --git a/Tests/JohnsonsAlgoTests/StrongComponentTest.swift b/Tests/JohnsonsAlgoTests/StrongComponentTest.swift new file mode 100644 index 0000000..a9ca01d --- /dev/null +++ b/Tests/JohnsonsAlgoTests/StrongComponentTest.swift @@ -0,0 +1,94 @@ +// +// StrongComponentTest.swift +// JohnsonsAlgoTests +// +// Created by Klaus Kneupner on 07/05/2022. +// + + +import XCTest +@testable import JohnsonsAlgo + +final class StrongComponentTests: XCTestCase { + + func buildEmptyGraph(n: Int) -> (AdjacencyMatrix, Array) { + var nodes = [String](repeating: "", count: n) + let adjMatrix = [[Bool]](repeating: [Bool](repeating: false, count: n), count: n); + + for i in 0..) + let cycles = try ecs.getElementaryCycles() + for i in 0.. " + }else { + representation += node as! String + } + } + print(representation + "\n") + } + } + + // from: https://en.wikipedia.org/wiki/Strongly_connected_component + func testWikiExample () throws { + var (adjMatrix,nodes) = buildEmptyGraph(n: 8) + adjMatrix[0][1] = true + adjMatrix[1][2] = true + adjMatrix[1][4] = true + adjMatrix[1][5] = true + adjMatrix[2][3] = true + adjMatrix[2][6] = true + adjMatrix[3][2] = true + adjMatrix[3][7] = true + adjMatrix[4][0] = true + adjMatrix[4][5] = true + adjMatrix[5][6] = true + adjMatrix[6][5] = true + adjMatrix[7][6] = true + adjMatrix[7][3] = true + + let ecs = ElementaryCyclesSearch(matrix: adjMatrix, graphNodes: nodes) + let cycles = try ecs.getElementaryCycles() + for i in 0.. " + }else { + representation += node + } + } + print(representation + "\n") + } + XCTAssertEqual(cycles.count,3 ) + + } +} diff --git a/Tests/JohnsonsAlgoTests/XCTestManifests.swift b/Tests/JohnsonsAlgoTests/XCTestManifests.swift new file mode 100644 index 0000000..a3932d4 --- /dev/null +++ b/Tests/JohnsonsAlgoTests/XCTestManifests.swift @@ -0,0 +1,9 @@ +import XCTest + +#if !canImport(ObjectiveC) +public func allTests() -> [XCTestCaseEntry] { + return [ + testCase(JohnsonsAlgoTests.allTests), + ] +} +#endif diff --git a/Tests/LinuxMain.swift b/Tests/LinuxMain.swift new file mode 100644 index 0000000..c9c922d --- /dev/null +++ b/Tests/LinuxMain.swift @@ -0,0 +1,7 @@ +import XCTest + +import JohnsonsAlgoTests + +var tests = [XCTestCaseEntry]() +tests += JohnsonsAlgoTests.allTests() +XCTMain(tests)