main
Matthew Butterick 6 years ago
parent 62c11e1676
commit fe94d1ff60

@ -9,7 +9,7 @@
;; queens problem ;; queens problem
;; place queens on chessboard so they do not intersect ;; place queens on chessboard so they do not intersect
(define queens (make-csp)) (define queens (make-csp))
(define qs (for/list ([q 10]) (string->symbol (format "q~a" q)))) (define qs (for/list ([q 8]) (string->symbol (format "q~a" q))))
(define rows (range (length qs))) (define rows (range (length qs)))
(add-vars! queens qs rows) (add-vars! queens qs rows)
(define (q-col q) (string->number (string-trim (symbol->string q) "q"))) (define (q-col q) (string->number (string-trim (symbol->string q) "q")))

@ -28,6 +28,7 @@
(define constraints $csp-constraints) (define constraints $csp-constraints)
(define-syntax-rule (in-constraints csp) (in-list ($csp-constraints csp))) (define-syntax-rule (in-constraints csp) (in-list ($csp-constraints csp)))
(define-syntax-rule (in-vars csp) (in-list ($csp-vars csp))) (define-syntax-rule (in-vars csp) (in-list ($csp-vars csp)))
(define-syntax-rule (in-var-names csp) (in-list (map $var-name ($csp-vars csp))))
(struct $constraint (names proc) #:transparent (struct $constraint (names proc) #:transparent
#:property prop:procedure #:property prop:procedure
@ -209,18 +210,11 @@
[(? empty?) #false] [(? empty?) #false]
[(cons x _) x])) [(cons x _) x]))
(define/contract (argmin-random-tie proc xs)
(procedure? (non-empty-listof any/c) . -> . any/c)
(let* ([xs (sort xs < #:key proc)]
[xs (takef xs (λ (x) (= (proc (car xs)) (proc x))))]
[xs ((if (current-shuffle) shuffle values) xs)])
(first xs)))
(define/contract (minimum-remaining-values csp) (define/contract (minimum-remaining-values csp)
(csp? . -> . (or/c #false (and/c $var? (not/c assigned-var?)))) (csp? . -> . (or/c #false (and/c $var? (not/c assigned-var?))))
(match (unassigned-vars csp) (match (unassigned-vars csp)
[(? empty?) #false] [(? empty?) #false]
[xs (argmin-random-tie (λ (var) (length ($var-domain var))) xs)])) [xs (argmin (λ (var) (length ($var-domain var))) (shuffle xs))]))
(define mrv minimum-remaining-values) (define mrv minimum-remaining-values)
@ -419,7 +413,7 @@
conflicts)])))) conflicts)]))))
(define/contract (min-conflicts csp [max-steps (expt 10 3)]) (define/contract (min-conflicts csp [max-steps 64])
(($csp?) (integer?) . ->* . generator?) (($csp?) (integer?) . ->* . generator?)
;; Solve a CSP by stochastic hillclimbing on the number of conflicts. ;; Solve a CSP by stochastic hillclimbing on the number of conflicts.
(generator () (generator ()
@ -434,7 +428,7 @@
(for/fold ([csp starting-assignment]) (for/fold ([csp starting-assignment])
([i (in-range max-steps)]) ([i (in-range max-steps)])
(match (conflicted-var-names csp) (match (conflicted-var-names csp)
[(? empty?) (when (check-constraints csp) (report i 'steps-taken) (yield csp))] [(? empty?) (when (check-constraints csp) (yield csp)) (loop csp0)]
[cvar-names [cvar-names
(define cvar-name (first ((if (current-shuffle) shuffle values) cvar-names))) (define cvar-name (first ((if (current-shuffle) shuffle values) cvar-names)))
(define val (min-conflicts-value csp cvar-name ($csp-vals csp0 cvar-name))) (define val (min-conflicts-value csp cvar-name ($csp-vals csp0 cvar-name)))
@ -444,14 +438,14 @@
(define/contract (conflicted-var-names csp) (define/contract (conflicted-var-names csp)
($csp? . -> . (listof name?)) ($csp? . -> . (listof name?))
;; Return a list of variables in current assignment that are conflicted ;; Return a list of variables in current assignment that are conflicted
(for/list ([var (in-vars csp)] (for/list ([name (in-var-names csp)]
#:when (positive? (nconflicts csp (var-name var)))) #:when (positive? (nconflicts csp name)))
(var-name var))) name))
(define/contract (min-conflicts-value csp name vals) (define/contract (min-conflicts-value csp name vals)
($csp? name? (listof any/c) . -> . any/c) ($csp? name? (listof any/c) . -> . any/c)
;; Return the value that will give var the least number of conflicts ;; Return the value that will give var the least number of conflicts
(argmin-random-tie (λ (val) (nconflicts csp name val)) vals)) (argmin (λ (val) (nconflicts csp name val)) (shuffle vals)))
(define no-value-sig (gensym)) (define no-value-sig (gensym))
@ -460,7 +454,7 @@
;; How many conflicts var: val assignment has with other variables. ;; How many conflicts var: val assignment has with other variables.
(check-constraints (if (eq? val no-value-sig) (check-constraints (if (eq? val no-value-sig)
csp csp
(assign-val csp name val)) (list name) #:conflicts #t)) (assign-val csp name val)) (list name) #:conflicts #true))
(define/contract (csp->assocs csp) (define/contract (csp->assocs csp)
(csp? . -> . (listof (cons/c name? any/c))) (csp? . -> . (listof (cons/c name? any/c)))

Loading…
Cancel
Save