2009-09-18 4 views
1

이 코드는 약간의 도움이 필요합니다. 나는 재귀 적이어야하는 섹션을 알고있다, 또는 적어도 나는 그것을한다고 생각하지만 그것을 구현하는 방법을 모르겠다. 여러 경로를 0 값으로 다시 찾을 정렬 행렬에서 경로 찾기 프로그램을 구현하려고합니다. 예를 들어 내 코드를 연습 한 후 첫 번째 시퀀스로 CGCA를 삽입하고 두 번째 시퀀스로 CACGTAT를 삽입하고 일치 항목으로 1, 0 및 -1을 불일치 및 간격 점수로 삽입합니다. A- -이 프로그램은 HDHHDD 같은 경로와Perl 재귀 기술?

CACGTAT

CGC로 aligment을 제공합니다.

그러나 더 많은 경로와 앨 라이트가 있지만 그 중 몇 가지를 모르겠다. 내가하고 싶은 일은 내 코드 루프 조각을 다시 만들어 다른 경로와 정렬을 찾고 가능한 한 정렬이 없어 질 때까지 처음으로 같은 코드를 사용하는 것입니다. 이 작업을 수행하기 위해 인터넷에서 찾은 가장 좋은 방법은 아무도이를 수행하는 방법을 설명 할 수 없다는 것 외에는 재귀입니다. 이 경우 HDDDHHD와 CACGTAT, C-GCA-, 그리고 두 개의 경로가 있어야합니다. HDDDDHH, CACGTAT 및 --CGCA-. 이 작업을 수행하는 코드 작성 방법을 모르겠습니다.

# Implementation of Needleman and Wunsch Algorithm 

my($seq1, $len1, $seq2, $len2, $data, @matrix, $i, $j, $x, $y, $val1, $val2); 
my($val3, $pathrow, $pathcol, $seq1loc, $seq2loc, $gapscore, $matchscore, $mismatchscore); 

#first obtain the data from the user. 
print "Please enter the first sequence for comaprsion\n"; 
$seq1=<STDIN>; 
chomp $seq1; 

print "Please enter the second sequence for comparsion\n"; 
$seq2=<STDIN>; 
chomp $seq2; 


# adding extra characters so sequences align with matrix 
# saves some calculations later on 
$seq1 = " " . $seq1; 
$seq2 = " " . $seq2; 
$len1 = length($seq1); 
$len2 = length($seq2); 

print "Enter the match score: "; 
$matchscore=<STDIN>; 
chomp $matchscore; 

print "Enter the mismatch score: "; 
$mismatchscore=<STDIN>; 
chomp $mismatchscore; 

print "Enter the gap score: "; 
$gapscore=<STDIN>; 
chomp $gapscore; 

# declare a two dimensional array and initialize to spaces 
# array must contain one extra row and one extra column 
@matrix =(); 
for($i = 0; $i < $len1; $i++){ 
    for($j = 0; $j < $len2; $j++){ 
     $matrix[$i][$j] = ' '; 
    } 
} 

# initialize 1st row and 1st column of matrix 
$matrix[0][0] = 0; 
for ($i = 1; $i < $len1; $i ++){ 
    $matrix[$i][0] = $matrix[$i-1][0] + $gapscore; 
} 
for ($i = 1; $i < $len2; $i ++){ 
    $matrix[0][$i] = $matrix[0][$i-1] + $gapscore; 
} 


# STEP 1: 
# Fill in rest of matrix using the following rules: 
# determine three possible values for matrix[x][y] 
# value 1 = add gap score to matrix[x][y-1] 
# value 2 = add gap score to matrix[x-1][y] 
# value 3 = add match score or mismatch score to 
#   matrix[x-1][y-1] depending on nucleotide 
#   match for position x of $seq1 and position y 
#   of seq2 
# place the largest of the three values in matrix[x][y] 
# 
# Best alignment score appears in matrix[$len1][$len2]. 

