Advertisement
dgulczynski

MP - rezolucja

Apr 6th, 2018
352
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Racket 13.88 KB | None | 0 0
  1. #lang racket
  2.  
  3. ;; pomocnicza funkcja dla list tagowanych o określonej długości
  4. (define (tagged-tuple? tag len p)
  5.   (and (list? p)
  6.        (= (length p) len)
  7.        (eq? (car p) tag)))
  8.  
  9. (define (tagged-list? tag p)
  10.   (and (pair? p)
  11.        (eq? (car p) tag)
  12.        (list? (cdr p))))
  13.  
  14. ;; reprezentacja danych wejściowych (z ćwiczeń)
  15. (define (var? x)
  16.   (symbol? x))
  17.  
  18. (define (var x)
  19.   x)
  20.  
  21. (define (var-name x)
  22.   x)
  23.  
  24. ;; przydatne predykaty na zmiennych
  25. (define (var<? x y)
  26.   (symbol<? x y))
  27.  
  28. (define (var=? x y)
  29.   (eq? x y))
  30.  
  31. (define (literal? x)
  32.   (and (tagged-tuple? 'literal 3 x)
  33.        (boolean? (cadr x))
  34.        (var? (caddr x))))
  35.  
  36. (define (literal pol x)
  37.   (list 'literal pol x))
  38.  
  39. (define (literal-pol x)
  40.   (cadr x))
  41.  
  42. (define (literal-var x)
  43.   (caddr x))
  44.  
  45. (define (clause? x)
  46.   (and (tagged-list? 'clause x)
  47.        (andmap literal? (cdr x))))
  48.  
  49. (define (clause . lits)
  50.   (cons 'clause lits))
  51.  
  52. (define (clause-lits c)
  53.   (cdr c))
  54.  
  55. (define (cnf? x)
  56.   (and (tagged-list? 'cnf x)
  57.        (andmap clause? (cdr x))))
  58.  
  59. (define (cnf . cs)
  60.     (cons 'cnf cs))
  61.  
  62. (define (cnf-clauses x)
  63.   (cdr x))
  64.  
  65. ;; oblicza wartość formuły w CNF z częściowym wartościowaniem. jeśli zmienna nie jest
  66. ;; zwartościowana, literał jest uznawany za fałszywy.
  67. (define (valuate-partial val form)
  68.   (define (val-lit l)
  69.     (let ((r (assoc (literal-var l) val)))
  70.       (cond
  71.        [(not r) false]
  72.        [(cadr r) (literal-pol l)]
  73.        [else     (not (literal-pol l))])))
  74.   (define (val-clause c)
  75.     (ormap val-lit (clause-lits c)))
  76.   (andmap val-clause (cnf-clauses form)))
  77.  
  78. ;; reprezentacja dowodów sprzeczności
  79.  
  80. (define (axiom? p)
  81.   (tagged-tuple? 'axiom 2 p))
  82.  
  83. (define (proof-axiom c)
  84.   (list 'axiom c))
  85.  
  86. (define (axiom-clause p)
  87.   (cadr p))
  88.  
  89. (define (res? p)
  90.   (tagged-tuple? 'resolve 4 p))
  91.  
  92. (define (proof-res x pp pn)
  93.   (list 'resolve x pp pn))
  94.  
  95. (define (res-var p)
  96.   (cadr p))
  97.  
  98. (define (res-proof-pos p)
  99.   (caddr p))
  100.  
  101. (define (res-proof-neg p)
  102.   (cadddr p))
  103.  
  104. ;; sprawdza strukturę, ale nie poprawność dowodu
  105. (define (proof? p)
  106.   (or (and (axiom? p)
  107.            (clause? (axiom-clause p)))
  108.       (and (res? p)
  109.            (var? (res-var p))
  110.            (proof? (res-proof-pos p))
  111.            (proof? (res-proof-neg p)))))
  112.  
  113. ;; procedura sprawdzająca poprawność dowodu
  114. (define (check-proof pf form)
  115.   (define (run-axiom c)
  116.     (displayln (list 'checking 'axiom c))
  117.     (and (member c (cnf-clauses form))
  118.          (clause-lits c)))
  119.   (define (run-res x cpos cneg)
  120.     (displayln (list 'checking 'resolution 'of x 'for cpos 'and cneg))
  121.     (and (findf (lambda (l) (and (literal-pol l)
  122.                                  (eq? x (literal-var l))))
  123.                 cpos)
  124.          (findf (lambda (l) (and (not (literal-pol l))
  125.                                  (eq? x (literal-var l))))
  126.                 cneg)
  127.          (append (remove* (list (literal true x))  cpos)
  128.                  (remove* (list (literal false x)) cneg))))
  129.   (define (run-proof pf)
  130.     (cond
  131.      [(axiom? pf) (run-axiom (axiom-clause pf))]
  132.      [(res? pf)   (run-res (res-var pf)
  133.                            (run-proof (res-proof-pos pf))
  134.                            (run-proof (res-proof-neg pf)))]
  135.      [else       false]))
  136.   (null? (run-proof pf)))
  137.  
  138.  
  139. ;; reprezentacja wewnętrzna
  140.  
  141. ;; sprawdza posortowanie w porządku ściśle rosnącym, bez duplikatów
  142. (define (sorted? vs)
  143.   (or (null? vs)
  144.       (null? (cdr vs))
  145.       (and (var<? (car vs) (cadr vs))
  146.            (sorted? (cdr vs)))))
  147.  
  148. (define (sorted-varlist? x)
  149.   (and (list? x)
  150.        (andmap (var? x))
  151.        (sorted? x)))
  152.  
  153. ;; klauzulę reprezentujemy jako parę list — osobno wystąpienia pozytywne i negatywne. Dodatkowo
  154. ;; pamiętamy wyprowadzenie tej klauzuli (dowód) i jej rozmiar.
  155. (define (res-clause? x)
  156.   (and (tagged-tuple? 'res-int 5 x)
  157.        (sorted-varlist? (second x))
  158.        (sorted-varlist? (third x))
  159.        (= (fourth x) (+ (length (second x)) (length (third x))))
  160.        (proof? (fifth x))))
  161.  
  162. (define (res-clause pos neg proof)
  163.   (list 'res-int pos neg (+ (length pos) (length neg)) proof))
  164.  
  165. (define (res-clause-pos c)
  166.   (second c))
  167.  
  168. (define (res-clause-neg c)
  169.   (third c))
  170.  
  171. (define (res-clause-size c)
  172.   (fourth c))
  173.  
  174. (define (res-clause-proof c)
  175.   (fifth c))
  176.  
  177. ;; przedstawia klauzulę jako parę list zmiennych występujących odpowiednio pozytywnie i negatywnie
  178. (define (print-res-clause c)
  179.   (list (res-clause-pos c) (res-clause-neg c)))
  180.  
  181. ;; sprawdzanie klauzuli sprzecznej
  182. (define (clause-false? c)
  183.   (and (null? (res-clause-pos c))
  184.        (null? (res-clause-neg c))))
  185.  
  186. ;; pomocnicze procedury: scalanie i usuwanie duplikatów z list posortowanych
  187. (define (merge-vars xs ys)
  188.   (cond [(null? xs) ys]
  189.         [(null? ys) xs]
  190.         [(var<? (car xs) (car ys))
  191.          (cons (car xs) (merge-vars (cdr xs) ys))]
  192.         [(var<? (car ys) (car xs))
  193.          (cons (car ys) (merge-vars xs (cdr ys)))]
  194.         [else (cons (car xs) (merge-vars (cdr xs) (cdr ys)))]))
  195.  
  196. (define (remove-duplicates-vars xs)
  197.   (cond [(null? xs) xs]
  198.         [(null? (cdr xs)) xs]
  199.         [(var=? (car xs) (cadr xs)) (remove-duplicates-vars (cdr xs))]
  200.         [else (cons (car xs) (remove-duplicates-vars (cdr xs)))]))
  201.  
  202. (define (rev-append xs ys)
  203.   (if (null? xs) ys
  204.       (rev-append (cdr xs) (cons (car xs) ys))))
  205.  
  206. ;; TODO: miejsce na uzupełnienie własnych funkcji pomocniczych
  207. (define (first-shared xs ys)
  208.   (cond [(null? xs) false]
  209.         [(null? ys) false]
  210.         [(var<? (car xs) (car ys)) (first-shared (cdr xs) ys)]
  211.         [(var<? (car ys) (car xs)) (first-shared xs (cdr ys))]
  212.         [else (car xs)]))
  213.  
  214. (define (easier? c1 c2)
  215.   (define (contains? xs ys)
  216.     (cond [(null? xs) true]
  217.           [(null? ys) false]        
  218.           [(var<? (car xs) (car ys))
  219.           false]
  220.           [(var<? (car ys) (car xs))
  221.            (contains? xs (cdr ys))]
  222.           [else (contains? (cdr xs) (cdr ys))]))
  223.   (and (contains? (res-clause-pos c2) (res-clause-pos c1))
  224.        (contains? (res-clause-neg c2) (res-clause-neg c1))))
  225. ;;;;;;;;
  226.  
  227. (define (clause-trivial? c)
  228.   (first-shared (res-clause-pos c)
  229.                 (res-clause-neg c)))
  230.  
  231. (define (resolve c1 c2)
  232.   (define (helper c1 c2)
  233.     (let ((res (first-shared (res-clause-pos c1)
  234.                              (res-clause-neg c2))))
  235.       (and res
  236.           (res-clause (remove res (merge-vars  (res-clause-pos c1)
  237.                                                (res-clause-pos c2)))
  238.                       (remove res (merge-vars  (res-clause-neg c1)
  239.                                                (res-clause-neg c2)))
  240.                       (proof-res  res
  241.                                   (res-clause-proof c1)
  242.                                   (res-clause-proof c2))))))
  243.   (or (helper c1 c2)
  244.       (helper c2 c1)))
  245.  
  246. (define (resolve-single-prove s-clause checked pending)
  247.   (subsume-add-prove (cons s-clause (filter (lambda (x) (not (resolve x s-clause))) checked))
  248.                      pending
  249.                      (sort-clauses (filter-map (lambda (c) (resolve c s-clause)) checked))))
  250.  
  251. ;;  (resolve-prove (cons s-clause (map (lambda(c) (or (resolve c s-clause) c)) checked)) pending)
  252. ;; wstawianie klauzuli w posortowaną względem rozmiaru listę klauzul
  253. (define (insert nc ncs)
  254.   (cond
  255.    [(null? ncs)                     (list nc)]
  256.    [(< (res-clause-size nc)
  257.        (res-clause-size (car ncs))) (cons nc ncs)]
  258.    [else                            (cons (car ncs) (insert nc (cdr ncs)))]))
  259.  
  260. ;; sortowanie klauzul względem rozmiaru (funkcja biblioteczna sort)
  261. (define (sort-clauses cs)
  262.   (sort cs < #:key res-clause-size))
  263.  
  264. ;; główna procedura szukająca dowodu sprzeczności
  265. ;; zakładamy że w checked i pending nigdy nie ma klauzuli sprzecznej
  266. (define (resolve-prove checked pending)
  267.   (cond
  268.    ;; jeśli lista pending jest pusta, to checked jest zamknięta na rezolucję czyli spełnialna
  269.    [(null? pending) (generate-valuation (sort-clauses checked))]
  270.    ;; jeśli klauzula ma jeden literał, to możemy traktować łatwo i efektywnie ją przetworzyć
  271.    [(= 1 (res-clause-size (car pending)))
  272.     (resolve-single-prove (car pending) checked (cdr pending))]
  273.    ;; w przeciwnym wypadku wykonujemy rezolucję z wszystkimi klauzulami już sprawdzonymi, a
  274.    ;; następnie dodajemy otrzymane klauzule do zbioru i kontynuujemy obliczenia
  275.    [else
  276.     (let* ((next-clause  (car pending))
  277.            (rest-pending (cdr pending))
  278.            (resolvents   (filter-map (lambda (c) (resolve c next-clause))
  279.                                      checked))
  280.            (sorted-rs    (sort-clauses resolvents)))
  281.       (subsume-add-prove (cons next-clause checked) rest-pending sorted-rs))]))
  282.  
  283. ;; procedura upraszczająca stan obliczeń biorąc pod uwagę świeżo wygenerowane klauzule i
  284. ;; kontynuująca obliczenia. Do uzupełnienia.
  285. (define (subsume-add-prove checked pending new)
  286.   (cond
  287.    [(null? new)                 (resolve-prove checked pending)]
  288.    ;; jeśli klauzula do przetworzenia jest sprzeczna to jej wyprowadzenie jest dowodem sprzeczności
  289.    ;; początkowej formuły
  290.    [(clause-false? (car new))   (list 'unsat (res-clause-proof (car new)))]
  291.    ;; jeśli klauzula jest trywialna to nie ma potrzeby jej przetwarzać
  292.    [(clause-trivial? (car new)) (subsume-add-prove checked pending (cdr new))]
  293.    [(ormap (lambda (x) (easier? (car new) x)) checked) (subsume-add-prove checked pending (cdr new))]
  294.    [else
  295.     (subsume-add-prove (filter (lambda (x) (not (easier? x (car new)))) checked)
  296.                        (insert (car new) (filter (lambda (x) (not (easier? x (car new))))pending))
  297.                        (cdr new))
  298.     ]))
  299.  
  300. (define (generate-valuation resolved)
  301.   (define (shorten-pos var clauses)
  302.     (map (lambda (c)
  303.            (if (member var (res-clause-neg c))
  304.                (res-clause (res-clause-pos c)
  305.                            (remove var (res-clause-neg c))
  306.                           null)
  307.                 c))
  308.          (filter (lambda (c) (not (member var (res-clause-pos c)))) clauses)))
  309.   (define (shorten-neg var clauses)
  310.     (map (lambda (c)
  311.            (if (member var (res-clause-pos c))
  312.                (res-clause (remove var (res-clause-pos c))
  313.                            (res-clause-neg c)
  314.                           null)
  315.                c))
  316.          (filter (lambda (c) (not (member var (res-clause-neg c)))) clauses)))
  317.   (define (iter clauses vals)
  318.     (if (null? clauses)
  319.         vals
  320.         (let ((clause (car clauses))
  321.               (rest (cdr clauses)))
  322.           (cond [(not (null? (res-clause-pos clause)))
  323.                  (iter (shorten-pos (car (res-clause-pos clause)) rest)
  324.                        (cons (list (car (res-clause-pos clause)) #t) vals))]
  325.                 [(not (null? (res-clause-neg clause)))
  326.                  (iter (shorten-neg (car (res-clause-neg clause)) rest)
  327.                        (cons (list (car (res-clause-neg clause)) #f) vals))]
  328.                 [else (iter rest vals)]))))
  329.   (cons 'sat (list (iter resolved null))))
  330.  
  331. ;; procedura przetwarzające wejściowy CNF na wewnętrzną reprezentację klauzul
  332. (define (form->clauses f)
  333.   (define (conv-clause c)
  334.     (define (aux ls pos neg)
  335.       (cond
  336.        [(null? ls)
  337.         (res-clause (remove-duplicates-vars (sort pos var<?))
  338.                     (remove-duplicates-vars (sort neg var<?))
  339.                     (proof-axiom c))]
  340.        [(literal-pol (car ls))
  341.         (aux (cdr ls)
  342.              (cons (literal-var (car ls)) pos)
  343.              neg)]
  344.        [else
  345.         (aux (cdr ls)
  346.              pos
  347.              (cons (literal-var (car ls)) neg))]))
  348.     (aux (clause-lits c) null null))
  349.   (map conv-clause (cnf-clauses f)))
  350.  
  351. (define (prove form)
  352.   (let* ((clauses (form->clauses form)))
  353.     (subsume-add-prove '() '() clauses)))
  354.  
  355. ;; procedura testująca: próbuje dowieść sprzeczność formuły i sprawdza czy wygenerowany
  356. ;; dowód/waluacja są poprawne. Uwaga: żeby działała dla formuł spełnialnych trzeba umieć wygenerować
  357. ;; poprawną waluację.
  358. (define (prove-and-check form)
  359.   (let* ((res (prove form))
  360.          (sat (car res))
  361.          (pf-val (cadr res)))
  362.     (if (eq? sat 'sat)
  363.         (valuate-partial pf-val form)
  364.         (check-proof pf-val form))))
  365.  
  366. ;;; TODO: poniżej wpisz swoje testy
  367. ;; x1 = (p ∨ q) ∧ (¬p ∨ q) ∧ (p ∨ ¬q) ∧ (¬p ∨ ¬q)
  368. (define x1 '(cnf (clause (literal #t p) (literal #t q))
  369.                  (clause (literal #f p) (literal #t q))
  370.                  (clause (literal #t p) (literal #f q))
  371.                  (clause (literal #f p) (literal #f q))))
  372. ;; x2 = (p ∨ q ∨ r) ∧ (¬r ∨ ¬q ∨ ¬p) ∧ (¬q ∨ r) ∧ (¬r ∨ p)
  373. (define x2 '(cnf (clause (literal #t p) (literal #t q) (literal #t r))
  374.                  (clause (literal #f p) (literal #f q) (literal #f r))
  375.                  (clause (literal #f q) (literal #t r))
  376.                  (clause (literal #t p) (literal #f r))))
  377. ;; x3 = p ∧ (q ∨ r) ∧ (¬p ∨ q ∨ r ∨ s) ∧ (p ∨ ¬q ∨ s )
  378. (define x3 '(cnf (clause (literal #t p))
  379.                  (clause (literal #t q) (literal #t r))
  380.                  (clause (literal #f p) (literal #t q) (literal #t r) (literal #t s))
  381.                  (clause (literal #t p) (literal #f q) (literal #t s))))
  382. ;; x4 = p ∧ ¬p
  383. (define x4 '(cnf (clause (literal #f p)) (clause (literal #t p))))
  384. ;; x5 = ¬p ∧ p
  385. (define x5 '(cnf (clause (literal #t p)) (clause (literal #f p))))
  386.  
  387. ;; testy:
  388. (display "Testing: ") x1
  389. (display "Result: ") (prove x1)
  390. (display "Proof-check: ") (prove-and-check x1)
  391. (newline)
  392. (display "Testing: ") x2
  393. (display "Result: ") (prove x2)
  394. (display "Proof-check: ") (prove-and-check x2)
  395. (newline)
  396. (display "Testing: ") x3
  397. (display "Result: ") (prove x3)
  398. (display "Proof-check: ") (prove-and-check x3)
  399. (newline)
  400. (display "Testing: ") x4
  401. (display "Result: ") (prove x4)
  402. (display "Proof-check: ") (prove-and-check x4)
  403. (newline)
  404. (display "Testing: ") x5
  405. (display "Result: ") (prove x5)
  406. (display "Proof-check: ") (prove-and-check x5)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement