#lang racket
(require "smt-interface.rkt")
(require "dimacs.rkt")
(provide (all-defined-out))
(define ACTIVITY_INC 1.0)
(define ACTIVITY_DROPOFF 2.0)
(struct SAT (clauses learned-clauses variables partial-assignment decision-level assigned-order))
(struct SMT (sat T-State strength))
(define (new-SAT smt sat)
(SMT sat
(SMT-T-State smt)
(SMT-strength smt)))
(define (new-T-State smt t-state)
(SMT (SMT-sat smt)
t-state
(SMT-strength smt)))
(define (SMT-clauses smt) (SAT-clauses (SMT-sat smt)))
(define (SMT-learned-clauses smt) (SAT-learned-clauses (SMT-sat smt)))
(define (SMT-variables smt) (SAT-variables (SMT-sat smt)))
(define (SMT-partial-assignment smt) (SAT-partial-assignment (SMT-sat smt)))
(define (SMT-decision-level smt) (SAT-decision-level (SMT-sat smt)))
(define (SMT-assigned-order smt) (SAT-assigned-order (SMT-sat smt)))
(struct bail-exn (sat))
(struct unsat-exn (sat))
(struct sat-exn (sat))
(define (initialize cnf t-state strength)
(match cnf
[`(,var-count ,clause-count ((,lit ...) ...))
(let ((vars (make-n-vars var-count)))
(SMT
(SAT (list->vector (map (dimacs-lits->clause vars) lit))
'()
vars
'(())
0
0)
t-state
strength))]
[`((,lit ...) ...)
(let ((vars (make-n-vars (symbolic-lits->var-count lits))))
(SAT (list->vector (map (symbolic-lits->clause vars) lit))
'()
vars
'(())
0
0))]))
(define (learn-clause sat clause)
(SAT (SAT-clauses sat)
(cons clause (SAT-learned-clauses sat))
(SAT-variables sat)
(SAT-partial-assignment sat)
(SAT-decision-level sat)
(SAT-assigned-order sat)))
(define (SMT-learn-clause smt clause)
(new-SAT smt (learn-clause (SMT-sat smt) clause)))
(define (set-partial-assignment sat val)
(if (empty? val)
(error 'set-partial-assignment "Reality that which, when stop believing it, doesn't go away")
(SAT (SAT-clauses sat)
(SAT-learned-clauses sat)
(SAT-variables sat)
val
(SAT-decision-level sat)
(SAT-assigned-order sat))))
(define (SMT-set-partial-assignment smt val)
(new-SAT smt (set-partial-assignment (SMT-sat smt) val)))
(define (set-decision-level sat val)
(SAT (SAT-clauses sat)
(SAT-learned-clauses sat)
(SAT-variables sat)
(SAT-partial-assignment sat)
val
(SAT-assigned-order sat)))
(define (SMT-set-decision-level smt val)
(new-SAT smt (set-decision-level (SMT-sat smt) val)))
(define (inc-assigned-order sat)
(SAT (SAT-clauses sat)
(SAT-learned-clauses sat)
(SAT-variables sat)
(SAT-partial-assignment sat)
(SAT-decision-level sat)
(+ 1 (SAT-assigned-order sat))))
(define (SMT-inc-assigned-order smt)
(new-SAT smt (inc-assigned-order (SMT-sat smt))))
(define (satisfy-literal! sat literal)
(begin (set-var-value! (literal-var literal) (literal-polarity literal))
(set-var-timestamp! (literal-var literal) (SAT-assigned-order sat))
(add-to-current-decision-level (inc-assigned-order sat) literal)))
(define (SMT-satisfy-literal! smt literal)
(SMT (satisfy-literal! (SMT-sat smt) literal)
((T-Satisfy) (SMT-T-State smt) (literal->dimacs literal))
(SMT-strength smt)))
(define (add-to-current-decision-level sat literal)
(set-partial-assignment
sat
(cons (cons literal (first (SAT-partial-assignment sat)))
(rest (SAT-partial-assignment sat)))))
(define (SMT-add-to-current-decision-level smt literal)
(SMT-set-partial-assignment smt literal))
(struct clause (literals watched1 watched2) #:mutable)
(struct node (dec-lev antecedent))
(struct literal (var polarity) #:transparent)
(struct var
(name pos-watched neg-watched pos-activation neg-activation timestamp igraph-node value) #:mutable #:transparent)
(define (make-n-vars n)
(build-vector n (lambda (idx) (var (+ 1 idx) '() '() 0.0 0.0 #f #f 'unassigned))))
(define (var-for-theory? v)
(not (number? (var-name v))))
(define (literal-for-theory? lit)
(var-for-theory? (literal-var lit)))
(define (literal-implied? literal)
(let ((node (var-igraph-node (literal-var literal))))
(and node
(node-antecedent node))))
(define (clause-size clause)
(vector-length (clause-literals clause)))
(define (nth-literal clause n)
(vector-ref (clause-literals clause) n))
(define (add-literal-watched! clause literal)
(set-literal-watched! literal
(cons clause (literal-watched literal))))
(define (rem-literal-watched! clause literal)
(set-literal-watched! literal
(remove clause (literal-watched literal) eqv?)))
(define (clause-other-watched clause literal)
(cond [(literal-eq? literal (clause-watched1 clause)) (clause-watched2 clause)]
[(literal-eq? literal (clause-watched2 clause)) (clause-watched1 clause)]
[else (error 'clause-other-watched "That's not being watched at all.")]))
(define (clause-watched-swap! clause cur-watched new-watched)
(cond [(literal-eq? cur-watched (clause-watched1 clause))
(set-clause-watched1! clause new-watched)]
[(literal-eq? cur-watched (clause-watched2 clause))
(set-clause-watched2! clause new-watched)]))
(define (literal-name lit)
(var-name (literal-var lit)))
(define (literal-eq? l1 l2)
(and (eqv? (literal-var l1) (literal-var l2))
(eq? (literal-polarity l1) (literal-polarity l2))))
(define (negate-literal lit)
(literal (literal-var lit) (not (literal-polarity lit))))
(define (var-unassigned? var)
(eqv? 'unassigned (var-value var)))
(define (polarize-valuation valuation polarity)
(if (symbol? valuation) valuation
(eqv? valuation polarity)))
(define (literal-valuation literal)
(polarize-valuation (var-value (literal-var literal))
(literal-polarity literal)))
(define (literal-unassigned? literal)
(var-unassigned? (literal-var literal)))
(define (literal-timestamp literal)
(var-timestamp (literal-var literal)))
(define (literal-watched literal)
(if (literal-polarity literal)
(var-pos-watched (literal-var literal))
(var-neg-watched (literal-var literal))))
(define (literal-activation literal)
(if (literal-polarity literal)
(var-pos-activation (literal-var literal))
(var-neg-activation (literal-var literal))))
(define (set-literal-watched! literal val)
(if (literal-polarity literal)
(set-var-pos-watched! (literal-var literal) val)
(set-var-neg-watched! (literal-var literal) val)))
(define (set-literal-activation! literal val)
(if (literal-polarity literal)
(set-var-pos-activation! (literal-var literal) val)
(set-var-neg-activation! (literal-var literal) val)))
(define (set-literal-igraph-node! literal val)
(set-var-igraph-node! (literal-var literal) val))
(define (literal-antecedent literal)
(node-antecedent (var-igraph-node (literal-var literal))))
(define (literal-explanation smt literal)
(lemma->lits smt (literal-antecedent literal)))
(define (lemma->lits smt lemma)
(if (procedure? lemma)
(lemma smt)
(clause-literals lemma)))
(define (literal-dec-lev literal)
(node-dec-lev (var-igraph-node (literal-var literal))))
(define (inc-literal-activation! literal)
(set-literal-activation! literal (+ ACTIVITY_INC
(literal-activation literal))))
(define (increase-scores! literals [idx 0])
(if (not (= idx (vector-length literals)))
(begin (inc-literal-activation! (vector-ref literals idx))
(increase-scores! literals (+ 1 idx)))
'*void*))
(define (slash-all-literals! variables)
(let walk ((idx 0))
(if (not (= idx (vector-length variables)))
(let ((var (vector-ref variables idx)))
(begin (set-var-pos-activation! var (/ (var-pos-activation var) ACTIVITY_DROPOFF))
(set-var-neg-activation! var (/ (var-neg-activation var) ACTIVITY_DROPOFF))
(walk (+ 1 idx))))
'*void*)))
(define (SMT-slash-all-literals! smt)
(slash-all-literals! (SAT-variables (SMT-sat smt))))
(define (literal->dimacs literal)
(if (literal-polarity literal)
(literal-name literal)
(- (literal-name literal))))
(define (var->dimacs v)
(match (var-value v)
[#t (var-name v)]
[#f (- (var-name v))]
['unassigned (error "[Internal error] var->dimacs called on unassigned variable")]))
(define ((dimacs-lit->literal variables) dimacs-lit)
(literal
(vector-ref variables (- (dimacs-lit->dimacs-var dimacs-lit) 1)) (dimacs-lit . > . 0)))
(define ((dimacs-lits->clause variables) dimacs-lits)
(cond
[(empty? dimacs-lits)
(error 'dimacs-lits->clause
"There is an empty clause. I don't think you will be satisfied.")]
[else
(let* ((literals (list->vector (map (dimacs-lit->literal variables) dimacs-lits)))
(w1 (vector-ref literals 0))
(w2 (vector-ref literals (- (vector-length literals) 1)))
(C (clause literals w1 w2)))
(add-literal-watched! C w1) (add-literal-watched! C w2)
C)]))