<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Brute Force on Mulatta Blog</title><link>https://blog.mulatta.io/tags/brute-force/</link><description>Recent content in Brute Force on Mulatta Blog</description><generator>Hugo -- gohugo.io</generator><language>ko-kr</language><lastBuildDate>Tue, 30 Jan 2024 00:00:00 +0000</lastBuildDate><atom:link href="https://blog.mulatta.io/tags/brute-force/index.xml" rel="self" type="application/rss+xml"/><item><title>1A 단어 세기</title><link>https://blog.mulatta.io/post/bioinformatics-algorithm/02-ch1-1a/</link><pubDate>Tue, 30 Jan 2024 00:00:00 +0000</pubDate><guid>https://blog.mulatta.io/post/bioinformatics-algorithm/02-ch1-1a/</guid><description>&lt;h2 id="개요"&gt;개요
&lt;/h2&gt;&lt;p&gt;앞서 단백질의 특이성(specificity)에 대해 이야기하였다. 세포 내에서 일어나는 이러한 단백질의 특이성은 마치 단백질에 눈이 달린 것 처럼 작동한다고 생각하기 쉽지만, 단백질의 특이성 또한 결국 물리화학적 법칙을 따르는 분자의 운동에 불과하다.&lt;/p&gt;
&lt;p&gt;즉, 단백질 분자가 외부 계의 물리적 힘 - 특히 열 - 에 의해 진동하거나 부유하는 brownian motion을 통해 돌아다니다가, 적절한 DNA 서열과 유효충돌이 일어나야 상호작용이 일어나는 것이다.&lt;/p&gt;
&lt;p&gt;따라서, 우리는 다음과 같은 가설을 세울 수 있다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;1. DnaA box가 많을수록 DnaA protein과의 유효충돌 횟수가 커진다.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;2. DnaA box가 많이 존재한다면, 이 서열들 중 일부에 변이가 일어나도 결합을 방해하는 데에 미치는 영향을 줄일 수 있다.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;그러므로, 위 가설에 따르면 문제는 반복되는 특정 서열을 찾는 것으로 귀결된다.
하지만 여전히 우리는 이 &lt;em&gt;특정 서열&lt;/em&gt; 의 길이가 어느정도인지 알지 못하기 때문에, 임의의 길이를 가지는 특정 서열을 k-mer로 정의한다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;k-mer&lt;/strong&gt;&lt;/em&gt;: 길이가 k인 문자열&lt;/p&gt;
&lt;p&gt;이렇게 k-mer pattern을 임의로 정한 뒤, 주어진 입력 Text에서 얼마나 등장하는지 그 횟수를 count 할 수 있다.
가장 간단한 방법으로, 다음과 같이 모든 각 문자열을 시작점으로 하는 k-mer와 비교할 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.mulatta.io/post/bioinformatics-algorithm/02-ch1-1a/countPattern1.png"
width="3611"
height="1292"
srcset="https://blog.mulatta.io/post/bioinformatics-algorithm/02-ch1-1a/countPattern1_hu_86e7b3ab27e05294.png 480w, https://blog.mulatta.io/post/bioinformatics-algorithm/02-ch1-1a/countPattern1_hu_176d04954d10a5dc.png 1024w"
loading="lazy"
alt="index가 0일 때 주어진 text에서 pattern(ACTA)찾기"
class="gallery-image"
data-flex-grow="279"
data-flex-basis="670px"
&gt;
&lt;em&gt;Fig 1. index가 0일 때 주어진 text에서 pattern(ACTA)찾기&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.mulatta.io/post/bioinformatics-algorithm/02-ch1-1a/countPattern2.png"
width="3611"
height="1310"
srcset="https://blog.mulatta.io/post/bioinformatics-algorithm/02-ch1-1a/countPattern2_hu_e4b79c989d167b00.png 480w, https://blog.mulatta.io/post/bioinformatics-algorithm/02-ch1-1a/countPattern2_hu_36657912217880e3.png 1024w"
loading="lazy"
alt="index가 1일 때 주어진 text에서 pattern(ACTA)찾기"
class="gallery-image"
data-flex-grow="275"
data-flex-basis="661px"
&gt;
&lt;em&gt;Fig 2. index가 1일 때 주어진 text에서 pattern(ACTA)찾기&lt;/em&gt;&lt;/p&gt;
&lt;h2 id="problem"&gt;Problem
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Input: 전체 문자열 Text, Text에서 찾으려는 문자열 Pattern&lt;/li&gt;
&lt;li&gt;Output: Text에서 등장하는 Pattern의 횟수&lt;/li&gt;
&lt;li&gt;function: Pattern $\to$ count&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="pseudo-code"&gt;Pseudo-code
&lt;/h2&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;span class="lnt"&gt;7
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;PatternCount(Text, Pattern)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; count &amp;lt;- 0
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; for i &amp;lt;- 0 to |Text| - |Pattern|
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Pattern&amp;#39; = Text(i, |Pattern|)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; if Pattern&amp;#39; == Pattern
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; count &amp;lt;-- count + 1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; return count
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id="evaluation"&gt;Evaluation
&lt;/h2&gt;&lt;h3 id="time-complexity"&gt;Time Complexity
&lt;/h3&gt;&lt;p&gt;이 알고리즘의 경우 Brute-force&lt;sup id="fnref:1"&gt;&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt; 방식으로, 모든 경우의 수를 순차적&lt;sup id="fnref:2"&gt;&lt;a href="#fn:2" class="footnote-ref" role="doc-noteref"&gt;2&lt;/a&gt;&lt;/sup&gt;으로 확인한다.&lt;/p&gt;
&lt;p&gt;입력 크기: $\left\vert Text \right\vert = n, \left\vert Pattern \right\vert = k$​&lt;/p&gt;
&lt;p&gt;$\text{Constraints: n ≥ k}$&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;line[1]: Pattern이 등장하는 횟수를 저장할 변수 선언&lt;sup id="fnref:3"&gt;&lt;a href="#fn:3" class="footnote-ref" role="doc-noteref"&gt;3&lt;/a&gt;&lt;/sup&gt; $\to O(1)$&lt;/li&gt;
&lt;li&gt;line[2]: Text와 Pattern의 입력 크기를 각각 $\left\vert Text \right\vert$ , $\left\vert Pattern \right\vert$ 이라 할 때, Text 문자열에서 Pattern 길이의 부분 문자열(substring)을 형성할 수 있는 모든 시작점은 0번째부터 $\left\vert Text \right\vert - \left\vert Pattern \right\vert $ 번째까지 이다. → $O(n-k)$&lt;/li&gt;
&lt;li&gt;line[3]: 현재 순번에서 가능한 부분 문자열 형성 - $Text(i, \left\vert Pattern \right\vert)$ 만큼을 slicing 해오는 연산 $\to O(1)$&lt;/li&gt;
&lt;li&gt;line[4]: sliced substring과 Pattern의 비교 연산 → $O(k)$ &lt;sup id="fnref:4"&gt;&lt;a href="#fn:4" class="footnote-ref" role="doc-noteref"&gt;4&lt;/a&gt;&lt;/sup&gt;&lt;/li&gt;
&lt;li&gt;line[5]: count 변수의 산술 연산 → $O(1)$&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;ul&gt;
&lt;li&gt;line[3] ~ line[5]의 경우 상수항의 시간이 소요된다.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Worst case&lt;/em&gt;: $n &amp;raquo; k \to n-k \approx n$&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Total Time Complexity&lt;/strong&gt;&lt;/em&gt;: $O(1) + O(n-k) \times (O(1)+O(k)+O(1)) \approxeq O(nk)$&lt;/p&gt;
&lt;h2 id="implementation"&gt;Implementation
&lt;/h2&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 전체 Text에서 주어진 Pattern의 등장 횟수를 반환하는 함수&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;PatternCount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pattern&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# 결과로 반환할 변수 선언&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# pattern의 시작점이 될 수 있는 영역을 모두 순회&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;idx&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pattern&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# 현재 인덱스를 시작으로 하는 pattern이 입력 pattern과 같다면 count&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;idx&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;idx&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pattern&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;pattern&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;count&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://rosalind.info/problems/ba1a/" target="_blank" rel="noopener"
&gt;Rosalind&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/mulatta/Bioinforamtics-Algorithm-practice/blob/main/Chapter%201/PatternInText.py" target="_blank" rel="noopener"
&gt;Code in Github&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="discussion-points"&gt;Discussion Points
&lt;/h2&gt;&lt;h3 id="summary"&gt;Summary
&lt;/h3&gt;&lt;ol&gt;
&lt;li&gt;주어진 유전체에서 어떤 &lt;strong&gt;특징&lt;/strong&gt;을 찾음으로써 특이성에 대한 단서를 얻을지도 모름&lt;/li&gt;
&lt;li&gt;이러한 특징에 대한 접근으로, 유전체에서 &lt;strong&gt;빈번하게 나타나는 패턴&lt;/strong&gt;을 찾는 접근을 시도해 볼 수 있음&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="implementation-strategy"&gt;Implementation Strategy
&lt;/h3&gt;&lt;p&gt;이러한 빈번한 패턴을 찾는 문제를 해결하기 위해 다음과 같은 전략을 통해 코드를 구성하였다.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;주어진 전체 text에서 가능한 모든 substring의 조합을 확인함&lt;/li&gt;
&lt;li&gt;가능한 모든 조합의 substring을 주어진 pattern과 일치하는지 확인하여 일치할 때마다 그 count를 셈.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="implications"&gt;Implications
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;유전체 상에서 임의의 서열이 &lt;em&gt;얼마나 등장&lt;/em&gt; 하는지 확인할 수 있게 되었다.&lt;/li&gt;
&lt;li&gt;이러한 임의의 서열은 DnaA box와 같이 &lt;em&gt;ori&lt;/em&gt; 를 구성하는 주요 서열의 &lt;em&gt;후보군&lt;/em&gt; 으로 생각할 수 있다.&lt;/li&gt;
&lt;li&gt;하지만, 이 방법만 가지고는 유전체 상에서 &lt;em&gt;&amp;ldquo;어느 위치에 반복적인 서열이 있는지&amp;rdquo;&lt;/em&gt; 를 확인하기는 어렵다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;다음 문제에서는, 이번에 구현한 함수를 통해 가장 많이 등장하는 단어가 &lt;em&gt;어떤&lt;/em&gt; 단어인지 확인하는 방법에 대해 알아보도록 한다.&lt;/p&gt;
&lt;h2 id="reference"&gt;Reference
&lt;/h2&gt;&lt;ol&gt;
&lt;li&gt;Compeu, P., Pevzner, P. (2018). Bioinformatics Algorithms 3/e. 에이콘 출판사&lt;/li&gt;
&lt;li&gt;Craig, N., Cohen-Fix, O., Green, R., Greider, C., Storz, G., &amp;amp; Wolberger, C. (2010). Molecular biology: Principles of genome function. Oxford University Press.&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;div class="footnotes" role="doc-endnotes"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:1"&gt;
&lt;p&gt;가능한 모든 경우의 수를 탐색하는 알고리즘 기법을 의미함&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:2"&gt;
&lt;p&gt;순차 탐색 - 순차적으로 탐색하는 기법&amp;#160;&lt;a href="#fnref:2" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:3"&gt;
&lt;p&gt;대입 연산&amp;#160;&lt;a href="#fnref:3" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:4"&gt;
&lt;p&gt;두 문자열의 길이는 k이므로, k번의 비교가 필요, 즉, $\left\vert Pattern \right\vert = k = m$ 이므로 $O(m)$&amp;#160;&lt;a href="#fnref:4" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description></item></channel></rss>