for($x = 1; $x < $len1; $x++){ 
    for($y = 1; $y < $len2; $y++){ 
$val1 = $matrix[$x][$y-1] + $gapscore; 
$val2 = $matrix[$x-1][$y] + $gapscore; 
if (substr($seq1, $x, 1) eq substr($seq2, $y, 1)){ 
      $val3 = $matrix[$x-1][$y-1] + $matchscore; 
} 
else{ 
    $val3 = $matrix[$x-1][$y-1] + $mismatchscore; 
} 
if (($val1 >= $val2) && ($val1 >= $val3)){ 
    $matrix[$x][$y] = $val1; 
} 
elsif (($val2 >= $val1) && ($val2 >= $val3)){ 
    $matrix[$x][$y] = $val2; 
} 
else{ 
    $matrix[$x][$y] = $val3; 
} 
    } 
} 

# Display scoring matrix 
print "MATRIX:\n"; 
for($x = 0; $x < $len1; $x++){ 
    for($y = 0; $y < $len2; $y++){ 
print "$matrix[$x][$y] "; 
    } 
    print "\n"; 
} 
print "\n";  

# STEP 2: 
# Begin at matrix[$len1][$len2] and find a path to 
# matrix[0][0]. 
# Build string to hold path pattern by concatenating either 
# 'H' (current cell produced by cell horizontally to left), 
# 'D' (current cell produced by cell on diagonal), 
# 'V' (current cell produced by cell vertically above) 
# ***This is were I need help I need this code to be recursive, so I can find more then one path*** 

$pathrow = $len1-1; 
$pathcol = $len2-1; 

while (($pathrow != 0) || ($pathcol != 0)){ 
    if ($pathrow == 0){ 
     # must be from cell to left 
     $path = $path . 'H'; 
     $pathcol = $pathcol - 1; 
    } 
    elsif ($pathcol == 0){ 
     # must be from cell above 
     $path = $path . 'V'; 
     $pathrow = $pathrow - 1; 
    } 
    # could be from any direction 
    elsif (($matrix[$pathrow][$pathcol-1] + $gapscore) == $matrix[$pathrow][$pathcol]){ 
     # from left 
     $path = $path . 'H'; 
     $pathcol = $pathcol - 1; 
    } 
    elsif (($matrix[$pathrow-1][$pathcol] + $gapscore) == $matrix[$pathrow][$pathcol]){ 
     # from above 
     $path = $path . 'V'; 
     $pathrow = $pathrow - 1; 
    } 
    else{ 
     # must be from diagonal 
     $path = $path . 'D'; 
     $pathrow = $pathrow - 1; 
     $pathcol = $pathcol - 1; 
    } 


} 



print "Path is $path\n"; 

# STEP 3: 
# Determine alignment pattern by reading path string 
# created in step 2. 
# Create two string variables ($alignseq1 and $alignseq2) to hold 
# the sequences for alignment. 
# Reading backwards from $seq1, $seq2 and path string, 
# if string character is 'D', then 
#  concatenate to front of $alignseq1, last char in $seq1 
#  and to the front of $alignseq2, last char in $seq2 
# if string character is 'V', then 
#  concatenate to front of $alignseq1, last char in $seq1 
#  and to the front of $alignseq2, the gap char 
# if string character is 'H', then 
#  concatenate to front of $alignseq1 the gap char 
#  and to the front of $alignseq2, last char in $seq2 
# Continue process until path string has been traversed. 
# Result appears in string $alignseq1 and $seq2 
***#I need this code to be recursive as well.*** 

$seq1loc = $len1-1; 
$seq2loc = $len2-1; 
$pathloc = 0; 
print length($path); 
while ($pathloc < length($path)){ 
    if (substr($path, $pathloc, 1) eq 'D'){ 
     $alignseq1 = substr($seq1, $seq1loc, 1) . $alignseq1; 
     $alignseq2 = substr($seq2, $seq2loc, 1) . $alignseq2; 
     $seq1loc--; 
     $seq2loc--; 
    } 
    elsif (substr($path, $pathloc, 1) eq 'V'){ 
     $alignseq1 = substr($seq1, $seq1loc, 1) . $alignseq1; 
     $alignseq2 = '-' . $alignseq2; 
     $seq1loc--; 
    }  
    else{ # must be an H 
     $alignseq1 = '-' . $alignseq1; 
     $alignseq2 = substr($seq2, $seq2loc, 1) . $alignseq2; 
     $seq2loc--; 
    }  
    $pathloc++; 
} 

print "\nAligned Sequences:\n"; 
print "$alignseq2 \n"; 
print "$alignseq1 \n"; 

# statement may be needed to hold output screen 
print "Press any key to exit program"; 
$x = <STDIN>; 

