├── Simple-Swift-AI ├── Simple-Swift-AI │ ├── Assets.xcassets │ │ ├── Contents.json │ │ └── AppIcon.appiconset │ │ │ ├── simpleSwiftAI-29.png │ │ │ ├── simpleSwiftAI-40.png │ │ │ ├── simpleSwiftAI-76.png │ │ │ ├── simpleSwiftAI-29@2x.png │ │ │ ├── simpleSwiftAI-29@3x.png │ │ │ ├── simpleSwiftAI-40@2x.png │ │ │ ├── simpleSwiftAI-40@3x.png │ │ │ ├── simpleSwiftAI-60@2x.png │ │ │ ├── simpleSwiftAI-60@3x.png │ │ │ ├── simpleSwiftAI-76@2x.png │ │ │ ├── simpleSwiftAI-83.5@2x.png │ │ │ └── Contents.json │ ├── Simple_Swift_AI.xcdatamodeld │ │ ├── .xccurrentversion │ │ └── Simple_Swift_AI.xcdatamodel │ │ │ └── contents │ ├── Network │ │ ├── ActivationFunctions.swift │ │ ├── InputA.swift │ │ ├── NeuronA.swift │ │ ├── AutoNetworkBuilder.swift │ │ └── NetworkA.swift │ ├── ViewController.swift │ ├── DebugView │ │ ├── OutputTableViewCell.swift │ │ ├── NeuronInputsView.swift │ │ ├── OutputTableController.swift │ │ └── NetworkViewController.swift │ ├── Utils │ │ ├── Utils.swift │ │ └── CoreDataUtil.swift │ ├── Examples │ │ └── AI_System_XOR.swift │ ├── Info.plist │ ├── AppDelegate.swift │ └── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard └── Simple-Swift-AI.xcodeproj │ ├── project.xcworkspace │ └── contents.xcworkspacedata │ └── project.pbxproj ├── LICENSE ├── README.md └── .gitignore /Simple-Swift-AI/Simple-Swift-AI/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /Simple-Swift-AI/Simple-Swift-AI/Assets.xcassets/AppIcon.appiconset/simpleSwiftAI-29.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arjungupta99/Simple-Swift-AI/HEAD/Simple-Swift-AI/Simple-Swift-AI/Assets.xcassets/AppIcon.appiconset/simpleSwiftAI-29.png -------------------------------------------------------------------------------- /Simple-Swift-AI/Simple-Swift-AI/Assets.xcassets/AppIcon.appiconset/simpleSwiftAI-40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arjungupta99/Simple-Swift-AI/HEAD/Simple-Swift-AI/Simple-Swift-AI/Assets.xcassets/AppIcon.appiconset/simpleSwiftAI-40.png -------------------------------------------------------------------------------- /Simple-Swift-AI/Simple-Swift-AI/Assets.xcassets/AppIcon.appiconset/simpleSwiftAI-76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arjungupta99/Simple-Swift-AI/HEAD/Simple-Swift-AI/Simple-Swift-AI/Assets.xcassets/AppIcon.appiconset/simpleSwiftAI-76.png -------------------------------------------------------------------------------- /Simple-Swift-AI/Simple-Swift-AI/Assets.xcassets/AppIcon.appiconset/simpleSwiftAI-29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arjungupta99/Simple-Swift-AI/HEAD/Simple-Swift-AI/Simple-Swift-AI/Assets.xcassets/AppIcon.appiconset/simpleSwiftAI-29@2x.png -------------------------------------------------------------------------------- /Simple-Swift-AI/Simple-Swift-AI/Assets.xcassets/AppIcon.appiconset/simpleSwiftAI-29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arjungupta99/Simple-Swift-AI/HEAD/Simple-Swift-AI/Simple-Swift-AI/Assets.xcassets/AppIcon.appiconset/simpleSwiftAI-29@3x.png -------------------------------------------------------------------------------- /Simple-Swift-AI/Simple-Swift-AI/Assets.xcassets/AppIcon.appiconset/simpleSwiftAI-40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arjungupta99/Simple-Swift-AI/HEAD/Simple-Swift-AI/Simple-Swift-AI/Assets.xcassets/AppIcon.appiconset/simpleSwiftAI-40@2x.png -------------------------------------------------------------------------------- /Simple-Swift-AI/Simple-Swift-AI/Assets.xcassets/AppIcon.appiconset/simpleSwiftAI-40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arjungupta99/Simple-Swift-AI/HEAD/Simple-Swift-AI/Simple-Swift-AI/Assets.xcassets/AppIcon.appiconset/simpleSwiftAI-40@3x.png -------------------------------------------------------------------------------- /Simple-Swift-AI/Simple-Swift-AI/Assets.xcassets/AppIcon.appiconset/simpleSwiftAI-60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arjungupta99/Simple-Swift-AI/HEAD/Simple-Swift-AI/Simple-Swift-AI/Assets.xcassets/AppIcon.appiconset/simpleSwiftAI-60@2x.png -------------------------------------------------------------------------------- /Simple-Swift-AI/Simple-Swift-AI/Assets.xcassets/AppIcon.appiconset/simpleSwiftAI-60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arjungupta99/Simple-Swift-AI/HEAD/Simple-Swift-AI/Simple-Swift-AI/Assets.xcassets/AppIcon.appiconset/simpleSwiftAI-60@3x.png -------------------------------------------------------------------------------- /Simple-Swift-AI/Simple-Swift-AI/Assets.xcassets/AppIcon.appiconset/simpleSwiftAI-76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arjungupta99/Simple-Swift-AI/HEAD/Simple-Swift-AI/Simple-Swift-AI/Assets.xcassets/AppIcon.appiconset/simpleSwiftAI-76@2x.png -------------------------------------------------------------------------------- /Simple-Swift-AI/Simple-Swift-AI/Assets.xcassets/AppIcon.appiconset/simpleSwiftAI-83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arjungupta99/Simple-Swift-AI/HEAD/Simple-Swift-AI/Simple-Swift-AI/Assets.xcassets/AppIcon.appiconset/simpleSwiftAI-83.5@2x.png -------------------------------------------------------------------------------- /Simple-Swift-AI/Simple-Swift-AI.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Simple-Swift-AI/Simple-Swift-AI/Simple_Swift_AI.xcdatamodeld/.xccurrentversion: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | _XCCurrentVersionName 6 | Simple_Swift_AI.xcdatamodel 7 | 8 | 9 | -------------------------------------------------------------------------------- /Simple-Swift-AI/Simple-Swift-AI/Network/ActivationFunctions.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ActivationFunctions.swift 3 | // Simple-Swift-AI 4 | // 5 | // Created by Arjun Gupta on 7/29/16. 6 | // Copyright © 2016 ArjunGupta. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | class ActivationFunctions { 12 | 13 | 14 | class func linear(x: Double) -> Double { 15 | return x 16 | } 17 | 18 | class func sigmoid(val: Double) -> Double { 19 | return 1 / (1 + exp(-val)) 20 | } 21 | 22 | 23 | } 24 | -------------------------------------------------------------------------------- /Simple-Swift-AI/Simple-Swift-AI/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // Simple-Swift-AI 4 | // 5 | // Created by Arjun Gupta on 9/30/16. 6 | // Copyright © 2016 Arjun Gupta. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class ViewController: UIViewController { 12 | 13 | override func viewDidLoad() { 14 | super.viewDidLoad() 15 | 16 | let _ = AI_System_XOR(rootVC:self) 17 | 18 | } 19 | 20 | override func didReceiveMemoryWarning() { 21 | super.didReceiveMemoryWarning() 22 | // Dispose of any resources that can be recreated. 23 | } 24 | 25 | 26 | } 27 | 28 | -------------------------------------------------------------------------------- /Simple-Swift-AI/Simple-Swift-AI/DebugView/OutputTableViewCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // OutputTableViewCell.swift 3 | // Simple-Swift-AI 4 | // 5 | // Created by Arjun Gupta on 9/27/16. 6 | // Copyright © 2016 ArjunGupta. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import UIKit 11 | 12 | class OutputTableViewCell:UITableViewCell { 13 | 14 | @IBOutlet weak var cellIndexLabel : UILabel! 15 | @IBOutlet weak var inputLabelView : UIView! 16 | @IBOutlet weak var outputLabelView : UIView! 17 | 18 | 19 | var inputLabels = [UILabel]() 20 | var outputLabels = [UILabel]() 21 | var inputNeuronLabels = [UILabel]() 22 | var outputNeuronLabels = [UILabel]() 23 | } 24 | -------------------------------------------------------------------------------- /Simple-Swift-AI/Simple-Swift-AI/Simple_Swift_AI.xcdatamodeld/Simple_Swift_AI.xcdatamodel/contents: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /Simple-Swift-AI/Simple-Swift-AI/Utils/Utils.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Utils.swift 3 | // Simple-Swift-AI 4 | // 5 | // Created by Arjun Gupta on 7/29/16. 6 | // Copyright © 2016 ArjunGupta. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import UIKit 11 | 12 | class Utils { 13 | 14 | } 15 | 16 | func DebugLog(_ logMessage: String, className: String = #file, lineNumber: NSInteger = #line) { 17 | let tempArr = className.characters.split(separator: "/").map(String.init) 18 | let last = tempArr[tempArr.count-1] 19 | print("\(last) ... Line: \(lineNumber) ... \(logMessage)", terminator: "\n") 20 | } 21 | 22 | 23 | extension Double { 24 | 25 | func roundToDigits(digits:Int) -> Double { 26 | let divisor = pow(10.0, Double(digits)) 27 | return (self * divisor).rounded() / divisor 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Simple-Swift-AI/Simple-Swift-AI/Network/InputA.swift: -------------------------------------------------------------------------------- 1 | // 2 | // InputA.swift 3 | // Simple-Swift-AI 4 | // 5 | // Created by Arjun Gupta on 7/29/16. 6 | // Copyright © 2016 ArjunGupta. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import UIKit 11 | 12 | @objc class InputA:NSObject { 13 | 14 | var weight :Double 15 | var neuron :NeuronA? 16 | var value :Double? { 17 | set (newValue) { self.valueStore = newValue } 18 | get { return (self.neuron != nil) ? self.neuron!.output! : self.valueStore } 19 | } 20 | private var valueStore:Double? 21 | var indexInLayer:Int = 0 22 | 23 | //Input layer 24 | init(value:Double, weight:Double) { 25 | self.weight = weight 26 | super.init() 27 | self.value = value 28 | } 29 | 30 | //Hidden layer 31 | init(neuron:NeuronA, weight:Double) { 32 | self.neuron = neuron 33 | self.weight = weight 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 Arjun Gupta 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Simple-Swift-AI 2 | A simple to use Feed Forward Neural Network built in Swift 3.0 3 | 4 | ### Usage 5 | * A data set with multiple inputs and outputs can be used to train the network. 6 | * The default number of hidden layers is one, more can be added as per need. 7 | * The neuron output values range from 0 to 1.0. Modify your data set accordingly. 8 | 9 | ### Features 10 | * Feed-forward neural network with input, hidden and output layers 11 | * Multiple hidden layers can be added with little extra code 12 | * Can come in use for categorization and function value prediction 13 | * Optional debug screen included for viewing the training and test outputs on simulator 14 | 15 | --- 16 | An example of XOR gate training is included. 17 | 18 | --- 19 | 20 | 21 | **FFNN Training screen** 22 | 23 | ![FFNN Training](http://www.agmotif.com/blog/wp-content/uploads/2016/10/FFNN-train2.png) 24 | 25 | --- 26 | 27 | **FFNN Test screen** 28 | 29 | ![FFNN Testing](http://www.agmotif.com/blog/wp-content/uploads/2016/10/FFNN-result2.png) 30 | 31 | --- 32 | 33 | By Arjun Gupta 34 | 35 | Can be reached at : arjungupta497 (at) gmail.com 36 | 37 | Twitter : https://www.twitter.com/arjunguptaxor 38 | -------------------------------------------------------------------------------- /Simple-Swift-AI/Simple-Swift-AI/Examples/AI_System_XOR.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AI_System_XOR.swift 3 | // Simple-Swift-AI 4 | // 5 | // Created by Arjun Gupta on 9/23/16. 6 | // Copyright © 2016 ArjunGupta. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import UIKit 11 | 12 | class AI_System_XOR { 13 | 14 | init(rootVC:UIViewController?) { 15 | 16 | //Building a large training set using the same four Input and Outputs of XOR Gate 17 | 18 | var trainingSet:[(input:[Double],output:[Double])] = 19 | [ 20 | ([0, 0], [0]), 21 | ([0, 1], [1]), 22 | ([1, 0], [1]), 23 | ([1, 1], [0]) 24 | ] 25 | 26 | for _ in stride(from: 0, to: 70000, by: 1) { 27 | let randomIndex = Int(arc4random_uniform(4)) 28 | trainingSet.append(trainingSet[randomIndex]) 29 | } 30 | 31 | let network = AutoNetworkBuilder().buildAutoNetwork(trainingSet: trainingSet, rootVC: rootVC, persistanceID: "XOR") 32 | 33 | network.trainNetwork(trainingSets: trainingSet) { (completion) in 34 | 35 | //Test your inputs here 36 | 37 | if (completion.0 == true) { 38 | DebugLog("Test output -> 0 1 1 0") 39 | let _ = network.getOutputFor(inputs: [[0 , 0],[0 , 1],[1 , 0],[1 , 1]]) 40 | } 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /Simple-Swift-AI/Simple-Swift-AI/Network/NeuronA.swift: -------------------------------------------------------------------------------- 1 | // 2 | // NeuronA.swift 3 | // Simple-Swift-AI 4 | // 5 | // Created by Arjun Gupta on 7/29/16. 6 | // Copyright © 2016 ArjunGupta. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import UIKit 11 | 12 | @objc class NeuronA:NSObject { 13 | 14 | var identifier :String 15 | var inputs = [String:InputA]() 16 | var bias :Double? 17 | var output :Double? 18 | var error :Double? 19 | 20 | //Input Neuron 21 | init(uid:String) { 22 | self.identifier = uid 23 | } 24 | 25 | //Hidden Neuron 26 | init(uid:String, bias:Double , inputs:[InputA]? = nil) { 27 | self.identifier = uid 28 | self.bias = bias 29 | super.init() 30 | if let theInputs = inputs { 31 | self.attachInputs(inputs: theInputs) 32 | self.calculateOutput() 33 | } 34 | } 35 | 36 | func attachInputs(inputs:[InputA]) { 37 | for input in inputs { 38 | self.inputs[input.neuron!.identifier] = input 39 | } 40 | } 41 | 42 | func calculateOutput() { 43 | 44 | if (self.inputs.keys.count == 0) { return } 45 | 46 | var inputWeightSummation:Double = 0 47 | for input in self.inputs.values { 48 | inputWeightSummation += (input.value! * input.weight) 49 | } 50 | 51 | let net = inputWeightSummation + self.bias! 52 | self.output = ActivationFunctions.sigmoid(val:net) 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 4 | 5 | ## Build generated 6 | build/ 7 | DerivedData/ 8 | 9 | ## Various settings 10 | *.pbxuser 11 | !default.pbxuser 12 | *.mode1v3 13 | !default.mode1v3 14 | *.mode2v3 15 | !default.mode2v3 16 | *.perspectivev3 17 | !default.perspectivev3 18 | xcuserdata/ 19 | 20 | ## Other 21 | *.moved-aside 22 | *.xcuserstate 23 | 24 | ## Obj-C/Swift specific 25 | *.hmap 26 | *.ipa 27 | *.dSYM.zip 28 | *.dSYM 29 | 30 | ## Playgrounds 31 | timeline.xctimeline 32 | playground.xcworkspace 33 | 34 | # Swift Package Manager 35 | # 36 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. 37 | # Packages/ 38 | .build/ 39 | 40 | # CocoaPods 41 | # 42 | # We recommend against adding the Pods directory to your .gitignore. However 43 | # you should judge for yourself, the pros and cons are mentioned at: 44 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 45 | # 46 | # Pods/ 47 | 48 | # Carthage 49 | # 50 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 51 | # Carthage/Checkouts 52 | 53 | Carthage/Build 54 | 55 | # fastlane 56 | # 57 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 58 | # screenshots whenever they are needed. 59 | # For more information about the recommended setup visit: 60 | # https://github.com/fastlane/fastlane/blob/master/fastlane/docs/Gitignore.md 61 | 62 | fastlane/report.xml 63 | fastlane/Preview.html 64 | fastlane/screenshots 65 | fastlane/test_output 66 | -------------------------------------------------------------------------------- /Simple-Swift-AI/Simple-Swift-AI/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | Simple-AI 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | UIInterfaceOrientationLandscapeRight 38 | 39 | UISupportedInterfaceOrientations~ipad 40 | 41 | UIInterfaceOrientationPortrait 42 | UIInterfaceOrientationPortraitUpsideDown 43 | UIInterfaceOrientationLandscapeLeft 44 | UIInterfaceOrientationLandscapeRight 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /Simple-Swift-AI/Simple-Swift-AI/Network/AutoNetworkBuilder.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AutoNetworkBuilder.swift 3 | // Simple-Swift-AI 4 | // 5 | // Created by Arjun Gupta on 9/23/16. 6 | // Copyright © 2016 ArjunGupta. All rights reserved. 7 | // 8 | 9 | //****************************************************************************** 10 | // 11 | // - This class is a quick and simple way to train and test a network. 12 | // - It checks the number of inputs and outputs of the training set to select 13 | // the number of neurons in Input, Hidden and Output layers. 14 | // - Follow the code below when making a custom network 15 | // 16 | //****************************************************************************** 17 | 18 | import Foundation 19 | import UIKit 20 | 21 | class AutoNetworkBuilder { 22 | 23 | var aNetwork:NetworkA? 24 | 25 | func buildAutoNetwork(trainingSet:[(input:[Double],output:[Double])], rootVC:UIViewController? = nil, persistanceID:String? = nil) -> NetworkA { 26 | 27 | let network = NetworkA(rootVC:rootVC, persistanceID:persistanceID) 28 | self.aNetwork = network 29 | network.learningRate = 0.5 30 | 31 | let infoSet = trainingSet[0] 32 | 33 | //Input layer 34 | for i in stride(from:0, to:infoSet.input.count, by:1) { 35 | 36 | let identifier = "I" + String(i) 37 | let neuron = NeuronA(uid:identifier) 38 | network.insert(neuron: neuron, layerNum: 0) 39 | } 40 | 41 | //Hidden layer 42 | for i in stride(from:0, to:infoSet.input.count * 3, by:1) { 43 | 44 | let identifier = "H1-" + String(i) 45 | let neuron = NeuronA(uid: identifier, bias: 0.35) 46 | network.insert(neuron: neuron, layerNum: 1) 47 | } 48 | 49 | //Output layer 50 | for i in stride(from:0, to:infoSet.output.count, by:1) { 51 | 52 | let identifier = "O" + String(i) 53 | let neuron = NeuronA(uid:identifier, bias: 0.6) 54 | network.insert(neuron: neuron, layerNum: 2) 55 | } 56 | 57 | network.connectNeuronsWithRandomizedWeights() 58 | 59 | return network 60 | } 61 | } 62 | 63 | -------------------------------------------------------------------------------- /Simple-Swift-AI/Simple-Swift-AI/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // Simple-Swift-AI 4 | // 5 | // Created by Arjun Gupta on 9/30/16. 6 | // Copyright © 2016 Arjun Gupta. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import CoreData 11 | 12 | @UIApplicationMain 13 | class AppDelegate: UIResponder, UIApplicationDelegate { 14 | 15 | var window: UIWindow? 16 | lazy var coreDataUtil = CoreDataUtil() 17 | 18 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { 19 | // Override point for customization after application launch. 20 | return true 21 | } 22 | 23 | func applicationWillResignActive(_ application: UIApplication) { 24 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 25 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. 26 | } 27 | 28 | func applicationDidEnterBackground(_ application: UIApplication) { 29 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 30 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 31 | } 32 | 33 | func applicationWillEnterForeground(_ application: UIApplication) { 34 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. 35 | } 36 | 37 | func applicationDidBecomeActive(_ application: UIApplication) { 38 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 39 | } 40 | 41 | func applicationWillTerminate(_ application: UIApplication) { 42 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 43 | // Saves changes in the application's managed object context before the application terminates. 44 | self.coreDataUtil.saveContext() 45 | } 46 | 47 | } 48 | 49 | -------------------------------------------------------------------------------- /Simple-Swift-AI/Simple-Swift-AI/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "size" : "29x29", 15 | "idiom" : "iphone", 16 | "filename" : "simpleSwiftAI-29@2x.png", 17 | "scale" : "2x" 18 | }, 19 | { 20 | "size" : "29x29", 21 | "idiom" : "iphone", 22 | "filename" : "simpleSwiftAI-29@3x.png", 23 | "scale" : "3x" 24 | }, 25 | { 26 | "size" : "40x40", 27 | "idiom" : "iphone", 28 | "filename" : "simpleSwiftAI-40@2x.png", 29 | "scale" : "2x" 30 | }, 31 | { 32 | "size" : "40x40", 33 | "idiom" : "iphone", 34 | "filename" : "simpleSwiftAI-40@3x.png", 35 | "scale" : "3x" 36 | }, 37 | { 38 | "size" : "60x60", 39 | "idiom" : "iphone", 40 | "filename" : "simpleSwiftAI-60@2x.png", 41 | "scale" : "2x" 42 | }, 43 | { 44 | "size" : "60x60", 45 | "idiom" : "iphone", 46 | "filename" : "simpleSwiftAI-60@3x.png", 47 | "scale" : "3x" 48 | }, 49 | { 50 | "idiom" : "ipad", 51 | "size" : "20x20", 52 | "scale" : "1x" 53 | }, 54 | { 55 | "idiom" : "ipad", 56 | "size" : "20x20", 57 | "scale" : "2x" 58 | }, 59 | { 60 | "size" : "29x29", 61 | "idiom" : "ipad", 62 | "filename" : "simpleSwiftAI-29.png", 63 | "scale" : "1x" 64 | }, 65 | { 66 | "size" : "29x29", 67 | "idiom" : "ipad", 68 | "filename" : "simpleSwiftAI-29@2x.png", 69 | "scale" : "2x" 70 | }, 71 | { 72 | "size" : "40x40", 73 | "idiom" : "ipad", 74 | "filename" : "simpleSwiftAI-40.png", 75 | "scale" : "1x" 76 | }, 77 | { 78 | "size" : "40x40", 79 | "idiom" : "ipad", 80 | "filename" : "simpleSwiftAI-40@2x.png", 81 | "scale" : "2x" 82 | }, 83 | { 84 | "size" : "76x76", 85 | "idiom" : "ipad", 86 | "filename" : "simpleSwiftAI-76.png", 87 | "scale" : "1x" 88 | }, 89 | { 90 | "size" : "76x76", 91 | "idiom" : "ipad", 92 | "filename" : "simpleSwiftAI-76@2x.png", 93 | "scale" : "2x" 94 | }, 95 | { 96 | "size" : "83.5x83.5", 97 | "idiom" : "ipad", 98 | "filename" : "simpleSwiftAI-83.5@2x.png", 99 | "scale" : "2x" 100 | } 101 | ], 102 | "info" : { 103 | "version" : 1, 104 | "author" : "xcode" 105 | } 106 | } -------------------------------------------------------------------------------- /Simple-Swift-AI/Simple-Swift-AI/Utils/CoreDataUtil.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CoreDataUtil.swift 3 | // Simple-Swift-AI 4 | // 5 | // Created by Arjun Gupta on 10/2/16. 6 | // Copyright © 2016 Arjun Gupta. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import CoreData 11 | 12 | class CoreDataUtil { 13 | 14 | lazy var persistentContainer: NSPersistentContainer = { 15 | 16 | let container = NSPersistentContainer(name: "Simple_Swift_AI") 17 | container.loadPersistentStores(completionHandler: { (storeDescription, error) in 18 | if let error = error { 19 | 20 | fatalError("Error: \(error)") 21 | } 22 | }) 23 | return container 24 | }() 25 | 26 | func saveContext() { 27 | 28 | let context = persistentContainer.viewContext 29 | 30 | context.reset() 31 | 32 | if context.hasChanges { 33 | do { 34 | try context.save() 35 | } catch let error as NSError { 36 | 37 | fatalError("Error: \(error), \(error.userInfo)") 38 | } 39 | } 40 | } 41 | 42 | 43 | func persistNewWeights(neurons:[[NeuronA]], persistanceID:String) { 44 | 45 | let context = persistentContainer.viewContext 46 | var layers = [[[String:Double]]]() 47 | for layer in neurons { 48 | 49 | var aLayer = [[String:Double]]() 50 | for neuron in layer { 51 | var inputIdentifiers = [String:Double]() 52 | for input in neuron.inputs { 53 | inputIdentifiers[input.key] = input.value.weight 54 | } 55 | aLayer.append(inputIdentifiers) 56 | } 57 | layers.append(aLayer) 58 | } 59 | 60 | 61 | let nObj = NetworkObj(context: context) 62 | nObj.persistanceID = persistanceID 63 | let arrayData = NSKeyedArchiver.archivedData(withRootObject: layers) 64 | nObj.neurons = arrayData as NSData? 65 | 66 | do { 67 | try context.save() 68 | } catch { 69 | fatalError("Failed to save context: \(error)") 70 | } 71 | 72 | } 73 | 74 | 75 | func fetchExistingWeights(persistanceID:String) -> [[[String:Double]]]? { 76 | 77 | let context = persistentContainer.viewContext 78 | let request:NSFetchRequest = NSFetchRequest(entityName: "NetworkObj") 79 | 80 | request.predicate = NSPredicate(format: "persistanceID == %@", persistanceID) 81 | 82 | var result:[[[String:Double]]]? 83 | do { 84 | let results = try context.fetch(request) 85 | if let res = results.last { 86 | if let arr = res as? NetworkObj { 87 | 88 | //DebugLog("nObj.objectID acc : \(arr.objectID.description)") 89 | if let ar = NSKeyedUnarchiver.unarchiveObject(with: arr.neurons! as Data) as? [[[String:Double]]] { 90 | 91 | result = ar 92 | } 93 | } 94 | } 95 | 96 | } catch let error as NSError { 97 | print("Failure to fetch \(error), \(error.userInfo)") 98 | } 99 | 100 | return result 101 | } 102 | 103 | } 104 | -------------------------------------------------------------------------------- /Simple-Swift-AI/Simple-Swift-AI/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 30 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /Simple-Swift-AI/Simple-Swift-AI/DebugView/NeuronInputsView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // NeuronInputsView.swift 3 | // Simple-Swift-AI 4 | // 5 | // Created by Arjun Gupta on 9/22/16. 6 | // Copyright © 2016 ArjunGupta. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import UIKit 11 | 12 | class NeuronInputsView:UIView { 13 | 14 | var idLabel :UILabel! 15 | var biasLabel :UILabel! 16 | var inputLabels = [String:UILabel]() 17 | var circleView:UIView! 18 | 19 | override init(frame: CGRect) { 20 | super.init(frame: frame) 21 | 22 | let f = CGRect(x: 0, y: 0, width: 60, height: 60) 23 | 24 | self.circleView = UIView(frame: f) 25 | self.circleView.backgroundColor = UIColor.lightGray 26 | self.circleView.backgroundColor = UIColor(red: 1.0, green: 0.39, blue: 0.39, alpha: 1.0) 27 | self.circleView.layer.cornerRadius = f.size.height/2 28 | self.circleView.center = CGPoint(x: frame.size.width - f.size.width/2 - 10, y: frame.size.height/2) 29 | self.addSubview(self.circleView) 30 | 31 | self.idLabel = NeuronInputsView.makeLabel(f: f) 32 | self.idLabel.center = CGPoint(x: f.size.width/2, y: f.size.height/2) 33 | self.circleView.addSubview(self.idLabel) 34 | self.idLabel.center = CGPoint(x: f.size.width/2, y: f.size.height/2) 35 | 36 | self.backgroundColor = UIColor(red: 0.9, green: 0.9, blue: 0.9, alpha: 0.9) 37 | } 38 | 39 | 40 | required init?(coder aDecoder: NSCoder) { 41 | fatalError("init(coder:) has not been implemented") 42 | } 43 | 44 | 45 | func buildInputs(inputs:[InputA]) { 46 | 47 | let vMargin:CGFloat = 25 48 | let hMargin:CGFloat = 5 49 | let hLabelMargin:CGFloat = 10 50 | let lbHeight:CGFloat = 16 51 | let lbWidth:CGFloat = self.circleView.frame.origin.x - 2*hLabelMargin 52 | var labelBase:UIView? 53 | if inputs.count > 0 { 54 | labelBase = UIView(frame:CGRect(x: hMargin, y: vMargin, width: lbWidth + hMargin, height: self.bounds.size.height - 2*vMargin)) 55 | labelBase?.backgroundColor = UIColor(red: 1.0, green: 1.0, blue: 1.0, alpha: 0.3) 56 | self.addSubview(labelBase!) 57 | } 58 | 59 | let topBase = UIView(frame:CGRect(x: 0, y: 0, width: self.bounds.size.width, height: vMargin - 5)) 60 | topBase.backgroundColor = UIColor(red: 0, green: 0, blue: 0, alpha: 0.05) 61 | self.addSubview(topBase) 62 | 63 | let bottomBase = UIView(frame:CGRect(x: 0, y: self.bounds.size.height - vMargin + 5, width: self.bounds.size.width, height: vMargin - 5)) 64 | bottomBase.backgroundColor = UIColor(red: 0, green: 0, blue: 0, alpha: 0.05) 65 | self.addSubview(bottomBase) 66 | 67 | if inputs.count > 0 { 68 | let wf = CGRect(x: 7, y: 0, width: 100, height: vMargin - 3) 69 | let weightLabel = self.makeWeightsLabel(f: wf) 70 | weightLabel.textColor = UIColor.gray 71 | weightLabel.font = UIFont(name: "Helvetica", size: 13) 72 | weightLabel.text = "WEIGHTS" 73 | topBase.addSubview(weightLabel) 74 | } 75 | 76 | let bf = CGRect(x: 0, y: 0, width: self.bounds.size.width - 10, height: vMargin - 3) 77 | self.biasLabel = self.makeWeightsLabel(f: bf) 78 | self.biasLabel.textColor = UIColor(red: 1.0, green: 0.39, blue: 0.39, alpha: 1.0) 79 | self.biasLabel.font = UIFont(name: "Helvetica", size: 13) 80 | self.biasLabel.textAlignment = .right 81 | bottomBase.addSubview(self.biasLabel) 82 | 83 | //Input labels 84 | for (_,input) in inputs.enumerated() { 85 | let f = CGRect(x: 0, y: 0, width: lbWidth, height: lbHeight) 86 | let lb = self.makeWeightsLabel(f: f) 87 | lb.center = CGPoint(x: 5 + lb.frame.size.width/2, y: 5 + lb.frame.size.height * CGFloat(input.indexInLayer) + lb.frame.size.height / 2) 88 | labelBase?.addSubview(lb) 89 | if let neuron = input.neuron { 90 | lb.text = neuron.identifier + " : " + String(input.weight) 91 | self.inputLabels[neuron.identifier] = lb 92 | 93 | if let theBias = neuron.bias { 94 | biasLabel.text = "BIAS \(theBias)" 95 | } 96 | } 97 | } 98 | } 99 | 100 | 101 | func makeWeightsLabel(f:CGRect) -> UILabel { 102 | let lb = NeuronInputsView.makeLabel(f: f) 103 | lb.frame = f 104 | lb.font = UIFont(name: "Helvetica", size: 13) 105 | lb.textColor = UIColor.black 106 | lb.textAlignment = .left 107 | lb.adjustsFontSizeToFitWidth = false 108 | lb.minimumScaleFactor = 1.0 109 | return lb 110 | } 111 | 112 | 113 | class func makeLabel(f:CGRect) -> UILabel { 114 | let lbl = UILabel(frame:f) 115 | lbl.font = UIFont(name: "Helvetica", size: 20) 116 | lbl.minimumScaleFactor = 0.5 117 | lbl.textColor = UIColor.white 118 | lbl.textAlignment = .center 119 | lbl.adjustsFontSizeToFitWidth = true 120 | return lbl 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /Simple-Swift-AI/Simple-Swift-AI/DebugView/OutputTableController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // OutputTableController.swift 3 | // Simple-Swift-AI 4 | // 5 | // Created by Arjun Gupta on 9/27/16. 6 | // Copyright © 2016 ArjunGupta. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import UIKit 11 | 12 | class OutputTableController:UITableViewController { 13 | 14 | var inputs :[[Double]]! 15 | var outputs :[[Double]]! 16 | var layers :[[NeuronA]]! 17 | private let neuronWidth :CGFloat = 35 18 | private let labelHeight :CGFloat = 50 19 | private let labelMargin :CGFloat = 10 20 | private let labelTopMargin :CGFloat = 30 21 | private let labelBottomMargin :CGFloat = 20 22 | private let labelSideMargin :CGFloat = 55 23 | private var cellHeight :CGFloat = 100 24 | 25 | override func viewDidLoad() { 26 | super.viewDidLoad() 27 | 28 | let bbi = UIBarButtonItem(title: "Close", style: .plain, target: self, action: #selector(self.closeButtonHandle)) 29 | self.navigationItem.rightBarButtonItem = bbi 30 | self.navigationItem.rightBarButtonItem?.tintColor = UIColor.black 31 | self.navigationItem.title = "Test results" 32 | } 33 | 34 | override func viewWillAppear(_ animated: Bool) { 35 | super.viewWillAppear(animated) 36 | 37 | let maxNeurons = max(self.inputs[0].count, self.outputs[0].count) 38 | self.cellHeight = self.labelTopMargin + self.labelHeight * CGFloat(maxNeurons) + self.labelMargin * CGFloat(maxNeurons - 1) + self.labelBottomMargin 39 | } 40 | 41 | override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 42 | 43 | return inputs.count 44 | } 45 | 46 | override func numberOfSections(in tableView: UITableView) -> Int { 47 | 48 | return 1 49 | } 50 | 51 | override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 52 | 53 | let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! OutputTableViewCell 54 | 55 | 56 | cell.contentView.backgroundColor = (indexPath.row % 2 == 0) ? UIColor.white : UIColor(red: 0.97, green: 0.97, blue: 0.97, alpha: 1.0) 57 | cell.cellIndexLabel.text = String(indexPath.row) 58 | 59 | if (cell.inputLabels.count == 0) { 60 | 61 | let f = cell.frame 62 | let labelWidth = f.size.width/2 - 2 * self.neuronWidth 63 | cell.contentView.frame = CGRect(x: 0, y: 0, width: f.size.width, height: f.size.height) 64 | 65 | //Init input labels 66 | for i in stride(from:0, to:self.inputs[0].count, by:1) { 67 | 68 | //Input label 69 | let fi = CGRect(x: self.labelSideMargin, y: self.labelTopMargin + CGFloat(i) * self.labelHeight, width: labelWidth, height: self.labelHeight) 70 | let ilbl = self.makeLabel(f: fi) 71 | ilbl.textAlignment = .left 72 | cell.inputLabelView.addSubview(ilbl) 73 | cell.inputLabels.append(ilbl) 74 | 75 | //Input neuron label 76 | var fni = fi 77 | fni.origin.x -= (self.neuronWidth + 10) 78 | fni.size.width = self.neuronWidth 79 | fni.size.height = self.neuronWidth 80 | fni.origin.y = fi.midY - self.neuronWidth/2 81 | let inlbl = self.makesSmallLabel(f: fni) 82 | cell.inputLabelView.addSubview(inlbl) 83 | cell.inputNeuronLabels.append(inlbl) 84 | 85 | } 86 | 87 | //Init output labels 88 | for i in stride(from:0, to:self.outputs[0].count, by:1) { 89 | 90 | let fo = CGRect(x: self.labelSideMargin, y: self.labelTopMargin + CGFloat(i) * self.labelHeight, width: labelWidth, height: self.labelHeight) 91 | let olbl = self.makeLabel(f: fo) 92 | olbl.textAlignment = .left 93 | cell.outputLabelView.addSubview(olbl) 94 | cell.outputLabels.append(olbl) 95 | 96 | //Output neuron label 97 | var fno = fo 98 | fno.origin.x -= (self.neuronWidth + 10) 99 | fno.size.width = self.neuronWidth 100 | fno.size.height = self.neuronWidth 101 | fno.origin.y = fo.midY - self.neuronWidth/2 102 | let onlbl = self.makesSmallLabel(f: fno) 103 | onlbl.backgroundColor = UIColor(red: 1.0, green: 0.39, blue: 0.39, alpha: 1.0) 104 | cell.outputLabelView.addSubview(onlbl) 105 | cell.outputNeuronLabels.append(onlbl) 106 | } 107 | } 108 | 109 | for i in stride(from:0, to:self.inputs[0].count, by:1) { 110 | 111 | //Input label 112 | let ilbl = cell.inputLabels[i] 113 | let inputVal = String(describing: self.inputs[indexPath.row][i]) 114 | ilbl.text = inputVal 115 | 116 | //Input neuron label 117 | let inlbl = cell.inputNeuronLabels[i] 118 | let inputNeuronVal = String(describing: self.layers[0][i].identifier) 119 | inlbl.text = inputNeuronVal 120 | } 121 | 122 | for i in stride(from:0, to:self.outputs[0].count, by:1) { 123 | 124 | //Output label 125 | let olbl = cell.outputLabels[i] 126 | 127 | let outputValue = self.outputs[indexPath.row][i] 128 | let outputVal = String(format:"%f", outputValue) 129 | olbl.text = outputVal 130 | 131 | //Output neuron label 132 | let onlbl = cell.outputNeuronLabels[i] 133 | let outputNeuronVal = String(describing: self.layers[self.layers.count-1][i].identifier) 134 | onlbl.text = outputNeuronVal 135 | } 136 | 137 | return cell 138 | } 139 | 140 | 141 | override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { 142 | 143 | return self.cellHeight 144 | } 145 | 146 | 147 | func closeButtonHandle() { 148 | 149 | self.dismiss(animated: true) { 150 | 151 | } 152 | } 153 | 154 | private func makeLabel(f:CGRect) -> UILabel { 155 | let lb = NeuronInputsView.makeLabel(f: f) 156 | lb.font = UIFont(name: "Helvetica", size: 41) 157 | lb.textColor = UIColor(red: 0.07, green: 0.47, blue: 0.81, alpha: 1.0) 158 | lb.textAlignment = .left 159 | //lb.backgroundColor = UIColor.orange 160 | return lb 161 | } 162 | 163 | private func makesSmallLabel(f:CGRect) -> UILabel { 164 | let lb = NeuronInputsView.makeLabel(f: f) 165 | lb.font = UIFont(name: "Helvetica", size: 17) 166 | lb.textColor = UIColor.white 167 | lb.textAlignment = .center 168 | lb.backgroundColor = UIColor(red: 1.0, green: 0.83, blue: 0.39, alpha: 1.0) 169 | lb.layer.cornerRadius = f.size.width/2 170 | lb.clipsToBounds = true 171 | return lb 172 | } 173 | } 174 | -------------------------------------------------------------------------------- /Simple-Swift-AI/Simple-Swift-AI/DebugView/NetworkViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // NetworkViewController.swift 3 | // Simple-Swift-AI 4 | // 5 | // Created by Arjun Gupta on 9/21/16. 6 | // Copyright © 2016 ArjunGupta. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import UIKit 11 | 12 | class NetworkViewController:UIViewController { 13 | 14 | 15 | @IBOutlet weak var networkContainer : UIView! 16 | @IBOutlet weak var infoLabel : UILabel! 17 | @IBOutlet weak var learningRateLabel : UILabel! 18 | @IBOutlet weak var scrollView : UIScrollView! 19 | @IBOutlet weak var progressBar : UIProgressView! 20 | @IBOutlet weak var trainingProgressLabel: UILabel! 21 | @IBOutlet weak var testInputsButton : UIButton! 22 | 23 | 24 | var neuronViews = [String:NeuronInputsView]() 25 | weak var parentView:UIView? 26 | private let outputTableController = OutputTableController() 27 | private var testInputs :[[Double]]? 28 | private var testOutputs :[[Double]]? 29 | private var testLayers :[[NeuronA]]? 30 | 31 | 32 | class func loadVC(rootVC:UIViewController) -> NetworkViewController { 33 | 34 | let storyboard = UIStoryboard(name: "Main", bundle: nil) 35 | let vc = storyboard.instantiateViewController(withIdentifier: "id_networkVC") as! NetworkViewController 36 | 37 | let navController = UINavigationController(rootViewController: vc) 38 | 39 | rootVC.present(navController, animated: false, completion: nil) 40 | 41 | vc.automaticallyAdjustsScrollViewInsets = false 42 | 43 | return vc 44 | } 45 | 46 | 47 | //MARK:- View Setup 48 | 49 | 50 | 51 | override func viewDidLoad() { 52 | super.viewDidLoad() 53 | 54 | self.navigationItem.title = "Simple Swift AI - FFNN" 55 | } 56 | 57 | 58 | func buildView(layers:[[NeuronA]], learningRate:CGFloat) { 59 | 60 | self.progressBar?.isHidden = false 61 | self.trainingProgressLabel?.isHidden = false 62 | self.testInputsButton?.isHidden = true 63 | 64 | let cSize = self.view.bounds.size 65 | 66 | let topOffset :CGFloat = 55 67 | let vertGap :CGFloat = 15 68 | let horizGap :CGFloat = 25 69 | let wInput :CGFloat = 80 70 | var wOther :CGFloat = (cSize.width - (CGFloat(layers.count + 2) * horizGap) - wInput) / CGFloat(layers.count - 1) 71 | wOther = max(wOther, 265) 72 | 73 | var maxW :CGFloat = 0 74 | var maxH :CGFloat = 0 75 | 76 | var maxNumOfNeurons = 0 77 | for layer in layers { 78 | maxNumOfNeurons = max(maxNumOfNeurons, layer.count) 79 | } 80 | let h :CGFloat = max(123, 123 + 16 * CGFloat(maxNumOfNeurons - 4)) 81 | 82 | for (layerIndex,layer) in layers.enumerated() { 83 | 84 | let w:CGFloat = layerIndex == 0 ? wInput : wOther 85 | let xPos = layerIndex == 0 ? horizGap : horizGap + CGFloat(layerIndex) * (horizGap + w) - (wOther - wInput) 86 | 87 | 88 | //Layer Label 89 | var layerLabelText = "Input" 90 | if (layerIndex == layers.count - 1) { 91 | layerLabelText = "Output" 92 | } 93 | else if (layerIndex == 0) { 94 | layerLabelText = "Input" 95 | } 96 | else { 97 | layerLabelText = "Hidden" 98 | } 99 | let llbFrame = CGRect(x: xPos, y: 25, width: 75, height: 25) 100 | let layerLabel = NeuronInputsView.makeLabel(f: llbFrame) 101 | layerLabel.text = layerLabelText 102 | layerLabel.textAlignment = .left 103 | layerLabel.textColor = UIColor.lightGray 104 | self.scrollView.addSubview(layerLabel) 105 | 106 | 107 | //Neuron Views 108 | for (neuronIndex,neuron) in layer.enumerated() { 109 | 110 | let nf = CGRect(x: xPos, y: topOffset + vertGap + CGFloat(neuronIndex) * (vertGap + h), width: w, height: h) 111 | let neuronView = NeuronInputsView(frame: nf) 112 | neuronView.idLabel.text = String(describing: neuron.identifier ) 113 | self.scrollView.addSubview(neuronView) 114 | 115 | var theInputs = [InputA]() 116 | for key in neuron.inputs.keys { 117 | let val = neuron.inputs[key]! 118 | theInputs.append(val) 119 | } 120 | neuronView.buildInputs(inputs:theInputs) 121 | 122 | self.neuronViews[neuron.identifier] = neuronView 123 | 124 | if (neuronView.frame.maxX > maxW) { 125 | maxW = neuronView.frame.maxX 126 | } 127 | if (neuronView.frame.maxY > maxH) { 128 | maxH = neuronView.frame.maxY 129 | } 130 | } 131 | } 132 | 133 | let sz = CGSize(width: maxW + 20, height: maxH + 20) 134 | self.scrollView.contentSize = sz 135 | 136 | let numInputs = layers[0].count 137 | let numOutputs = layers[layers.count - 1].count 138 | let numHidden = layers.count - 2 139 | 140 | let inputStr = numInputs > 1 ? "Inputs" : "Input" 141 | let outputStr = numOutputs > 1 ? "Outputs" : "Output" 142 | let hiddenStr = numHidden > 1 ? "layers" : "layer" 143 | self.infoLabel.text = "\(numInputs) \(inputStr) and \(numOutputs) \(outputStr) | \(numHidden) Hidden \(hiddenStr)" 144 | self.learningRateLabel.text = String(describing: learningRate) 145 | 146 | } 147 | 148 | 149 | 150 | //MARK:- View Updating 151 | 152 | 153 | 154 | func updateNetworkView(layers:[[NeuronA]], percentComplete:CGFloat) { 155 | 156 | DispatchQueue.main.async { [weak self] in 157 | guard let theSelf = self else { return } 158 | 159 | for (_,layer) in layers.enumerated() { 160 | for (_,neuron) in layer.enumerated() { 161 | let neuronView = theSelf.neuronViews[neuron.identifier]! 162 | if neuron.inputs.count > 0 { 163 | for inputKey in neuron.inputs.keys { 164 | let inputLabel = neuronView.inputLabels[inputKey] 165 | let input = neuron.inputs[inputKey]! 166 | 167 | inputLabel?.text = inputKey + " : " + String(input.weight) 168 | if let theBias = neuron.bias { 169 | neuronView.biasLabel.text = "BIAS " + String(theBias) 170 | } 171 | } 172 | } 173 | else { 174 | //Input neuron 175 | } 176 | } 177 | } 178 | 179 | //Progress bar 180 | let progress = Float(percentComplete) 181 | theSelf.progressBar.setProgress(progress, animated: true) 182 | } 183 | } 184 | 185 | 186 | 187 | //MARK:- Output View 188 | 189 | 190 | 191 | func displayOutputView(inputs:[[Double]], outputs:[[Double]], layers:[[NeuronA]]) { 192 | 193 | if inputs.count != outputs.count { return } 194 | 195 | self.testInputs = inputs 196 | self.testOutputs = outputs 197 | self.testLayers = layers 198 | 199 | self.deployTestOutputView() 200 | } 201 | 202 | 203 | private func deployTestOutputView() { 204 | 205 | guard let theTestInputs = self.testInputs else { return } 206 | guard let theTestOutputs = self.testOutputs else { return } 207 | guard let theTestLayers = self.testLayers else { return } 208 | 209 | let storyboard = UIStoryboard(name: "Main", bundle: nil) 210 | let vc = storyboard.instantiateViewController(withIdentifier: "id_outputTable") as! OutputTableController 211 | vc.inputs = theTestInputs 212 | vc.outputs = theTestOutputs 213 | vc.layers = theTestLayers 214 | 215 | let navController = UINavigationController(rootViewController: vc) 216 | 217 | self.present(navController, animated: true) { 218 | 219 | self.progressBar.isHidden = true 220 | self.trainingProgressLabel.isHidden = true 221 | self.testInputsButton.isHidden = false 222 | 223 | } 224 | 225 | } 226 | 227 | @IBAction func testInputsButtonHandle(_ sender: AnyObject) { 228 | 229 | self.deployTestOutputView() 230 | } 231 | 232 | 233 | } 234 | -------------------------------------------------------------------------------- /Simple-Swift-AI/Simple-Swift-AI/Network/NetworkA.swift: -------------------------------------------------------------------------------- 1 | // 2 | // NetworkA.swift 3 | // Simple-Swift-AI 4 | // 5 | // Created by Arjun Gupta on 7/29/16. 6 | // Copyright © 2016 ArjunGupta. All rights reserved. 7 | // 8 | 9 | import Accelerate 10 | import Foundation 11 | import UIKit 12 | 13 | class NetworkA { 14 | 15 | var learningRate :Double = 0.5 16 | var layers = [[NeuronA]]() 17 | private var networkVC :NetworkViewController? 18 | private var persistUtil :CoreDataUtil? 19 | private var persistanceID :String? = nil 20 | 21 | 22 | init(rootVC:UIViewController? = nil, persistanceID:String? = nil) { 23 | if let theRootVC = rootVC { 24 | self.networkVC = NetworkViewController.loadVC(rootVC:theRootVC) 25 | } 26 | if let _ = persistanceID { 27 | self.persistanceID = persistanceID 28 | self.persistUtil = CoreDataUtil() 29 | } 30 | } 31 | 32 | 33 | func insert(neuron:NeuronA, layerNum:Int) { 34 | if (self.layers.count <= layerNum) { 35 | while self.layers.count <= layerNum { 36 | let layer = [NeuronA]() 37 | self.layers.append(layer) 38 | } 39 | } 40 | self.layers[layerNum].append(neuron) 41 | } 42 | 43 | 44 | //Assign weights to begin 45 | func connectNeuronsWithRandomizedWeights() { 46 | 47 | //Check persisted weights 48 | var persistedWeights:[[[String:Double]]]? 49 | if let thePersistantUtil = self.persistUtil { 50 | 51 | if let thePersistedWeights = thePersistantUtil.fetchExistingWeights(persistanceID:self.persistanceID!) { 52 | 53 | func checkLayerCompatibility() -> Bool { 54 | var compatible = true 55 | if (self.layers.count != thePersistedWeights.count) { 56 | compatible = false 57 | } 58 | else { 59 | for (layerIndex, layer) in self.layers.enumerated() { 60 | if layer.count != thePersistedWeights[layerIndex].count { 61 | compatible = false 62 | break 63 | } 64 | } 65 | } 66 | return compatible 67 | } 68 | 69 | if (checkLayerCompatibility()) { 70 | DebugLog("Using persisted weights. Persistance ID : \(self.persistanceID)") 71 | persistedWeights = thePersistedWeights 72 | } 73 | } 74 | } 75 | 76 | for (index,neuronLayer) in self.layers.enumerated() { 77 | 78 | if index == 0 { continue } 79 | 80 | for (nIndex,neuron) in neuronLayer.enumerated() { 81 | var neuronInputs = [InputA]() 82 | 83 | 84 | for (prevNeuronIndex,prevNeuron) in self.layers[index-1].enumerated() { 85 | 86 | var inputWt:Double? 87 | 88 | if let thePersistedWeights = persistedWeights { 89 | inputWt = thePersistedWeights[index][nIndex][prevNeuron.identifier] 90 | } 91 | 92 | if (inputWt == nil) { 93 | //DebugLog("Random assigned weights for : \(neuron.identifier) -->") 94 | let randomWeight:Double = Double(arc4random_uniform(15) + 45) * 0.01 95 | inputWt = randomWeight 96 | } 97 | 98 | let input = InputA(neuron: prevNeuron, weight: inputWt!) 99 | input.indexInLayer = prevNeuronIndex 100 | //DebugLog("\(input.neuron?.identifier) : \(randomWeight)") 101 | 102 | neuronInputs.append(input) 103 | } 104 | neuron.attachInputs(inputs: neuronInputs) 105 | } 106 | } 107 | 108 | self.networkVC?.buildView(layers: self.layers, learningRate: CGFloat(self.learningRate)) 109 | } 110 | 111 | 112 | func checkCompatibility(input:[Double],output:[Double]?) -> Bool { 113 | //Fail safe check 114 | 115 | var trainingSetCompatible = true 116 | if (input.count != self.layers[0].count) { 117 | DebugLog("ERROR: Input neuron count mismatch with training inputs. Expected \(self.layers[0].count). Got \(input.count)") 118 | trainingSetCompatible = false 119 | } 120 | if let theOutput = output { 121 | if (theOutput.count != self.layers.last!.count) { 122 | DebugLog("ERROR: Out neuron count mismatch with training outputs. Expected \(self.layers.last!.count) Got \(theOutput.count)") 123 | trainingSetCompatible = false 124 | } 125 | } 126 | return trainingSetCompatible 127 | } 128 | 129 | 130 | 131 | func trainNetwork(trainingSets:[(input:[Double],output:[Double])], completionBlock: ((Bool,CGFloat) -> Void)?) { 132 | 133 | DispatchQueue.global(qos: .userInitiated).async { [weak self] in 134 | 135 | guard let theSelf = self else { 136 | DebugLog("ERROR: Self cannot be nil!") 137 | return 138 | } 139 | 140 | var currentPercentCompletion:CGFloat = 0 141 | 142 | for (ioSetIndex, ioSet) in trainingSets.enumerated() { 143 | 144 | if (theSelf.checkCompatibility(input:ioSet.input, output:ioSet.output) == false) { break } 145 | 146 | ///////DebugLog("setIndex : \(setIndex)") 147 | 148 | //MARK:- Forward pass 149 | for (layerIndex,layer) in theSelf.layers.enumerated() { 150 | 151 | for (neuronIndex,neuron) in layer.enumerated() { 152 | if (layerIndex == 0) { 153 | neuron.output = ioSet.input[neuronIndex] 154 | } 155 | else { 156 | neuron.calculateOutput() 157 | } 158 | } 159 | } 160 | 161 | 162 | //MARK:- Output error 163 | /* 164 | var totalError:Double = 0 165 | for (setIndex,targetOutput) in ioSet.output.enumerated() { 166 | 167 | let outputLayerNeurons = theSelf.layers.last! 168 | let outputNeuron = outputLayerNeurons[setIndex] 169 | let outputError = 0.5 * pow((targetOutput - outputNeuron.output!), 2) 170 | totalError += outputError 171 | 172 | //DebugLog("\(outputNeuron.identifier) output:\(outputNeuron.output!) expOutput:\(targetOutput), error : \(outputError)") 173 | } 174 | DebugLog("TotalError : \(totalError.roundToDigits(digits: 5))") 175 | */ 176 | 177 | 178 | //MARK:- Backward pass 179 | var newWeights = [NeuronA:[(String,Double)]]() 180 | var layersErrorOByNetO = [[NeuronA:Double]]() 181 | var currentLayerCount = 0 182 | 183 | for i in stride(from: theSelf.layers.count - 1, through: 1, by: -1) { 184 | 185 | var aLayerErrorOByNetO = [NeuronA:Double]() 186 | let alayer = theSelf.layers[i] 187 | for (neuronIndex, aNeuron) in alayer.enumerated() { 188 | 189 | var newInputWeights = [(String,Double)]() 190 | 191 | var deltaO:Double = 0 192 | if (i == theSelf.layers.count - 1) { //Output layer 193 | let targetOutput = ioSet.output[neuronIndex] 194 | let deltaErrorByNet = -(targetOutput - aNeuron.output!) * aNeuron.output! * (1 - aNeuron.output!) 195 | aLayerErrorOByNetO[aNeuron] = deltaErrorByNet 196 | deltaO = deltaErrorByNet 197 | } 198 | else { 199 | var deltaErrorOByNetO:Double = 0 200 | let theLayerSigmaOutputs = layersErrorOByNetO[currentLayerCount - 1] 201 | for outputNeuron in theLayerSigmaOutputs.keys { 202 | 203 | let connectedInput = outputNeuron.inputs[aNeuron.identifier]! 204 | deltaErrorOByNetO += theLayerSigmaOutputs[outputNeuron]! * connectedInput.weight 205 | 206 | } 207 | 208 | //Store this in an array for use in deeper layers 209 | aLayerErrorOByNetO[aNeuron] = deltaErrorOByNetO 210 | 211 | deltaErrorOByNetO = deltaErrorOByNetO * aNeuron.output!*(1 - aNeuron.output!) 212 | 213 | deltaO = deltaErrorOByNetO 214 | } 215 | 216 | for input in aNeuron.inputs.values { 217 | 218 | 219 | let dTotalError_by_dOutputWeight = deltaO * input.value! 220 | 221 | let newWeight = input.weight - (theSelf.learningRate * dTotalError_by_dOutputWeight) 222 | 223 | //DebugLog("\(aNeuron.identifier) newWeight\(input.neuron?.identifier) : \(newWeight)") 224 | 225 | let inputWtDict = (input.neuron!.identifier,newWeight) 226 | newInputWeights.append(inputWtDict) 227 | } 228 | newWeights[aNeuron] = newInputWeights 229 | } 230 | 231 | layersErrorOByNetO.append(aLayerErrorOByNetO) 232 | currentLayerCount += 1 233 | } 234 | 235 | for aNeuron in newWeights.keys { 236 | 237 | let newNeuronInputWeights = newWeights[aNeuron] 238 | for tp in newNeuronInputWeights! { 239 | aNeuron.inputs[tp.0]!.weight = tp.1 240 | } 241 | } 242 | 243 | //Completion block 244 | let cutOff:CGFloat = 0.005 //Reducing number of UI updates 245 | let percentComplete = CGFloat(ioSetIndex) / CGFloat(trainingSets.count) 246 | if (percentComplete - currentPercentCompletion > cutOff || percentComplete > 0.99) { 247 | currentPercentCompletion += cutOff 248 | 249 | theSelf.networkVC?.updateNetworkView(layers: theSelf.layers, percentComplete:percentComplete) 250 | 251 | //DispatchQueue.main.async { 252 | // completionBlock!(false, percentComplete) 253 | //} 254 | } 255 | } 256 | 257 | 258 | DispatchQueue.main.async { 259 | 260 | theSelf.persistUtil?.persistNewWeights(neurons: theSelf.layers, persistanceID: theSelf.persistanceID!) 261 | 262 | completionBlock!(true, 100.0) 263 | } 264 | } 265 | 266 | } 267 | 268 | 269 | //Use this for testing the FFNN after the training 270 | 271 | 272 | func getOutputFor(inputs:[[Double]]) -> [[Double]] { 273 | 274 | var outputs = [[Double]]() 275 | 276 | for (inputIndex,inputSet) in inputs.enumerated() { 277 | 278 | DebugLog("^^^ Test result \(inputIndex)-->") 279 | 280 | if (self.checkCompatibility(input:inputSet, output:nil) == false) { break } 281 | 282 | var output = [Double]() 283 | 284 | for (index,layer) in self.layers.enumerated() { 285 | 286 | if index == 0 { 287 | for (neuronIndex,neuron) in layer.enumerated() { 288 | neuron.output = inputSet[neuronIndex] 289 | neuron.calculateOutput() 290 | } 291 | } 292 | else { 293 | for neuron in layer { 294 | neuron.calculateOutput() 295 | if (index == self.layers.count - 1) { 296 | DebugLog("\(neuron.identifier) output : \(neuron.output)") 297 | 298 | output.append(neuron.output!) 299 | } 300 | } 301 | } 302 | } 303 | 304 | outputs.append(output) 305 | 306 | DebugLog("--------") 307 | } 308 | 309 | self.networkVC?.displayOutputView(inputs: inputs, outputs: outputs, layers:self.layers) 310 | 311 | return outputs 312 | } 313 | 314 | 315 | } 316 | -------------------------------------------------------------------------------- /Simple-Swift-AI/Simple-Swift-AI.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 67B9AF981D9F030C0058E2BA /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67B9AF971D9F030C0058E2BA /* AppDelegate.swift */; }; 11 | 67B9AF9A1D9F030C0058E2BA /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67B9AF991D9F030C0058E2BA /* ViewController.swift */; }; 12 | 67B9AF9D1D9F030C0058E2BA /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 67B9AF9B1D9F030C0058E2BA /* Main.storyboard */; }; 13 | 67B9AFA01D9F030C0058E2BA /* Simple_Swift_AI.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = 67B9AF9E1D9F030C0058E2BA /* Simple_Swift_AI.xcdatamodeld */; }; 14 | 67B9AFA21D9F030C0058E2BA /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 67B9AFA11D9F030C0058E2BA /* Assets.xcassets */; }; 15 | 67B9AFA51D9F030C0058E2BA /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 67B9AFA31D9F030C0058E2BA /* LaunchScreen.storyboard */; }; 16 | 67B9AFB91D9F03990058E2BA /* ActivationFunctions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67B9AFAD1D9F03990058E2BA /* ActivationFunctions.swift */; }; 17 | 67B9AFBA1D9F03990058E2BA /* AutoNetworkBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67B9AFAE1D9F03990058E2BA /* AutoNetworkBuilder.swift */; }; 18 | 67B9AFBB1D9F03990058E2BA /* InputA.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67B9AFAF1D9F03990058E2BA /* InputA.swift */; }; 19 | 67B9AFBC1D9F03990058E2BA /* NetworkA.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67B9AFB01D9F03990058E2BA /* NetworkA.swift */; }; 20 | 67B9AFBD1D9F03990058E2BA /* NeuronA.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67B9AFB11D9F03990058E2BA /* NeuronA.swift */; }; 21 | 67B9AFC01D9F03990058E2BA /* Utils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67B9AFB81D9F03990058E2BA /* Utils.swift */; }; 22 | 67B9AFC31D9F03DE0058E2BA /* AI_System_XOR.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67B9AFC21D9F03DE0058E2BA /* AI_System_XOR.swift */; }; 23 | 67B9AFC91D9F042B0058E2BA /* NetworkViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67B9AFC51D9F042B0058E2BA /* NetworkViewController.swift */; }; 24 | 67B9AFCA1D9F042B0058E2BA /* NeuronInputsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67B9AFC61D9F042B0058E2BA /* NeuronInputsView.swift */; }; 25 | 67B9AFCB1D9F042B0058E2BA /* OutputTableController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67B9AFC71D9F042B0058E2BA /* OutputTableController.swift */; }; 26 | 67B9AFCC1D9F042B0058E2BA /* OutputTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67B9AFC81D9F042B0058E2BA /* OutputTableViewCell.swift */; }; 27 | 67B9AFEF1DA1EF410058E2BA /* CoreDataUtil.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67B9AFEE1DA1EF410058E2BA /* CoreDataUtil.swift */; }; 28 | /* End PBXBuildFile section */ 29 | 30 | /* Begin PBXFileReference section */ 31 | 67B9AF941D9F030C0058E2BA /* Simple-Swift-AI.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Simple-Swift-AI.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 32 | 67B9AF971D9F030C0058E2BA /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 33 | 67B9AF991D9F030C0058E2BA /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; 34 | 67B9AF9C1D9F030C0058E2BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 35 | 67B9AF9F1D9F030C0058E2BA /* Simple_Swift_AI.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = Simple_Swift_AI.xcdatamodel; sourceTree = ""; }; 36 | 67B9AFA11D9F030C0058E2BA /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 37 | 67B9AFA41D9F030C0058E2BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 38 | 67B9AFA61D9F030C0058E2BA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 39 | 67B9AFAD1D9F03990058E2BA /* ActivationFunctions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ActivationFunctions.swift; sourceTree = ""; }; 40 | 67B9AFAE1D9F03990058E2BA /* AutoNetworkBuilder.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AutoNetworkBuilder.swift; sourceTree = ""; }; 41 | 67B9AFAF1D9F03990058E2BA /* InputA.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = InputA.swift; sourceTree = ""; }; 42 | 67B9AFB01D9F03990058E2BA /* NetworkA.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NetworkA.swift; sourceTree = ""; }; 43 | 67B9AFB11D9F03990058E2BA /* NeuronA.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NeuronA.swift; sourceTree = ""; }; 44 | 67B9AFB81D9F03990058E2BA /* Utils.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Utils.swift; sourceTree = ""; }; 45 | 67B9AFC21D9F03DE0058E2BA /* AI_System_XOR.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AI_System_XOR.swift; sourceTree = ""; }; 46 | 67B9AFC51D9F042B0058E2BA /* NetworkViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NetworkViewController.swift; sourceTree = ""; }; 47 | 67B9AFC61D9F042B0058E2BA /* NeuronInputsView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NeuronInputsView.swift; sourceTree = ""; }; 48 | 67B9AFC71D9F042B0058E2BA /* OutputTableController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OutputTableController.swift; sourceTree = ""; }; 49 | 67B9AFC81D9F042B0058E2BA /* OutputTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OutputTableViewCell.swift; sourceTree = ""; }; 50 | 67B9AFEE1DA1EF410058E2BA /* CoreDataUtil.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = CoreDataUtil.swift; path = ../Utils/CoreDataUtil.swift; sourceTree = ""; }; 51 | /* End PBXFileReference section */ 52 | 53 | /* Begin PBXFrameworksBuildPhase section */ 54 | 67B9AF911D9F030C0058E2BA /* Frameworks */ = { 55 | isa = PBXFrameworksBuildPhase; 56 | buildActionMask = 2147483647; 57 | files = ( 58 | ); 59 | runOnlyForDeploymentPostprocessing = 0; 60 | }; 61 | /* End PBXFrameworksBuildPhase section */ 62 | 63 | /* Begin PBXGroup section */ 64 | 67B9AF8B1D9F030C0058E2BA = { 65 | isa = PBXGroup; 66 | children = ( 67 | 67B9AF961D9F030C0058E2BA /* Simple-Swift-AI */, 68 | 67B9AF951D9F030C0058E2BA /* Products */, 69 | ); 70 | sourceTree = ""; 71 | }; 72 | 67B9AF951D9F030C0058E2BA /* Products */ = { 73 | isa = PBXGroup; 74 | children = ( 75 | 67B9AF941D9F030C0058E2BA /* Simple-Swift-AI.app */, 76 | ); 77 | name = Products; 78 | sourceTree = ""; 79 | }; 80 | 67B9AF961D9F030C0058E2BA /* Simple-Swift-AI */ = { 81 | isa = PBXGroup; 82 | children = ( 83 | 67B9AF971D9F030C0058E2BA /* AppDelegate.swift */, 84 | 67B9AF991D9F030C0058E2BA /* ViewController.swift */, 85 | 67B9AFC11D9F03DE0058E2BA /* Examples */, 86 | 67B9AFAC1D9F03990058E2BA /* Network */, 87 | 67B9AFC41D9F042B0058E2BA /* DebugView */, 88 | 67B9AFF01DA1FADF0058E2BA /* Persistance */, 89 | 67B9AFB71D9F03990058E2BA /* Utils */, 90 | 67B9AF9B1D9F030C0058E2BA /* Main.storyboard */, 91 | 67B9AFA11D9F030C0058E2BA /* Assets.xcassets */, 92 | 67B9AFA31D9F030C0058E2BA /* LaunchScreen.storyboard */, 93 | 67B9AFA61D9F030C0058E2BA /* Info.plist */, 94 | 67B9AF9E1D9F030C0058E2BA /* Simple_Swift_AI.xcdatamodeld */, 95 | ); 96 | path = "Simple-Swift-AI"; 97 | sourceTree = ""; 98 | }; 99 | 67B9AFAC1D9F03990058E2BA /* Network */ = { 100 | isa = PBXGroup; 101 | children = ( 102 | 67B9AFAE1D9F03990058E2BA /* AutoNetworkBuilder.swift */, 103 | 67B9AFB01D9F03990058E2BA /* NetworkA.swift */, 104 | 67B9AFAF1D9F03990058E2BA /* InputA.swift */, 105 | 67B9AFB11D9F03990058E2BA /* NeuronA.swift */, 106 | 67B9AFAD1D9F03990058E2BA /* ActivationFunctions.swift */, 107 | ); 108 | path = Network; 109 | sourceTree = ""; 110 | }; 111 | 67B9AFB71D9F03990058E2BA /* Utils */ = { 112 | isa = PBXGroup; 113 | children = ( 114 | 67B9AFB81D9F03990058E2BA /* Utils.swift */, 115 | ); 116 | path = Utils; 117 | sourceTree = ""; 118 | }; 119 | 67B9AFC11D9F03DE0058E2BA /* Examples */ = { 120 | isa = PBXGroup; 121 | children = ( 122 | 67B9AFC21D9F03DE0058E2BA /* AI_System_XOR.swift */, 123 | ); 124 | path = Examples; 125 | sourceTree = ""; 126 | }; 127 | 67B9AFC41D9F042B0058E2BA /* DebugView */ = { 128 | isa = PBXGroup; 129 | children = ( 130 | 67B9AFC51D9F042B0058E2BA /* NetworkViewController.swift */, 131 | 67B9AFC61D9F042B0058E2BA /* NeuronInputsView.swift */, 132 | 67B9AFC71D9F042B0058E2BA /* OutputTableController.swift */, 133 | 67B9AFC81D9F042B0058E2BA /* OutputTableViewCell.swift */, 134 | ); 135 | path = DebugView; 136 | sourceTree = ""; 137 | }; 138 | 67B9AFF01DA1FADF0058E2BA /* Persistance */ = { 139 | isa = PBXGroup; 140 | children = ( 141 | 67B9AFEE1DA1EF410058E2BA /* CoreDataUtil.swift */, 142 | ); 143 | name = Persistance; 144 | path = DebugView; 145 | sourceTree = ""; 146 | }; 147 | /* End PBXGroup section */ 148 | 149 | /* Begin PBXNativeTarget section */ 150 | 67B9AF931D9F030C0058E2BA /* Simple-Swift-AI */ = { 151 | isa = PBXNativeTarget; 152 | buildConfigurationList = 67B9AFA91D9F030C0058E2BA /* Build configuration list for PBXNativeTarget "Simple-Swift-AI" */; 153 | buildPhases = ( 154 | 67B9AF901D9F030C0058E2BA /* Sources */, 155 | 67B9AF911D9F030C0058E2BA /* Frameworks */, 156 | 67B9AF921D9F030C0058E2BA /* Resources */, 157 | ); 158 | buildRules = ( 159 | ); 160 | dependencies = ( 161 | ); 162 | name = "Simple-Swift-AI"; 163 | productName = "Simple-Swift-AI"; 164 | productReference = 67B9AF941D9F030C0058E2BA /* Simple-Swift-AI.app */; 165 | productType = "com.apple.product-type.application"; 166 | }; 167 | /* End PBXNativeTarget section */ 168 | 169 | /* Begin PBXProject section */ 170 | 67B9AF8C1D9F030C0058E2BA /* Project object */ = { 171 | isa = PBXProject; 172 | attributes = { 173 | LastSwiftUpdateCheck = 0800; 174 | LastUpgradeCheck = 0800; 175 | ORGANIZATIONNAME = "Arjun Gupta"; 176 | TargetAttributes = { 177 | 67B9AF931D9F030C0058E2BA = { 178 | CreatedOnToolsVersion = 8.0; 179 | DevelopmentTeam = W9K648WB82; 180 | ProvisioningStyle = Automatic; 181 | }; 182 | }; 183 | }; 184 | buildConfigurationList = 67B9AF8F1D9F030C0058E2BA /* Build configuration list for PBXProject "Simple-Swift-AI" */; 185 | compatibilityVersion = "Xcode 3.2"; 186 | developmentRegion = English; 187 | hasScannedForEncodings = 0; 188 | knownRegions = ( 189 | en, 190 | Base, 191 | ); 192 | mainGroup = 67B9AF8B1D9F030C0058E2BA; 193 | productRefGroup = 67B9AF951D9F030C0058E2BA /* Products */; 194 | projectDirPath = ""; 195 | projectRoot = ""; 196 | targets = ( 197 | 67B9AF931D9F030C0058E2BA /* Simple-Swift-AI */, 198 | ); 199 | }; 200 | /* End PBXProject section */ 201 | 202 | /* Begin PBXResourcesBuildPhase section */ 203 | 67B9AF921D9F030C0058E2BA /* Resources */ = { 204 | isa = PBXResourcesBuildPhase; 205 | buildActionMask = 2147483647; 206 | files = ( 207 | 67B9AFA51D9F030C0058E2BA /* LaunchScreen.storyboard in Resources */, 208 | 67B9AFA21D9F030C0058E2BA /* Assets.xcassets in Resources */, 209 | 67B9AF9D1D9F030C0058E2BA /* Main.storyboard in Resources */, 210 | ); 211 | runOnlyForDeploymentPostprocessing = 0; 212 | }; 213 | /* End PBXResourcesBuildPhase section */ 214 | 215 | /* Begin PBXSourcesBuildPhase section */ 216 | 67B9AF901D9F030C0058E2BA /* Sources */ = { 217 | isa = PBXSourcesBuildPhase; 218 | buildActionMask = 2147483647; 219 | files = ( 220 | 67B9AFEF1DA1EF410058E2BA /* CoreDataUtil.swift in Sources */, 221 | 67B9AFBD1D9F03990058E2BA /* NeuronA.swift in Sources */, 222 | 67B9AF9A1D9F030C0058E2BA /* ViewController.swift in Sources */, 223 | 67B9AFC91D9F042B0058E2BA /* NetworkViewController.swift in Sources */, 224 | 67B9AF981D9F030C0058E2BA /* AppDelegate.swift in Sources */, 225 | 67B9AFBC1D9F03990058E2BA /* NetworkA.swift in Sources */, 226 | 67B9AFC01D9F03990058E2BA /* Utils.swift in Sources */, 227 | 67B9AFBB1D9F03990058E2BA /* InputA.swift in Sources */, 228 | 67B9AFC31D9F03DE0058E2BA /* AI_System_XOR.swift in Sources */, 229 | 67B9AFA01D9F030C0058E2BA /* Simple_Swift_AI.xcdatamodeld in Sources */, 230 | 67B9AFBA1D9F03990058E2BA /* AutoNetworkBuilder.swift in Sources */, 231 | 67B9AFCA1D9F042B0058E2BA /* NeuronInputsView.swift in Sources */, 232 | 67B9AFCB1D9F042B0058E2BA /* OutputTableController.swift in Sources */, 233 | 67B9AFCC1D9F042B0058E2BA /* OutputTableViewCell.swift in Sources */, 234 | 67B9AFB91D9F03990058E2BA /* ActivationFunctions.swift in Sources */, 235 | ); 236 | runOnlyForDeploymentPostprocessing = 0; 237 | }; 238 | /* End PBXSourcesBuildPhase section */ 239 | 240 | /* Begin PBXVariantGroup section */ 241 | 67B9AF9B1D9F030C0058E2BA /* Main.storyboard */ = { 242 | isa = PBXVariantGroup; 243 | children = ( 244 | 67B9AF9C1D9F030C0058E2BA /* Base */, 245 | ); 246 | name = Main.storyboard; 247 | sourceTree = ""; 248 | }; 249 | 67B9AFA31D9F030C0058E2BA /* LaunchScreen.storyboard */ = { 250 | isa = PBXVariantGroup; 251 | children = ( 252 | 67B9AFA41D9F030C0058E2BA /* Base */, 253 | ); 254 | name = LaunchScreen.storyboard; 255 | sourceTree = ""; 256 | }; 257 | /* End PBXVariantGroup section */ 258 | 259 | /* Begin XCBuildConfiguration section */ 260 | 67B9AFA71D9F030C0058E2BA /* Debug */ = { 261 | isa = XCBuildConfiguration; 262 | buildSettings = { 263 | ALWAYS_SEARCH_USER_PATHS = NO; 264 | CLANG_ANALYZER_NONNULL = YES; 265 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 266 | CLANG_CXX_LIBRARY = "libc++"; 267 | CLANG_ENABLE_MODULES = YES; 268 | CLANG_ENABLE_OBJC_ARC = YES; 269 | CLANG_WARN_BOOL_CONVERSION = YES; 270 | CLANG_WARN_CONSTANT_CONVERSION = YES; 271 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 272 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 273 | CLANG_WARN_EMPTY_BODY = YES; 274 | CLANG_WARN_ENUM_CONVERSION = YES; 275 | CLANG_WARN_INFINITE_RECURSION = YES; 276 | CLANG_WARN_INT_CONVERSION = YES; 277 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 278 | CLANG_WARN_SUSPICIOUS_MOVES = YES; 279 | CLANG_WARN_UNREACHABLE_CODE = YES; 280 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 281 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 282 | COPY_PHASE_STRIP = NO; 283 | DEBUG_INFORMATION_FORMAT = dwarf; 284 | ENABLE_STRICT_OBJC_MSGSEND = YES; 285 | ENABLE_TESTABILITY = YES; 286 | GCC_C_LANGUAGE_STANDARD = gnu99; 287 | GCC_DYNAMIC_NO_PIC = NO; 288 | GCC_NO_COMMON_BLOCKS = YES; 289 | GCC_OPTIMIZATION_LEVEL = 0; 290 | GCC_PREPROCESSOR_DEFINITIONS = ( 291 | "DEBUG=1", 292 | "$(inherited)", 293 | ); 294 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 295 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 296 | GCC_WARN_UNDECLARED_SELECTOR = YES; 297 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 298 | GCC_WARN_UNUSED_FUNCTION = YES; 299 | GCC_WARN_UNUSED_VARIABLE = YES; 300 | IPHONEOS_DEPLOYMENT_TARGET = 10.0; 301 | MTL_ENABLE_DEBUG_INFO = YES; 302 | ONLY_ACTIVE_ARCH = YES; 303 | SDKROOT = iphoneos; 304 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 305 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 306 | TARGETED_DEVICE_FAMILY = "1,2"; 307 | }; 308 | name = Debug; 309 | }; 310 | 67B9AFA81D9F030C0058E2BA /* Release */ = { 311 | isa = XCBuildConfiguration; 312 | buildSettings = { 313 | ALWAYS_SEARCH_USER_PATHS = NO; 314 | CLANG_ANALYZER_NONNULL = YES; 315 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 316 | CLANG_CXX_LIBRARY = "libc++"; 317 | CLANG_ENABLE_MODULES = YES; 318 | CLANG_ENABLE_OBJC_ARC = YES; 319 | CLANG_WARN_BOOL_CONVERSION = YES; 320 | CLANG_WARN_CONSTANT_CONVERSION = YES; 321 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 322 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 323 | CLANG_WARN_EMPTY_BODY = YES; 324 | CLANG_WARN_ENUM_CONVERSION = YES; 325 | CLANG_WARN_INFINITE_RECURSION = YES; 326 | CLANG_WARN_INT_CONVERSION = YES; 327 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 328 | CLANG_WARN_SUSPICIOUS_MOVES = YES; 329 | CLANG_WARN_UNREACHABLE_CODE = YES; 330 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 331 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 332 | COPY_PHASE_STRIP = NO; 333 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 334 | ENABLE_NS_ASSERTIONS = NO; 335 | ENABLE_STRICT_OBJC_MSGSEND = YES; 336 | GCC_C_LANGUAGE_STANDARD = gnu99; 337 | GCC_NO_COMMON_BLOCKS = YES; 338 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 339 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 340 | GCC_WARN_UNDECLARED_SELECTOR = YES; 341 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 342 | GCC_WARN_UNUSED_FUNCTION = YES; 343 | GCC_WARN_UNUSED_VARIABLE = YES; 344 | IPHONEOS_DEPLOYMENT_TARGET = 10.0; 345 | MTL_ENABLE_DEBUG_INFO = NO; 346 | SDKROOT = iphoneos; 347 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 348 | TARGETED_DEVICE_FAMILY = "1,2"; 349 | VALIDATE_PRODUCT = YES; 350 | }; 351 | name = Release; 352 | }; 353 | 67B9AFAA1D9F030C0058E2BA /* Debug */ = { 354 | isa = XCBuildConfiguration; 355 | buildSettings = { 356 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 357 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 358 | DEVELOPMENT_TEAM = W9K648WB82; 359 | INFOPLIST_FILE = "Simple-Swift-AI/Info.plist"; 360 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 361 | PRODUCT_BUNDLE_IDENTIFIER = "Arjun-Gupta.Simple-Swift-AI"; 362 | PRODUCT_NAME = "$(TARGET_NAME)"; 363 | SWIFT_VERSION = 3.0; 364 | }; 365 | name = Debug; 366 | }; 367 | 67B9AFAB1D9F030C0058E2BA /* Release */ = { 368 | isa = XCBuildConfiguration; 369 | buildSettings = { 370 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 371 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 372 | DEVELOPMENT_TEAM = W9K648WB82; 373 | INFOPLIST_FILE = "Simple-Swift-AI/Info.plist"; 374 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 375 | PRODUCT_BUNDLE_IDENTIFIER = "Arjun-Gupta.Simple-Swift-AI"; 376 | PRODUCT_NAME = "$(TARGET_NAME)"; 377 | SWIFT_VERSION = 3.0; 378 | }; 379 | name = Release; 380 | }; 381 | /* End XCBuildConfiguration section */ 382 | 383 | /* Begin XCConfigurationList section */ 384 | 67B9AF8F1D9F030C0058E2BA /* Build configuration list for PBXProject "Simple-Swift-AI" */ = { 385 | isa = XCConfigurationList; 386 | buildConfigurations = ( 387 | 67B9AFA71D9F030C0058E2BA /* Debug */, 388 | 67B9AFA81D9F030C0058E2BA /* Release */, 389 | ); 390 | defaultConfigurationIsVisible = 0; 391 | defaultConfigurationName = Release; 392 | }; 393 | 67B9AFA91D9F030C0058E2BA /* Build configuration list for PBXNativeTarget "Simple-Swift-AI" */ = { 394 | isa = XCConfigurationList; 395 | buildConfigurations = ( 396 | 67B9AFAA1D9F030C0058E2BA /* Debug */, 397 | 67B9AFAB1D9F030C0058E2BA /* Release */, 398 | ); 399 | defaultConfigurationIsVisible = 0; 400 | defaultConfigurationName = Release; 401 | }; 402 | /* End XCConfigurationList section */ 403 | 404 | /* Begin XCVersionGroup section */ 405 | 67B9AF9E1D9F030C0058E2BA /* Simple_Swift_AI.xcdatamodeld */ = { 406 | isa = XCVersionGroup; 407 | children = ( 408 | 67B9AF9F1D9F030C0058E2BA /* Simple_Swift_AI.xcdatamodel */, 409 | ); 410 | currentVersion = 67B9AF9F1D9F030C0058E2BA /* Simple_Swift_AI.xcdatamodel */; 411 | path = Simple_Swift_AI.xcdatamodeld; 412 | sourceTree = ""; 413 | versionGroupType = wrapper.xcdatamodel; 414 | }; 415 | /* End XCVersionGroup section */ 416 | }; 417 | rootObject = 67B9AF8C1D9F030C0058E2BA /* Project object */; 418 | } 419 | -------------------------------------------------------------------------------- /Simple-Swift-AI/Simple-Swift-AI/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 74 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 215 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 245 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | --------------------------------------------------------------------------------