0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Needleman–Wunsch アルゴリズム

Posted at

導入

グローバルアライメントを求めるアルゴリズムである!
詳しくはこちらをご覧ください。
https://bi.biopapyrus.jp/seq/alignment/needleman%E2%80%93wunsch.html

プログラム

日本語で書いてある事を、そのまま実装しただけです。
といっても書き方は人それぞれですので、これが正解ということはありません。
実装の一例というだけです。

(define nil '())

(define f (make-hash-table 'equal?))
(define p (make-hash-table 'equal?))

(define score-match 2)
(define score-mismatch -1)
(define score-gap -2)
(define d (* -1 score-gap))

(define (score w1 w2)
  (cond ((or (null? w1) (null? w2)) score-gap)
        ((eq? w1 w2) score-match)
        (else score-mismatch)))

(define (s x y)
  (score (hash-table-get f (make-key x -1) nil)
         (hash-table-get f (make-key -1 y) nil)))

(define (make-key a b)
  (string-append (number->string a) "," (number->string b)))

(define (get-x key)
  (if (null? key)
      nil
      (string->number (car (string-split key ",")))))

(define (get-y key)
  (if (null? key)
      nil
      (string->number (cadr (string-split key ",")))))

(define (init word1 word2 lim-x lim-y)
  (define (iter-x x w)
    (if (> x lim-x)
        'done
        (begin
          (hash-table-put! f (make-key x 0) (* x -1 d))
          (hash-table-put! f (make-key x -1) (car w))
          (hash-table-put! p (make-key x 0) (list (list 3 (make-key (- x 1) 0))))
          (iter-x (+ x 1) (cdr w)))))
  (define (iter-y y w)
    (if (> y lim-y)
        'done
        (begin
          (hash-table-put! f (make-key 0 y) (* y -1 d))
          (hash-table-put! f (make-key -1 y) (car w))
          (hash-table-put! p (make-key 0 y) (list (list 1 (make-key 0 (- y 1)))))
          (iter-y (+ y 1) (cdr w)))))
  (iter-x 1 word1)
  (iter-y 1 word2)
  (hash-table-put! f (make-key 0 0) 0))

(define (evaluate-scores lim-x lim-y)
  (define (iter-x x y)
    (if (> x lim-x)
        'done
        (let* ((key (make-key x y))
               (up-key (make-key x (- y 1)))
               (up-left-key (make-key (- x 1) (- y 1)))
               (left-key (make-key (- x 1) y))
               (up-left (+ (hash-table-get f up-left-key) (s x y)))
               (up (+ (hash-table-get f up-key) (* -1 d)))
               (left (+ (hash-table-get f left-key) (* -1 d)))
               (p0 (sort `((,up 1 ,up-key) (,up-left 2 ,up-left-key) (,left 3 ,left-key)) > car))
               (p1 (car p0))
               (p2 (cadr p0))
               (p3 (caddr p0)))
          (hash-table-put! f key (car p1))
          (cond ((= (car p1) (car p2) (car p3))
                 (hash-table-put! p key (sort (cons (cdr p1) (hash-table-get p key nil)) < car))
                 (hash-table-put! p key (sort (cons (cdr p2) (hash-table-get p key nil)) < car))
                 (hash-table-put! p key (sort (cons (cdr p3) (hash-table-get p key nil)) < car)))
                ((= (car p1) (car p2))
                 (hash-table-put! p key (sort (cons (cdr p1) (hash-table-get p key nil)) < car))
                 (hash-table-put! p key (sort (cons (cdr p2) (hash-table-get p key nil)) < car)))
                (else
                 (hash-table-put! p key (sort (cons (cdr p1) (hash-table-get p key nil)) < car))))
          (iter-x (+ x 1) y))))
  (define (iter-y y)
    (if (> y lim-y)
        'done
        (begin
          (iter-x 1 y)
          (iter-y (+ y 1)))
        ))
  (iter-y 1))

(define (make-global-alignment key)
  (if (equal? key (make-key 0 0))
      nil
      (let* ((val (hash-table-get p key nil))
             (up (assv 1 val))
             (up-left (assv 2 val))
             (left (assv 3 val)))
        (cons key
              (list
               (if up (make-global-alignment (cadr up)) nil)
               (if up-left (make-global-alignment (cadr up-left)) nil)
               (if left (make-global-alignment (cadr left)) nil))))))

(define (make-word paths)
  (define (iter p xx yy w1 w2)
    (if (null? p)
        (begin
          (print (reverse w1))
          (print (reverse w2))
          (print ""))
        (let ((x (get-x (car p)))
              (y (get-y (car p))))
          (cond ((and (> x xx) (> y yy))
                 (iter (cdr p) x y (cons (hash-table-get f (make-key x -1)) w1) (cons (hash-table-get f (make-key -1 y)) w2)))
                ((> x xx)
                 (iter (cdr p) x yy (cons (hash-table-get f (make-key x -1)) w1) (cons "-" w2)))
                ((> y yy)
                 (iter (cdr p) xx y (cons "-" w1) (cons (hash-table-get f (make-key -1 y)) w2)))))))
  (iter paths 0 0 nil nil))

(define (print-score len1 len2)
  (print "SCORE: " (hash-table-get f (make-key len1 len2))))

(define (print-words lst paths)
  (let* ((nodes (cdr lst))
         (up (car nodes))
         (up-left (cadr nodes))
         (left (caddr nodes)))
    (if (and (null? up) (null? up-left) (null? left))
        (make-word (cons (car lst) paths))
        (begin
          (and (not (null? up)) (print-words (car nodes) (cons (car lst) paths)))
          (and (not (null? up-left)) (print-words (cadr nodes) (cons (car lst) paths)))
          (and (not (null? left)) (print-words (caddr nodes) (cons (car lst) paths)))
          'done))))

(define (needleman-wunsch word-lst1 word-lst2)
  (hash-table-clear! f)
  (hash-table-clear! p)

  (let ((len1 (length word-lst1))
        (len2 (length word-lst2)))
    (init word-lst1 word-lst2 len1 len2)
    (evaluate-scores len1 len2)
    (print-score len1 len2)
    (print-words (make-global-alignment (make-key len1 len2)) nil)))

実行

gosh> (needleman-wunsch '(A T T G C) '(A T G C))
SCORE: 6
(A T T G C)
(A - T G C)

(A T T G C)
(A T - G C)

done

で、具体的に何の役に立つの?

それを言っちゃあ、おしまいよ。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?