누구나 궁금한 점이 있다면 needleman-wunsch 알고리즘입니다. 여기있는 어떤 도움도 크게 호소 될 것입니다.

+1

서브 루틴은 어떻습니까? –

답변

7

나는 당신이하려고하는 것을 정확히 이해하지 못하기 때문에 답변을 드릴 수는 없지만 몇 가지 일반적인 조언을 해드릴 수 있습니다.

좁게 정의 된 작업을 수행하는 별도의 서브 루틴으로 코드를 구성하십시오. 또한, 중앙 알고리즘을 구현하는 서브 루틴은 키보드에서 입력을 받아 화면으로 출력하는 방향으로 향하게해서는 안됩니다. 오히려 인수로 인수를 받아 결과를 반환해야합니다. 사용자 입력 또는 화면 출력이 필요한 경우 이러한 작업은 기본 알고리즘과 함께하지 않고 별도의 서브 루틴에 있어야합니다.

첫 번째 (부분) 단계는 전체 프로그램을 가져 와서 서브 루틴 정의로 묶은 다음 필수 인수를 사용하여 서브 루틴을 호출하는 것입니다. 키 결과를 인쇄하는 대신 서브 루틴은 @matrix에 대한 참조와 함께 $path, $alignseq1, $alignseq2의 값을 반환해야합니다. 이 시점에서

sub NW_algo { 
    my ($seq1, $seq2, $matchscore, $mismatchscore, $gapscore) = @_; 

    # The rest of your code here, but with all print 
    # statements and <STDIN> inputs commented out. 

    return \@matrix, $path, $alignseq1, $alignseq2; 
} 

my(@return_values) = NW_algo('CGCA', 'CACGTAT', 1, 0, -1); 

Print_matrix($return_values[0]); 

sub Print_matrix { 
    for my $m (@{$_[0]}){ 
     print join(' ', @$m), "\n"; 
    } 
} 

, 당신은 쉽게 테스트하고 디버그 프로그램이 앞으로하고, 다른 코드를 호출 할 수있는 알고리즘을해야합니다. 예를 들어 다양한 입력 데이터 집합을 정의하고 각 집합에 NW_algo()을 실행할 수 있습니다. 그런 다음에 만 재귀 또는 다른 기술에 대해 생각할 수 있습니다.

5

Needleman-Wunsch는 동적 프로그래밍 알고리즘이므로 대부분의 작업은 DP 매트릭스를 계산할 때 이미 수행됩니다. DP 매트릭스를 얻었 으면 최적의 정렬을 찾기 위해 매트릭스를 역 추적해야합니다. 문제는 당신이 대각선으로 이동할 수 있다는 것을 제외하면 택시 도형과 약간 비슷합니다. 본질적으로 행렬을 뒤돌아 다니면서 위로, 왼쪽 또는 대각선으로 선택하는 대신 3 개의 순환 호출을 수행하여 3 개 모두를 수행하고 각 호출은 각각 위쪽, 왼쪽 또는 대각선으로 호출합니다. 당신은 당신의 출발점에 도달합니다. 재귀의 각 가닥에 의해 추적 된 경로는 각 정렬을 그립니다.

편집 : 기본적으로 2 단계를 위치 절차와 경로 추적을 통해 하위 절차에 넣어야하므로 반복해서 호출 할 수 있습니다.프로 시저를 정의 후 물론, 당신은 실제로 추적 프로세스를 시작하는 데 하나의 호출을해야합니다

sub tracePaths { 
    $x = shift; 
    $y = shift; 
    $pathSoFar = shift; # assuming you're storing your path as a string 
    # 
    # ... do some work ... 
    # 
    tracePaths($x - 1, $y, $pathSoFar . something); 
    tracePaths($x, $y - 1, $pathSoFar . somethingelse); 
    tracePaths($x - 1, $y - 1, $pathSoFar . somethingelselse); 
    # 
    # 
    # 
    if(reached the end) return $pathSoFar; 
} 
# launch the recursion 
tracePaths(beginningx, beginningy, ""); 
4

이 문제에 특별히 말을하지 않습니다,하지만 당신은 어쩌면이 책 Higher Order Perl을 확인해야합니다. 많은 고급 기술 (예 : 재귀)을 사용하는 방법을 설명합니다.