Giter Club home page Giter Club logo

swiftcsp's Introduction

SwiftCSP

Swift Versions CocoaPods Version SPM Compatible CocoaPods Platforms Linux Compatible Twitter Contact

SwiftCSP is a constraint satisfaction problem solver written in pure Swift (no Cocoa). It utilizes a simple backtracking algorithm with optional standard heuristics to improve performance on some problems. At this stage of development, it's fairly slow but it includes examples of solving actual problems. It should run on all Swift platforms (iOS, OS X, Linux, tvOS, etc.).

A constraint satisfaction problem is a problem composed of variables that have possible values (domains) and constraints on what those values can be. A solver finds a potential solution to that problem by selecting values from the domains of each variable that fit the constraints. For more information you should checkout Chapter 6 of Artificial Intelligence: A Modern Approach (Third Edition) by Norvig and Russell.

Installation

Use the cocoapod SwiftCSP or include the files in the Sources directory (CSP.swift, Constraint.swift, and Backtrack.swift) in your project. Alternatively, you can also install SwiftCSP through the Swift Package Manager (SPM) by pointing to this repository. Release 0.9.7 and above requires Swift 5. Use release 0.9.6 for Swift 4 support. Use release 0.9.5 for Swift 3 support. Use release 0.9.4 for Swift 2 support. For Swift 1.2 support use release 0.9 on CocoaPods or 0.9.1 on GitHub.

Examples/Unit Tests

The unit tests included with the project are also well known toy problems including:

Looking at them should give you a good idea about how to use the library. In addition, the program included in the main project is a nice graphical example of the circuit board layout problem (it's also a great example of Cocoa Bindings on macOS).

Usage

You will need to create an instance of CSP and set its variables and domains at initialization. You will also need to subclass one of Constraint's canonical subclasses: UnaryConstraint, BinaryConstraint, or ListConstraint and implement the isSatisfied() method. Then you will need to add instances of your Constraint subclass to the CSP. All of these classes make use of generics - specifically you should specify the type of the variables and the type of the domains.

To solve your CSP you will call the function backtrackingSearch(). If your CSP is of any significant size, you will probably want to do this in an asynchronous block or background thread. You can also try the minConflicts() solver which is not as mature.

Example

Once again, I suggest looking at the unit tests, but here's a quick overview of what it's like to setup the eight queens problem:

let variables: [Int] = [0, 1, 2, 3, 4, 5, 6, 7]  // create the variables, just Ints in this case
var domains = Dictionary<Int, [Int]>() // create the domain (also of Int type)
for variable in variables {
  domains[variable] = []
  for i in variable.stride(to: 64, by: 8) {
    domains[variable]?.append(i)
  }
}
        
csp = CSP<Int, Int>(variables: variables, domains: domains)  // initialize the previously defined CSP
// Note that we specified through generics that its variables and domain are of type Int
let smmc = EightQueensConstraint(variables: variables) // create a custom constraint
// note that once again we specified both the variables and domain are of type Int
csp?.addConstraint(smmc) // add the constraint

When subclassing a Constraint subclass, you will want to specify types for the superclass's generics as so:

final class EightQueensConstraint: ListConstraint <Int, Int>

We therefore have a non-generic subclass of a generic superclass.

Performance

Performance is currently not great for problems with a medium size domain space. Profiling has shown a large portion of this may be attributable to the performance of Swift's native Dictionary type. Improved heuristics such as MAC3 are planned (spaces in the source code are left for them and contributions are welcome!) and should improve the situation. You can turn on the MRV or LCV heuristics (which are already implemented) when calling backtrackingSearch() to improve performance in many instances. In my testing MRV improves many searches, whereas the LCV implementation still leaves something to be desired, but may be useful in very specific problems. Note that these heuristics can also decrease performance for some problems.

Generics

SwiftCSP makes extensive use of generics. It seems like a lot of unnecessary angle brackets, but it allows the type checker to ensure variables fit with their domains and constraints. Due to a limitation in Swift generics, Constraint is a class instead of a protocol.

Help Wanted

Contributions that implement heuristics, improve performance in other ways, or simplify the design are more than welcome. Just make sure all of the unit tests still run and the new version maintains the flexibility of having any Hashable type as a variable and any type as a Domain. Additional unit tests are also welcome. A simple MinConflicts solver is also implemented, but could be improved.

Authorship and License

SwiftCSP was written by David Kopec and released under the Apache License (see LICENSE). It was originally a port of a Dart library I wrote called constraineD which itself was a port of a Python library I wrote many years before that.

swiftcsp's People

Contributors

davecom avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

swiftcsp's Issues

Confusing AC-3 and MAC-3

I am confusing AC-3 and MAC-3 .I don't see the main difference between them.
Please guide me.

Regards,
Thwin

MRV heuristic should choose smallest domain

The currently implemented MRV heuristic appears to be choosing a variable with the largest domain. But unless I'm misunderstanding something, MRV should choose the smallest domain instead, right?

MRV stands for "minimum remaining values" - it even says so in the code in a comment on line 87:

/// Return an unassigned variable - we may want to use some logic here to return the
/// minimum-remaining values

But then later the variable name is maximumRemainingValues and the code follows that logic

Error when overriding isSatisfied

When version 0.9.6 is installed for Swift 4.2 via CocoaPods, I'm getting this error on build:

Overriding non-open instance method outside of its defining module

I'm trying to create a Constraint subclass from outside the module as such (error on "override func..." line:

final class SampleConstraint: UnaryConstraint<String, String> {
    init(str: String) {
        super.init(variable: str)
    }
    override func isSatisfied(assignment: Dictionary<String, String>) -> Bool {
        if (something) {
            return true
        } else {
            return false
        }
    }
}

It appears that because isSatisfied is defined as public, I can't override it. Does the source just need to be changed to make this method open, or is this my fault?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.