From 5efc1406ff719cb10fcf33f491747ed70d6d567b Mon Sep 17 00:00:00 2001 From: Matthew Butterick Date: Fri, 19 Oct 2018 22:15:19 -0700 Subject: [PATCH] how do you start --- csp/hacs-test-workbench.rkt | 120 +- csp/hacs-test.rkt | 80 +- csp/hacs.rkt | 134 +- csp/port2/python-constraint-master/.gitignore | 60 - .../python-constraint-master/.travis.yml | 21 - csp/port2/python-constraint-master/LICENSE | 23 - csp/port2/python-constraint-master/README.rst | 159 -- .../constraint/__init__.py | 1461 ----------------- .../constraint/compat.py | 14 - .../constraint/version.py | 8 - .../examples/__init__.py | 0 .../examples/abc/__init__.py | 0 .../examples/abc/abc.py | 37 - .../examples/coins/__init__.py | 0 .../examples/coins/coins.py | 36 - .../examples/crosswords/__init__.py | 0 .../examples/crosswords/crosswords.py | 154 -- .../examples/crosswords/large.mask | 27 - .../examples/crosswords/medium.mask | 19 - .../examples/crosswords/python.mask | 8 - .../examples/crosswords/small.mask | 8 - .../examples/einstein/__init__.py | 0 .../examples/einstein/einstein.py | 209 --- .../examples/queens/__init__.py | 0 .../examples/queens/queens.py | 54 - .../examples/rooks/__init__.py | 0 .../examples/rooks/rooks.py | 57 - .../examples/studentdesks/__init__.py | 0 .../examples/studentdesks/studentdesks.py | 48 - .../examples/sudoku/__init__.py | 0 .../examples/sudoku/sudoku.py | 71 - .../examples/wordmath/__init__.py | 0 .../examples/wordmath/seisseisdoze.py | 39 - .../examples/wordmath/sendmoremoney.py | 42 - .../examples/wordmath/twotwofour.py | 37 - .../examples/xsum/__init__.py | 0 .../examples/xsum/xsum.py | 48 - csp/port2/python-constraint-master/setup.cfg | 9 - csp/port2/python-constraint-master/setup.py | 123 -- .../tests/test_constraint.py | 91 - .../tests/test_solvers.py | 17 - .../tests/test_some_not_in_set.py | 102 -- 42 files changed, 274 insertions(+), 3042 deletions(-) delete mode 100755 csp/port2/python-constraint-master/.gitignore delete mode 100755 csp/port2/python-constraint-master/.travis.yml delete mode 100755 csp/port2/python-constraint-master/LICENSE delete mode 100755 csp/port2/python-constraint-master/README.rst delete mode 100755 csp/port2/python-constraint-master/constraint/__init__.py delete mode 100755 csp/port2/python-constraint-master/constraint/compat.py delete mode 100755 csp/port2/python-constraint-master/constraint/version.py delete mode 100755 csp/port2/python-constraint-master/examples/__init__.py delete mode 100755 csp/port2/python-constraint-master/examples/abc/__init__.py delete mode 100755 csp/port2/python-constraint-master/examples/abc/abc.py delete mode 100755 csp/port2/python-constraint-master/examples/coins/__init__.py delete mode 100755 csp/port2/python-constraint-master/examples/coins/coins.py delete mode 100755 csp/port2/python-constraint-master/examples/crosswords/__init__.py delete mode 100755 csp/port2/python-constraint-master/examples/crosswords/crosswords.py delete mode 100755 csp/port2/python-constraint-master/examples/crosswords/large.mask delete mode 100755 csp/port2/python-constraint-master/examples/crosswords/medium.mask delete mode 100755 csp/port2/python-constraint-master/examples/crosswords/python.mask delete mode 100755 csp/port2/python-constraint-master/examples/crosswords/small.mask delete mode 100755 csp/port2/python-constraint-master/examples/einstein/__init__.py delete mode 100755 csp/port2/python-constraint-master/examples/einstein/einstein.py delete mode 100755 csp/port2/python-constraint-master/examples/queens/__init__.py delete mode 100755 csp/port2/python-constraint-master/examples/queens/queens.py delete mode 100755 csp/port2/python-constraint-master/examples/rooks/__init__.py delete mode 100755 csp/port2/python-constraint-master/examples/rooks/rooks.py delete mode 100755 csp/port2/python-constraint-master/examples/studentdesks/__init__.py delete mode 100755 csp/port2/python-constraint-master/examples/studentdesks/studentdesks.py delete mode 100755 csp/port2/python-constraint-master/examples/sudoku/__init__.py delete mode 100755 csp/port2/python-constraint-master/examples/sudoku/sudoku.py delete mode 100755 csp/port2/python-constraint-master/examples/wordmath/__init__.py delete mode 100755 csp/port2/python-constraint-master/examples/wordmath/seisseisdoze.py delete mode 100755 csp/port2/python-constraint-master/examples/wordmath/sendmoremoney.py delete mode 100755 csp/port2/python-constraint-master/examples/wordmath/twotwofour.py delete mode 100755 csp/port2/python-constraint-master/examples/xsum/__init__.py delete mode 100755 csp/port2/python-constraint-master/examples/xsum/xsum.py delete mode 100755 csp/port2/python-constraint-master/setup.cfg delete mode 100755 csp/port2/python-constraint-master/setup.py delete mode 100755 csp/port2/python-constraint-master/tests/test_constraint.py delete mode 100755 csp/port2/python-constraint-master/tests/test_solvers.py delete mode 100755 csp/port2/python-constraint-master/tests/test_some_not_in_set.py diff --git a/csp/hacs-test-workbench.rkt b/csp/hacs-test-workbench.rkt index 2a17f32e..d592c496 100644 --- a/csp/hacs-test-workbench.rkt +++ b/csp/hacs-test-workbench.rkt @@ -2,16 +2,118 @@ (require sugar "hacs.rkt") (current-inference forward-check) -(current-select-variable mrv) +(current-select-variable mrv-degree-hybrid) (current-order-values shuffle) (current-shuffle #true) -(define xsum (make-csp)) -(add-vars! xsum '(l1 l2 l3 l4 r1 r2 r3 r4 x) (range 1 10)) -(add-pairwise-constraint! xsum < '(l1 l2 l3 l4)) -(add-pairwise-constraint! xsum < '(r1 r2 r3 r4)) -(add-constraint! xsum (λ (l1 l2 l3 l4 x) (= 27 (+ l1 l2 l3 l4 x))) '(l1 l2 l3 l4 x)) -(add-constraint! xsum (λ (r1 r2 r3 r4 x) (= 27 (+ r1 r2 r3 r4 x))) '(r1 r2 r3 r4 x)) -(add-pairwise-constraint! xsum alldiff= '(l1 l2 l3 l4 r1 r2 r3 r4 x)) -(time (solve xsum)) +#| +# There are no tricks, just pure logic, so good luck and don't give up. +# +# 1. In a street there are five houses, painted five different colours. +# 2. In each house lives a person of different nationality +# 3. These five homeowners each drink a different kind of beverage, smoke +# different brand of cigar and keep a different pet. +# +# THE QUESTION: WHO OWNS THE zebra? +# +# HINTS +# +# 1. The englishman lives in a red house. +# 2. The spaniard keeps dogs as pets. +# 5. The owner of the Green house drinks coffee. +# 3. The ukrainian drinks tea. +# 4. The Green house is on the left of the ivory house. +# 6. The person who smokes oldgold rears snails. +# 7. The owner of the Yellow house smokes kools. +# 8. The man living in the centre house drinks milk. +# 9. The Norwegian lives in the first house. +# 10. The man who smokes chesterfields lives next to the one who keeps foxes. +# 11. The man who keeps horses lives next to the man who smokes kools. +# 12. The man who smokes luckystrike drinks orangejuice. +# 13. The japanese smokes parliaments. +# 14. The Norwegian lives next to the blue house. +# 15. The man who smokes chesterfields has a neighbour who drinks water. +|# + +(define (sym . args) (string->symbol (apply format args))) + +(define zebra (make-csp)) + +(define ns (map (curry sym "nationality-~a") (range 5))) +(define cs (map (curry sym "color-~a") (range 5))) +(define ds (map (curry sym "drink-~a") (range 5))) +(define ss (map (curry sym "smoke-~a") (range 5))) +(define ps (map (curry sym "pet-~a") (range 5))) + +(add-vars! zebra ns '(englishman spaniard ukrainian norwegian japanese)) +(add-vars! zebra cs '(red ivory green yellow blue)) +(add-vars! zebra ds '(tea coffee milk orange-juice water)) +(add-vars! zebra ss '(oldgold kools chesterfields luckystrike parliaments)) +(add-vars! zebra ps '(dogs snails foxes horses zebra)) + +(for ([vars (list ns cs ds ss ps)]) + (add-pairwise-constraint! zebra neq? vars)) + +(define (paired-with lval left rval right) + (add-constraint! zebra (λ (left right) (or (not (eq? left lval)) (eq? rval right))) (list left right))) + +(define (paired-with* lval lefts rval rights) + (for ([left lefts][right rights]) + (paired-with lval left rval right))) + +;# 1. The englishman lives in a red house. +('englishman ns . paired-with* . 'red cs) + +;# 2. The spaniard keeps dogs as pets. +('spaniard ns . paired-with* . 'dogs ps) + +;# 5. The owner of the Green house drinks coffee. +('green cs . paired-with* . 'coffee ds) + +;# 3. The ukrainian drinks tea. +('ukrainian ns . paired-with* . 'tea ds) + +;# 4. The Green house is on the left of the ivory house. +('green (drop-right cs 1) . paired-with* . 'ivory (drop cs 1)) +(add-constraint! zebra (curry neq? 'ivory) (list 'color-0)) +(add-constraint! zebra (curry neq? 'green) (list 'color-4)) + +;# 6. The person who smokes oldgold rears snails. +('oldgold ss . paired-with* . 'snails ps) + +;# 7. The owner of the Yellow house smokes kools. +('yellow cs . paired-with* . 'kools ss) + +;# 8. The man living in the centre house drinks milk. +(add-constraint! zebra (λ (d) (eq? d 'milk)) (list 'drink-2)) + +;# 9. The Norwegian lives in the first house. +(add-constraint! zebra (λ (x) (eq? x 'norwegian)) (list 'nationality-0)) + +(define (next-to lval lefts rval rights) + (lval (drop-right lefts 1) . paired-with* . rval (drop rights 1)) + (lval (drop lefts 1) . paired-with* . rval (drop-right rights 1))) + +;# 10. The man who smokes chesterfields lives next to the one who keeps foxes. +('chesterfields ss . next-to . 'foxes ps) + +;# 11. The man who keeps horses lives next to the man who smokes kools. +;('horses ps . next-to . 'kools ss) + +;# 12. The man who smokes luckystrike drinks orangejuice. +('luckystrike ss . paired-with* . 'orange-juice ds) + +;# 13. The japanese smokes parliaments. +('japanese ns . paired-with* . 'parliaments ss) + +;# 14. The Norwegian lives next to the blue house. +;('norwegian ns . next-to . 'water ds) + +;# 15. The man who smokes chesterfields has a neighbour who drinks water. +;('chesterfields ss . next-to . 'water ds) + +(define (finish x) + (apply map list (slice-at x 5))) + +(map finish (list (time (solve zebra)))) \ No newline at end of file diff --git a/csp/hacs-test.rkt b/csp/hacs-test.rkt index 1569e09a..02c07af4 100644 --- a/csp/hacs-test.rkt +++ b/csp/hacs-test.rkt @@ -1,6 +1,10 @@ #lang debug racket (require "hacs.rkt" rackunit) +(current-inference forward-check) +(current-select-variable mrv-degree-hybrid) +(current-order-values shuffle) +(current-shuffle #true) (check-equal? (first-unassigned-variable ($csp (list ($var 'a (range 3)) ($var 'b (range 3))) null)) ($var 'a (range 3))) @@ -78,5 +82,77 @@ '((dollars . 14) (quarters . 12))) - -#;(check-equal? (length (time (solve* xsum))) 8) +;; xsum +#| +# Reorganize the following numbers in a way that each line of +# 5 numbers sum to 27. +# +# 1 6 +# 2 7 +# 3 +# 8 4 +# 9 5 +# +|# +(define xsum (make-csp)) +(add-vars! xsum '(l1 l2 l3 l4 r1 r2 r3 r4 x) (range 1 10)) +(add-pairwise-constraint! xsum < '(l1 l2 l3 l4)) +(add-pairwise-constraint! xsum < '(r1 r2 r3 r4)) +(add-constraint! xsum (λ (l1 l2 l3 l4 x) (= 27 (+ l1 l2 l3 l4 x))) '(l1 l2 l3 l4 x)) +(add-constraint! xsum (λ (r1 r2 r3 r4 x) (= 27 (+ r1 r2 r3 r4 x))) '(r1 r2 r3 r4 x)) +(add-pairwise-constraint! xsum alldiff= '(l1 l2 l3 l4 r1 r2 r3 r4 x)) + +(check-equal? (length (time (solve* xsum))) 8) + + + +;; send more money problem +#| +# Assign equal values to equal letters, and different values to +# different letters, in a way that satisfies the following sum: +# +# SEND +# + MORE +# ------ +# MONEY +|# + +(define (word-value . xs) + (for/sum ([(x idx) (in-indexed (reverse xs))]) + (* x (expt 10 idx)))) + +(define smm (make-csp)) +(add-vars! smm '(s e n d m o r y) (λ () (range 10))) +(add-constraint! smm positive? '(s)) +(add-constraint! smm positive? '(m)) +(add-constraint! smm (λ (d e y) (= (modulo (+ d e) 10) y)) '(d e y)) +(add-constraint! smm (λ (n d r e y) + (= (modulo (+ (word-value n d) (word-value r e)) 100) + (word-value e y))) '(n d r e y)) +(add-constraint! smm (λ (e n d o r y) + (= (modulo (+ (word-value e n d) (word-value o r e)) 1000) (word-value n e y))) '(e n d o r y)) +(add-constraint! smm (λ (s e n d m o r y) + (= (+ (word-value s e n d) (word-value m o r e)) + (word-value m o n e y))) '(s e n d m o r y)) +(add-pairwise-constraint! smm alldiff= '(s e n d m o r y)) +(check-equal? (time (solve smm)) '((s . 9) (e . 5) (n . 6) (d . 7) (m . 1) (o . 0) (r . 8) (y . 2))) + + +;; queens problem +;; place queens on chessboard so they do not intersect +(define queens (make-csp)) +(define qs (for/list ([q 8]) (string->symbol (format "q~a" q)))) +(define rows (range (length qs))) +(add-vars! queens qs rows) +(define (q-col q) (string->number (string-trim (symbol->string q) "q"))) +(for* ([qs (in-combinations qs 2)]) + (match-define (list qa qb) qs) + (match-define (list qa-col qb-col) (map q-col qs)) + (add-constraint! queens + (λ (qa-row qb-row) + (and + (not (= (abs (- qa-row qb-row)) (abs (- qa-col qb-col)))) ; same diagonal? + (not (= qa-row qb-row)))) ; same row? + (list qa qb))) + +(check-equal? 92 (length (time (solve* queens)))) \ No newline at end of file diff --git a/csp/hacs.rkt b/csp/hacs.rkt index 0598d01d..db0fa941 100644 --- a/csp/hacs.rkt +++ b/csp/hacs.rkt @@ -8,7 +8,7 @@ (if (null? argss) (yield (reverse acc)) (for ([arg (in-list (car argss))]) - (loop (cdr argss) (cons arg acc)))))))) + (loop (cdr argss) (cons arg acc)))))))) (struct $csp ([vars #:mutable] [constraints #:mutable]) #:transparent) @@ -19,7 +19,7 @@ (raise-argument-error '$constraint-proc "$csp" csp)) ;; apply proc in many-to-many style (for/and ([args (in-cartesian (map (λ (cname) ($csp-vals csp cname)) ($constraint-names constraint)))]) - (apply ($constraint-proc constraint) args)))) + (apply ($constraint-proc constraint) args)))) (struct $var (name domain) #:transparent) (define $var-name? symbol?) @@ -28,7 +28,6 @@ (struct $cvar $var (past) #:transparent) (struct $avar $var () #:transparent) - (define (make-csp [vds null] [constraints null]) ($csp vds constraints)) @@ -54,11 +53,11 @@ (($csp? procedure? (listof (listof $var-name?))) ((or/c #false $var-name?)) . ->* . void?) (set-$csp-constraints! csp (append ($csp-constraints csp) (for/list ([names (in-list namess)]) - (for ([name (in-list names)]) - (check-name-in-csp! 'add-constraints! csp name)) - ($constraint names (if proc-name - (procedure-rename proc proc-name) - proc)))))) + (for ([name (in-list names)]) + (check-name-in-csp! 'add-constraints! csp name)) + ($constraint names (if proc-name + (procedure-rename proc proc-name) + proc)))))) (define/contract (add-pairwise-constraint! csp proc var-names [proc-name #false]) (($csp? procedure? (listof $var-name?)) ($var-name?) . ->* . void?) @@ -93,7 +92,7 @@ (check-name-in-csp! '$csp-var csp name) (for/first ([var (in-list ($csp-vars csp))] #:when (eq? name ($var-name var))) - var)) + var)) (define/contract ($csp-vals csp name) ($csp? $var-name? . -> . (listof any/c)) @@ -135,34 +134,34 @@ (ormap assigned-name? ($constraint-names constraint))) ($csp ($csp-vars csp) (for/list ([constraint (in-list ($csp-constraints csp))]) - (cond - [(and (if minimum-arity (<= minimum-arity (constraint-arity constraint)) #true) - (partially-assigned? constraint)) - (match-define ($constraint cnames proc) constraint) - ($constraint (filter-not assigned-name? cnames) - ;; pattern is mix of values and symbols (indicating variables to persist) - (let ([reduce-arity-pattern (for/list ([cname (in-list cnames)]) - (if (assigned-name? cname) - (first ($csp-vals csp cname)) - cname))]) - (reduce-arity proc reduce-arity-pattern)))] - [else constraint]))))) + (cond + [(and (if minimum-arity (<= minimum-arity (constraint-arity constraint)) #true) + (partially-assigned? constraint)) + (match-define ($constraint cnames proc) constraint) + ($constraint (filter-not assigned-name? cnames) + ;; pattern is mix of values and symbols (indicating variables to persist) + (let ([reduce-arity-pattern (for/list ([cname (in-list cnames)]) + (if (assigned-name? cname) + (first ($csp-vals csp cname)) + cname))]) + (reduce-arity proc reduce-arity-pattern)))] + [else constraint]))))) (define/contract (assign-val csp name val) ($csp? $var-name? any/c . -> . $csp?) (define assigned-csp ($csp (for/list ([var ($csp-vars csp)]) - (if (eq? name ($var-name var)) - ($avar name (list val)) - var)) + (if (eq? name ($var-name var)) + ($avar name (list val)) + var)) ($csp-constraints csp))) - (reduce-constraint-arity assigned-csp)) + assigned-csp) (define/contract (unassigned-vars csp) ($csp? . -> . (listof (and/c $var? (not/c $avar?)))) (for/list ([var (in-list ($csp-vars csp))] #:unless ($avar? var)) - var)) + var)) (define/contract (first-unassigned-variable csp) ($csp? . -> . (or/c #false (and/c $var? (not/c $avar?)))) @@ -188,7 +187,7 @@ ($csp? $var? . -> . exact-nonnegative-integer?) (for/sum ([constraint (in-list ($csp-constraints csp))] #:when (memq ($var-name var) ($constraint-names constraint))) - 1)) + 1)) (define/contract (blended-variable-selector csp) ($csp? . -> . (or/c #false (and/c $var? (not/c $avar?)))) @@ -199,6 +198,26 @@ [else (first (let* ([uvars-by-mrv (sort uvars < #:key (λ (var) (length ($var-domain var))))] [uvars-by-degree (sort uvars-by-mrv > #:key (λ (var) (var-degree csp var)))]) uvars-by-degree))])) + +(define/contract (remaining-values var) + ($var? . -> . exact-nonnegative-integer?) + (length ($var-vals var))) + +(define/contract (mrv-degree-hybrid csp) + ($csp? . -> . (or/c #f $var?)) + (define uvars (unassigned-vars csp)) + (cond + [(empty? uvars) #false] + [else + ;; minimum remaining values (MRV) rule + (define mrv-arg (argmin remaining-values uvars)) + (match (filter (λ (var) (= (remaining-values mrv-arg) (remaining-values var))) uvars) + [(list winning-uvar) winning-uvar] + [(list mrv-uvars ...) + ;; use degree as tiebreaker for mrv + (define max-degree-arg (argmax (λ (var) (var-degree csp var)) mrv-uvars)) + ;; use random tiebreaker for degree + (first (shuffle (filter (λ (var) (= (var-degree csp max-degree-arg) (var-degree csp var))) mrv-uvars)))])])) (define first-domain-value values) @@ -210,8 +229,8 @@ [cnames (in-value ($constraint-names constraint))] #:when (and (= (length names) (length cnames)) (for/and ([name (in-list names)]) - (memq name cnames)))) - constraint)) + (memq name cnames)))) + constraint)) (define/contract (forward-check csp aname) ($csp? $var-name? . -> . $csp?) @@ -228,11 +247,11 @@ (define new-vals (for/list ([val (in-list vals)] #:when (for/and ([constraint (in-list constraints)]) - (let ([proc ($constraint-proc constraint)]) - (if (eq? name (first ($constraint-names constraint))) - (proc val aval) - (proc aval val))))) - val)) + (let ([proc ($constraint-proc constraint)]) + (if (eq? name (first ($constraint-names constraint))) + (proc val aval) + (proc aval val))))) + val)) ($cvar name new-vals (cons aname (if ($cvar? var) ($cvar-past var) null)))])])) @@ -241,7 +260,7 @@ (define conflict-set (for*/list ([var (in-list checked-vars)] #:when (empty? ($var-domain var)) [name (in-list ($cvar-past var))]) - name)) + name)) ;; for conflict-directed backjumping it's essential to forward-check ALL vars ;; (even after an empty domain is generated) and combine their conflicts ;; so we can discover the *most recent past var* that could be the culprit. @@ -253,18 +272,18 @@ ;; (they have no further use) (define nonsingleton-constraints (for/list ([constraint (in-list ($csp-constraints csp))] - #:unless (and - (= 2 (constraint-arity constraint)) ; binary constraint - (memq aname ($constraint-names constraint)) ; includes target name - (let ([other-name (first (remq aname ($constraint-names constraint)))]) ; and something else - (= (length ($csp-vals csp other-name)) 1)))) ; that has only one value - constraint)) + #:unless (and + (= 2 (constraint-arity constraint)) ; binary constraint + (memq aname ($constraint-names constraint)) ; includes target name + (let ([other-name (first (remq aname ($constraint-names constraint)))]) ; and something else + (= (length ($csp-vals csp other-name)) 1)))) ; that has only one value + constraint)) ($csp checked-vars nonsingleton-constraints)) (define/contract (constraint-checkable? c names) ($constraint? (listof $var-name?) . -> . boolean?) (and (for/and ([cname (in-list ($constraint-names c))]) - (memq cname names)) + (memq cname names)) #true)) (define/contract (constraint-arity constraint) @@ -281,14 +300,30 @@ ;; we also want to use "singleton" vars (that is, vars that have been reduced to a single domain value by forward checking) (define singleton-varnames (for/list ([var (in-list ($csp-vars csp))] #:when (singleton-var? var)) - ($var-name var))) + ($var-name var))) (define-values (checkable-constraints other-constraints) (partition (λ (c) (constraint-checkable? c singleton-varnames)) ($csp-constraints csp))) (for ([constraint (in-list (sort checkable-constraints < #:key constraint-arity))] #:unless (constraint csp)) - (raise ($backtrack null))) + (raise ($backtrack null))) ($csp ($csp-vars csp) other-constraints)) +(define/contract (make-nodes-consistent csp) + ($csp? . -> . $csp?) + ;; todo: why does this function make searches so much slower? + ($csp + (for/list ([var (in-list ($csp-vars csp))]) + (match-define ($var name vals) var) + (define procs (for*/list ([constraint (in-list ($csp-constraints csp))] + [cnames (in-value ($constraint-names constraint))] + #:when (and (= 1 (length cnames)) (eq? name (car cnames)))) + ($constraint-proc constraint))) + ($var name + (for*/fold ([vals vals]) + ([proc (in-list procs)]) + (filter proc vals)))) + ($csp-constraints csp))) + (define/contract (backtracking-solver csp #:select-variable [select-unassigned-variable @@ -310,18 +345,19 @@ (with-handlers ([wants-backtrack? (λ (bt) (append conflicts (remq name ($backtrack-names bt))))]) (let* ([csp (assign-val csp name val)] + ;; reduce constraints before inference, + ;; to create more forward-checkable (binary) constraints + [csp (reduce-constraint-arity csp)] [csp (inference csp name)] [csp (check-constraints csp)]) (loop csp))) conflicts)])))) - - (define/contract ($csp-assocs csp) ($csp? . -> . (listof (cons/c $var-name? any/c))) (for/list ([var (in-list ($csp-vars csp))]) - (match var - [($var name domain) (cons name (first domain))]))) + (match var + [($var name domain) (cons name (first domain))]))) (define/contract (solve* csp #:finish-proc [finish-proc $csp-assocs] @@ -330,7 +366,7 @@ (($csp?) (#:finish-proc procedure? #:solver procedure? #:count integer?) . ->* . (listof any/c)) (for/list ([solution (in-producer (solver csp) (void))] [idx (in-range max-solutions)]) - (finish-proc solution))) + (finish-proc solution))) (define/contract (solve csp #:finish-proc [finish-proc $csp-assocs] diff --git a/csp/port2/python-constraint-master/.gitignore b/csp/port2/python-constraint-master/.gitignore deleted file mode 100755 index b102207f..00000000 --- a/csp/port2/python-constraint-master/.gitignore +++ /dev/null @@ -1,60 +0,0 @@ -# Byte-compiled / optimized / DLL files -__pycache__/ -*.py[cod] - -# C extensions -*.so - -# Distribution / packaging -.Python -env/ -build/ -develop-eggs/ -dist/ -downloads/ -eggs/ -.eggs/ -lib/ -lib64/ -parts/ -sdist/ -var/ -*.egg-info/ -.installed.cfg -*.egg - -# PyInstaller -# Usually these files are written by a python script from a template -# before PyInstaller builds the exe, so as to inject date/other infos into it. -*.manifest -*.spec - -# Installer logs -pip-log.txt -pip-delete-this-directory.txt - -# Unit test / coverage reports -htmlcov/ -.tox/ -.coverage -.coverage.* -.cache -nosetests.xml -coverage.xml -*,cover - -# Translations -*.mo -*.pot - -# Django stuff: -*.log - -# Sphinx documentation -docs/_build/ - -# PyBuilder -target/ - -# PyCharm / Intellij -.idea/ diff --git a/csp/port2/python-constraint-master/.travis.yml b/csp/port2/python-constraint-master/.travis.yml deleted file mode 100755 index 2bf2b8a3..00000000 --- a/csp/port2/python-constraint-master/.travis.yml +++ /dev/null @@ -1,21 +0,0 @@ -language: python -python: - - "2.7" - - "3.3" - - "3.4" - - "3.5" - - "3.6" - -# command to install dependencies -install: - - "pip install -qq flake8" - - "pip install coveralls --quiet" - - "pip install ." - -# command to run tests -script: - - nosetests -s -v --with-coverage --cover-package=constraint - - flake8 --ignore E501 constraint examples tests - -after_success: - - coveralls diff --git a/csp/port2/python-constraint-master/LICENSE b/csp/port2/python-constraint-master/LICENSE deleted file mode 100755 index 1551a23a..00000000 --- a/csp/port2/python-constraint-master/LICENSE +++ /dev/null @@ -1,23 +0,0 @@ -Copyright (c) 2005-2014 - Gustavo Niemeyer - -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. -2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/csp/port2/python-constraint-master/README.rst b/csp/port2/python-constraint-master/README.rst deleted file mode 100755 index 564e46a5..00000000 --- a/csp/port2/python-constraint-master/README.rst +++ /dev/null @@ -1,159 +0,0 @@ -|Build Status| |Code Health| |Code Coverage| - -python-constraint -================= - -Introduction ------------- -The Python constraint module offers solvers for `Constraint Satisfaction Problems (CSPs) `_ over finite domains in simple and pure Python. CSP is class of problems which may be represented in terms of variables (a, b, ...), domains (a in [1, 2, 3], ...), and constraints (a < b, ...). - -Examples --------- - -Basics -~~~~~~ - -This interactive Python session demonstrates the module basic operation: - -.. code-block:: python - - >>> from constraint import * - >>> problem = Problem() - >>> problem.addVariable("a", [1,2,3]) - >>> problem.addVariable("b", [4,5,6]) - >>> problem.getSolutions() - [{'a': 3, 'b': 6}, {'a': 3, 'b': 5}, {'a': 3, 'b': 4}, - {'a': 2, 'b': 6}, {'a': 2, 'b': 5}, {'a': 2, 'b': 4}, - {'a': 1, 'b': 6}, {'a': 1, 'b': 5}, {'a': 1, 'b': 4}] - - >>> problem.addConstraint(lambda a, b: a*2 == b, - ("a", "b")) - >>> problem.getSolutions() - [{'a': 3, 'b': 6}, {'a': 2, 'b': 4}] - - >>> problem = Problem() - >>> problem.addVariables(["a", "b"], [1, 2, 3]) - >>> problem.addConstraint(AllDifferentConstraint()) - >>> problem.getSolutions() - [{'a': 3, 'b': 2}, {'a': 3, 'b': 1}, {'a': 2, 'b': 3}, - {'a': 2, 'b': 1}, {'a': 1, 'b': 2}, {'a': 1, 'b': 3}] - -Rooks problem -~~~~~~~~~~~~~ - -The following example solves the classical Eight Rooks problem: - -.. code-block:: python - - >>> problem = Problem() - >>> numpieces = 8 - >>> cols = range(numpieces) - >>> rows = range(numpieces) - >>> problem.addVariables(cols, rows) - >>> for col1 in cols: - ... for col2 in cols: - ... if col1 < col2: - ... problem.addConstraint(lambda row1, row2: row1 != row2, - ... (col1, col2)) - >>> solutions = problem.getSolutions() - >>> solutions - >>> solutions - [{0: 7, 1: 6, 2: 5, 3: 4, 4: 3, 5: 2, 6: 1, 7: 0}, - {0: 7, 1: 6, 2: 5, 3: 4, 4: 3, 5: 2, 6: 0, 7: 1}, - {0: 7, 1: 6, 2: 5, 3: 4, 4: 3, 5: 1, 6: 2, 7: 0}, - {0: 7, 1: 6, 2: 5, 3: 4, 4: 3, 5: 1, 6: 0, 7: 2}, - ... - {0: 7, 1: 5, 2: 3, 3: 6, 4: 2, 5: 1, 6: 4, 7: 0}, - {0: 7, 1: 5, 2: 3, 3: 6, 4: 1, 5: 2, 6: 0, 7: 4}, - {0: 7, 1: 5, 2: 3, 3: 6, 4: 1, 5: 2, 6: 4, 7: 0}, - {0: 7, 1: 5, 2: 3, 3: 6, 4: 1, 5: 4, 6: 2, 7: 0}, - {0: 7, 1: 5, 2: 3, 3: 6, 4: 1, 5: 4, 6: 0, 7: 2}, - ...] - - -Magic squares -~~~~~~~~~~~~~ - -This example solves a 4x4 magic square: - -.. code-block:: python - - >>> problem = Problem() - >>> problem.addVariables(range(0, 16), range(1, 16 + 1)) - >>> problem.addConstraint(AllDifferentConstraint(), range(0, 16)) - >>> problem.addConstraint(ExactSumConstraint(34), [0, 5, 10, 15]) - >>> problem.addConstraint(ExactSumConstraint(34), [3, 6, 9, 12]) - >>> for row in range(4): - ... problem.addConstraint(ExactSumConstraint(34), - [row * 4 + i for i in range(4)]) - >>> for col in range(4): - ... problem.addConstraint(ExactSumConstraint(34), - [col + 4 * i for i in range(4)]) - >>> solutions = problem.getSolutions() - -Features --------- - -The following solvers are available: - -- Backtracking solver -- Recursive backtracking solver -- Minimum conflicts solver - - -.. role:: python(code) - :language: python - -Predefined constraint types currently available: - -- :python:`FunctionConstraint` -- :python:`AllDifferentConstraint` -- :python:`AllEqualConstraint` -- :python:`ExactSumConstraint` -- :python:`MaxSumConstraint` -- :python:`MinSumConstraint` -- :python:`InSetConstraint` -- :python:`NotInSetConstraint` -- :python:`SomeInSetConstraint` -- :python:`SomeNotInSetConstraint` - -API documentation ------------------ -Documentation for the module is available at: http://labix.org/doc/constraint/ - -Download and install --------------------- - -.. code-block:: shell - - $ pip install python-constraint - -Roadmap -------- - -This GitHub organization and repository is a global effort to help to -maintain python-constraint which was written by Gustavo Niemeyer -and originaly located at https://labix.org/python-constraint - -- Create some unit tests - DONE -- Enable continuous integration - DONE -- Port to Python 3 (Python 2 being also supported) - DONE -- Respect Style Guide for Python Code (PEP8) - DONE -- Improve code coverage writting more unit tests - ToDo -- Move doc to Sphinx or MkDocs - https://readthedocs.org/ - ToDo - -Contact -------- -- `Gustavo Niemeyer `_ -- `Sébastien Celles `_ - -But it's probably better to `open an issue `_. - - -.. |Build Status| image:: https://travis-ci.org/python-constraint/python-constraint.svg?branch=master - :target: https://travis-ci.org/python-constraint/python-constraint -.. |Code Health| image:: https://landscape.io/github/python-constraint/python-constraint/master/landscape.svg?style=flat - :target: https://landscape.io/github/python-constraint/python-constraint/master - :alt: Code Health -.. |Code Coverage| image:: https://coveralls.io/repos/github/python-constraint/python-constraint/badge.svg - :target: https://coveralls.io/github/python-constraint/python-constraint diff --git a/csp/port2/python-constraint-master/constraint/__init__.py b/csp/port2/python-constraint-master/constraint/__init__.py deleted file mode 100755 index 7932aa33..00000000 --- a/csp/port2/python-constraint-master/constraint/__init__.py +++ /dev/null @@ -1,1461 +0,0 @@ -#!/usr/bin/python -# -# Copyright (c) 2005-2014 - Gustavo Niemeyer -# -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are met: -# -# 1. Redistributions of source code must retain the above copyright notice, this -# list of conditions and the following disclaimer. -# 2. Redistributions in binary form must reproduce the above copyright notice, -# this list of conditions and the following disclaimer in the documentation -# and/or other materials provided with the distribution. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE -# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -""" -@var Unassigned: Helper object instance representing unassigned values - -@sort: Problem, Variable, Domain -@group Solvers: Solver, - BacktrackingSolver, - RecursiveBacktrackingSolver, - MinConflictsSolver -@group Constraints: Constraint, - FunctionConstraint, - AllDifferentConstraint, - AllEqualConstraint, - MaxSumConstraint, - ExactSumConstraint, - MinSumConstraint, - InSetConstraint, - NotInSetConstraint, - SomeInSetConstraint, - SomeNotInSetConstraint -""" - -from __future__ import absolute_import, division, print_function - - -from .version import (__author__, __copyright__, __credits__, __license__, # noqa - __version__, __email__, __status__, __url__) # noqa - -import random -import copy -from .compat import xrange - -__all__ = ["Problem", "Variable", "Domain", "Unassigned", - "Solver", "BacktrackingSolver", "RecursiveBacktrackingSolver", - "MinConflictsSolver", "Constraint", "FunctionConstraint", - "AllDifferentConstraint", "AllEqualConstraint", "MaxSumConstraint", - "ExactSumConstraint", "MinSumConstraint", "InSetConstraint", - "NotInSetConstraint", "SomeInSetConstraint", - "SomeNotInSetConstraint"] - - -class Problem(object): - """ - Class used to define a problem and retrieve solutions - """ - - def __init__(self, solver=None): - """ - @param solver: Problem solver used to find solutions - (default is L{BacktrackingSolver}) - @type solver: instance of a L{Solver} subclass - """ - self._solver = solver or BacktrackingSolver() - self._constraints = [] - self._variables = {} - - def reset(self): - """ - Reset the current problem definition - - Example: - - >>> problem = Problem() - >>> problem.addVariable("a", [1, 2]) - >>> problem.reset() - >>> problem.getSolution() - >>> - """ - del self._constraints[:] - self._variables.clear() - - def setSolver(self, solver): - """ - Change the problem solver currently in use - - Example: - - >>> solver = BacktrackingSolver() - >>> problem = Problem(solver) - >>> problem.getSolver() is solver - True - - @param solver: New problem solver - @type solver: instance of a C{Solver} subclass - """ - self._solver = solver - - def getSolver(self): - """ - Obtain the problem solver currently in use - - Example: - - >>> solver = BacktrackingSolver() - >>> problem = Problem(solver) - >>> problem.getSolver() is solver - True - - @return: Solver currently in use - @rtype: instance of a L{Solver} subclass - """ - return self._solver - - def addVariable(self, variable, domain): - """ - Add a variable to the problem - - Example: - - >>> problem = Problem() - >>> problem.addVariable("a", [1, 2]) - >>> problem.getSolution() in ({'a': 1}, {'a': 2}) - True - - @param variable: Object representing a problem variable - @type variable: hashable object - @param domain: Set of items defining the possible values that - the given variable may assume - @type domain: list, tuple, or instance of C{Domain} - """ - if variable in self._variables: - msg = "Tried to insert duplicated variable %s" % repr(variable) - raise ValueError(msg) - if hasattr(domain, '__getitem__'): - domain = Domain(domain) - elif isinstance(domain, Domain): - domain = copy.copy(domain) - else: - msg = "Domains must be instances of subclasses of the Domain class" - raise TypeError(msg) - if not domain: - raise ValueError("Domain is empty") - self._variables[variable] = domain - - def addVariables(self, variables, domain): - """ - Add one or more variables to the problem - - Example: - - >>> problem = Problem() - >>> problem.addVariables(["a", "b"], [1, 2, 3]) - >>> solutions = problem.getSolutions() - >>> len(solutions) - 9 - >>> {'a': 3, 'b': 1} in solutions - True - - @param variables: Any object containing a sequence of objects - represeting problem variables - @type variables: sequence of hashable objects - @param domain: Set of items defining the possible values that - the given variables may assume - @type domain: list, tuple, or instance of C{Domain} - """ - for variable in variables: - self.addVariable(variable, domain) - - def addConstraint(self, constraint, variables=None): - """ - Add a constraint to the problem - - Example: - - >>> problem = Problem() - >>> problem.addVariables(["a", "b"], [1, 2, 3]) - >>> problem.addConstraint(lambda a, b: b == a+1, ["a", "b"]) - >>> solutions = problem.getSolutions() - >>> - - @param constraint: Constraint to be included in the problem - @type constraint: instance a L{Constraint} subclass or a - function to be wrapped by L{FunctionConstraint} - @param variables: Variables affected by the constraint (default to - all variables). Depending on the constraint type - the order may be important. - @type variables: set or sequence of variables - """ - if not isinstance(constraint, Constraint): - if callable(constraint): - constraint = FunctionConstraint(constraint) - else: - msg = "Constraints must be instances of subclasses "\ - "of the Constraint class" - raise ValueError(msg) - self._constraints.append((constraint, variables)) - - def getSolution(self): - """ - Find and return a solution to the problem - - Example: - - >>> problem = Problem() - >>> problem.getSolution() is None - True - >>> problem.addVariables(["a"], [42]) - >>> problem.getSolution() - {'a': 42} - - @return: Solution for the problem - @rtype: dictionary mapping variables to values - """ - domains, constraints, vconstraints = self._getArgs() - if not domains: - return None - return self._solver.getSolution(domains, constraints, vconstraints) - - def getSolutions(self): - """ - Find and return all solutions to the problem - - Example: - - >>> problem = Problem() - >>> problem.getSolutions() == [] - True - >>> problem.addVariables(["a"], [42]) - >>> problem.getSolutions() - [{'a': 42}] - - @return: All solutions for the problem - @rtype: list of dictionaries mapping variables to values - """ - domains, constraints, vconstraints = self._getArgs() - if not domains: - return [] - return self._solver.getSolutions(domains, constraints, vconstraints) - - def getSolutionIter(self): - """ - Return an iterator to the solutions of the problem - - Example: - - >>> problem = Problem() - >>> list(problem.getSolutionIter()) == [] - True - >>> problem.addVariables(["a"], [42]) - >>> iter = problem.getSolutionIter() - >>> next(iter) - {'a': 42} - >>> next(iter) - Traceback (most recent call last): - File "", line 1, in ? - StopIteration - """ - domains, constraints, vconstraints = self._getArgs() - if not domains: - return iter(()) - return self._solver.getSolutionIter(domains, constraints, - vconstraints) - - def _getArgs(self): - domains = self._variables.copy() - allvariables = domains.keys() - constraints = [] - for constraint, variables in self._constraints: - if not variables: - variables = list(allvariables) - constraints.append((constraint, variables)) - vconstraints = {} - for variable in domains: - vconstraints[variable] = [] - for constraint, variables in constraints: - for variable in variables: - vconstraints[variable].append((constraint, variables)) - for constraint, variables in constraints[:]: - constraint.preProcess(variables, domains, - constraints, vconstraints) - for domain in domains.values(): - domain.resetState() - if not domain: - return None, None, None - # doArc8(getArcs(domains, constraints), domains, {}) - return domains, constraints, vconstraints - -# ---------------------------------------------------------------------- -# Solvers -# ---------------------------------------------------------------------- - - -def getArcs(domains, constraints): - """ - Return a dictionary mapping pairs (arcs) of constrained variables - - @attention: Currently unused. - """ - arcs = {} - for x in constraints: - constraint, variables = x - if len(variables) == 2: - variable1, variable2 = variables - arcs.setdefault(variable1, {})\ - .setdefault(variable2, [])\ - .append(x) - arcs.setdefault(variable2, {})\ - .setdefault(variable1, [])\ - .append(x) - return arcs - - -def doArc8(arcs, domains, assignments): - """ - Perform the ARC-8 arc checking algorithm and prune domains - - @attention: Currently unused. - """ - check = dict.fromkeys(domains, True) - while check: - variable, _ = check.popitem() - if variable not in arcs or variable in assignments: - continue - domain = domains[variable] - arcsvariable = arcs[variable] - for othervariable in arcsvariable: - arcconstraints = arcsvariable[othervariable] - if othervariable in assignments: - otherdomain = [assignments[othervariable]] - else: - otherdomain = domains[othervariable] - if domain: - # changed = False - for value in domain[:]: - assignments[variable] = value - if otherdomain: - for othervalue in otherdomain: - assignments[othervariable] = othervalue - for constraint, variables in arcconstraints: - if not constraint(variables, domains, - assignments, True): - break - else: - # All constraints passed. Value is safe. - break - else: - # All othervalues failed. Kill value. - domain.hideValue(value) - # changed = True - del assignments[othervariable] - del assignments[variable] - # if changed: - # check.update(dict.fromkeys(arcsvariable)) - if not domain: - return False - return True - - -class Solver(object): - """ - Abstract base class for solvers - - @sort: getSolution, getSolutions, getSolutionIter - """ - - def getSolution(self, domains, constraints, vconstraints): - """ - Return one solution for the given problem - - @param domains: Dictionary mapping variables to their domains - @type domains: dict - @param constraints: List of pairs of (constraint, variables) - @type constraints: list - @param vconstraints: Dictionary mapping variables to a list of - constraints affecting the given variables. - @type vconstraints: dict - """ - msg = "%s is an abstract class" % self.__class__.__name__ - raise NotImplementedError(msg) - - def getSolutions(self, domains, constraints, vconstraints): - """ - Return all solutions for the given problem - - @param domains: Dictionary mapping variables to domains - @type domains: dict - @param constraints: List of pairs of (constraint, variables) - @type constraints: list - @param vconstraints: Dictionary mapping variables to a list of - constraints affecting the given variables. - @type vconstraints: dict - """ - msg = "%s provides only a single solution" % self.__class__.__name__ - raise NotImplementedError(msg) - - def getSolutionIter(self, domains, constraints, vconstraints): - """ - Return an iterator for the solutions of the given problem - - @param domains: Dictionary mapping variables to domains - @type domains: dict - @param constraints: List of pairs of (constraint, variables) - @type constraints: list - @param vconstraints: Dictionary mapping variables to a list of - constraints affecting the given variables. - @type vconstraints: dict - """ - msg = "%s doesn't provide iteration" % self.__class__.__name__ - raise NotImplementedError(msg) - - -class BacktrackingSolver(Solver): - """ - Problem solver with backtracking capabilities - - Examples: - - >>> result = [[('a', 1), ('b', 2)], - ... [('a', 1), ('b', 3)], - ... [('a', 2), ('b', 3)]] - - >>> problem = Problem(BacktrackingSolver()) - >>> problem.addVariables(["a", "b"], [1, 2, 3]) - >>> problem.addConstraint(lambda a, b: b > a, ["a", "b"]) - - >>> solution = problem.getSolution() - >>> sorted(solution.items()) in result - True - - >>> for solution in problem.getSolutionIter(): - ... sorted(solution.items()) in result - True - True - True - - >>> for solution in problem.getSolutions(): - ... sorted(solution.items()) in result - True - True - True - """ - - def __init__(self, forwardcheck=True): - """ - @param forwardcheck: If false forward checking will not be requested - to constraints while looking for solutions - (default is true) - @type forwardcheck: bool - """ - self._forwardcheck = forwardcheck - - def getSolutionIter(self, domains, constraints, vconstraints): - forwardcheck = self._forwardcheck - assignments = {} - - queue = [] - - while True: - - # Mix the Degree and Minimum Remaing Values (MRV) heuristics - lst = [(-len(vconstraints[variable]), - len(domains[variable]), variable) for variable in domains] - lst.sort() - for item in lst: - if item[-1] not in assignments: - # Found unassigned variable - variable = item[-1] - values = domains[variable][:] - if forwardcheck: - pushdomains = [domains[x] for x in domains - if x not in assignments and x != variable] - else: - pushdomains = None - break - else: - # No unassigned variables. We've got a solution. Go back - # to last variable, if there's one. - yield assignments.copy() - if not queue: - return - variable, values, pushdomains = queue.pop() - if pushdomains: - for domain in pushdomains: - domain.popState() - - while True: - # We have a variable. Do we have any values left? - if not values: - # No. Go back to last variable, if there's one. - del assignments[variable] - while queue: - variable, values, pushdomains = queue.pop() - if pushdomains: - for domain in pushdomains: - domain.popState() - if values: - break - del assignments[variable] - else: - return - - # Got a value. Check it. - assignments[variable] = values.pop() - - if pushdomains: - for domain in pushdomains: - domain.pushState() - - for constraint, variables in vconstraints[variable]: - if not constraint(variables, domains, assignments, - pushdomains): - # Value is not good. - break - else: - break - - if pushdomains: - for domain in pushdomains: - domain.popState() - - # Push state before looking for next variable. - queue.append((variable, values, pushdomains)) - - raise RuntimeError("Can't happen") - - def getSolution(self, domains, constraints, vconstraints): - iter = self.getSolutionIter(domains, constraints, vconstraints) - try: - return next(iter) - except StopIteration: - return None - - def getSolutions(self, domains, constraints, vconstraints): - return list(self.getSolutionIter(domains, constraints, vconstraints)) - - -class RecursiveBacktrackingSolver(Solver): - """ - Recursive problem solver with backtracking capabilities - - Examples: - - >>> result = [[('a', 1), ('b', 2)], - ... [('a', 1), ('b', 3)], - ... [('a', 2), ('b', 3)]] - - >>> problem = Problem(RecursiveBacktrackingSolver()) - >>> problem.addVariables(["a", "b"], [1, 2, 3]) - >>> problem.addConstraint(lambda a, b: b > a, ["a", "b"]) - - >>> solution = problem.getSolution() - >>> sorted(solution.items()) in result - True - - >>> for solution in problem.getSolutions(): - ... sorted(solution.items()) in result - True - True - True - - >>> problem.getSolutionIter() - Traceback (most recent call last): - ... - NotImplementedError: RecursiveBacktrackingSolver doesn't provide iteration - """ - - def __init__(self, forwardcheck=True): - """ - @param forwardcheck: If false forward checking will not be requested - to constraints while looking for solutions - (default is true) - @type forwardcheck: bool - """ - self._forwardcheck = forwardcheck - - def recursiveBacktracking(self, solutions, domains, vconstraints, - assignments, single): - - # Mix the Degree and Minimum Remaing Values (MRV) heuristics - lst = [(-len(vconstraints[variable]), - len(domains[variable]), variable) for variable in domains] - lst.sort() - for item in lst: - if item[-1] not in assignments: - # Found an unassigned variable. Let's go. - break - else: - # No unassigned variables. We've got a solution. - solutions.append(assignments.copy()) - return solutions - - variable = item[-1] - assignments[variable] = None - - forwardcheck = self._forwardcheck - if forwardcheck: - pushdomains = [domains[x] for x in domains if x not in assignments] - else: - pushdomains = None - - for value in domains[variable]: - assignments[variable] = value - if pushdomains: - for domain in pushdomains: - domain.pushState() - for constraint, variables in vconstraints[variable]: - if not constraint(variables, domains, assignments, - pushdomains): - # Value is not good. - break - else: - # Value is good. Recurse and get next variable. - self.recursiveBacktracking(solutions, domains, vconstraints, - assignments, single) - if solutions and single: - return solutions - if pushdomains: - for domain in pushdomains: - domain.popState() - del assignments[variable] - return solutions - - def getSolution(self, domains, constraints, vconstraints): - solutions = self.recursiveBacktracking([], domains, vconstraints, - {}, True) - return solutions and solutions[0] or None - - def getSolutions(self, domains, constraints, vconstraints): - return self.recursiveBacktracking([], domains, vconstraints, - {}, False) - - -class MinConflictsSolver(Solver): - """ - Problem solver based on the minimum conflicts theory - - Examples: - - >>> result = [[('a', 1), ('b', 2)], - ... [('a', 1), ('b', 3)], - ... [('a', 2), ('b', 3)]] - - >>> problem = Problem(MinConflictsSolver()) - >>> problem.addVariables(["a", "b"], [1, 2, 3]) - >>> problem.addConstraint(lambda a, b: b > a, ["a", "b"]) - - >>> solution = problem.getSolution() - >>> sorted(solution.items()) in result - True - - >>> problem.getSolutions() - Traceback (most recent call last): - ... - NotImplementedError: MinConflictsSolver provides only a single solution - - >>> problem.getSolutionIter() - Traceback (most recent call last): - ... - NotImplementedError: MinConflictsSolver doesn't provide iteration - """ - - def __init__(self, steps=1000): - """ - @param steps: Maximum number of steps to perform before giving up - when looking for a solution (default is 1000) - @type steps: int - """ - self._steps = steps - - def getSolution(self, domains, constraints, vconstraints): - assignments = {} - # Initial assignment - for variable in domains: - assignments[variable] = random.choice(domains[variable]) - for _ in xrange(self._steps): - conflicted = False - lst = list(domains.keys()) - random.shuffle(lst) - for variable in lst: - # Check if variable is not in conflict - for constraint, variables in vconstraints[variable]: - if not constraint(variables, domains, assignments): - break - else: - continue - # Variable has conflicts. Find values with less conflicts. - mincount = len(vconstraints[variable]) - minvalues = [] - for value in domains[variable]: - assignments[variable] = value - count = 0 - for constraint, variables in vconstraints[variable]: - if not constraint(variables, domains, assignments): - count += 1 - if count == mincount: - minvalues.append(value) - elif count < mincount: - mincount = count - del minvalues[:] - minvalues.append(value) - # Pick a random one from these values. - assignments[variable] = random.choice(minvalues) - conflicted = True - if not conflicted: - return assignments - return None - -# ---------------------------------------------------------------------- -# Variables -# ---------------------------------------------------------------------- - - -class Variable(object): - """ - Helper class for variable definition - - Using this class is optional, since any hashable object, - including plain strings and integers, may be used as variables. - """ - - def __init__(self, name): - """ - @param name: Generic variable name for problem-specific purposes - @type name: string - """ - self.name = name - - def __repr__(self): - return self.name - - -Unassigned = Variable("Unassigned") - -# ---------------------------------------------------------------------- -# Domains -# ---------------------------------------------------------------------- - - -class Domain(list): - """ - Class used to control possible values for variables - - When list or tuples are used as domains, they are automatically - converted to an instance of that class. - """ - - def __init__(self, set): - """ - @param set: Set of values that the given variables may assume - @type set: set of objects comparable by equality - """ - list.__init__(self, set) - self._hidden = [] - self._states = [] - - def resetState(self): - """ - Reset to the original domain state, including all possible values - """ - self.extend(self._hidden) - del self._hidden[:] - del self._states[:] - - def pushState(self): - """ - Save current domain state - - Variables hidden after that call are restored when that state - is popped from the stack. - """ - self._states.append(len(self)) - - def popState(self): - """ - Restore domain state from the top of the stack - - Variables hidden since the last popped state are then available - again. - """ - diff = self._states.pop() - len(self) - if diff: - self.extend(self._hidden[-diff:]) - del self._hidden[-diff:] - - def hideValue(self, value): - """ - Hide the given value from the domain - - After that call the given value won't be seen as a possible value - on that domain anymore. The hidden value will be restored when the - previous saved state is popped. - - @param value: Object currently available in the domain - """ - list.remove(self, value) - self._hidden.append(value) - -# ---------------------------------------------------------------------- -# Constraints -# ---------------------------------------------------------------------- - - -class Constraint(object): - """ - Abstract base class for constraints - """ - - def __call__(self, variables, domains, assignments, forwardcheck=False): - """ - Perform the constraint checking - - If the forwardcheck parameter is not false, besides telling if - the constraint is currently broken or not, the constraint - implementation may choose to hide values from the domains of - unassigned variables to prevent them from being used, and thus - prune the search space. - - @param variables: Variables affected by that constraint, in the - same order provided by the user - @type variables: sequence - @param domains: Dictionary mapping variables to their domains - @type domains: dict - @param assignments: Dictionary mapping assigned variables to their - current assumed value - @type assignments: dict - @param forwardcheck: Boolean value stating whether forward checking - should be performed or not - @return: Boolean value stating if this constraint is currently - broken or not - @rtype: bool - """ - return True - - def preProcess(self, variables, domains, constraints, vconstraints): - """ - Preprocess variable domains - - This method is called before starting to look for solutions, - and is used to prune domains with specific constraint logic - when possible. For instance, any constraints with a single - variable may be applied on all possible values and removed, - since they may act on individual values even without further - knowledge about other assignments. - - @param variables: Variables affected by that constraint, in the - same order provided by the user - @type variables: sequence - @param domains: Dictionary mapping variables to their domains - @type domains: dict - @param constraints: List of pairs of (constraint, variables) - @type constraints: list - @param vconstraints: Dictionary mapping variables to a list of - constraints affecting the given variables. - @type vconstraints: dict - """ - if len(variables) == 1: - variable = variables[0] - domain = domains[variable] - for value in domain[:]: - if not self(variables, domains, {variable: value}): - domain.remove(value) - constraints.remove((self, variables)) - vconstraints[variable].remove((self, variables)) - - def forwardCheck(self, variables, domains, assignments, - _unassigned=Unassigned): - """ - Helper method for generic forward checking - - Currently, this method acts only when there's a single - unassigned variable. - - @param variables: Variables affected by that constraint, in the - same order provided by the user - @type variables: sequence - @param domains: Dictionary mapping variables to their domains - @type domains: dict - @param assignments: Dictionary mapping assigned variables to their - current assumed value - @type assignments: dict - @return: Boolean value stating if this constraint is currently - broken or not - @rtype: bool - """ - unassignedvariable = _unassigned - for variable in variables: - if variable not in assignments: - if unassignedvariable is _unassigned: - unassignedvariable = variable - else: - break - else: - if unassignedvariable is not _unassigned: - # Remove from the unassigned variable domain's all - # values which break our variable's constraints. - domain = domains[unassignedvariable] - if domain: - for value in domain[:]: - assignments[unassignedvariable] = value - if not self(variables, domains, assignments): - domain.hideValue(value) - del assignments[unassignedvariable] - if not domain: - return False - return True - - -class FunctionConstraint(Constraint): - """ - Constraint which wraps a function defining the constraint logic - - Examples: - - >>> problem = Problem() - >>> problem.addVariables(["a", "b"], [1, 2]) - >>> def func(a, b): - ... return b > a - >>> problem.addConstraint(func, ["a", "b"]) - >>> problem.getSolution() - {'a': 1, 'b': 2} - - >>> problem = Problem() - >>> problem.addVariables(["a", "b"], [1, 2]) - >>> def func(a, b): - ... return b > a - >>> problem.addConstraint(FunctionConstraint(func), ["a", "b"]) - >>> problem.getSolution() - {'a': 1, 'b': 2} - """ - - def __init__(self, func, assigned=True): - """ - @param func: Function wrapped and queried for constraint logic - @type func: callable object - @param assigned: Whether the function may receive unassigned - variables or not - @type assigned: bool - """ - self._func = func - self._assigned = assigned - - def __call__(self, variables, domains, assignments, forwardcheck=False, - _unassigned=Unassigned): - parms = [assignments.get(x, _unassigned) for x in variables] - missing = parms.count(_unassigned) - if missing: - return ((self._assigned or self._func(*parms)) and - (not forwardcheck or missing != 1 or - self.forwardCheck(variables, domains, assignments))) - return self._func(*parms) - - -class AllDifferentConstraint(Constraint): - """ - Constraint enforcing that values of all given variables are different - - Example: - - >>> problem = Problem() - >>> problem.addVariables(["a", "b"], [1, 2]) - >>> problem.addConstraint(AllDifferentConstraint()) - >>> sorted(sorted(x.items()) for x in problem.getSolutions()) - [[('a', 1), ('b', 2)], [('a', 2), ('b', 1)]] - """ - - def __call__(self, variables, domains, assignments, forwardcheck=False, - _unassigned=Unassigned): - seen = {} - for variable in variables: - value = assignments.get(variable, _unassigned) - if value is not _unassigned: - if value in seen: - return False - seen[value] = True - if forwardcheck: - for variable in variables: - if variable not in assignments: - domain = domains[variable] - for value in seen: - if value in domain: - domain.hideValue(value) - if not domain: - return False - return True - - -class AllEqualConstraint(Constraint): - """ - Constraint enforcing that values of all given variables are equal - - Example: - - >>> problem = Problem() - >>> problem.addVariables(["a", "b"], [1, 2]) - >>> problem.addConstraint(AllEqualConstraint()) - >>> sorted(sorted(x.items()) for x in problem.getSolutions()) - [[('a', 1), ('b', 1)], [('a', 2), ('b', 2)]] - """ - - def __call__(self, variables, domains, assignments, forwardcheck=False, - _unassigned=Unassigned): - singlevalue = _unassigned - for variable in variables: - value = assignments.get(variable, _unassigned) - if singlevalue is _unassigned: - singlevalue = value - elif value is not _unassigned and value != singlevalue: - return False - if forwardcheck and singlevalue is not _unassigned: - for variable in variables: - if variable not in assignments: - domain = domains[variable] - if singlevalue not in domain: - return False - for value in domain[:]: - if value != singlevalue: - domain.hideValue(value) - return True - - -class MaxSumConstraint(Constraint): - """ - Constraint enforcing that values of given variables sum up to - a given amount - - Example: - - >>> problem = Problem() - >>> problem.addVariables(["a", "b"], [1, 2]) - >>> problem.addConstraint(MaxSumConstraint(3)) - >>> sorted(sorted(x.items()) for x in problem.getSolutions()) - [[('a', 1), ('b', 1)], [('a', 1), ('b', 2)], [('a', 2), ('b', 1)]] - """ - - def __init__(self, maxsum, multipliers=None): - """ - @param maxsum: Value to be considered as the maximum sum - @type maxsum: number - @param multipliers: If given, variable values will be multiplied by - the given factors before being summed to be checked - @type multipliers: sequence of numbers - """ - self._maxsum = maxsum - self._multipliers = multipliers - - def preProcess(self, variables, domains, constraints, vconstraints): - Constraint.preProcess(self, variables, domains, - constraints, vconstraints) - multipliers = self._multipliers - maxsum = self._maxsum - if multipliers: - for variable, multiplier in zip(variables, multipliers): - domain = domains[variable] - for value in domain[:]: - if value * multiplier > maxsum: - domain.remove(value) - else: - for variable in variables: - domain = domains[variable] - for value in domain[:]: - if value > maxsum: - domain.remove(value) - - def __call__(self, variables, domains, assignments, forwardcheck=False): - multipliers = self._multipliers - maxsum = self._maxsum - sum = 0 - if multipliers: - for variable, multiplier in zip(variables, multipliers): - if variable in assignments: - sum += assignments[variable] * multiplier - if type(sum) is float: - sum = round(sum, 10) - if sum > maxsum: - return False - if forwardcheck: - for variable, multiplier in zip(variables, multipliers): - if variable not in assignments: - domain = domains[variable] - for value in domain[:]: - if sum + value * multiplier > maxsum: - domain.hideValue(value) - if not domain: - return False - else: - for variable in variables: - if variable in assignments: - sum += assignments[variable] - if type(sum) is float: - sum = round(sum, 10) - if sum > maxsum: - return False - if forwardcheck: - for variable in variables: - if variable not in assignments: - domain = domains[variable] - for value in domain[:]: - if sum + value > maxsum: - domain.hideValue(value) - if not domain: - return False - return True - - -class ExactSumConstraint(Constraint): - """ - Constraint enforcing that values of given variables sum exactly - to a given amount - - Example: - - >>> problem = Problem() - >>> problem.addVariables(["a", "b"], [1, 2]) - >>> problem.addConstraint(ExactSumConstraint(3)) - >>> sorted(sorted(x.items()) for x in problem.getSolutions()) - [[('a', 1), ('b', 2)], [('a', 2), ('b', 1)]] - """ - - def __init__(self, exactsum, multipliers=None): - """ - @param exactsum: Value to be considered as the exact sum - @type exactsum: number - @param multipliers: If given, variable values will be multiplied by - the given factors before being summed to be checked - @type multipliers: sequence of numbers - """ - self._exactsum = exactsum - self._multipliers = multipliers - - def preProcess(self, variables, domains, constraints, vconstraints): - Constraint.preProcess(self, variables, domains, - constraints, vconstraints) - multipliers = self._multipliers - exactsum = self._exactsum - if multipliers: - for variable, multiplier in zip(variables, multipliers): - domain = domains[variable] - for value in domain[:]: - if value * multiplier > exactsum: - domain.remove(value) - else: - for variable in variables: - domain = domains[variable] - for value in domain[:]: - if value > exactsum: - domain.remove(value) - - def __call__(self, variables, domains, assignments, forwardcheck=False): - multipliers = self._multipliers - exactsum = self._exactsum - sum = 0 - missing = False - if multipliers: - for variable, multiplier in zip(variables, multipliers): - if variable in assignments: - sum += assignments[variable] * multiplier - else: - missing = True - if type(sum) is float: - sum = round(sum, 10) - if sum > exactsum: - return False - if forwardcheck and missing: - for variable, multiplier in zip(variables, multipliers): - if variable not in assignments: - domain = domains[variable] - for value in domain[:]: - if sum + value * multiplier > exactsum: - domain.hideValue(value) - if not domain: - return False - else: - for variable in variables: - if variable in assignments: - sum += assignments[variable] - else: - missing = True - if type(sum) is float: - sum = round(sum, 10) - if sum > exactsum: - return False - if forwardcheck and missing: - for variable in variables: - if variable not in assignments: - domain = domains[variable] - for value in domain[:]: - if sum + value > exactsum: - domain.hideValue(value) - if not domain: - return False - if missing: - return sum <= exactsum - else: - return sum == exactsum - - -class MinSumConstraint(Constraint): - """ - Constraint enforcing that values of given variables sum at least - to a given amount - - Example: - - >>> problem = Problem() - >>> problem.addVariables(["a", "b"], [1, 2]) - >>> problem.addConstraint(MinSumConstraint(3)) - >>> sorted(sorted(x.items()) for x in problem.getSolutions()) - [[('a', 1), ('b', 2)], [('a', 2), ('b', 1)], [('a', 2), ('b', 2)]] - """ - - def __init__(self, minsum, multipliers=None): - """ - @param minsum: Value to be considered as the minimum sum - @type minsum: number - @param multipliers: If given, variable values will be multiplied by - the given factors before being summed to be checked - @type multipliers: sequence of numbers - """ - self._minsum = minsum - self._multipliers = multipliers - - def __call__(self, variables, domains, assignments, forwardcheck=False): - for variable in variables: - if variable not in assignments: - return True - else: - multipliers = self._multipliers - minsum = self._minsum - sum = 0 - if multipliers: - for variable, multiplier in zip(variables, multipliers): - sum += assignments[variable] * multiplier - else: - for variable in variables: - sum += assignments[variable] - if type(sum) is float: - sum = round(sum, 10) - return sum >= minsum - - -class InSetConstraint(Constraint): - """ - Constraint enforcing that values of given variables are present in - the given set - - Example: - - >>> problem = Problem() - >>> problem.addVariables(["a", "b"], [1, 2]) - >>> problem.addConstraint(InSetConstraint([1])) - >>> sorted(sorted(x.items()) for x in problem.getSolutions()) - [[('a', 1), ('b', 1)]] - """ - - def __init__(self, set): - """ - @param set: Set of allowed values - @type set: set - """ - self._set = set - - def __call__(self, variables, domains, assignments, forwardcheck=False): - # preProcess() will remove it. - raise RuntimeError("Can't happen") - - def preProcess(self, variables, domains, constraints, vconstraints): - set = self._set - for variable in variables: - domain = domains[variable] - for value in domain[:]: - if value not in set: - domain.remove(value) - vconstraints[variable].remove((self, variables)) - constraints.remove((self, variables)) - - -class NotInSetConstraint(Constraint): - """ - Constraint enforcing that values of given variables are not present in - the given set - - Example: - - >>> problem = Problem() - >>> problem.addVariables(["a", "b"], [1, 2]) - >>> problem.addConstraint(NotInSetConstraint([1])) - >>> sorted(sorted(x.items()) for x in problem.getSolutions()) - [[('a', 2), ('b', 2)]] - """ - - def __init__(self, set): - """ - @param set: Set of disallowed values - @type set: set - """ - self._set = set - - def __call__(self, variables, domains, assignments, forwardcheck=False): - # preProcess() will remove it. - raise RuntimeError("Can't happen") - - def preProcess(self, variables, domains, constraints, vconstraints): - set = self._set - for variable in variables: - domain = domains[variable] - for value in domain[:]: - if value in set: - domain.remove(value) - vconstraints[variable].remove((self, variables)) - constraints.remove((self, variables)) - - -class SomeInSetConstraint(Constraint): - """ - Constraint enforcing that at least some of the values of given - variables must be present in a given set - - Example: - - >>> problem = Problem() - >>> problem.addVariables(["a", "b"], [1, 2]) - >>> problem.addConstraint(SomeInSetConstraint([1])) - >>> sorted(sorted(x.items()) for x in problem.getSolutions()) - [[('a', 1), ('b', 1)], [('a', 1), ('b', 2)], [('a', 2), ('b', 1)]] - """ - - def __init__(self, set, n=1, exact=False): - """ - @param set: Set of values to be checked - @type set: set - @param n: Minimum number of assigned values that should be present - in set (default is 1) - @type n: int - @param exact: Whether the number of assigned values which are - present in set must be exactly C{n} - @type exact: bool - """ - self._set = set - self._n = n - self._exact = exact - - def __call__(self, variables, domains, assignments, forwardcheck=False): - set = self._set - missing = 0 - found = 0 - for variable in variables: - if variable in assignments: - found += assignments[variable] in set - else: - missing += 1 - if missing: - if self._exact: - if not (found <= self._n <= missing + found): - return False - else: - if self._n > missing + found: - return False - if forwardcheck and self._n - found == missing: - # All unassigned variables must be assigned to - # values in the set. - for variable in variables: - if variable not in assignments: - domain = domains[variable] - for value in domain[:]: - if value not in set: - domain.hideValue(value) - if not domain: - return False - else: - if self._exact: - if found != self._n: - return False - else: - if found < self._n: - return False - return True - - -class SomeNotInSetConstraint(Constraint): - """ - Constraint enforcing that at least some of the values of given - variables must not be present in a given set - - Example: - - >>> problem = Problem() - >>> problem.addVariables(["a", "b"], [1, 2]) - >>> problem.addConstraint(SomeNotInSetConstraint([1])) - >>> sorted(sorted(x.items()) for x in problem.getSolutions()) - [[('a', 1), ('b', 2)], [('a', 2), ('b', 1)], [('a', 2), ('b', 2)]] - """ - - def __init__(self, set, n=1, exact=False): - """ - @param set: Set of values to be checked - @type set: set - @param n: Minimum number of assigned values that should not be present - in set (default is 1) - @type n: int - @param exact: Whether the number of assigned values which are - not present in set must be exactly C{n} - @type exact: bool - """ - self._set = set - self._n = n - self._exact = exact - - def __call__(self, variables, domains, assignments, forwardcheck=False): - set = self._set - missing = 0 - found = 0 - for variable in variables: - if variable in assignments: - found += assignments[variable] not in set - else: - missing += 1 - if missing: - if self._exact: - if not (found <= self._n <= missing + found): - return False - else: - if self._n > missing + found: - return False - if forwardcheck and self._n - found == missing: - # All unassigned variables must be assigned to - # values not in the set. - for variable in variables: - if variable not in assignments: - domain = domains[variable] - for value in domain[:]: - if value in set: - domain.hideValue(value) - if not domain: - return False - else: - if self._exact: - if found != self._n: - return False - else: - if found < self._n: - return False - return True - - -if __name__ == "__main__": - import doctest - doctest.testmod() diff --git a/csp/port2/python-constraint-master/constraint/compat.py b/csp/port2/python-constraint-master/constraint/compat.py deleted file mode 100755 index ef31a009..00000000 --- a/csp/port2/python-constraint-master/constraint/compat.py +++ /dev/null @@ -1,14 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -import sys - -PY2 = sys.version_info[0] == 2 -PY3 = (sys.version_info[0] >= 3) - -if PY3: - string_types = str - xrange = range -else: - string_types = basestring # noqa - xrange = xrange diff --git a/csp/port2/python-constraint-master/constraint/version.py b/csp/port2/python-constraint-master/constraint/version.py deleted file mode 100755 index af97862e..00000000 --- a/csp/port2/python-constraint-master/constraint/version.py +++ /dev/null @@ -1,8 +0,0 @@ -__author__ = "Gustavo Niemeyer" -__copyright__ = "Copyright (c) 2005-2014 - Gustavo Niemeyer " -__credits__ = ["Sebastien Celles"] -__license__ = "" -__version__ = "1.3.1" -__email__ = "gustavo@niemeyer.net" -__status__ = "Development" -__url__ = 'https://github.com/python-constraint/python-constraint' diff --git a/csp/port2/python-constraint-master/examples/__init__.py b/csp/port2/python-constraint-master/examples/__init__.py deleted file mode 100755 index e69de29b..00000000 diff --git a/csp/port2/python-constraint-master/examples/abc/__init__.py b/csp/port2/python-constraint-master/examples/abc/__init__.py deleted file mode 100755 index e69de29b..00000000 diff --git a/csp/port2/python-constraint-master/examples/abc/abc.py b/csp/port2/python-constraint-master/examples/abc/abc.py deleted file mode 100755 index 27b72906..00000000 --- a/csp/port2/python-constraint-master/examples/abc/abc.py +++ /dev/null @@ -1,37 +0,0 @@ -#!/usr/bin/python -# -# What's the minimum value for: -# -# ABC -# ------- -# A+B+C -# -# From http://www.umassd.edu/mathcontest/abc.cfm -# -from constraint import Problem - - -def solve(): - problem = Problem() - problem.addVariables("abc", range(1, 10)) - problem.getSolutions() - minvalue = 999 / (9 * 3) - minsolution = {} - for solution in problem.getSolutions(): - a = solution["a"] - b = solution["b"] - c = solution["c"] - value = (a * 100 + b * 10 + c) / (a + b + c) - if value < minvalue: - minsolution = solution - return minvalue, minsolution - - -def main(): - minvalue, minsolution = solve() - print(minvalue) - print(minsolution) - - -if __name__ == "__main__": - main() diff --git a/csp/port2/python-constraint-master/examples/coins/__init__.py b/csp/port2/python-constraint-master/examples/coins/__init__.py deleted file mode 100755 index e69de29b..00000000 diff --git a/csp/port2/python-constraint-master/examples/coins/coins.py b/csp/port2/python-constraint-master/examples/coins/coins.py deleted file mode 100755 index 98c2b62d..00000000 --- a/csp/port2/python-constraint-master/examples/coins/coins.py +++ /dev/null @@ -1,36 +0,0 @@ -#!/usr/bin/python -# -# 100 coins must sum to $5.00 -# -# That's kind of a country-specific problem, since depending on the -# country there are different values for coins. Here is presented -# the solution for a given set. -# -from constraint import Problem, ExactSumConstraint -import sys - - -def solve(): - problem = Problem() - total = 5.00 - variables = ("0.01", "0.05", "0.10", "0.50", "1.00") - values = [float(x) for x in variables] - for variable, value in zip(variables, values): - problem.addVariable(variable, range(int(total / value))) - problem.addConstraint(ExactSumConstraint(total, values), variables) - problem.addConstraint(ExactSumConstraint(100)) - solutions = problem.getSolutionIter() - return solutions, variables - - -def main(): - solutions, variables = solve() - for i, solution in enumerate(solutions): - sys.stdout.write("%03d -> " % (i + 1)) - for variable in variables: - sys.stdout.write("%s:%d " % (variable, solution[variable])) - sys.stdout.write("\n") - - -if __name__ == "__main__": - main() diff --git a/csp/port2/python-constraint-master/examples/crosswords/__init__.py b/csp/port2/python-constraint-master/examples/crosswords/__init__.py deleted file mode 100755 index e69de29b..00000000 diff --git a/csp/port2/python-constraint-master/examples/crosswords/crosswords.py b/csp/port2/python-constraint-master/examples/crosswords/crosswords.py deleted file mode 100755 index df0fce61..00000000 --- a/csp/port2/python-constraint-master/examples/crosswords/crosswords.py +++ /dev/null @@ -1,154 +0,0 @@ -#!/usr/bin/python -from constraint import Problem, AllDifferentConstraint -import random -import sys - -MINLEN = 3 - - -def main(puzzle, lines): - puzzle = puzzle.rstrip().splitlines() - while puzzle and not puzzle[0]: - del puzzle[0] - - # Extract horizontal words - horizontal = [] - word = [] - predefined = {} - for row in range(len(puzzle)): - for col in range(len(puzzle[row])): - char = puzzle[row][col] - if not char.isspace(): - word.append((row, col)) - if char != "#": - predefined[row, col] = char - elif word: - if len(word) > MINLEN: - horizontal.append(word[:]) - del word[:] - if word: - if len(word) > MINLEN: - horizontal.append(word[:]) - del word[:] - - # Extract vertical words - vertical = [] - validcol = True - col = 0 - while validcol: - validcol = False - for row in range(len(puzzle)): - if col >= len(puzzle[row]): - if word: - if len(word) > MINLEN: - vertical.append(word[:]) - del word[:] - else: - validcol = True - char = puzzle[row][col] - if not char.isspace(): - word.append((row, col)) - if char != "#": - predefined[row, col] = char - elif word: - if len(word) > MINLEN: - vertical.append(word[:]) - del word[:] - if word: - if len(word) > MINLEN: - vertical.append(word[:]) - del word[:] - col += 1 - - # hnames = ["h%d" % i for i in range(len(horizontal))] - # vnames = ["v%d" % i for i in range(len(vertical))] - - # problem = Problem(MinConflictsSolver()) - problem = Problem() - - for hi, hword in enumerate(horizontal): - for vi, vword in enumerate(vertical): - for hchar in hword: - if hchar in vword: - hci = hword.index(hchar) - vci = vword.index(hchar) - problem.addConstraint(lambda hw, vw, hci=hci, vci=vci: - hw[hci] == vw[vci], - ("h%d" % hi, "v%d" % vi)) - - for char, letter in predefined.items(): - for hi, hword in enumerate(horizontal): - if char in hword: - hci = hword.index(char) - problem.addConstraint(lambda hw, hci=hci, letter=letter: - hw[hci] == letter, ("h%d" % hi,)) - for vi, vword in enumerate(vertical): - if char in vword: - vci = vword.index(char) - problem.addConstraint(lambda vw, vci=vci, letter=letter: - vw[vci] == letter, ("v%d" % vi,)) - - wordsbylen = {} - for hword in horizontal: - wordsbylen[len(hword)] = [] - for vword in vertical: - wordsbylen[len(vword)] = [] - - for line in lines: - line = line.strip() - ll = len(line) - if ll in wordsbylen: - wordsbylen[ll].append(line.upper()) - - for hi, hword in enumerate(horizontal): - words = wordsbylen[len(hword)] - random.shuffle(words) - problem.addVariable("h%d" % hi, words) - for vi, vword in enumerate(vertical): - words = wordsbylen[len(vword)] - random.shuffle(words) - problem.addVariable("v%d" % vi, words) - - problem.addConstraint(AllDifferentConstraint()) - - solution = problem.getSolution() - if not solution: - print("No solution found!") - - maxcol = 0 - maxrow = 0 - for hword in horizontal: - for row, col in hword: - if row > maxrow: - maxrow = row - if col > maxcol: - maxcol = col - for vword in vertical: - for row, col in vword: - if row > maxrow: - maxrow = row - if col > maxcol: - maxcol = col - - matrix = [] - for row in range(maxrow + 1): - matrix.append([" "] * (maxcol + 1)) - - for variable in solution: - if variable[0] == "v": - word = vertical[int(variable[1:])] - else: - word = horizontal[int(variable[1:])] - for (row, col), char in zip(word, solution[variable]): - matrix[row][col] = char - - for row in range(maxrow + 1): - for col in range(maxcol + 1): - sys.stdout.write(matrix[row][col]) - sys.stdout.write("\n") - - -if __name__ == "__main__": - if len(sys.argv) != 3: - sys.exit("Usage: crosswords.py ") - main(open(sys.argv[1]).read(), open(sys.argv[2])) diff --git a/csp/port2/python-constraint-master/examples/crosswords/large.mask b/csp/port2/python-constraint-master/examples/crosswords/large.mask deleted file mode 100755 index ba5364c8..00000000 --- a/csp/port2/python-constraint-master/examples/crosswords/large.mask +++ /dev/null @@ -1,27 +0,0 @@ - -# ######## # -# # # # # -######## # # -# # # # # -# # ######## -# # # # # # -######## # # -# # # # # # - # # # -######## # # - # # # # # - # ######## - # # # # # - # # ######## - # # # # # # - # # ######## - # # # # -######## # # - # # # # # # - # # # # # # - ######## # # - # # # # - # ######## - # # # # -######## # # - diff --git a/csp/port2/python-constraint-master/examples/crosswords/medium.mask b/csp/port2/python-constraint-master/examples/crosswords/medium.mask deleted file mode 100755 index 3332a097..00000000 --- a/csp/port2/python-constraint-master/examples/crosswords/medium.mask +++ /dev/null @@ -1,19 +0,0 @@ - - # -######### -# # # -# # ###### -# # # -# # # # -# # # # -######## # -# # # - # # # - ######### - # # # - ######### - # # # - # # -####### - # - diff --git a/csp/port2/python-constraint-master/examples/crosswords/python.mask b/csp/port2/python-constraint-master/examples/crosswords/python.mask deleted file mode 100755 index fe5a5767..00000000 --- a/csp/port2/python-constraint-master/examples/crosswords/python.mask +++ /dev/null @@ -1,8 +0,0 @@ - P - Y -####T#### - # H # - # O # -####N # - # # -######### diff --git a/csp/port2/python-constraint-master/examples/crosswords/small.mask b/csp/port2/python-constraint-master/examples/crosswords/small.mask deleted file mode 100755 index 0e43ff78..00000000 --- a/csp/port2/python-constraint-master/examples/crosswords/small.mask +++ /dev/null @@ -1,8 +0,0 @@ - # - # -######### - # # - # # # # -##### # # - # # # -######### diff --git a/csp/port2/python-constraint-master/examples/einstein/__init__.py b/csp/port2/python-constraint-master/examples/einstein/__init__.py deleted file mode 100755 index e69de29b..00000000 diff --git a/csp/port2/python-constraint-master/examples/einstein/einstein.py b/csp/port2/python-constraint-master/examples/einstein/einstein.py deleted file mode 100755 index 2ce6e45b..00000000 --- a/csp/port2/python-constraint-master/examples/einstein/einstein.py +++ /dev/null @@ -1,209 +0,0 @@ -#!/usr/bin/python -# -# ALBERT EINSTEIN'S RIDDLE -# -# ARE YOU IN THE TOP 2% OF INTELLIGENT PEOPLE IN THE WORLD? -# SOLVE THE RIDDLE AND FIND OUT. -# -# There are no tricks, just pure logic, so good luck and don't give up. -# -# 1. In a street there are five houses, painted five different colours. -# 2. In each house lives a person of different nationality -# 3. These five homeowners each drink a different kind of beverage, smoke -# different brand of cigar and keep a different pet. -# -# THE QUESTION: WHO OWNS THE FISH? -# -# HINTS -# -# 1. The Brit lives in a red house. -# 2. The Swede keeps dogs as pets. -# 3. The Dane drinks tea. -# 4. The Green house is on the left of the White house. -# 5. The owner of the Green house drinks coffee. -# 6. The person who smokes Pall Mall rears birds. -# 7. The owner of the Yellow house smokes Dunhill. -# 8. The man living in the centre house drinks milk. -# 9. The Norwegian lives in the first house. -# 10. The man who smokes Blends lives next to the one who keeps cats. -# 11. The man who keeps horses lives next to the man who smokes Dunhill. -# 12. The man who smokes Blue Master drinks beer. -# 13. The German smokes Prince. -# 14. The Norwegian lives next to the blue house. -# 15. The man who smokes Blends has a neighbour who drinks water. -# -# ALBERT EINSTEIN WROTE THIS RIDDLE EARLY DURING THE 19th CENTURY. HE -# SAID THAT 98% OF THE WORLD POPULATION WOULD NOT BE ABLE TO SOLVE IT. - -from constraint import Problem, AllDifferentConstraint - -# Check http://www.csc.fi/oppaat/f95/python/talot.py - - -def solve(): - problem = Problem() - for i in range(1, 6): - problem.addVariable("color%d" % i, - ["red", "white", "green", "yellow", "blue"]) - problem.addVariable("nationality%d" % i, - ["brit", "swede", "dane", "norwegian", "german"]) - problem.addVariable("drink%d" % i, - ["tea", "coffee", "milk", "beer", "water"]) - problem.addVariable("smoke%d" % i, - ["pallmall", "dunhill", "blends", - "bluemaster", "prince"]) - problem.addVariable("pet%d" % i, - ["dogs", "birds", "cats", "horses", "fish"]) - - problem.addConstraint(AllDifferentConstraint(), - ["color%d" % i for i in range(1, 6)]) - problem.addConstraint(AllDifferentConstraint(), - ["nationality%d" % i for i in range(1, 6)]) - problem.addConstraint(AllDifferentConstraint(), - ["drink%d" % i for i in range(1, 6)]) - problem.addConstraint(AllDifferentConstraint(), - ["smoke%d" % i for i in range(1, 6)]) - problem.addConstraint(AllDifferentConstraint(), - ["pet%d" % i for i in range(1, 6)]) - - for i in range(1, 6): - - # Hint 1 - problem.addConstraint(lambda nationality, color: - nationality != "brit" or color == "red", - ("nationality%d" % i, "color%d" % i)) - - # Hint 2 - problem.addConstraint(lambda nationality, pet: - nationality != "swede" or pet == "dogs", - ("nationality%d" % i, "pet%d" % i)) - - # Hint 3 - problem.addConstraint(lambda nationality, drink: - nationality != "dane" or drink == "tea", - ("nationality%d" % i, "drink%d" % i)) - - # Hint 4 - if i < 5: - problem.addConstraint(lambda colora, colorb: - colora != "green" or colorb == "white", - ("color%d" % i, "color%d" % (i + 1))) - else: - problem.addConstraint(lambda color: color != "green", - ("color%d" % i,)) - - # Hint 5 - problem.addConstraint(lambda color, drink: - color != "green" or drink == "coffee", - ("color%d" % i, "drink%d" % i)) - - # Hint 6 - problem.addConstraint(lambda smoke, pet: - smoke != "pallmall" or pet == "birds", - ("smoke%d" % i, "pet%d" % i)) - - # Hint 7 - problem.addConstraint(lambda color, smoke: - color != "yellow" or smoke == "dunhill", - ("color%d" % i, "smoke%d" % i)) - - # Hint 8 - if i == 3: - problem.addConstraint(lambda drink: drink == "milk", - ("drink%d" % i,)) - - # Hint 9 - if i == 1: - problem.addConstraint(lambda nationality: - nationality == "norwegian", - ("nationality%d" % i,)) - - # Hint 10 - if 1 < i < 5: - problem.addConstraint(lambda smoke, peta, petb: - smoke != "blends" or peta == "cats" or - petb == "cats", - ("smoke%d" % i, "pet%d" % (i - 1), - "pet%d" % (i + 1))) - else: - problem.addConstraint(lambda smoke, pet: - smoke != "blends" or pet == "cats", - ("smoke%d" % i, - "pet%d" % (i == 1 and 2 or 4))) - - # Hint 11 - if 1 < i < 5: - problem.addConstraint(lambda pet, smokea, smokeb: - pet != "horses" or smokea == "dunhill" or - smokeb == "dunhill", - ("pet%d" % i, "smoke%d" % (i - 1), - "smoke%d" % (i + 1))) - else: - problem.addConstraint(lambda pet, smoke: - pet != "horses" or smoke == "dunhill", - ("pet%d" % i, - "smoke%d" % (i == 1 and 2 or 4))) - - # Hint 12 - problem.addConstraint(lambda smoke, drink: - smoke != "bluemaster" or drink == "beer", - ("smoke%d" % i, "drink%d" % i)) - - # Hint 13 - problem.addConstraint(lambda nationality, smoke: - nationality != "german" or smoke == "prince", - ("nationality%d" % i, "smoke%d" % i)) - - # Hint 14 - if 1 < i < 5: - problem.addConstraint(lambda nationality, colora, colorb: - nationality != "norwegian" or - colora == "blue" or colorb == "blue", - ("nationality%d" % i, "color%d" % (i - 1), - "color%d" % (i + 1))) - else: - problem.addConstraint(lambda nationality, color: - nationality != "norwegian" or - color == "blue", - ("nationality%d" % i, - "color%d" % (i == 1 and 2 or 4))) - - # Hint 15 - if 1 < i < 5: - problem.addConstraint(lambda smoke, drinka, drinkb: - smoke != "blends" or - drinka == "water" or drinkb == "water", - ("smoke%d" % i, "drink%d" % (i - 1), - "drink%d" % (i + 1))) - else: - problem.addConstraint(lambda smoke, drink: - smoke != "blends" or drink == "water", - ("smoke%d" % i, - "drink%d" % (i == 1 and 2 or 4))) - - solutions = problem.getSolutions() - return solutions - - -def showSolution(solution): - for i in range(1, 6): - print("House %d" % i) - print("--------") - print("Nationality: %s" % solution["nationality%d" % i]) - print("Color: %s" % solution["color%d" % i]) - print("Drink: %s" % solution["drink%d" % i]) - print("Smoke: %s" % solution["smoke%d" % i]) - print("Pet: %s" % solution["pet%d" % i]) - print("") - - -def main(): - solutions = solve() - print("Found %d solution(s)!" % len(solutions)) - print("") - for solution in solutions: - showSolution(solution) - - -if __name__ == "__main__": - main() diff --git a/csp/port2/python-constraint-master/examples/queens/__init__.py b/csp/port2/python-constraint-master/examples/queens/__init__.py deleted file mode 100755 index e69de29b..00000000 diff --git a/csp/port2/python-constraint-master/examples/queens/queens.py b/csp/port2/python-constraint-master/examples/queens/queens.py deleted file mode 100755 index 88aa5651..00000000 --- a/csp/port2/python-constraint-master/examples/queens/queens.py +++ /dev/null @@ -1,54 +0,0 @@ -#!/usr/bin/python -# -# http://mathworld.wolfram.com/QueensProblem.html -# -from constraint import Problem -import sys - - -def solve(): - problem = Problem() - size = 8 - cols = range(size) - rows = range(size) - problem.addVariables(cols, rows) - for col1 in cols: - for col2 in cols: - if col1 < col2: - problem.addConstraint(lambda row1, row2, col1=col1, col2=col2: - abs(row1 - row2) != abs(col1 - col2) and - row1 != row2, (col1, col2)) - solutions = problem.getSolutions() - return solutions, size - - -def showSolution(solution, size): - sys.stdout.write(" %s \n" % ("-" * ((size * 4) - 1))) - for i in range(size): - sys.stdout.write(" |") - for j in range(size): - if solution[j] == i: - sys.stdout.write(" %d |" % j) - else: - sys.stdout.write(" |") - sys.stdout.write("\n") - if i != size - 1: - sys.stdout.write(" |%s|\n" % ("-" * ((size * 4) - 1))) - sys.stdout.write(" %s \n" % ("-" * ((size * 4) - 1))) - - -def main(show=False): - solutions, size = solve() - print("Found %d solution(s)!" % len(solutions)) - if show: - for solution in solutions: - showSolution(solution, size) - - -if __name__ == "__main__": - show = False - if len(sys.argv) == 2 and sys.argv[1] == "-s": - show = True - elif len(sys.argv) != 1: - sys.exit("Usage: queens.py [-s]") - main(show) diff --git a/csp/port2/python-constraint-master/examples/rooks/__init__.py b/csp/port2/python-constraint-master/examples/rooks/__init__.py deleted file mode 100755 index e69de29b..00000000 diff --git a/csp/port2/python-constraint-master/examples/rooks/rooks.py b/csp/port2/python-constraint-master/examples/rooks/rooks.py deleted file mode 100755 index a7979019..00000000 --- a/csp/port2/python-constraint-master/examples/rooks/rooks.py +++ /dev/null @@ -1,57 +0,0 @@ -#!/usr/bin/python -# -# http://mathworld.wolfram.com/RooksProblem.html -# -from constraint import Problem -import sys - - -def factorial(x): - return x == 1 or factorial(x - 1) * x - - -def solve(size): - problem = Problem() - cols = range(size) - rows = range(size) - problem.addVariables(cols, rows) - for col1 in cols: - for col2 in cols: - if col1 < col2: - problem.addConstraint(lambda row1, row2: row1 != row2, - (col1, col2)) - solutions = problem.getSolutions() - return solutions - - -def main(show=False): - size = 8 - solutions = solve(size) - print("Found %d solution(s)!" % len(solutions)) - if show: - for solution in solutions: - showSolution(solution, size) - - -def showSolution(solution, size): - sys.stdout.write(" %s \n" % ("-" * ((size * 4) - 1))) - for i in range(size): - sys.stdout.write(" |") - for j in range(size): - if solution[j] == i: - sys.stdout.write(" %d |" % j) - else: - sys.stdout.write(" |") - sys.stdout.write("\n") - if i != size - 1: - sys.stdout.write(" |%s|\n" % ("-" * ((size * 4) - 1))) - sys.stdout.write(" %s \n" % ("-" * ((size * 4) - 1))) - - -if __name__ == "__main__": - show = False - if len(sys.argv) == 2 and sys.argv[1] == "-s": - show = True - elif len(sys.argv) != 1: - sys.exit("Usage: rooks.py [-s]") - main(show) diff --git a/csp/port2/python-constraint-master/examples/studentdesks/__init__.py b/csp/port2/python-constraint-master/examples/studentdesks/__init__.py deleted file mode 100755 index e69de29b..00000000 diff --git a/csp/port2/python-constraint-master/examples/studentdesks/studentdesks.py b/csp/port2/python-constraint-master/examples/studentdesks/studentdesks.py deleted file mode 100755 index a2978ec9..00000000 --- a/csp/port2/python-constraint-master/examples/studentdesks/studentdesks.py +++ /dev/null @@ -1,48 +0,0 @@ -#!/usr/bin/python -# -# http://home.chello.no/~dudley/ -# -from constraint import Problem, AllDifferentConstraint, SomeInSetConstraint -import sys - -STUDENTDESKS = [[0, 1, 0, 0, 0, 0], - [0, 2, 3, 4, 5, 6], - [0, 7, 8, 9, 10, 0], - [0, 11, 12, 13, 14, 0], - [15, 16, 17, 18, 19, 0], - [0, 0, 0, 0, 20, 0]] - - -def solve(): - problem = Problem() - problem.addVariables(range(1, 21), ["A", "B", "C", "D", "E"]) - problem.addConstraint(SomeInSetConstraint(["A"], 4, True)) - problem.addConstraint(SomeInSetConstraint(["B"], 4, True)) - problem.addConstraint(SomeInSetConstraint(["C"], 4, True)) - problem.addConstraint(SomeInSetConstraint(["D"], 4, True)) - problem.addConstraint(SomeInSetConstraint(["E"], 4, True)) - for row in range(len(STUDENTDESKS) - 1): - for col in range(len(STUDENTDESKS[row]) - 1): - lst = [STUDENTDESKS[row][col], STUDENTDESKS[row][col + 1], - STUDENTDESKS[row + 1][col], STUDENTDESKS[row + 1][col + 1]] - lst = [x for x in lst if x] - problem.addConstraint(AllDifferentConstraint(), lst) - solutions = problem.getSolution() - return solutions - - -def main(): - solutions = solve() - showSolution(solutions) - - -def showSolution(solution): - for row in range(len(STUDENTDESKS)): - for col in range(len(STUDENTDESKS[row])): - id = STUDENTDESKS[row][col] - sys.stdout.write(" %s" % (id and solution[id] or " ")) - sys.stdout.write("\n") - - -if __name__ == "__main__": - main() diff --git a/csp/port2/python-constraint-master/examples/sudoku/__init__.py b/csp/port2/python-constraint-master/examples/sudoku/__init__.py deleted file mode 100755 index e69de29b..00000000 diff --git a/csp/port2/python-constraint-master/examples/sudoku/sudoku.py b/csp/port2/python-constraint-master/examples/sudoku/sudoku.py deleted file mode 100755 index 820c76dd..00000000 --- a/csp/port2/python-constraint-master/examples/sudoku/sudoku.py +++ /dev/null @@ -1,71 +0,0 @@ -# -# Sudoku puzzle solver by by Luigi Poderico (www.poderico.it). -# -import sys -from constraint import Problem, AllDifferentConstraint - - -def solve(): - problem = Problem() - - # Define the variables: 9 rows of 9 variables rangin in 1...9 - for i in range(1, 10): - problem.addVariables(range(i * 10 + 1, i * 10 + 10), range(1, 10)) - - # Each row has different values - for i in range(1, 10): - problem.addConstraint(AllDifferentConstraint(), range(i * 10 + 1, i * 10 + 10)) - - # Each colum has different values - for i in range(1, 10): - problem.addConstraint(AllDifferentConstraint(), range(10 + i, 100 + i, 10)) - - # Each 3x3 box has different values - problem.addConstraint(AllDifferentConstraint(), [11, 12, 13, 21, 22, 23, 31, 32, 33]) - problem.addConstraint(AllDifferentConstraint(), [41, 42, 43, 51, 52, 53, 61, 62, 63]) - problem.addConstraint(AllDifferentConstraint(), [71, 72, 73, 81, 82, 83, 91, 92, 93]) - - problem.addConstraint(AllDifferentConstraint(), [14, 15, 16, 24, 25, 26, 34, 35, 36]) - problem.addConstraint(AllDifferentConstraint(), [44, 45, 46, 54, 55, 56, 64, 65, 66]) - problem.addConstraint(AllDifferentConstraint(), [74, 75, 76, 84, 85, 86, 94, 95, 96]) - - problem.addConstraint(AllDifferentConstraint(), [17, 18, 19, 27, 28, 29, 37, 38, 39]) - problem.addConstraint(AllDifferentConstraint(), [47, 48, 49, 57, 58, 59, 67, 68, 69]) - problem.addConstraint(AllDifferentConstraint(), [77, 78, 79, 87, 88, 89, 97, 98, 99]) - - # Some value is given. - initValue = [[0, 9, 0, 7, 0, 0, 8, 6, 0], - [0, 3, 1, 0, 0, 5, 0, 2, 0], - [8, 0, 6, 0, 0, 0, 0, 0, 0], - [0, 0, 7, 0, 5, 0, 0, 0, 6], - [0, 0, 0, 3, 0, 7, 0, 0, 0], - [5, 0, 0, 0, 1, 0, 7, 0, 0], - [0, 0, 0, 0, 0, 0, 1, 0, 9], - [0, 2, 0, 6, 0, 0, 0, 5, 0], - [0, 5, 4, 0, 0, 8, 0, 7, 0]] - - for i in range(1, 10): - for j in range(1, 10): - if initValue[i - 1][j - 1] != 0: - problem.addConstraint(lambda var, val=initValue[i - 1][j - 1]: - var == val, (i * 10 + j,)) - - # Get the solutions. - solutions = problem.getSolutions() - return solutions - - -def main(): - solutions = solve() - # Print the solutions - for solution in solutions: - for i in range(1, 10): - for j in range(1, 10): - index = i * 10 + j - sys.stdout.write("%s " % solution[index]) - print("") - print("") - - -if __name__ == "__main__": - main() diff --git a/csp/port2/python-constraint-master/examples/wordmath/__init__.py b/csp/port2/python-constraint-master/examples/wordmath/__init__.py deleted file mode 100755 index e69de29b..00000000 diff --git a/csp/port2/python-constraint-master/examples/wordmath/seisseisdoze.py b/csp/port2/python-constraint-master/examples/wordmath/seisseisdoze.py deleted file mode 100755 index 22776db0..00000000 --- a/csp/port2/python-constraint-master/examples/wordmath/seisseisdoze.py +++ /dev/null @@ -1,39 +0,0 @@ -#!/usr/bin/python -# -# Assign equal values to equal letters, and different values to -# different letters, in a way that satisfies the following sum: -# -# SEIS -# + SEIS -# ------ -# DOZE -# -from constraint import Problem, AllDifferentConstraint - - -def solve(): - problem = Problem() - problem.addVariables("seidoz", range(10)) - problem.addConstraint(lambda s, e: (2 * s) % 10 == e, "se") - problem.addConstraint(lambda i, s, z, e: ((10 * 2 * i) + (2 * s)) % 100 == - z * 10 + e, "isze") - problem.addConstraint(lambda s, e, i, d, o, z: - 2 * (s * 1000 + e * 100 + i * 10 + s) == - d * 1000 + o * 100 + z * 10 + e, "seidoz") - problem.addConstraint(lambda s: s != 0, "s") - problem.addConstraint(lambda d: d != 0, "d") - problem.addConstraint(AllDifferentConstraint()) - solutions = problem.getSolutions() - return solutions - - -def main(): - solutions = solve() - print("SEIS+SEIS=DOZE") - for s in solutions: - print("%(s)d%(e)d%(i)d%(s)s+%(s)d%(e)d%(i)d%(s)d=" - "%(d)d%(o)d%(z)d%(e)d") % s - - -if __name__ == "__main__": - main() diff --git a/csp/port2/python-constraint-master/examples/wordmath/sendmoremoney.py b/csp/port2/python-constraint-master/examples/wordmath/sendmoremoney.py deleted file mode 100755 index 9e9578ec..00000000 --- a/csp/port2/python-constraint-master/examples/wordmath/sendmoremoney.py +++ /dev/null @@ -1,42 +0,0 @@ -#!/usr/bin/python -# -# Assign equal values to equal letters, and different values to -# different letters, in a way that satisfies the following sum: -# -# SEND -# + MORE -# ------ -# MONEY -# -from constraint import Problem, NotInSetConstraint, AllDifferentConstraint - - -def solve(): - problem = Problem() - problem.addVariables("sendmory", range(10)) - problem.addConstraint(lambda d, e, y: (d + e) % 10 == y, "dey") - problem.addConstraint(lambda n, d, r, e, y: (n * 10 + d + r * 10 + e) % 100 == - e * 10 + y, "ndrey") - problem.addConstraint(lambda e, n, d, o, r, y: - (e * 100 + n * 10 + d + o * 100 + r * 10 + e) % 1000 == - n * 100 + e * 10 + y, "endory") - problem.addConstraint(lambda s, e, n, d, m, o, r, y: - 1000 * s + 100 * e + 10 * n + d + 1000 * m + 100 * o + 10 * r + e == - 10000 * m + 1000 * o + 100 * n + 10 * e + y, "sendmory") - problem.addConstraint(NotInSetConstraint([0]), "sm") - problem.addConstraint(AllDifferentConstraint()) - solutions = problem.getSolutions() - return solutions - - -def main(): - solutions = solve() - print("SEND+MORE=MONEY") - for s in solutions: - print("%(s)d%(e)d%(n)d%(d)d+" - "%(m)d%(o)d%(r)d%(e)d=" - "%(m)d%(o)d%(n)d%(e)d%(y)d" % s) - - -if __name__ == "__main__": - main() diff --git a/csp/port2/python-constraint-master/examples/wordmath/twotwofour.py b/csp/port2/python-constraint-master/examples/wordmath/twotwofour.py deleted file mode 100755 index 33e4aabb..00000000 --- a/csp/port2/python-constraint-master/examples/wordmath/twotwofour.py +++ /dev/null @@ -1,37 +0,0 @@ -#!/usr/bin/python -# -# Assign equal values to equal letters, and different values to -# different letters, in a way that satisfies the following sum: -# -# TWO -# + TWO -# ----- -# FOUR -# -from constraint import Problem, AllDifferentConstraint, NotInSetConstraint - - -def solve(): - problem = Problem() - problem.addVariables("twofur", range(10)) - problem.addConstraint(lambda o, r: (2 * o) % 10 == r, "or") - problem.addConstraint(lambda w, o, u, - r: ((10 * 2 * w) + (2 * o)) % 100 == u * 10 + r, "wour") - problem.addConstraint(lambda t, w, o, f, u, r: - 2 * (t * 100 + w * 10 + o) == - f * 1000 + o * 100 + u * 10 + r, "twofur") - problem.addConstraint(NotInSetConstraint([0]), "ft") - problem.addConstraint(AllDifferentConstraint()) - solutions = problem.getSolutions() - return solutions - - -def main(): - solutions = solve() - print("TWO+TWO=FOUR") - for s in solutions: - print("%(t)d%(w)d%(o)d+%(t)d%(w)d%(o)d=%(f)d%(o)d%(u)d%(r)d" % s) - - -if __name__ == "__main__": - main() diff --git a/csp/port2/python-constraint-master/examples/xsum/__init__.py b/csp/port2/python-constraint-master/examples/xsum/__init__.py deleted file mode 100755 index e69de29b..00000000 diff --git a/csp/port2/python-constraint-master/examples/xsum/xsum.py b/csp/port2/python-constraint-master/examples/xsum/xsum.py deleted file mode 100755 index 987438f3..00000000 --- a/csp/port2/python-constraint-master/examples/xsum/xsum.py +++ /dev/null @@ -1,48 +0,0 @@ -#!/usr/bin/python -# -# Reorganize the following numbers in a way that each line of -# 5 numbers sum to 27. -# -# 1 6 -# 2 7 -# 3 -# 8 4 -# 9 5 -# -from constraint import Problem, AllDifferentConstraint - - -def solve(): - problem = Problem() - problem.addVariables("abcdxefgh", range(1, 10)) - problem.addConstraint(lambda a, b, c, d, x: - a < b < c < d and a + b + c + d + x == 27, "abcdx") - problem.addConstraint(lambda e, f, g, h, x: - e < f < g < h and e + f + g + h + x == 27, "efghx") - problem.addConstraint(AllDifferentConstraint()) - solutions = problem.getSolutions() - return solutions - - -def main(): - solutions = solve() - print("Found %d solutions!" % len(solutions)) - showSolutions(solutions) - - -def showSolutions(solutions): - for solution in solutions: - print(""" %d %d - %d %d - %d - %d %d - %d %d -""" % (solution["a"], solution["e"], - solution["b"], solution["f"], - solution["x"], - solution["g"], solution["c"], - solution["h"], solution["d"])) - - -if __name__ == "__main__": - main() diff --git a/csp/port2/python-constraint-master/setup.cfg b/csp/port2/python-constraint-master/setup.cfg deleted file mode 100755 index 5bf04527..00000000 --- a/csp/port2/python-constraint-master/setup.cfg +++ /dev/null @@ -1,9 +0,0 @@ -[bdist_wheel] -universal = 1 - -[bdist_rpm] -doc_files = README.rst -use_bzip2 = 1 - -[sdist] -formats = bztar diff --git a/csp/port2/python-constraint-master/setup.py b/csp/port2/python-constraint-master/setup.py deleted file mode 100755 index 4a597e55..00000000 --- a/csp/port2/python-constraint-master/setup.py +++ /dev/null @@ -1,123 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -from setuptools import setup, find_packages # Always prefer setuptools over distutils -from codecs import open # To use a consistent encoding -from os import path -import io - -NAME = 'python-constraint' -filename = "%s/version.py" % 'constraint' -with open(filename) as f: - exec(f.read()) - -here = path.abspath(path.dirname(__file__)) - -def readme(): - filename = path.join(here, 'README.rst') - with io.open(filename, 'rt', encoding='UTF-8') as f: - return f.read() - -setup( - name=NAME, - - # Versions should comply with PEP440. For a discussion on single-sourcing - # the version across setup.py and the project code, see - # https://packaging.python.org/en/latest/development.html#single-sourcing-the-version - #version='0.0.1', - version=__version__, - - description="python-constraint is a module implementing support "\ - "for handling CSPs (Constraint Solving Problems) over finite domain", - - long_description=readme(), - - # The project's main homepage. - url=__url__, - - # Author details - author=__author__, - author_email=__email__, - - # Choose your license - license=__license__, - - # See https://pypi.python.org/pypi?%3Aaction=list_classifiers - classifiers=[ - # How mature is this project? Common values are - # 3 - Alpha - # 4 - Beta - # 5 - Production/Stable - 'Development Status :: 3 - Alpha', - - # Indicate who your project is intended for - 'Environment :: Console', - #'Topic :: Software Development :: Build Tools', - 'Intended Audience :: Science/Research', - 'Operating System :: OS Independent', - - # Specify the Python versions you support here. In particular, ensure - # that you indicate whether you support Python 2, Python 3 or both. - 'Programming Language :: Cython', - - 'Programming Language :: Python', - #'Programming Language :: Python :: 2', - #'Programming Language :: Python :: 2.6', - 'Programming Language :: Python :: 2.7', - #'Programming Language :: Python :: 3', - #'Programming Language :: Python :: 3.2', - 'Programming Language :: Python :: 3.3', - 'Programming Language :: Python :: 3.4', - 'Programming Language :: Python :: 3.5', - 'Programming Language :: Python :: 3.6', - - 'Topic :: Scientific/Engineering', - - # Pick your license as you wish (should match "license" above) - 'License :: OSI Approved :: BSD License', - - ], - - # What does your project relate to? - keywords='csp constraint solving problems problem solver', - - # You can just specify the packages manually here if your project is - # simple. Or you can use find_packages(). - packages=find_packages(exclude=['contrib', 'docs', 'tests*']), - - # List run-time dependencies here. These will be installed by pip when your - # project is installed. For an analysis of "install_requires" vs pip's - # requirements files see: - # https://packaging.python.org/en/latest/technical.html#install-requires-vs-requirements-files - install_requires=[], - - # List additional groups of dependencies here (e.g. development dependencies). - # You can install these using the following syntax, for example: - # $ pip install -e .[dev,test] - extras_require = { - 'dev': ['check-manifest', 'nose'], - 'test': ['coverage', 'nose'], - }, - - # If there are data files included in your packages that need to be - # installed, specify them here. If using Python 2.6 or less, then these - # have to be included in MANIFEST.in as well. - #package_data={ - # 'sample': ['logging.conf'], - #}, - - # Although 'package_data' is the preferred approach, in some case you may - # need to place data files outside of your packages. - # see http://docs.python.org/3.4/distutils/setupscript.html#installing-additional-files - # In this case, 'data_file' will be installed into '/my_data' - #data_files=[('my_data', ['data/data_file'])], - - # To provide executable scripts, use entry points in preference to the - # "scripts" keyword. Entry points provide cross-platform support and allow - # pip to create the appropriate form of executable for the target platform. - #entry_points={ - # 'console_scripts': [ - # 'sample=sample:main', - # ], - #}, -) diff --git a/csp/port2/python-constraint-master/tests/test_constraint.py b/csp/port2/python-constraint-master/tests/test_constraint.py deleted file mode 100755 index e644bf4b..00000000 --- a/csp/port2/python-constraint-master/tests/test_constraint.py +++ /dev/null @@ -1,91 +0,0 @@ -import constraint - -from examples.abc import abc -from examples.coins import coins -# from examples.crosswords import crosswords -from examples.einstein import einstein -from examples.queens import queens -from examples.rooks import rooks -from examples.studentdesks import studentdesks -# from examples.sudoku import sudoku -# from examples.wordmath import (seisseisdoze, sendmoremoney, twotwofour) -# from examples.xsum import xsum - -import constraint.compat as compat - - -def test_abc(): - solutions = abc.solve() - minvalue, minsolution = solutions - assert minvalue == 37 - assert minsolution == {'a': 1, 'c': 2, 'b': 1} - - -def test_coins(): - solutions = coins.solve() - assert len(solutions) == 2 - - -def test_einstein(): - solutions = einstein.solve() - expected_solutions = [ - { - 'nationality2': 'dane', - 'nationality3': 'brit', - 'nationality1': 'norwegian', - 'nationality4': 'german', - 'nationality5': 'swede', - 'color1': 'yellow', - 'color3': 'red', - 'color2': 'blue', - 'color5': 'white', - 'color4': 'green', - 'drink4': 'coffee', - 'drink5': 'beer', - 'drink1': 'water', - 'drink2': 'tea', - 'drink3': 'milk', - 'smoke5': 'bluemaster', - 'smoke4': 'prince', - 'smoke3': 'pallmall', - 'smoke2': 'blends', - 'smoke1': 'dunhill', - 'pet5': 'dogs', - 'pet4': 'fish', - 'pet1': 'cats', - 'pet3': 'birds', - 'pet2': 'horses' - } - ] - assert solutions == expected_solutions - - -def test_queens(): - solutions, size = queens.solve() - assert size == 8 - for solution in solutions: - queens.showSolution(solution, size) - - -def test_rooks(): - size = 8 - solutions = rooks.solve(size) - assert len(solutions) == rooks.factorial(size) - - -def test_studentdesks(): - solutions = studentdesks.solve() - expected_solutions = {1: 'A', 2: 'E', 3: 'D', 4: 'E', 5: 'D', 6: 'A', 7: 'C', 8: 'B', 9: 'C', 10: 'B', 11: 'E', 12: 'D', 13: 'E', 14: 'D', 15: 'A', 16: 'C', 17: 'B', 18: 'C', 19: 'B', 20: 'A'} - assert solutions == expected_solutions - - -def test_constraint_without_variables(): - problem = constraint.Problem() - problem.addVariable("a", [1, 2, 3]) - problem.addConstraint(lambda a: a * 2 == 6) - solutions = problem.getSolutions() - assert solutions == [{'a': 3}] - - -def test_version(): - assert isinstance(constraint.__version__, compat.string_types) diff --git a/csp/port2/python-constraint-master/tests/test_solvers.py b/csp/port2/python-constraint-master/tests/test_solvers.py deleted file mode 100755 index 1a24d382..00000000 --- a/csp/port2/python-constraint-master/tests/test_solvers.py +++ /dev/null @@ -1,17 +0,0 @@ -from constraint import Problem, MinConflictsSolver - - -def test_min_conflicts_solver(): - problem = Problem(MinConflictsSolver()) - problem.addVariable("x", [0, 1]) - problem.addVariable("y", [0, 1]) - solution = problem.getSolution() - - possible_solutions = [ - {'x': 0, 'y': 0}, - {'x': 0, 'y': 1}, - {'x': 1, 'y': 0}, - {'x': 1, 'y': 1} - ] - - assert solution in possible_solutions diff --git a/csp/port2/python-constraint-master/tests/test_some_not_in_set.py b/csp/port2/python-constraint-master/tests/test_some_not_in_set.py deleted file mode 100755 index 31ac4fc4..00000000 --- a/csp/port2/python-constraint-master/tests/test_some_not_in_set.py +++ /dev/null @@ -1,102 +0,0 @@ -from constraint import Domain, Variable, SomeNotInSetConstraint - - -def test_empty_constraint(): - constrainer = SomeNotInSetConstraint(set()) - v1, v2 = variables = [Variable('v1'), Variable('v2')] - assignments = {v1: 'a', v2: 'b'} - - assert constrainer(variables, {}, assignments) - - -def test_no_overlap(): - constrainer = SomeNotInSetConstraint(set('zy')) - v1, v2 = variables = [Variable('v1'), Variable('v2')] - assignments = {v1: 'a', v2: 'b'} - - assert constrainer(variables, {}, assignments) - - -def test_some_overlap(): - constrainer = SomeNotInSetConstraint(set('b')) - v1, v2 = variables = [Variable('v1'), Variable('v2')] - assignments = {v1: 'a', v2: 'b'} - - assert constrainer(variables, {}, assignments) - - -def test_too_much_overlap(): - constrainer = SomeNotInSetConstraint(set('ab')) - v1, v2 = variables = [Variable('v1'), Variable('v2')] - assignments = {v1: 'a', v2: 'b'} - - assert not constrainer(variables, {}, assignments) - - -def test_exact(): - constrainer = SomeNotInSetConstraint(set('abc'), n=2, exact=True) - v1, v2, v3 = variables = [Variable('v1'), Variable('v2'), Variable('v3')] - - assignments = {v1: 'a', v2: 'y', v3: 'z'} - assert constrainer(variables, {}, assignments) - - assignments = {v1: 'a', v2: 'y'} - assert constrainer(variables, {}, assignments) - - assignments = {v1: 'a', v2: 'b', v3: 'z'} - assert not constrainer(variables, {}, assignments) - - assignments = {v1: 'a', v2: 'b'} - assert not constrainer(variables, {}, assignments) - - assignments = {v1: 'a', v2: 'b', v3: 'c'} - assert not constrainer(variables, {}, assignments) - - assignments = {v1: 'x', v2: 'y', v3: 'z'} - assert not constrainer(variables, {}, assignments) - - -def test_forwardcheck(): - constrainer = SomeNotInSetConstraint(set('abc'), n=2) - v1, v2, v3 = variables = [Variable('v1'), Variable('v2'), Variable('v3')] - - domains = {v1: Domain(['a']), v2: Domain(['b', 'y']), - v3: Domain(['c', 'z'])} - assert constrainer(variables, domains, {v1: 'a'}) - assert ['a'] == list(domains[v1]) - assert ['b', 'y'] == list(domains[v2]) - assert ['c', 'z'] == list(domains[v3]) - - assert constrainer(variables, domains, {v1: 'a'}, True) - assert ['a'] == list(domains[v1]) - assert ['y'] == list(domains[v2]) - assert ['z'] == list(domains[v3]) - - -def test_forwardcheck_empty_domain(): - constrainer = SomeNotInSetConstraint(set('abc')) - v1, v2 = variables = [Variable('v1'), Variable('v2')] - - domains = {v1: Domain(['a']), v2: Domain(['b'])} - assert constrainer(variables, domains, {v1: 'a'}) - assert not constrainer(variables, domains, {v1: 'a'}, True) - - -def test_forwardcheck_exact(): - constrainer = SomeNotInSetConstraint(set('abc'), n=2, exact=True) - v1, v2, v3 = variables = [Variable('v1'), Variable('v2'), Variable('v3')] - assignments = {v1: 'a'} - - domains = {v1: Domain(['a', 'x']), v2: Domain(['b', 'y']), - v3: Domain(['c', 'z'])} - assert constrainer(variables, domains, assignments) - assert constrainer(variables, domains, assignments, True) - assert 'b' not in domains[v2] - assert 'y' in domains[v2] - assert 'c' not in domains[v3] - assert 'z' in domains[v3] - - domains = {v1: Domain(['a', 'x']), v2: Domain(['b', 'y']), - v3: Domain(['c'])} - assert constrainer(variables, domains, assignments) - assert not constrainer(variables, domains, assignments, True)