The most efficient way to build tree from dictionary data - swift
I have a dictionary with the following structure: [Point:[Line]], where:
Point - custom data structure that contains two coordinates (X, Y)
Line - tuple (Point, Point) that contains the first and last points of the line.
Key - first point of the line.
So, it is a dictionary of lines grouped by their first point, like following:
[a: [(a,b),(a,c)], b: [(b,c), (b,d)], c: [(c,d)] ]
The goal is to convert this dictionary into a list of data structures like following:
(a,b) -> (b,c) -> (c,d)
(a,b) -> (b,d)
(a,c) -> (c,d)
So, basically a tree with the root at the first point.
I tried to use builder pattern and stack to perform this operation, so I created a builder using first point and put in into stack, then started a while loop until stack is empty and then in the loop was removing current builder and creating new ones based on last & first points, the code looked like following:
import Foundation
typealias ProcessedLine = (UUID, [LineModel])
typealias LinePointDict = [Point: [Line]]
class LineAggregator {
var builderStack: Stack<LineModel.LineModelBuilder>
let startPointMap: LinePointDict
var result: ProcessedLine
var currentBuilder: (Point, LineModel.LineModelBuilder)?
let startPoint: Point
init(LineUid: UUID, startPointMap: LinePointDict, startPoint: Point) {
self.builderStack = Stack<LineModel.LineModelBuilder>()
self.startPointMap = startPointMap
self.result = (LineUid, [])
self.startPoint = startPoint
self.currentBuilder = nil
}
func getLineAggregation() -> ProcessedLine {
for Line in startPointMap[startPoint]! {
var bldr = LineModel.LineModelBuilder(initialLineUuid: result.0)
bldr = bldr.addLine(Line: Line)
builderStack.push(bldr)
}
return aggregateModels()
}
func aggregateModels() -> ProcessedLine {
while !builderStack.isEmpty() {
takeBuilderFromStack()
aggregateLine()
}
return result
}
/**
* This functions pops Builder object from stack if the stack is not empty and sets it as a Current object to be processed.
* #param object
* #return
*/
private func takeBuilderFromStack() {
if(!builderStack.isEmpty()) {
let curBuilder = builderStack.pop()!
currentBuilder = (curBuilder.getLastElement(), curBuilder)
}
}
private func aggregateLine() {
if currentBuilder?.1.isLastAdded() ?? true {
//If there is only one Line in the Line model
if(currentBuilder!.1.isLastAddedLineLast()) {
result.1.append(currentBuilder!.1.build())
return
}
if(!builderStack.isEmpty()) {
print("ERROR: Empty builder stack! Such situation should not happen. Pay attention at it.");
builderStack.removeAll()
}
return
}
if currentBuilder != nil {
for Line in startPointMap[currentBuilder!.0]! {
var newBuilder = LineModel.LineModelBuilder(builder: currentBuilder!.1)
newBuilder = newBuilder.addLine(Line: Line)
if Line.isLast {
result.1.append(newBuilder.build())
} else {
builderStack.push(newBuilder)
}
}
}
}
}
This solution is a very straightforward one. It works, but I have a very large amount of data in the dictionary, and the number of combinations is even larger, so this algorithm is extremely slow and not memory efficient.
The main slowness is caused by adding and retrieving data to/from stack which has following implementation:
import Foundation
protocol Stackable {
associatedtype Element
func peek() -> Element?
mutating func push(_ element: Element)
#discardableResult mutating func pop() -> Element?
}
extension Stackable {
var isEmpty: Bool { peek() == nil }
}
struct Stack<Element>: Stackable where Element: Equatable {
private var storage = [Element]()
func peek() -> Element? { storage.first }
mutating func push(_ element: Element) { storage.append(element) }
mutating func pop() -> Element? { storage.popLast() }
func size() -> Int { storage.count }
func isEmpty() -> Bool { storage.isEmpty }
mutating func removeAll() { storage.removeAll() }
}
extension Stack: Equatable {
static func == (lhs: Stack<Element>, rhs: Stack<Element>) -> Bool { lhs.storage == rhs.storage }
}
extension Stack: CustomStringConvertible {
var description: String { "\(storage)" }
}
extension Stack: ExpressibleByArrayLiteral {
init(arrayLiteral elements: Self.Element...) { storage = elements }
}
And another bottleneck is related to copying data and deinit method.
I was trying to find a better solution, but couldn't find anything yet. Would be grateful for any suggestions. Thanks.
While the builder pattern is useful, I think in this case it just complicates the straight-forward solution, although as you'll see, I'll present a couple that are more complicated, but those are based on increased performance optimizations on the first simple solution.
As you you noted, initializing and deinitializing classes is kind of slow. Actually the worst part is the dynamic memory allocation. Classes are powerful and definitely have their uses, but they're not the fastest tool in the Swift toolbox. Unless you make methods final, calling them can require a virtual dispatch. That can happen with protocols too depending on the particulars of their declaration, though in that case it's called "witness table thunking". But the worst part about classes is that their instances can be littered pretty much anywhere in memory. That's hell on the processor's on-chip cache. So for performance try to avoid dynamic dispatch, and reference types (ie, classes), and when you do need to allocate memory (such as Array or Dictionary), try to allocate all you need at once, and reuse it as much as possible. In Swift that requres some thought because of copy-on-write. You can easily end up allocating memory when you didn't intend to.
I present three solutions. Each one is more complicated, but also (hopefully) faster than the previous one. I'll explain why, and what to look out for. I should mention that I am not including the simplest solution. It is much like my first solution but with local variable arrays. The performance would not be especially good, and you're question makes it clear that performance is an issue.
First there's some boiler plate. To code it up and test it, I needed to define your Point and Line types, plus a few others I use for convenience, as well as some extensions purely for generating output. This code is common to all three solutions. Substitue your own definitions for Point and Line.
struct Point: Hashable
{
// This is just to give the points uniqueness, and letter names
static private let pointNames = [Character]("abcdefghijklmnopqrstuvwxyz")
static private var curNameIndex = 0
static private var nextID: Character
{
defer { curNameIndex += 1 }
return pointNames[curNameIndex]
}
let id = nextID
}
typealias Line = (Point, Point)
typealias Graph = [Point: [Line]]
typealias Path = [Line]
// Now we add some extensions for convenient output
extension Point: CustomStringConvertible {
var description: String { "\(id)" }
}
extension String.StringInterpolation
{
mutating func appendInterpolation(_ line: Line) {
appendLiteral("(\(line.0),\(line.1))")
}
mutating func appendInterpolation(_ lines: [Line]) {
appendLiteral(lines.map { "\($0)" }.joined(separator: "->"))
}
}
You mention that Point has an X and Y, but for this problem it doesn't matter. You just need unique "things" to serve as end-points for your Line instances.
Then I declared the inputs from your example:
let (a, b, c, d) = (Point(), Point(), Point(), Point())
let input = [ a: [(a,b),(a,c)], b: [(b,c), (b,d)], c: [(c,d)] ]
With the common code out of the way, here are the actual solutions:
Solution 1
Although the recursion introduces overhead all by itself, the main problem with the most straight-forward solution is that it requres local arrays that are allocated and deallocated up and down the call stack. The dynamic memory allocations and deallocations for them are actually the main performance problem with the simple recursive solution.
The solution is to attempt to pre-allocate working storage, and re-use it all through-out the recursion, or at least make reallocations rare.
One way would be to allocate the working arrays at the top level and pass them in as inout parameters. Another is to make them mutable properties of a struct (actually, a class wouldn't be too bad in this case, because you only allocate one instance). I chose the latter approach.
As I mentioned in my comment, I think of this problem as a graph theory problem.. Point = node. Line = edge. Though it's not explicitly stated, I assume there are no cycles. Putting in code to detect cycles isn't that hard, but would complicate the solution slightly. I also assume that the output should not contain entries with just one Line, because your example doesn't include any examples of that.
struct PathFinderVersion1
{
private let graph: Graph
private var pathList = [Path]()
private var currentPath = Path()
private init(for graph: Graph)
{
self.graph = graph
self.pathList.reserveCapacity(graph.count)
self.currentPath.reserveCapacity(graph.count)
}
static func pathList(for graph: Graph) -> [Path]
{
var pathFinder = Self(for: graph)
return pathFinder.makePathLists()
}
private mutating func makePathLists() -> [Path]
{
for src in graph.keys
{
for edge in graph[src]!
{
assert(edge.0 == src, "sanity check failed")
currentPath.append(edge)
appendAllPaths()
currentPath.removeLast()
}
}
return pathList
}
private mutating func appendAllPaths()
{
assert(currentPath.count > 0, "currentPath must not be empty on entry")
guard let src = currentPath.last?.1 else { return }
guard let edges = graph[src] else
{
if currentPath.count > 1 {
pathList.append(currentPath)
}
return
}
for edge in edges
{
assert(edge.0 == src, "sanity check failed")
currentPath.append(edge)
appendAllPaths()
currentPath.removeLast()
}
}
}
Apart from the init, and static wrapper function, pathList(for:), the algorithm is really just two functions. The initializer is where I pre-allocate the working storage. Assuming there is an entry in the graph Dictionary for each Point, no path can ever be longer than there entries keys in the graph ... at least not without cycles, so currentPath is initialized with that much capacity. Similar thinking applies to the other working arrays. The pathList is likely to be be larger than graph.count, but unless there are a lot of unconnected Lines, it will need to be at least as big as graph is.
makePathLists() is the part that gets thing started, extracting the Point and array of Line for each of its entries. It initializes the first entry in a currentPath, then calls appendAllPaths() to recursively append new Line instances to currentPath on the way down. When it reaches the end, it has found a complete path, so it adds the currentPath to the pathList. On the way back up, it removes the entry it added from currentPath so that it's in a state that it can be reused again to go down another path in the graph.
Once makePathLists() has iterated over all its keys and appendAllPaths() has recursed for each one, pathList contains the result. I'm not 100% sure it's in the format you want. It's basically a flat list of all the paths it found. So it's kind of one data structure. But all the paths will be grouped together according to the starting point in the line, so splitting it into smaller lists is easy enough, if that's what you actually want.
In any case, the re-use of existing storage is where this version gets most of its performance.
You can call it like this:
print("Version 1")
for path in PathFinderVersion1.pathList(for: input) {
print("\(path)")
}
And here's the output for the data I set up as input:
Version 1
(b,c)->(c,d)
(a,b)->(b,c)->(c,d)
(a,b)->(b,d)
(a,c)->(c,d)
The exact order changes slightly from run-to-run because Dictionary doesn't necessarily hand out its keys in an order that is consistent from run to run, even if they are inserted exactly the same way every time. I tested each version to verify they all emit the same output (and so should you), but I won't include the output again for the other versions.
Solution 2
This version is based on solution 1, so everything about it applies to this version too. What's different is the addition of the dynamic programming technique of caching intermediate values. Basically I cache paths along the way, so that when I encounter them again, I don't have do all that recursion. I can just used the cached path instead.
There is one snag with this caching, it requres allocating some local caches, which introduces dynamic memory allocation again. However hope is not lost. For starters, assuming lots of nodes in the graph have multiple input edges (ie, lots of different lines connect to the same line), the result should be a win overall from being able to avoid a vast amount of recursion. Additionally i, re-use the local caches, so I only ever have to actually allocate a new one when I recurse deeper than the previous maximum depth reached. So while some allocation does happen, it's minimized.
All that cache handling makes the code longer, but faster.
To make the code more readable I put the local caching in nested struct. Here's the code for version 2:
struct PathFinderVersion2
{
private typealias CachedPath = Path.SubSequence
private typealias CachedPaths = Array<CachedPath>
private let graph: Graph
private var pathList = [Path]()
private var currentPath = Path()
private var pathCache = [Point: CachedPaths]()
private struct LocalPathCache
{
var cache = [CachedPath]()
var pathListIndex: Int
var curPathLength: Int
mutating func updateLocalPathCache(from pathList: [Path])
{
while pathListIndex < pathList.endIndex
{
let pathToCache =
pathList[pathListIndex][curPathLength...]
cache.append(pathToCache)
pathListIndex += 1
}
}
mutating func update(
mainCache: inout [Point: CachedPaths],
for src: Point)
{
if cache.count > 0 {
mainCache[src] = cache
}
}
}
private var localCaches = [LocalPathCache]()
private mutating func getLocalCache(
pathListIndex: Int,
curPathLength: Int) -> LocalPathCache
{
if var cache = localCaches.last
{
localCaches.removeLast()
cache.cache.removeAll(keepingCapacity: true)
cache.pathListIndex = pathListIndex
cache.curPathLength = curPathLength
return cache
}
return LocalPathCache(
pathListIndex: pathListIndex,
curPathLength: curPathLength
)
}
private mutating func freeLocalCache(_ cache: LocalPathCache) {
localCaches.append(cache)
}
private init(for graph: Graph)
{
self.graph = graph
self.pathList.reserveCapacity(graph.count)
self.currentPath.reserveCapacity(graph.count)
self.pathCache.reserveCapacity(graph.count)
}
static func pathList(for graph: Graph) -> [Path]
{
var pathFinder = Self(for: graph)
return pathFinder.makePathLists()
}
private mutating func makePathLists() -> [Path]
{
for src in graph.keys
{
for edge in graph[src]!
{
assert(edge.0 == src, "sanity check failed")
currentPath.append(edge)
appendAllPaths()
currentPath.removeLast()
}
}
return pathList
}
private mutating func appendAllPaths()
{
assert(currentPath.count > 0, "currentPath must not be empty on entry")
guard let src = currentPath.last?.1 else { return }
if updatePathListFromCache(for: src) { return }
guard let edges = graph[src] else
{
if currentPath.count > 1 {
pathList.append(currentPath)
}
return
}
var localCache = getLocalCache(
pathListIndex: pathList.endIndex,
curPathLength: currentPath.endIndex
)
defer { freeLocalCache(localCache) }
for edge in edges
{
assert(edge.0 == src, "sanity check failed")
currentPath.append(edge)
appendAllPaths()
currentPath.removeLast()
localCache.updateLocalPathCache(from: pathList)
}
localCache.update(mainCache: &pathCache, for: src)
}
mutating func updatePathListFromCache(for src: Point) -> Bool
{
if let cachedPaths = pathCache[src]
{
let curPathIndex = currentPath.endIndex
for path in cachedPaths
{
currentPath.append(contentsOf: path)
pathList.append(currentPath)
currentPath.removeSubrange(curPathIndex...)
}
return true
}
return false
}
}
Solution 3
Solutions 1 and 2 still use recursion. Recursion is elegant, and nice to think about, because you can express a problem as a slightly simpler problem plus a bit. But unless it's tail-recursive, compilers can't optimize it particularly well. So the solution to that problem is to use iteration instead of recursion.
Turning a recursive algorithm into an iterative one is not always so easy, and can result in ugly code. That is the definitely the case here. There might be a simpler iterative algorithm, but I don't know it. So I basically replaced recursion with a state machine + stack. I've used this technique before for recursive code the desperately needed to be faster, and it does work. The code is a total pain for a human to read and maintain, but compilers can optimize the hell out of it.
This version still uses the cached intermediate solutions from version 2.
struct PathFinderVersion3
{
private typealias CachedPath = Path.SubSequence
private typealias CachedPaths = Array<CachedPath>
private let graph: Graph
private var pathList = [Path]()
private var currentPath = Path()
private var pathCache = [Point: CachedPaths]()
private struct LocalPathCache
{
var cache = [CachedPath]()
var pathListIndex: Int
var curPathLength: Int
mutating func updateLocalPathCache(from pathList: [Path])
{
while pathListIndex < pathList.endIndex
{
let pathToCache =
pathList[pathListIndex][curPathLength...]
cache.append(pathToCache)
pathListIndex += 1
}
}
mutating func update(
mainCache: inout [Point: CachedPaths],
for src: Point)
{
if cache.count > 0 {
mainCache[src] = cache
}
}
}
private var localCaches = [LocalPathCache]()
private mutating func getLocalCache(
pathListIndex: Int,
curPathLength: Int) -> LocalPathCache
{
if var cache = localCaches.last
{
localCaches.removeLast()
cache.cache.removeAll(keepingCapacity: true)
cache.pathListIndex = pathListIndex
cache.curPathLength = curPathLength
return cache
}
return LocalPathCache(
pathListIndex: pathListIndex,
curPathLength: curPathLength
)
}
private mutating func freeLocalCache(_ cache: LocalPathCache) {
localCaches.append(cache)
}
private init(for graph: Graph)
{
self.graph = graph
self.pathList.reserveCapacity(graph.count)
self.currentPath.reserveCapacity(graph.count)
self.pathCache.reserveCapacity(graph.count)
}
static func pathList(for graph: Graph) -> [Path]
{
var pathFinder = Self(for: graph)
return pathFinder.makePathLists()
}
private mutating func makePathLists() -> [Path]
{
for src in graph.keys
{
for edge in graph[src]!
{
assert(edge.0 == src, "sanity check failed")
currentPath.append(edge)
appendAllPaths()
currentPath.removeLast()
}
}
return pathList
}
struct Stack<T>
{
var storage: [T] = []
var isEmpty: Bool { storage.isEmpty }
var count: Int { storage.count }
init(capacity: Int) { storage.reserveCapacity(capacity) }
mutating func push(_ element: T) { storage.append(element) }
mutating func pop() -> T? { storage.popLast() }
}
private mutating func appendAllPaths()
{
assert(currentPath.count > 0, "currentPath must not be empty on entry")
enum State
{
case entry
case inLoopPart1
case inLoopPart2
case exit
}
var state: State = .entry
typealias StackElement =
(Point, Int, Line, [Line], LocalPathCache, State)
var stack = Stack<StackElement>(capacity: graph.count)
var src: Point! = nil
var edges: [Line]! = nil
var edgeIndex: Int = 0
var edge: Line! = nil
var localCache: LocalPathCache! = nil
outer: while true
{
switch state
{
case .entry:
if let s = currentPath.last?.1 {
src = s
}
else
{
state = .exit
continue outer
}
if updatePathListFromCache(for: src)
{
state = .exit
continue outer
}
if let e = graph[src] { edges = e }
else
{
if currentPath.count > 1 {
pathList.append(currentPath)
}
state = .exit
continue outer
}
localCache = getLocalCache(
pathListIndex: pathList.endIndex,
curPathLength: currentPath.endIndex
)
edgeIndex = edges.startIndex
state = .inLoopPart1
continue outer
case .inLoopPart1:
if edgeIndex < edges.endIndex
{
edge = edges[edgeIndex]
assert(edge.0 == src, "sanity check failed")
currentPath.append(edge)
// Simulate function call
stack.push((src, edgeIndex, edge, edges, localCache, .inLoopPart2))
state = .entry
continue outer
}
localCache.update(mainCache: &pathCache, for: src)
state = .exit
case .inLoopPart2:
localCache.updateLocalPathCache(from: pathList)
edgeIndex += 1
state = .inLoopPart1 // Simulate goto top of inner loop
case .exit: // Simulate return
if let c = localCache { freeLocalCache(c) }
if let savedState = stack.pop()
{
(src, edgeIndex, edge, edges, localCache, state) = savedState
currentPath.removeLast()
}
else { break outer }
}
}
assert(stack.isEmpty)
}
mutating func updatePathListFromCache(for src: Point) -> Bool
{
if let cachedPaths = pathCache[src]
{
let curPathIndex = currentPath.endIndex
for path in cachedPaths
{
currentPath.append(contentsOf: path)
pathList.append(currentPath)
currentPath.removeSubrange(curPathIndex...)
}
return true
}
return false
}
}
Ummm... yeah, there it is in all its ugly glory. It works. It's fast. Good luck maintaining it.
The question is whether the speed is worth it when weighed against the readability issues and maintenance headaches, and that all depends on the application requirements. In my opinion that speed would have to be pretty darn important to put up with maintaining this version, and I'm normally fine with putting up with some ugliness to get speed in critical code. Somehow, this version, written in a language that doesn't even have a goto statement is nonetheless a poster-child for why goto is considered bad in the first place.
Solution 4 (Bonus)
Originally I just mentioned that you could parallelize it, but I didn't implement it. I decided that for completeness, a parallelization example really should be included.
I chose to parallelize solution 1, but all three of the previous solutions can be parallelized in exactly the same way. The changes that have to be made are to add the split method, and modify the static pathList(for:) method as well as the private makePathLists instance method. You also need a concurrent DispatchQueue. I create a global one for this example, but you can use an existing one. Don't use DispatchQueue.main for this, if you want your app to be responsive while processing.
Here's the code:
import Foundation
let dispatchQueue =
DispatchQueue(label: "PathFinder-\(UUID())",attributes: .concurrent)
struct PathFinderVersion4
{
private let graph: Graph
private var pathList = [Path]()
private var currentPath = Path()
private init(for graph: Graph)
{
self.graph = graph
self.pathList.reserveCapacity(graph.count)
self.currentPath.reserveCapacity(graph.count)
}
public static func pathList(for graph: Graph) -> [Path]
{
let concurrency = min(4, graph.count)
let pointGroups = split(.init(graph.keys), numberOfGroups: concurrency)
var pathLists = [[Path]](repeating: [], count: concurrency)
let waitSems = Array(
repeating: DispatchSemaphore(value: 0),
count: concurrency
)
for groupIndex in pointGroups.indices
{
dispatchQueue.async
{
defer { waitSems[groupIndex].signal() }
var pathFinder = Self(for: graph)
pathLists[groupIndex] =
pathFinder.makePathLists(for: pointGroups[groupIndex])
}
}
// Need to signal each semaphore after waiting or will crash on return.
// See Apple documentation for DispatchSemaphore
waitSems.forEach { $0.wait(); $0.signal() }
var result = [Path]()
result.reserveCapacity(pathLists.reduce(0) { $0 + $1.count })
pathLists.forEach { result.append(contentsOf: $0) }
return result
}
private static func split<Value>(
_ values: [Value],
numberOfGroups: Int) -> [[Value]]
{
var groups = [[Value]]()
groups.reserveCapacity(numberOfGroups)
let groupSize = values.count / numberOfGroups
+ (values.count % numberOfGroups == 0 ? 0 : 1)
var valueIndex = values.startIndex
while valueIndex < values.endIndex
{
var group = [Value]()
group.reserveCapacity(groupSize)
let valueEnd = min(valueIndex + groupSize, values.endIndex)
while valueIndex < valueEnd
{
group.append(values[valueIndex])
valueIndex += 1
}
groups.append(group)
}
return groups
}
private mutating func makePathLists(for points: [Point]) -> [Path]
{
for src in points
{
for edge in graph[src]!
{
assert(edge.0 == src, "sanity check failed")
currentPath.append(edge)
appendAllPaths()
currentPath.removeLast()
}
}
return pathList
}
private mutating func appendAllPaths()
{
assert(currentPath.count > 0, "currentPath must not be empty on entry")
guard let src = currentPath.last?.1 else { return }
guard let edges = graph[src] else
{
if currentPath.count > 1 {
pathList.append(currentPath)
}
return
}
for edge in edges
{
assert(edge.0 == src, "sanity check failed")
currentPath.append(edge)
appendAllPaths()
currentPath.removeLast()
}
}
}
Related
When declaring static variable for conformance to AdditiveArithmetic, cannot call instance member from same type
I know this sounds crazy for a 10-year-old, but because S4TF doesn't work for me, I'm building my own neural network library in Swift. (I haven't gotten that far.) I'm creating a structure that conforms to AdditiveArithmetic. It also uses Philip Turner's Differentiable, but that's unimportant. Anyway, when defining the zero variable, I call another variable dimen, defined in the same structure. This raises an error: instance member 'dimen' cannot be used on type 'Electron<T>' note: the structure I am creating is going to be used to create a multi-dimensional array for neural networks. Total code (stripped down to remove unimportant bits): public struct Electron<T> where T: ExpressibleByFloatLiteral, T: AdditiveArithmetic { var energy: [[Int]: T] = [:] var dimen: [Int] public init(_ dim: [Int], with: ElectronInitializer) { self.dimen = dim self.energy = [:] var curlay = [Int](repeating: 0, count: dimen.count) curlay[curlay.count-1] = -1 while true { var max: Int = -1 for x in 0..<curlay.count { if curlay[curlay.count-1-x] == dimen[curlay.count-1-x]-1 { max = curlay.count-1-x } else {break} } if max == 0 {break} else if max != -1 { for n in max..<curlay.count { curlay[n] = -1 } curlay[max-1] += 1 } curlay[curlay.count-1] += 1 print(curlay) energy[curlay] = { () -> T in switch with { case ElectronInitializer.repeating(let value): return value as! T case ElectronInitializer.random(let minimum, let maximum): return Double.random(in: minimum..<maximum) as! T } }() } } subscript(_ coordinate: Int...) -> T { var convertList: [Int] = [] for conversion in coordinate { convertList.append(conversion) } return self.energy[convertList]! } public mutating func setQuantum(_ replace: T, at: [Int]) { self.energy[at]! = replace } } extension Electron: AdditiveArithmetic { public static func - (lhs: Electron<T>, rhs: Electron<T>) -> Electron<T> where T: AdditiveArithmetic, T: ExpressibleByFloatLiteral { var output: Electron<T> = lhs for value in lhs.energy { output.energy[value.key] = output.energy[value.key]!-rhs.energy[value.key]! } return output } public static var zero: Electron<T> { return Electron.init(dimen, with: ElectronInitializer.repeating(0.0)) } static prefix func + (x: Electron) -> Electron { return x } public static func + (lhs: Electron<T>, rhs: Electron<T>) -> Electron<T> where T: AdditiveArithmetic, T: ExpressibleByFloatLiteral { var output: Electron<T> = lhs for value in lhs.energy { output.energy[value.key] = output.energy[value.key]!+rhs.energy[value.key]! } return output } } public enum ElectronInitializer { case random(Double, Double) case repeating(Double) } Error: NeuralNetwork.xcodeproj:59:30: error: instance member 'dimen' cannot be used on type 'Electron' return Electron.init(dimen, with: ElectronInitializer.repeating(0.0)) I don't know what's happening, but thanks in advance. I'm new to Stack Overflow, so sorry if I did something wrong.
The root of the problem is that dimen is an instance property, while zero is a static property. In a static context, you don't have an instance from which to access dimen, and so the compiler gives you the error. static properties and methods are a lot like global variables and free-functions with respect to accessing instance properties and methods. You'd have to make an instance available somehow. For a static function, you could pass it in, but for a static computed property, you'd either have to store an instance in a stored static property, which isn't allowed for generics, or you'd have to store it in a global variable, which isn't good either, and would be tricky to make work for all the possible T. There are ways to do what you need though. They all involve implementing some special behavior for a zero Electron rather than relying on access to an instance property in your static .zero implementation. I made some off-the-cuff suggestions in comments, which would work; however, I think a more elegant solution is to solve the problem by creating a custom type for energy, which would require very few changes to your existing code. Specifically you could make an Energy type nested in your Electron type: internal struct Energy: Equatable, Sequence { public typealias Value = T public typealias Key = [Int] public typealias Element = (key: Key, value: Value) public typealias Storage = [Key: Value] public typealias Iterator = Storage.Iterator public typealias Keys = Storage.Keys public typealias Values = Storage.Values private var storage = Storage() public var keys: Keys { storage.keys } public var values: Values { storage.values } public var count: Int { storage.count } public init() { } public subscript (key: Key) -> Value? { get { storage.isEmpty ? .zero : storage[key] } set { storage[key] = newValue } } public func makeIterator() -> Iterator { storage.makeIterator() } } The idea here is that when energy.storage is empty, it returns 0 for any key, which allows you to use it as a .zero value. I've made it internal, because energy defaults to internal, and so I've done a minimalist job of wrapping a Dictionary, mainly providing subscript operator, and making it conform to Sequence, which is all that is needed by code you provided. The only changes needed in the rest of your code are to change the definition of energy var energy: Energy Then to set it in your initializer, by-passing the bulk of your init when dim is empty. public init(_ dim: [Int], with: ElectronInitializer) { self.dimen = dim self.energy = Energy() // <- Initialize `energy` // Empty dim indicates a zero electron which doesn't need the // rest of the initialization guard dim.count > 0 else { return } var curlay = [Int](repeating: 0, count: dimen.count) curlay[curlay.count-1] = -1 while true { var max: Int = -1 for x in 0..<curlay.count { if curlay[curlay.count-1-x] == dimen[curlay.count-1-x]-1 { max = curlay.count-1-x } else {break} } if max == 0 {break} else if max != -1 { for n in max..<curlay.count { curlay[n] = -1 } curlay[max-1] += 1 } curlay[curlay.count-1] += 1 print(curlay) energy[curlay] = { () -> T in switch with { case ElectronInitializer.repeating(let value): return value as! T case ElectronInitializer.random(let minimum, let maximum): return Double.random(in: minimum..<maximum) as! T } }() } } And then of course, to change how you create it in your zero property public static var zero: Electron<T> { return Electron.init([], with: ElectronInitializer.repeating(0.0)) } ElectronInitializer isn't actually used in this case. It's just a required parameter of your existing init. This suggests an opportunity to refactor initialization, so you could have an init() that creates a zero Electron in addition to your existing init(dim:with:)
Using the swift proxy pattern, how do you modify a private variable?
I am experimenting with a basic proxy pattern in Swift playgrounds; I am not 100% familiar with it; but some videos are helping. In my experiment, the subject, C is called through a proxy to perform said actions ie: A - Proxy - C However, in my experiments I find out I can just call C itself directly, without even needing the proxy; so I am left wondering why bother with a proxy when I can call C directly anyway? So I decided to make the variables in C private; but now I can't call them, or make modifications, and I am not sure how to resolve it. I also tried a "decorator" pattern I found on stackoverflow to try to manipulate Cs variables, but still its marked private, so its not possible. Also, the decorator pattern I found uses static variables. This makes me think well, why not just write a static function that creates c in memory, and then update the reference in proxy to that of the results of the static function. I guess what I'm mis-understanding here is what is the point of a proxy class if you can just call the subject (in this case C) directly anyway? Examples use Swift playground: class A { let proxy: Proxy = Proxy() var funds: Int { return self.proxy.funds } } class Proxy { private let c: C = C() public var funds: Int { return c.funds } private func canIGetFunds() -> Bool { guard (self.funds > 0) else { return false } return true } func subtractFunds(funds: Int = 0) { if (canIGetFunds()) { print ("you have enough funds") willDebit(funds: funds) } else { print ("Not enough funds") } } private func willDebit(funds: Int = 0) { self.c.funds -= funds } } class C { private (set) var funds: Int = 100 } let a = A() print (a.funds) a.proxy.subtractFunds(funds: 50) This code will throw up a compiler error on: self.c.funds -= funds because: funds setter is inaccessible the funds variable is indeed private. So, I tried a decorator too; code I found from stackoverflow (its not mine): #propertyWrapper struct Announced<T, U> { private var announcedFunction: (T) -> U var wrappedValue: (T) -> U { announcedFunction } init(wrappedValue: #escaping (T) -> U) { announcedFunction = { args in let rv = wrappedValue(args) print("In: \(args)") print("Out: \(rv)") return rv } } } extension Wallet { #Announced static var add: ((Int, Int)) -> Int = { $0.0 + $0.1 } #Announced static var subtract: ((Int, Int)) -> Int = { $0.0 - $0.1 } } Now here the add and subtract are static variables; and the contents of the closure are of course wrong because I make no reference to the actual Wallet variables -- I've only put it like this to help with discussion. The way I got around it is to try to make the (Int, Int) take in a Wallet class, and then return a modified Wallet object where the add or subtract has been completed So something like this: #Announced static var subtract: ((w:Wallet, Int)) -> Wallet = { let newWallet = Wallet() newWallet.cash = w.cash newWallet.cash -= $0.1 return newWallet } But if I do this pattern, I don't see why I don't just write a static function and disregard this decorator. I've even tried making C follow a delegate pattern where the Wallet is a delegate of C and adds, subtracts funds; but this too has an issue in that you can call C directly and because is its own delegate it has no reason to fail or throw up an error, etc. So anyway, probably I'm just overcomplicating: Whats the point of having a proxy if you can just call the subject directly and do your manipulation that way? Is there a way to make the proxy pattern the only way you can call and make actions on the subject? With thanks?
The easiest way is using public/internal setter class C { var funds: Int = 100 } But if you define C in this same file with Proxy then you can use fileprivate(set) access modifier class Proxy { ... } class C { fileprivate(set) var funds: Int = 100 }
Linked list declaration in Swift with finger type that can transparently insert in either middle or start
I am attempting to declare a linked list in Swift, with a finger type that is a reference to either a node, allowing to insert or remove beyond that node, or to the linked list itself, in which case inserting or removing at the top of the linked list. I want to see if this can be made uniform down to the implementation, instead of having to special-case everything: Swift is object-oriented, after all. I previously had a version which required forced casts, but again I'd like to see if this can be made to work without them (e.g. even if they never end up faulting they still imply runtime checks each time). I currently have this code: protocol ContainerNodeInterface: class { associatedtype ContainedItem; var contents: ContainedItem { get }; } protocol ParentNodeInterface: class { associatedtype LinkedItem: ContainerNodeInterface; var next: LinkedItem? {get set}; } class ProtoNode<Contents, NodeType: ParentNodeInterface>: ParentNodeInterface where NodeType.ContainedItem==Contents, NodeType.LinkedItem==NodeType { // not meant to be instantiated or directly referenced typealias LinkedItem = NodeType; var next: NodeType?; init() { next = nil; } final func insertThisAfterMe(_ node: NodeType) { node.next = next; next = .some(node); } final func removeNodeAfterMe() -> NodeType? { guard let nextNode = next else { return nil; } let result = nextNode; next = result.next; result.next = nil; return nextNode; } } class Node<Contents>: ProtoNode<Contents, Node<Contents>>, ContainerNodeInterface { typealias ContainedItem = Contents; typealias NextItem = Node<Contents>; var contents: Contents; init(withContents: Contents) { contents = withContents; super.init(); } } typealias ParentNode<Contents> = ProtoNode<Contents, Node<Contents>>; But the Swift compiler, via Xcode, is complaining that Type 'Node<Contents>' does not conform to protocol 'ParentNodeInterface'. This makes no sense! And if I add explicit conformance to ParentNodeInterface to Node, then I get simultaneously that error and one of redundant conformance to the same protocol. What is missing here? Xcode Version 10.2 (10E125), Swift 5
I resolved it by splitting ProtoNode into an initial declaration and an extension: protocol ContainerNodeInterface: class { associatedtype ContainedItem; var contents: ContainedItem { get }; } protocol ParentNodeInterface: class { associatedtype LinkedItem: ContainerNodeInterface; var next: LinkedItem? {get set}; } class ProtoNode<Contents, NodeType: ContainerNodeInterface>: ParentNodeInterface where NodeType.ContainedItem==Contents { // not meant to be instantiated or directly referenced typealias LinkedItem = NodeType; var next: NodeType?; init() { next = nil; } } extension ProtoNode where NodeType: ParentNodeInterface, NodeType.LinkedItem==NodeType { final func insertThisAfterMe(_ node: NodeType) { node.next = next; next = .some(node); } final func removeNodeAfterMe() -> NodeType? { guard let nextNode = next else { return nil; } let result = nextNode; next = result.next; result.next = nil; return nextNode; } } class Node<Contents>: ProtoNode<Contents, Node<Contents>>, ContainerNodeInterface { typealias ContainedItem = Contents; typealias NextItem = Node<Contents>; var contents: Contents; init(withContents: Contents) { contents = withContents; super.init(); } } typealias ParentNode<Contents> = ProtoNode<Contents, Node<Contents>>; I figure it helps the compiler break the dependency loop, where it has to determine whether Node, as a generic parameter, conforms to the protocol before it can determine the declaration is valid and consider the declared type, i.e. Node, as conforming to the protocol, but still it feels a bit silly for me to have to make this seemingly pointless extension declaration. At the very least, the compiler could be slightly more helpful…
First, I would start with a simple linked-list Node type: final class Node<Value> { let value: Value var next: Node<Value>? init(_ value: Value) { self.value = value } func insert(_ node: Node<Value>) { node.next = next next = node } func removeNext() -> Node<Value>? { guard let removedNode = next else { return nil } next = removedNode.next removedNode.next = nil return removedNode } } Then, you can add the concept that you describe: a pointer to "either a node...or to the linked list itself." When you see "or" in a description, that implies a sum type, which in Swift is an enum, either a pointer to the head of a (possibly empty) list, or a pointer to a node. Each has slightly different behaviors, which you manage with switch. enum NodePointer<Value> { case head(Node<Value>?) case node(Node<Value>) mutating func insert(_ node: Node<Value>) { switch self { case .head(let n): self = .head(node) node.next = n case .node(let n): n.insert(node) } } mutating func removeNext() -> Node<Value>? { switch self { case .head(let n): self = .head(n?.next) return n case .node(let n): return n.removeNext() } } var pointee: Node<Value>? { switch self { case .head(let n): return n case .node(let n): return n } } } With that you would have an interface like: var list = Node(1) list.insert(Node(2)) var ptr = NodePointer.head(list) ptr.insert(Node(1)) ptr.pointee?.next?.next?.value // 2 Note that the specific problem you ran into (that the compiler couldn't work out the conformance) I believe is a compiler bug, though I also believe it's one that's fixed on master currently. I haven't tested that out though. But I don't believe the protocol-based approach is correct for this problem.
Can you simultaneously define and instantiate implicit types in Swift?
Just messing around with the language thinking of how I want to structure some UserDefaults that automatically generate keys based on the hierarchy. That got me wondering... Is it possible to simultaneously define, and instantiate a type, like this? let myUserSettings = { let formatting = { var lastUsedFormat:String } } let lastUsedFormat = myUserSettings.formatting.lastUsedFormat Note: I can't use statics because I specifically need instancing so nested structs/classes with static members will not work for my case. Here's the closest thing I could come up with, but I hate that I have to create initializers to set the members. I'm hoping for something a little less verbose. class DefaultsScope { init(_ userDefaults:UserDefaults){ self.userDefaults = userDefaults } let userDefaults:UserDefaults func keyForSelf(property:String = #function) -> String { return "\(String(reflecting: self)).\(property)" } } let sharedDefaults = SharedDefaults(UserDefaults(suiteName: "A")!) class SharedDefaults : DefaultsScope { override init(_ userDefaults:UserDefaults){ formatting = Formatting(userDefaults) misc = Misc(userDefaults) super.init(userDefaults) } let formatting:Formatting class Formatting:DefaultsScope { let maxLastUsedFormats = 5 fileprivate(set) var lastUsedFormats:[String]{ get { return userDefaults.stringArray(forKey:keyForSelf()) ?? [] } set { userDefaults.set(newValue, forKey:keyForSelf()) } } func appendFormat(_ format:String) -> [String] { var updatedListOfFormats = Array<String>(lastUsedFormats.suffix(maxLastUsedFormats - 1)) updatedListOfFormats.append(format) lastUsedFormats = updatedListOfFormats return updatedListOfFormats } } let misc:Misc class Misc:DefaultsScope { var someBool:Bool{ get { return userDefaults.bool(forKey:keyForSelf()) } set { userDefaults.set(newValue, forKey:keyForSelf()) } } } } So is there a simpler way?
Disclaimer: this is, probably, just an abstract solution that should not be used in real life :) enum x { enum y { static func success() { print("Success") } } } x.y.success() Update: Sorry, folks, I can't stop experimenting. This one looks pretty awful :) let x2= [ "y2": [ "success": { print("Success") } ] ] x2["y2"]?["success"]?() Update 2: One more try, this time with tuples. And since tuples must have at least two values, I had to add some dummies in there. Also, tuples cannot have mutating functions. let x3 = ( y3: ( success: { print("Success") }, failure: { print("Failure") } ), z3: 0 ) x3.y3.success()
How about you try nesting some swift structs? struct x { struct y { static func success() { print("success") } } } x.y.success()
You cannot have that kind of structure but you cant access y from inside x, since y is only visible inside the scope of x and so is success inside the scope of y. There is no way that you can access them from outside One other alternative is to have higher order function like so, which return closure which is callable. let x = { { { print("Success") } } } let y = x() let success = y() success() or x()()() The real world usage of higher order function for userdefaults could be something like this, typealias StringType = (String) -> ((String) -> Void) typealias IntType = (String) -> ((Int) -> Void) typealias BoolType = (String) -> ((Bool) -> Void) typealias StringValue = (String) -> String? typealias IntValue = (String) -> Int? typealias BoolValue = (String) -> Bool? func userDefaults<T>(_ defaults: UserDefaults) -> (String) -> ((T) -> Void) { return { key in return { value in defaults.setValue(value, forKey: key) } } } func getDefaultsValue<T>(_ defaults: UserDefaults) -> (String) -> T? { return { key in return defaults.value(forKey: key) as? T } } let setStringDefaults: StringType = userDefaults(.standard) setStringDefaults("Name")("Jack Jones") setStringDefaults("Address")("Australia") let setIntDefaults: IntType = userDefaults(.standard) setIntDefaults("Age")(35) setIntDefaults("Salary")(2000) let setBoolDefaults: BoolType = userDefaults(.standard) setBoolDefaults("Married")(false) setBoolDefaults("Employed")(true) let getStringValue: StringValue = getDefaultsValue(.standard) let name = getStringValue("Name") let address = getStringValue("Address") let getIntValue: IntValue = getDefaultsValue(.standard) let age = getIntValue("Age") let salary = getIntValue("Salary") let getBoolValue: BoolValue = getDefaultsValue(.standard) let married = getBoolValue("Married") let employed = getBoolValue("Employed") I am not sure if you like the pattern, but it has some good use cases as you can see from below, setStringDefaults you can set strings value to string key and all of them are typesafe. You can extend this for your use case. But, you could use struct as well and use imperative code, which could be easier to understand. I see beauty in this as well.
Ok, I think I've figured it out. This first class can go in some common library that you use for all your apps. class SettingsScopeBase { private init(){} static func getKey(setting:String = #function) -> String { return "\(String(reflecting:self)).\(setting)" } } The next part is a pair of classes: The 'Scoping' class where you define which user defaults instance to use (along with anything else you may want to specify for this particular settings instance) The actual hierarchy that defines your settings Here's the first. I'm setting this up for my shared settings between my application and it's extension: class SharedSettingsScope : SettingsScopeBase{ static let defaults = UserDefaults(suiteName: "group.com.myco.myappgroup")! } And finally, here's how you 'set up' your hierarchy as well as how you implement the properties' bodies. class SharedSettings:SharedSettingsScope{ class Formatting:SharedSettingsScope{ static var groupsOnWhitespaceOnlyLines:Bool{ get { return defaults.bool(forKey: getKey()) } set { defaults.set(newValue, forKey: getKey()) } } } } And here's how you use them... let x = SharedSettings.Formatting.groupsOnWhitespaceOnlyLines // x = false SharedSettings.Formatting.groupsOnWhitespaceOnlyLines = true let y = SharedSettings.Formatting.groupsOnWhitespaceOnlyLines // y = true I'm going to see if I can refine/optimize it a little more, but this is pretty close to where I want to be. No hard-coded strings, keys defined by the hierarchy where they're used, and only setting the specific UserDefaults instance in one place.
Implementing recursive generator for simple tree structure in Swift
I have a simple tree structure in memory based on an XML document and I am trying to write a recursive generator to support SequenceType, but I am stuck on how to actually do this. Here was my first attempt: #objc public class XMLNode: NSObject, SequenceType { public weak var parentNode: XMLNode? public var nodeName: String public var attributes: [String: String] public var childNodes = [XMLNode]() public func generate() -> AnyGenerator<XMLNode> { var childGenerator = childNodes.generate() var returnedSelf = false return anyGenerator { let child = childGenerator.next() if child != nil { // I need to somehow recurse on child here return child } else if !returnedSelf { returnedSelf = true return self } else { return nil } } } } Since childNodes is an array, I'm calling its own built-in generate() function to create a generator on the child nodes and iterating it, and then returning self at the end. The problem is it's not recursing on each child, so it only ever goes one level deep. I can't figure out how to combine two generators in that way. I'm having a hard time wrapping my head around how to do this! What do I need to do to make a recursive generator?
I don't know if a generator itself can be recursive. Will M proved me wrong! Here is a possible implementation for a pre-order traversal, using a stack for the child nodes which still have to be enumerated: extension XMLNode : SequenceType { public func generate() -> AnyGenerator<XMLNode> { var stack : [XMLNode] = [self] return anyGenerator { if let next = stack.first { stack.removeAtIndex(0) stack.insertContentsOf(next.childNodes, at: 0) return next } return nil } } } For a level-order traversal, replace stack.insertContentsOf(next.childNodes, at: 0) by stack.appendContentsOf(next.childNodes)
Here is a recursive post-order generator. Can't say I'd recommend actually using it though. #MartinR's answer seems a bit more practical public func generate() -> AnyGenerator<XMLNode> { var childGenerator:AnyGenerator<XMLNode>? var childArrayGenerator:IndexingGenerator<[XMLNode]>? = self.childNodes.generate() var returnedSelf = false return anyGenerator { if let next = childGenerator?.next() { return next } if let child = childArrayGenerator?.next() { childGenerator = child.generate() return childGenerator?.next() } else if !returnedSelf { returnedSelf = true return self } else { return nil } } }
While Martin's answer is certainly more concise, it has the downside of making a lot of using a lot of array/insert operations and is not particularly usable in lazy sequence operations. This alternative should work in those environments, I've used something similar for UIView hierarchies. public typealias Generator = AnyGenerator<XMLNode> public func generate() -> AnyGenerator<XMLNode> { var childGenerator = childNodes.generate() var subGenerator : AnyGenerator<XMLNode>? var returnedSelf = false return anyGenerator { if !returnedSelf { returnedSelf = true return self } if let subGenerator = subGenerator, let next = subGenerator.next() { return next } if let child = childGenerator.next() { subGenerator = child.generate() return subGenerator!.next() } return nil } } Note that this is preorder iteration, you can move the if !returnedSelf block around for post order.