<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>情報 - 工業大学生ももやまのうさぎ塾 (Momousagi Academy)</title>
	<atom:link href="https://www.momoyama-usagi.com/entry/category/%E6%83%85%E5%A0%B1/feed" rel="self" type="application/rss+xml" />
	<link>https://www.momoyama-usagi.com</link>
	<description>人間からうさぎまで数学と情報をわかりやすくお届け！</description>
	<lastBuildDate>Wed, 14 Dec 2022 23:19:34 +0000</lastBuildDate>
	<language>ja</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.4</generator>

<image>
	<url>https://www.momoyama-usagi.com/wp-content/uploads/cropped-New-Usagi-Dosei-2-32x32.jpg</url>
	<title>情報 - 工業大学生ももやまのうさぎ塾 (Momousagi Academy)</title>
	<link>https://www.momoyama-usagi.com</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>うさぎでもわかる情報理論　第4羽　シャノン・ファノ符号化</title>
		<link>https://www.momoyama-usagi.com/entry/info-joho4</link>
					<comments>https://www.momoyama-usagi.com/entry/info-joho4#respond</comments>
		
		<dc:creator><![CDATA[ももうさ]]></dc:creator>
		<pubDate>Wed, 14 Dec 2022 23:12:46 +0000</pubDate>
				<category><![CDATA[情報]]></category>
		<category><![CDATA[情報理論]]></category>
		<guid isPermaLink="false">https://www.momoyama-usagi.com/?p=18163</guid>

					<description><![CDATA[瞬時復号可能な符号を作成する手法である「シャノン・ファノ符号化」の手順を例題や練習問題を踏まえながら説明しています。]]></description>
										<content:encoded><![CDATA[




<p>こんにちは、ももうさです。</p>



<p>前回は、瞬時復号可能な符号を作る手法の1つである「ハフマン符号化」についてみていきました。</p>



<figure class="wp-block-embed is-type-wp-embed is-provider-工業大学生ももやまのうさぎ塾 wp-block-embed-工業大学生ももやまのうさぎ塾"><div class="wp-block-embed__wrapper">
        <article class="pb p-id-17916 is-position-relative pb-embed">
            <a class="pb-contents" href="https://www.momoyama-usagi.com/entry/info-joho3">
                <div class="pb__thumb"><img width="300" height="187" src="https://www.momoyama-usagi.com/wp-content/uploads/joho3-2-3-300x187.jpg" class="is-position-overlay wp-post-image" alt="" lazysizes="1" srcset="https://www.momoyama-usagi.com/wp-content/uploads/joho3-2-3-300x187.jpg 300w, https://www.momoyama-usagi.com/wp-content/uploads/joho3-2-3-1024x638.jpg 1024w, https://www.momoyama-usagi.com/wp-content/uploads/joho3-2-3-768x479.jpg 768w, https://www.momoyama-usagi.com/wp-content/uploads/joho3-2-3-1536x957.jpg 1536w, https://www.momoyama-usagi.com/wp-content/uploads/joho3-2-3.jpg 2003w" /></div><div class="pb__body l-column is-flex-1"><div class="pb-title is-omit-line:2">[基本情報・応用情報] うさぎでもわかる情報理論　第3羽　ハフマン符号化</div><div class="pb-substr is-font-size:s is-omit-line:2">こんにちは、ももうさです。 前回では、「一意復号可能な符号」と「瞬時復号可能な符号」がどのような符号なのかについてみてい</div></div>            </a>
        </article>
        
</div></figure>



<p>今回は、瞬時復号可能な符号を作るもう1つの手法である「シャノン・ファノ符号化」の符号化手順について、実際に例題や練習問題を踏まえながら見ていきましょう。</p>



<div style="height:71px" class="wp-block-spacer"></div>



<h2 class="wp-block-heading">1. まずは例題で確認</h2>



<p>まずは、例題でシャノン・ファノ符号化の方法を見ていきましょう。</p>


<div class='wp-block-dbp-frame l-frame-float is-design-onframe is-frame-style-default dbp-frame has-bgcolor'><div class="dbp-frame-title">例題</div><div class="dbp-frame-content has-content-gap">
<p>つぎの表は、とある文字列中（情報源）に出てくる文字の出現確率を表にしたものである。</p>

<figure class="wp-block-table aligncenter"><table><thead><tr><th class="has-text-align-center">文字(記号)</th><th class="has-text-align-center">符号 (ビット表記)</th><th class="has-text-align-right">出現確率</th></tr></thead><tbody><tr><td class="has-text-align-center">A</td><td class="has-text-align-center">(ア)</td><td class="has-text-align-right">12%</td></tr><tr><td class="has-text-align-center">B</td><td class="has-text-align-center">(イ)</td><td class="has-text-align-right">56%</td></tr><tr><td class="has-text-align-center">C</td><td class="has-text-align-center">(ウ)</td><td class="has-text-align-right">4%</td></tr><tr><td class="has-text-align-center">D</td><td class="has-text-align-center">(エ)</td><td class="has-text-align-right">20%</td></tr><tr><td class="has-text-align-center">E</td><td class="has-text-align-center">(オ)</td><td class="has-text-align-right">8%</td></tr></tbody></table></figure>

<p>(1) この文字列をシャノン・ファノ符号化法によって符号化し、ビット表記の (ア) ～ (オ) に当てはまるビット表記を答えなさい。<br>(2) (1)で符号化した符号の平均符号長 \( L \) を小数第2位まで答えなさい。（必要であれば小数第3位を四捨五入すること）</p>
</div></div>


<div style="height:51px" class="wp-block-spacer"></div>



<h3 class="wp-block-heading">Step1. 各文字を出現確率 (回数) の多い順に並べ、全体で1つのグループと仮定</h3>



<p>シャノン・ファノ符号化をする際にはまず、与えられた文字（記号・情報）を出現確率が大きい順に並び替えます。</p>



<figure class="wp-block-table aligncenter"><table><thead><tr><th class="has-text-align-center">文字</th><th class="has-text-align-right">出現確率</th></tr></thead><tbody><tr><td class="has-text-align-center">B</td><td class="has-text-align-right">56%</td></tr><tr><td class="has-text-align-center">D</td><td class="has-text-align-right">20%</td></tr><tr><td class="has-text-align-center">A</td><td class="has-text-align-right">12%</td></tr><tr><td class="has-text-align-center">E</td><td class="has-text-align-right">8%</td></tr><tr><td class="has-text-align-center">C</td><td class="has-text-align-right">4%</td></tr></tbody></table></figure>


<p>ここからがハフマン符号と方法が変わってくるので、注意してみていきましょう。</p>
<p>シャノン・ファノ符号化では、最初に<span  style="background-image:linear-gradient(to bottom,transparent 0%,#FFF387 0%);" class="dbp-e-marker-animation y">すべての文字 (記号・情報) を1つのグループと仮定します</span>。</p>


<div style="height:52px" class="wp-block-spacer"></div>



<h3 class="wp-block-heading">Step2. グループ内の情報を、確率が半分になるように分解していく。(すべてのグループの情報が1つになるまで)</h3>


<p><span>すべてのグループに属する文字が1つになるまで、「2つ以上の文字が属するグループ」を出現確率の和が最も半分に近くなる部分で2分割していきます。</span></p>
<p><span>ここで、</span>「<span>出現確率の和が</span>最も半分に近くなる部分」を選んでいく際に、グループ内の各文字の確率を大きい順に足していくことで確認します。（<span>シャノン・ファノ符号化の特徴）</span></p>


<div style="height:50px" class="wp-block-spacer"></div>



<p><strong>Step2-1. BDAED (100%) を2分割</strong></p>



<p>まずは、BDAED (合計確率: 100%) を2分割します。</p>



<p>ここで、最も半分 (50%) に近くなるように分割するためには、<mark style="background-color:rgba(0, 0, 0, 0);color:#0051ff" class="has-inline-color">B (56%)</mark> と<mark style="background-color:rgba(0, 0, 0, 0);color:#ff0071" class="has-inline-color">DAEC (44%)</mark> に分ければOKですね。</p>



<figure class="wp-block-table aligncenter"><table><thead><tr><th class="has-text-align-center">文字</th><th class="has-text-align-right">出現確率</th></tr></thead><tbody><tr><td class="has-text-align-center"><mark style="background-color:rgba(0, 0, 0, 0);color:#0051ff" class="has-inline-color">B</mark></td><td class="has-text-align-right"><mark style="background-color:rgba(0, 0, 0, 0);color:#0051ff" class="has-inline-color">56%</mark></td></tr><tr><td class="has-text-align-center"><mark style="background-color:rgba(0, 0, 0, 0);color:#ff0071" class="has-inline-color">D</mark></td><td class="has-text-align-right"><mark style="background-color:rgba(0, 0, 0, 0);color:#ff0071" class="has-inline-color">20%</mark></td></tr><tr><td class="has-text-align-center"><mark style="background-color:rgba(0, 0, 0, 0);color:#ff0071" class="has-inline-color">A</mark></td><td class="has-text-align-right"><mark style="background-color:rgba(0, 0, 0, 0);color:#ff0071" class="has-inline-color">12%</mark></td></tr><tr><td class="has-text-align-center"><mark style="background-color:rgba(0, 0, 0, 0);color:#0051ff" class="has-inline-color"><mark style="background-color:rgba(0, 0, 0, 0);color:#ff0071" class="has-inline-color">E</mark></mark></td><td class="has-text-align-right"><mark style="background-color:rgba(0, 0, 0, 0);color:#0051ff" class="has-inline-color"><mark style="background-color:rgba(0, 0, 0, 0);color:#ff0071" class="has-inline-color">8%</mark></mark></td></tr><tr><td class="has-text-align-center"><mark style="background-color:rgba(0, 0, 0, 0);color:#ff0071" class="has-inline-color">C</mark></td><td class="has-text-align-right"><mark style="background-color:rgba(0, 0, 0, 0);color:#ff0071" class="has-inline-color">4%</mark></td></tr></tbody></table></figure>



<p>つぎに、分けた2つのグループを下のように二分木で書きます。</p>



<figure class="wp-block-image aligncenter size-full"><img width="817" height="602" src="https://www.momoyama-usagi.com/wp-content/uploads/joho4-2-1.jpg" alt="" class="wp-image-18207" srcset="https://www.momoyama-usagi.com/wp-content/uploads/joho4-2-1.jpg 817w, https://www.momoyama-usagi.com/wp-content/uploads/joho4-2-1-300x221.jpg 300w, https://www.momoyama-usagi.com/wp-content/uploads/joho4-2-1-768x566.jpg 768w" /></figure>



<p>ここで、Bはすでに1つの文字のグループとなったため、これ以上の操作は不要です。一方、ACDEはまだ2つ以上の文字のグループなため、さらに分割をしていきます。</p>



<div style="height:50px" class="wp-block-spacer"></div>



<p><strong>Step2-2. ACDE (44%) を2分割</strong></p>



<p>つぎに、ACDE (合計確率: 44%) を確率が最も半分 (22%) に近くなるところで2分割します。</p>



<figure class="wp-block-table aligncenter"><table><thead><tr><th class="has-text-align-center">文字</th><th class="has-text-align-right">出現確率</th></tr></thead><tbody><tr><td class="has-text-align-center"><mark style="background-color:rgba(0, 0, 0, 0);color:#0051ff" class="has-inline-color">D</mark></td><td class="has-text-align-right"><mark style="background-color:rgba(0, 0, 0, 0);color:#ff0071" class="has-inline-color"><mark style="background-color:rgba(0, 0, 0, 0);color:#0051ff" class="has-inline-color">20%</mark></mark></td></tr><tr><td class="has-text-align-center"><mark style="background-color:rgba(0, 0, 0, 0);color:#ff0071" class="has-inline-color">A</mark></td><td class="has-text-align-right"><mark style="background-color:rgba(0, 0, 0, 0);color:#ff0071" class="has-inline-color">12%</mark></td></tr><tr><td class="has-text-align-center"><mark style="background-color:rgba(0, 0, 0, 0);color:#0051ff" class="has-inline-color"><mark style="background-color:rgba(0, 0, 0, 0);color:#ff0071" class="has-inline-color">E</mark></mark></td><td class="has-text-align-right"><mark style="background-color:rgba(0, 0, 0, 0);color:#0051ff" class="has-inline-color"><mark style="background-color:rgba(0, 0, 0, 0);color:#ff0071" class="has-inline-color">8%</mark></mark></td></tr><tr><td class="has-text-align-center"><mark style="background-color:rgba(0, 0, 0, 0);color:#ff0071" class="has-inline-color">C</mark></td><td class="has-text-align-right"><mark style="background-color:rgba(0, 0, 0, 0);color:#ff0071" class="has-inline-color">4%</mark></td></tr></tbody></table></figure>



<p>ここで、最も半分 (22%) に近くなるように分割するためには、<mark style="background-color:rgba(0, 0, 0, 0);color:#0051ff" class="has-inline-color">D (20%)</mark> と<mark style="background-color:rgba(0, 0, 0, 0);color:#ff0071" class="has-inline-color">AEC (24%)</mark> に分ければOKですね。</p>



<p>さらに、分けた2つのグループを下のように二分木で書きます。</p>



<figure class="wp-block-image aligncenter size-large"><img width="1024" height="844" src="https://www.momoyama-usagi.com/wp-content/uploads/joho4-2-2-1024x844.jpg" alt="" class="wp-image-18208" srcset="https://www.momoyama-usagi.com/wp-content/uploads/joho4-2-2-1024x844.jpg 1024w, https://www.momoyama-usagi.com/wp-content/uploads/joho4-2-2-300x247.jpg 300w, https://www.momoyama-usagi.com/wp-content/uploads/joho4-2-2-768x633.jpg 768w, https://www.momoyama-usagi.com/wp-content/uploads/joho4-2-2.jpg 1049w" /></figure>



<p>ここで、Dはすでに1つの文字のグループとなったため、これ以上の操作は不要です。一方、AECはまだ2つ以上の文字のグループなため、さらに分割をしていきます。</p>



<div style="height:50px" class="wp-block-spacer"></div>



<p><strong>Step2-3. AEC (24%) を2分割</strong></p>



<p>つぎに、ACDE (24%) を確率が最も半分 (12%) に近くなるところで2分割します。</p>



<figure class="wp-block-table aligncenter"><table><thead><tr><th class="has-text-align-center">文字</th><th class="has-text-align-right">出現確率</th></tr></thead><tbody><tr><td class="has-text-align-center"><mark style="background-color:rgba(0, 0, 0, 0);color:#0051ff" class="has-inline-color">A</mark></td><td class="has-text-align-right"><mark style="background-color:rgba(0, 0, 0, 0);color:#ff0071" class="has-inline-color"><mark style="background-color:rgba(0, 0, 0, 0);color:#0051ff" class="has-inline-color">12%</mark></mark></td></tr><tr><td class="has-text-align-center"><mark style="background-color:rgba(0, 0, 0, 0);color:#0051ff" class="has-inline-color"><mark style="background-color:rgba(0, 0, 0, 0);color:#ff0071" class="has-inline-color">E</mark></mark></td><td class="has-text-align-right"><mark style="background-color:rgba(0, 0, 0, 0);color:#0051ff" class="has-inline-color"><mark style="background-color:rgba(0, 0, 0, 0);color:#ff0071" class="has-inline-color">8%</mark></mark></td></tr><tr><td class="has-text-align-center"><mark style="background-color:rgba(0, 0, 0, 0);color:#ff0071" class="has-inline-color">C</mark></td><td class="has-text-align-right"><mark style="background-color:rgba(0, 0, 0, 0);color:#ff0071" class="has-inline-color">4%</mark></td></tr></tbody></table></figure>



<p>ここで、最も半分 (12%) に近くなるように分割するためには、<mark style="background-color:rgba(0, 0, 0, 0);color:#0051ff" class="has-inline-color">A (12%)</mark> と<mark style="background-color:rgba(0, 0, 0, 0);color:#ff0071" class="has-inline-color">EC (12%)</mark> に分ければOKですね。</p>



<p>さらに、分けた2つのグループを下のように二分木で書きます。</p>



<figure class="wp-block-image aligncenter size-large"><img width="1024" height="918" src="https://www.momoyama-usagi.com/wp-content/uploads/joho4-2-3-1024x918.jpg" alt="" class="wp-image-18209" srcset="https://www.momoyama-usagi.com/wp-content/uploads/joho4-2-3-1024x918.jpg 1024w, https://www.momoyama-usagi.com/wp-content/uploads/joho4-2-3-300x269.jpg 300w, https://www.momoyama-usagi.com/wp-content/uploads/joho4-2-3-768x688.jpg 768w, https://www.momoyama-usagi.com/wp-content/uploads/joho4-2-3.jpg 1244w" /></figure>



<p>ここで、Aはすでに1つの文字のグループとなったため、これ以上の操作は不要です。一方、ECはまだ2つ以上の文字のグループなため、さらに分割をしていきます。</p>



<div style="height:50px" class="wp-block-spacer"></div>



<p><strong>Step2-4. EC (12%) を2分割</strong></p>



<p>つぎに、EC (合計確率: 12%) を確率が最も半分 (6%) に近くなるところで2分割します。<br>（とはいっても、グループ内の文字が2つなので、確率に関係なしに1-1に分割するしかありませんが…）</p>



<figure class="wp-block-table aligncenter"><table><thead><tr><th class="has-text-align-center">文字</th><th class="has-text-align-right">出現確率</th></tr></thead><tbody><tr><td class="has-text-align-center"><mark style="background-color:rgba(0, 0, 0, 0);color:#0051ff" class="has-inline-color">E</mark></td><td class="has-text-align-right"><mark style="background-color:rgba(0, 0, 0, 0);color:#ff0071" class="has-inline-color"><mark style="background-color:rgba(0, 0, 0, 0);color:#0051ff" class="has-inline-color">8%</mark></mark></td></tr><tr><td class="has-text-align-center"><mark style="background-color:rgba(0, 0, 0, 0);color:#ff0071" class="has-inline-color">C</mark></td><td class="has-text-align-right"><mark style="background-color:rgba(0, 0, 0, 0);color:#ff0071" class="has-inline-color">4%</mark></td></tr></tbody></table></figure>



<p>分けた2つのグループを下のように二分木で書きます。</p>



<figure class="wp-block-image aligncenter size-large"><img width="1024" height="965" src="https://www.momoyama-usagi.com/wp-content/uploads/joho4-2-4-1024x965.jpg" alt="" class="wp-image-18210" srcset="https://www.momoyama-usagi.com/wp-content/uploads/joho4-2-4-1024x965.jpg 1024w, https://www.momoyama-usagi.com/wp-content/uploads/joho4-2-4-300x283.jpg 300w, https://www.momoyama-usagi.com/wp-content/uploads/joho4-2-4-768x724.jpg 768w, https://www.momoyama-usagi.com/wp-content/uploads/joho4-2-4.jpg 1489w" /></figure>



<p>すると、E, C ともに1つの文字のグループとなり、すべてのグループに属する文字が1つとなりましたね。</p>



<p>そのため、Step2の操作はここで完了です。</p>



<div style="height:50px" class="wp-block-spacer"></div>



<h3 class="wp-block-heading">Step3. 作成した二分木から各文字(情報)ごとの符号を求める</h3>



<p>あとは、作成した二分木を見ていくことで、各文字ごとの符号を求めていきましょう。<br>（※ この部分はハフマン符号化と手順は同じです。）</p>



<p>まず、下のように各節（ノード）の左側を0、右側を1として考えます。<br>（葉となっていないノードの名前は、見やすさのため消しています。）</p>



<figure class="wp-block-image aligncenter size-full"><img width="2000" height="1470" src="https://www.momoyama-usagi.com/wp-content/uploads/9UzQft1fQ700XtVVYiX31670540939-1670541147.gif" alt="" class="wp-image-18200"/></figure>



<p>あとは、各文字（A～E）に対応するノードごとに「木構造の一番上の部分から対応するノードまでたどっていく」という操作をし、たどっていく際に通った0, 1を左から順番に並べていったものが符号となります。</p>



<p>よって、各文字A～Eごとの符号は下のように求まります。</p>



<figure class="wp-block-table aligncenter"><table><thead><tr><th class="has-text-align-center">文字(記号)</th><th class="has-text-align-center">符号 (ビット表記)</th><th class="has-text-align-right">出現確率</th></tr></thead><tbody><tr><td class="has-text-align-center">A</td><td class="has-text-align-center">110</td><td class="has-text-align-right">12%</td></tr><tr><td class="has-text-align-center">B</td><td class="has-text-align-center">0</td><td class="has-text-align-right">56%</td></tr><tr><td class="has-text-align-center">C</td><td class="has-text-align-center">1111</td><td class="has-text-align-right">4%</td></tr><tr><td class="has-text-align-center">D</td><td class="has-text-align-center">10</td><td class="has-text-align-right">20%</td></tr><tr><td class="has-text-align-center">E</td><td class="has-text-align-center">1110</td><td class="has-text-align-right">8%</td></tr></tbody></table></figure>


<p><span>結果を見てみると、<span  style="background-image:linear-gradient(to bottom,transparent 0%,#FFF387 0%);" class="dbp-e-marker-animation blue">出現確率が高い符号には短い符号</span>を、<span  style="background-image:linear-gradient(to bottom,transparent 0%,#FFF387 0%);" class="dbp-e-marker-animation red">出現確率が低い符号には長い符号</span>が付いていることがわかりますね。</span></p>
<p>このように、シャノン・ファノ符号化も、ハフマン符号化と同じく文字列の平均符号長がなるべく短くなるような符号の決め方を機械的に決めることができるのです！</p>


<p>※ シャノン・ファノ符号化において、二分木を書くことで瞬時復号可能な符号が作成できる理由は<a rel="noreferrer noopener" href="https://www.momoyama-usagi.com/entry/info-joho3#2" data-type="URL" target="_blank">こちら</a>に記しています<span class="footnote_referrer"><a tabindex="0" onclick="footnote_moveToReference_18163_1('footnote_plugin_reference_18163_1_1');" onkeypress="footnote_moveToReference_18163_1('footnote_plugin_reference_18163_1_1');" ><sup id="footnote_plugin_tooltip_18163_1_1" class="footnote_plugin_tooltip_text">[1]</sup></a><span id="footnote_plugin_tooltip_text_18163_1_1" class="footnote_tooltip">&nbsp;&#x2026; <span class="footnote_tooltip_continue"  onclick="footnote_moveToReference_18163_1('footnote_plugin_reference_18163_1_1');">Continue reading</span></span></span>。</p>



<div style="height:54px" class="wp-block-spacer"></div>



<p>(2) </p>



<p>平均符号長は、各文字ごとに「符号長（符号の文字数） × 出現確率」を求め、それらを足すことで求めることができます。</p>



<p>今回の場合は、各文字ごとの「符号長」、および「符号長 × 出現確率」を下のように求めることができます。</p>



<figure class="wp-block-table aligncenter"><table><thead><tr><th class="has-text-align-center">文字(記号)</th><th class="has-text-align-center">符号 (ビット表記)</th><th class="has-text-align-center">符号長</th><th class="has-text-align-right">出現確率</th><th class="has-text-align-center">符号長 × 出現確率</th></tr></thead><tbody><tr><td class="has-text-align-center">A</td><td class="has-text-align-center">110</td><td class="has-text-align-center">3</td><td class="has-text-align-right">12%</td><td class="has-text-align-center">0.36</td></tr><tr><td class="has-text-align-center">B</td><td class="has-text-align-center">0</td><td class="has-text-align-center">1</td><td class="has-text-align-right">56%</td><td class="has-text-align-center">0.56</td></tr><tr><td class="has-text-align-center">C</td><td class="has-text-align-center">1111</td><td class="has-text-align-center">4</td><td class="has-text-align-right">4%</td><td class="has-text-align-center">0.16</td></tr><tr><td class="has-text-align-center">D</td><td class="has-text-align-center">10</td><td class="has-text-align-center">2</td><td class="has-text-align-right">20%</td><td class="has-text-align-center">0.40</td></tr><tr><td class="has-text-align-center">E</td><td class="has-text-align-center">1110</td><td class="has-text-align-center">4</td><td class="has-text-align-right">8%</td><td class="has-text-align-center">0.32</td></tr></tbody></table></figure>



<p>よって、平均符号長 \( L \) は\[\begin{align*}<br>L &amp; = 0.36 + 0.56 + 0.16 + 0.40 + 0.32 <br>\\ &amp; = 1.80<br>\end{align*}\]と求まります。</p>



<p>※ ハフマン符号のときと全く同じ平均符号長が得られます。</p>



<div style="height:100px" class="wp-block-spacer"></div>



<h2 class="wp-block-heading">2. シャノン・ファノ符号化手順まとめ</h2>


<div class='wp-block-dbp-frame l-frame-inner is-design-inline is-frame-style-default dbp-frame has-bgcolor'><div class="dbp-frame-title">シャノン・ファノ符号化手順まとめ</div><div class="dbp-frame-content has-content-gap">
<p>ある情報 (文字列) をハフマン符号化する場合、次の1-3を順にすればOK。</p>

<ol class="wp-block-list">
<li>各情報 (文字) を出現確率 (頻度) の大きい順に並び替え、情報全てが同じグループに属していると仮定する</li>



<li>2つ以上の情報 (文字) が属しているグループに対し、「グループ内の各情報の確率を大きい順に足していき、グループ全体の確率の和の半分に最も近くなるところ」で2つのグループに分け、二分木を書いていく。</li>



<li>2を、全ての情報がそれぞれ異なるグループに属するまで行い、完成した二分木から符号を決める</li>
</ol>

<p>※ シャノン・ファノ符号化により作成された符号は必ず瞬時復号可能な符号となる。</p>
</div></div>


<div style="height:100px" class="wp-block-spacer"></div>



<h2 class="wp-block-heading">3. 練習問題</h2>



<p>実際に練習問題で、シャノン・ファノ符号化ができるか確認してみましょう。</p>


<div class='wp-block-dbp-frame l-frame-float is-design-onframe is-frame-style-default dbp-frame has-bgcolor'><div class="dbp-frame-title">問題</div><div class="dbp-frame-content has-content-gap">
<p>つぎの表は、とある文字列中（情報源）に出てくる文字の出現回数を表にしたものである。</p>

<figure class="wp-block-table aligncenter"><table><thead><tr><th class="has-text-align-center">文字(記号)</th><th class="has-text-align-center">符号 (ビット表記)</th><th class="has-text-align-right">出現回数</th></tr></thead><tbody><tr><td class="has-text-align-center">A</td><td class="has-text-align-center">(ア)</td><td class="has-text-align-right">5</td></tr><tr><td class="has-text-align-center">B</td><td class="has-text-align-center">(イ)</td><td class="has-text-align-right">1</td></tr><tr><td class="has-text-align-center">C</td><td class="has-text-align-center">(ウ)</td><td class="has-text-align-right">6</td></tr><tr><td class="has-text-align-center">D</td><td class="has-text-align-center">(エ)</td><td class="has-text-align-right">4</td></tr><tr><td class="has-text-align-center">E</td><td class="has-text-align-center">(オ)</td><td class="has-text-align-right">3</td></tr><tr><td class="has-text-align-center">F</td><td class="has-text-align-center">(カ)</td><td class="has-text-align-right">1</td></tr></tbody></table></figure>

<p>(1) この文字列をシャノン・ファノ符号化法によって符号化し、ビット表記の (ア) ～ (カ) に当てはまるビット表記を答えなさい。<br>(2) (1)で符号化した符号の平均符号長 \( L \) を小数第2位まで答えなさい。（必要であれば小数第3位を四捨五入すること）</p>
</div></div>


<div style="height:100px" class="wp-block-spacer"></div>



<h2 class="wp-block-heading">4. 練習問題の答え</h2>



<p>(1)を解く前に各文字の出現回数から出現確率を求めましょう。（(2)で使うため）</p>



<p>各文字の出現確率は、( 各文字の出現回数 ) ÷ ( 文字全体の出現回数[今回の場合は20] ) で求めることができます。</p>



<figure class="wp-block-table aligncenter"><table><thead><tr><th class="has-text-align-center">文字(記号)</th><th class="has-text-align-center">符号 (ビット表記)</th><th class="has-text-align-right">出現回数</th><th class="has-text-align-right">出現確率</th></tr></thead><tbody><tr><td class="has-text-align-center">A</td><td class="has-text-align-center">(ア)</td><td class="has-text-align-right">5</td><td class="has-text-align-right">25%</td></tr><tr><td class="has-text-align-center">B</td><td class="has-text-align-center">(イ)</td><td class="has-text-align-right">1</td><td class="has-text-align-right">5%</td></tr><tr><td class="has-text-align-center">C</td><td class="has-text-align-center">(ウ)</td><td class="has-text-align-right">6</td><td class="has-text-align-right">30%</td></tr><tr><td class="has-text-align-center">D</td><td class="has-text-align-center">(エ)</td><td class="has-text-align-right">4</td><td class="has-text-align-right">20%</td></tr><tr><td class="has-text-align-center">E</td><td class="has-text-align-center">(オ)</td><td class="has-text-align-right">3</td><td class="has-text-align-right">15%</td></tr><tr><td class="has-text-align-center">F</td><td class="has-text-align-center">(カ)</td><td class="has-text-align-right">1</td><td class="has-text-align-right">5%</td></tr></tbody></table></figure>



<div style="height:50px" class="wp-block-spacer"></div>



<p><strong>(1) ハフマン符号による符号化</strong></p>



<h3 class="wp-block-heading">Step1. 各文字を出現確率 (回数) の多い順に並べ、全体で1つのグループと仮定</h3>



<p>まず、与えられた文字（記号・情報）を出現確率が大きい順に並び替えます。</p>



<figure class="wp-block-table aligncenter"><table><thead><tr><th class="has-text-align-center">文字</th><th class="has-text-align-right">出現確率</th></tr></thead><tbody><tr><td class="has-text-align-center">C</td><td class="has-text-align-right">30%</td></tr><tr><td class="has-text-align-center">A</td><td class="has-text-align-right">25%</td></tr><tr><td class="has-text-align-center">D</td><td class="has-text-align-right">20%</td></tr><tr><td class="has-text-align-center">E</td><td class="has-text-align-right">15%</td></tr><tr><td class="has-text-align-center">B</td><td class="has-text-align-right">5%</td></tr><tr><td class="has-text-align-center">F</td><td class="has-text-align-right">5%</td></tr></tbody></table></figure>



<p>これら6つの文字をいったん、全て1つのグループに属していると仮定します。</p>



<div style="height:50px" class="wp-block-spacer"></div>



<h3 class="wp-block-heading">Step2. グループ内の情報を、確率が半分になるように分解していく。(すべてのグループの情報が1つになるまで)</h3>


<p><span>つぎに、すべてのグループに属する文字が1つになるまで、「2つ以上の文字が属するグループ」を出現確率の和が最も半分に近くなる部分で2分割していきます。</span></p>
<p><span>（</span>「<span>出現確率の和が</span>最も半分に近くなる部分」を選んでいく際に、グループ内の各文字の確率を大きい順に足していくことで確認します）</p>


<div style="height:50px" class="wp-block-spacer"></div>



<p><strong>Step2-1. CADEBF (100%) を2分割</strong></p>



<p>まずは、CADEBF (合計確率: 100%) を2分割します。</p>



<p>ここで、最も半分 (50%) に近くなるように分割するためには、<mark style="background-color:rgba(0, 0, 0, 0);color:#0051ff" class="has-inline-color">CA (55%)</mark> と<mark style="background-color:rgba(0, 0, 0, 0);color:#ff0071" class="has-inline-color">DEBF (45%)</mark> に分ければOKですね<span class="footnote_referrer"><a tabindex="0" onclick="footnote_moveToReference_18163_1('footnote_plugin_reference_18163_1_2');" onkeypress="footnote_moveToReference_18163_1('footnote_plugin_reference_18163_1_2');" ><sup id="footnote_plugin_tooltip_18163_1_2" class="footnote_plugin_tooltip_text">[2]</sup></a><span id="footnote_plugin_tooltip_text_18163_1_2" class="footnote_tooltip"><mark style="background-color:rgba(0, 0, 0, 0);color:#0051ff" class="has-inline-color">C (30%)</mark> と<mark style="background-color:rgba(0, 0, 0, 0);color:#ff0071" class="has-inline-color">ADEBF (70%)</mark>  だと最も半分に近くなるわけでないのでNG。</span></span>。</p>



<figure class="wp-block-table aligncenter"><table><thead><tr><th class="has-text-align-center">文字</th><th class="has-text-align-right">出現確率</th></tr></thead><tbody><tr><td class="has-text-align-center"><mark style="background-color:rgba(0, 0, 0, 0);color:#0051ff" class="has-inline-color">C</mark></td><td class="has-text-align-right"><mark style="background-color:rgba(0, 0, 0, 0);color:#0051ff" class="has-inline-color">30%</mark></td></tr><tr><td class="has-text-align-center"><mark style="background-color:rgba(0, 0, 0, 0);color:#ff0071" class="has-inline-color"><mark style="background-color:rgba(0, 0, 0, 0);color:#0051ff" class="has-inline-color">A</mark></mark></td><td class="has-text-align-right"><mark style="background-color:rgba(0, 0, 0, 0);color:#0051ff" class="has-inline-color">25%</mark></td></tr><tr><td class="has-text-align-center"><mark style="background-color:rgba(0, 0, 0, 0);color:#ff0071" class="has-inline-color">D</mark></td><td class="has-text-align-right"><mark style="background-color:rgba(0, 0, 0, 0);color:#ff0071" class="has-inline-color">20%</mark></td></tr><tr><td class="has-text-align-center"><mark style="background-color:rgba(0, 0, 0, 0);color:#ff0071" class="has-inline-color">E</mark></td><td class="has-text-align-right"><mark style="background-color:rgba(0, 0, 0, 0);color:#ff0071" class="has-inline-color">15%</mark></td></tr><tr><td class="has-text-align-center"><mark style="background-color:rgba(0, 0, 0, 0);color:#0051ff" class="has-inline-color"><mark style="background-color:rgba(0, 0, 0, 0);color:#ff0071" class="has-inline-color">B</mark></mark></td><td class="has-text-align-right"><mark style="background-color:rgba(0, 0, 0, 0);color:#0051ff" class="has-inline-color"><mark style="background-color:rgba(0, 0, 0, 0);color:#ff0071" class="has-inline-color">5%</mark></mark></td></tr><tr><td class="has-text-align-center"><mark style="background-color:rgba(0, 0, 0, 0);color:#ff0071" class="has-inline-color">F</mark></td><td class="has-text-align-right"><mark style="background-color:rgba(0, 0, 0, 0);color:#ff0071" class="has-inline-color">5%</mark></td></tr></tbody></table></figure>



<p>分けた2つのグループを下のように二分木で書きます。</p>



<figure class="wp-block-image aligncenter size-large"><img width="1024" height="484" src="https://www.momoyama-usagi.com/wp-content/uploads/joho4-2-5-1024x484.jpg" alt="" class="wp-image-18211" srcset="https://www.momoyama-usagi.com/wp-content/uploads/joho4-2-5-1024x484.jpg 1024w, https://www.momoyama-usagi.com/wp-content/uploads/joho4-2-5-300x142.jpg 300w, https://www.momoyama-usagi.com/wp-content/uploads/joho4-2-5-768x363.jpg 768w, https://www.momoyama-usagi.com/wp-content/uploads/joho4-2-5.jpg 1302w" /></figure>



<p>ここで、CA, DEBFの2つのグループともに、まだ2つ以上の文字のグループなため、さらに分割をしていきます。</p>



<div style="height:50px" class="wp-block-spacer"></div>



<p><strong>Step2-2. CA (55%) を2分割</strong></p>



<p>先にCA (合計確率: 55%) からグループを分割していきましょう。</p>



<p>グループ内に2つの文字しかないため、確率を気にせず1つずつに分割すればOKです。</p>



<figure class="wp-block-table aligncenter"><table><thead><tr><th class="has-text-align-center">文字</th><th class="has-text-align-right">出現確率</th></tr></thead><tbody><tr><td class="has-text-align-center"><mark style="background-color:rgba(0, 0, 0, 0);color:#0051ff" class="has-inline-color">C</mark></td><td class="has-text-align-right"><mark style="background-color:rgba(0, 0, 0, 0);color:#ff0071" class="has-inline-color"><mark style="background-color:rgba(0, 0, 0, 0);color:#0051ff" class="has-inline-color">30%</mark></mark></td></tr><tr><td class="has-text-align-center"><mark style="background-color:rgba(0, 0, 0, 0);color:#ff0071" class="has-inline-color">A</mark></td><td class="has-text-align-right"><mark style="background-color:rgba(0, 0, 0, 0);color:#ff0071" class="has-inline-color">25%</mark></td></tr></tbody></table></figure>



<p>分けた2つのグループを下のように二分木で書きます。</p>



<figure class="wp-block-image aligncenter size-large"><img width="1024" height="569" src="https://www.momoyama-usagi.com/wp-content/uploads/joho4-2-6-1024x569.jpg" alt="" class="wp-image-18212" srcset="https://www.momoyama-usagi.com/wp-content/uploads/joho4-2-6-1024x569.jpg 1024w, https://www.momoyama-usagi.com/wp-content/uploads/joho4-2-6-300x167.jpg 300w, https://www.momoyama-usagi.com/wp-content/uploads/joho4-2-6-768x426.jpg 768w, https://www.momoyama-usagi.com/wp-content/uploads/joho4-2-6.jpg 1484w" /></figure>



<p>これで、CAのグループは、互いに1つの文字のグループの文字に分割できたため、これ以上の操作は不要です。</p>



<p>なので、ここからはDEBFのグループを分割していきましょう。</p>



<div style="height:50px" class="wp-block-spacer"></div>



<p><strong>Step2-3. DEBF (45%) を2分割</strong></p>



<p>残った、DEBF (合計確率: 45%) を2分割します。</p>



<p>最も半分 (45%) に近くなるように分割するためには、<mark style="background-color:rgba(0, 0, 0, 0);color:#0051ff" class="has-inline-color">D (20%)</mark> と<mark style="background-color:rgba(0, 0, 0, 0);color:#ff0071" class="has-inline-color">EBF (25%)</mark> に分ければOKですね<span class="footnote_referrer"><a tabindex="0" onclick="footnote_moveToReference_18163_1('footnote_plugin_reference_18163_1_3');" onkeypress="footnote_moveToReference_18163_1('footnote_plugin_reference_18163_1_3');" ><sup id="footnote_plugin_tooltip_18163_1_3" class="footnote_plugin_tooltip_text">[3]</sup></a><span id="footnote_plugin_tooltip_text_18163_1_3" class="footnote_tooltip"><mark style="background-color:rgba(0, 0, 0, 0);color:#0051ff" class="has-inline-color">DE (35%)</mark> と<mark style="background-color:rgba(0, 0, 0, 0);color:#ff0071" class="has-inline-color">BF (10%)</mark>  だと最も半分に近くなるわけでないのでNG。</span></span>。</p>



<figure class="wp-block-table aligncenter"><table><thead><tr><th class="has-text-align-center">文字</th><th class="has-text-align-right">出現確率</th></tr></thead><tbody><tr><td class="has-text-align-center"><mark style="background-color:rgba(0, 0, 0, 0);color:#ff0071" class="has-inline-color"><mark style="background-color:rgba(0, 0, 0, 0);color:#0051ff" class="has-inline-color">D</mark></mark></td><td class="has-text-align-right"><mark style="background-color:rgba(0, 0, 0, 0);color:#ff0071" class="has-inline-color"><mark style="background-color:rgba(0, 0, 0, 0);color:#0051ff" class="has-inline-color">20%</mark></mark></td></tr><tr><td class="has-text-align-center"><mark style="background-color:rgba(0, 0, 0, 0);color:#ff0071" class="has-inline-color">E</mark></td><td class="has-text-align-right"><mark style="background-color:rgba(0, 0, 0, 0);color:#ff0071" class="has-inline-color">15%</mark></td></tr><tr><td class="has-text-align-center"><mark style="background-color:rgba(0, 0, 0, 0);color:#0051ff" class="has-inline-color"><mark style="background-color:rgba(0, 0, 0, 0);color:#ff0071" class="has-inline-color">B</mark></mark></td><td class="has-text-align-right"><mark style="background-color:rgba(0, 0, 0, 0);color:#0051ff" class="has-inline-color"><mark style="background-color:rgba(0, 0, 0, 0);color:#ff0071" class="has-inline-color">5%</mark></mark></td></tr><tr><td class="has-text-align-center"><mark style="background-color:rgba(0, 0, 0, 0);color:#ff0071" class="has-inline-color">F</mark></td><td class="has-text-align-right"><mark style="background-color:rgba(0, 0, 0, 0);color:#ff0071" class="has-inline-color">5%</mark></td></tr></tbody></table></figure>



<p>分けた2つのグループを下のように二分木で書きます。</p>



<figure class="wp-block-image aligncenter size-large"><img width="1024" height="492" src="https://www.momoyama-usagi.com/wp-content/uploads/joho4-3-1-1024x492.jpg" alt="" class="wp-image-18232" srcset="https://www.momoyama-usagi.com/wp-content/uploads/joho4-3-1-1024x492.jpg 1024w, https://www.momoyama-usagi.com/wp-content/uploads/joho4-3-1-300x144.jpg 300w, https://www.momoyama-usagi.com/wp-content/uploads/joho4-3-1-768x369.jpg 768w, https://www.momoyama-usagi.com/wp-content/uploads/joho4-3-1-1536x738.jpg 1536w, https://www.momoyama-usagi.com/wp-content/uploads/joho4-3-1.jpg 1732w" /></figure>



<p>Dはすでに1つの文字のグループとなったため、これ以上の操作は不要です。一方、EBFはまだ2つ以上の文字のグループなため、さらに分割をしていきます。</p>



<div style="height:50px" class="wp-block-spacer"></div>



<p><strong>Step2-4. EBF (25%) を2分割</strong></p>



<p>EBF (合計確率: 25%) を2分割します。</p>



<p>最も半分 (25%) に近くなるように分割するためには、<mark style="background-color:rgba(0, 0, 0, 0);color:#0051ff" class="has-inline-color">E (15%)</mark> と<mark style="background-color:rgba(0, 0, 0, 0);color:#ff0071" class="has-inline-color">BF (10%)</mark> に分ければOKですね。</p>



<figure class="wp-block-table aligncenter"><table><thead><tr><th class="has-text-align-center">文字</th><th class="has-text-align-right">出現確率</th></tr></thead><tbody><tr><td class="has-text-align-center"><mark style="background-color:rgba(0, 0, 0, 0);color:#ff0071" class="has-inline-color"><mark style="background-color:rgba(0, 0, 0, 0);color:#0051ff" class="has-inline-color">E</mark></mark></td><td class="has-text-align-right"><mark style="background-color:rgba(0, 0, 0, 0);color:#ff0071" class="has-inline-color"><mark style="background-color:rgba(0, 0, 0, 0);color:#0051ff" class="has-inline-color">15%</mark></mark></td></tr><tr><td class="has-text-align-center"><mark style="background-color:rgba(0, 0, 0, 0);color:#0051ff" class="has-inline-color"><mark style="background-color:rgba(0, 0, 0, 0);color:#ff0071" class="has-inline-color">B</mark></mark></td><td class="has-text-align-right"><mark style="background-color:rgba(0, 0, 0, 0);color:#0051ff" class="has-inline-color"><mark style="background-color:rgba(0, 0, 0, 0);color:#ff0071" class="has-inline-color">5%</mark></mark></td></tr><tr><td class="has-text-align-center"><mark style="background-color:rgba(0, 0, 0, 0);color:#ff0071" class="has-inline-color">F</mark></td><td class="has-text-align-right"><mark style="background-color:rgba(0, 0, 0, 0);color:#ff0071" class="has-inline-color">5%</mark></td></tr></tbody></table></figure>



<p>分けた2つのグループを下のように二分木で書きます。</p>



<figure class="wp-block-image aligncenter size-large"><img width="1024" height="585" src="https://www.momoyama-usagi.com/wp-content/uploads/joho4-3-2-1024x585.jpg" alt="" class="wp-image-18233" srcset="https://www.momoyama-usagi.com/wp-content/uploads/joho4-3-2-1024x585.jpg 1024w, https://www.momoyama-usagi.com/wp-content/uploads/joho4-3-2-300x171.jpg 300w, https://www.momoyama-usagi.com/wp-content/uploads/joho4-3-2-768x439.jpg 768w, https://www.momoyama-usagi.com/wp-content/uploads/joho4-3-2-1536x878.jpg 1536w, https://www.momoyama-usagi.com/wp-content/uploads/joho4-3-2.jpg 1947w" /></figure>



<p>Eはすでに1つの文字のグループとなったため、これ以上の操作は不要です。一方、BFはまだ2つ以上の文字のグループなため、さらに分割をしていきます。</p>



<div style="height:50px" class="wp-block-spacer"></div>



<p><strong>Step2-5. BF (10%) を2分割</strong></p>



<p>最後にBF (合計確率: 10%) からグループを分割していきましょう。</p>



<p>とはいっても、グループ内に2つの文字しかないため、確率を気にせず1つずつに分割すればOKです。</p>



<figure class="wp-block-table aligncenter"><table><thead><tr><th class="has-text-align-center">文字</th><th class="has-text-align-right">出現確率</th></tr></thead><tbody><tr><td class="has-text-align-center"><mark style="background-color:rgba(0, 0, 0, 0);color:#0051ff" class="has-inline-color">B</mark></td><td class="has-text-align-right"><mark style="background-color:rgba(0, 0, 0, 0);color:#ff0071" class="has-inline-color"><mark style="background-color:rgba(0, 0, 0, 0);color:#0051ff" class="has-inline-color">5%</mark></mark></td></tr><tr><td class="has-text-align-center"><mark style="background-color:rgba(0, 0, 0, 0);color:#ff0071" class="has-inline-color">F</mark></td><td class="has-text-align-right"><mark style="background-color:rgba(0, 0, 0, 0);color:#ff0071" class="has-inline-color">5%</mark></td></tr></tbody></table></figure>



<p>分けた2つのグループを下のように二分木で書きます。</p>



<figure class="wp-block-image aligncenter size-large"><img width="1024" height="648" src="https://www.momoyama-usagi.com/wp-content/uploads/joho4-3-3-1024x648.jpg" alt="" class="wp-image-18234" srcset="https://www.momoyama-usagi.com/wp-content/uploads/joho4-3-3-1024x648.jpg 1024w, https://www.momoyama-usagi.com/wp-content/uploads/joho4-3-3-300x190.jpg 300w, https://www.momoyama-usagi.com/wp-content/uploads/joho4-3-3-768x486.jpg 768w, https://www.momoyama-usagi.com/wp-content/uploads/joho4-3-3-1536x972.jpg 1536w, https://www.momoyama-usagi.com/wp-content/uploads/joho4-3-3-2048x1296.jpg 2048w" /></figure>



<p>これで、すべてのグループの文字が1つになったため、Step2はクリアです。</p>



<div style="height:50px" class="wp-block-spacer"></div>



<h3 class="wp-block-heading">Step3. 作成した二分木から各文字(情報)ごとの符号を求める</h3>



<p>あとは、各文字（A～E）に対応するノードごとに「木構造の一番上の部分から対応するノードまでたどっていく」という操作をし、たどっていく際に通った0, 1を左から順番に並べていったものが符号となります。</p>



<figure class="wp-block-image aligncenter size-full"><img width="2000" height="1206" src="https://www.momoyama-usagi.com/wp-content/uploads/HXM5RvfrURptGE4cpDvw1671028569-1671028856-2.gif" alt="" class="wp-image-18235"/></figure>



<p>よって、各文字A～Fごとの符号は下のように求まります。</p>



<figure class="wp-block-table aligncenter"><table><thead><tr><th class="has-text-align-center">文字(記号)</th><th class="has-text-align-center">符号 (ビット表記)</th><th class="has-text-align-right">出現確率</th></tr></thead><tbody><tr><td class="has-text-align-center">A</td><td class="has-text-align-center">01</td><td class="has-text-align-right">25%</td></tr><tr><td class="has-text-align-center">B</td><td class="has-text-align-center">1110</td><td class="has-text-align-right">5%</td></tr><tr><td class="has-text-align-center">C</td><td class="has-text-align-center">00</td><td class="has-text-align-right">30%</td></tr><tr><td class="has-text-align-center">D</td><td class="has-text-align-center">10</td><td class="has-text-align-right">20%</td></tr><tr><td class="has-text-align-center">E</td><td class="has-text-align-center">110</td><td class="has-text-align-right">15%</td></tr><tr><td class="has-text-align-center">F</td><td class="has-text-align-center">1111</td><td class="has-text-align-right">5%</td></tr></tbody></table></figure>



<div style="height:50px" class="wp-block-spacer"></div>



<p><strong>(2) 平均符号長の計算</strong></p>



<p>まず、各文字ごとの「符号長」および「符号長 × 出現確率」を求めましょう。</p>



<figure class="wp-block-table aligncenter"><table><thead><tr><th class="has-text-align-center">文字(記号)</th><th class="has-text-align-center">符号 (ビット表記)</th><th class="has-text-align-center">符号長</th><th class="has-text-align-right">出現確率</th><th class="has-text-align-center">符号長 × 出現確率</th></tr></thead><tbody><tr><td class="has-text-align-center">A</td><td class="has-text-align-center">01</td><td class="has-text-align-center">2</td><td class="has-text-align-right">25%</td><td class="has-text-align-center">0.50</td></tr><tr><td class="has-text-align-center">B</td><td class="has-text-align-center">1110</td><td class="has-text-align-center">4</td><td class="has-text-align-right">5%</td><td class="has-text-align-center">0.20</td></tr><tr><td class="has-text-align-center">C</td><td class="has-text-align-center">00</td><td class="has-text-align-center">2</td><td class="has-text-align-right">30%</td><td class="has-text-align-center">0.60</td></tr><tr><td class="has-text-align-center">D</td><td class="has-text-align-center">10</td><td class="has-text-align-center">2</td><td class="has-text-align-right">20%</td><td class="has-text-align-center">0.40</td></tr><tr><td class="has-text-align-center">E</td><td class="has-text-align-center">110</td><td class="has-text-align-center">3</td><td class="has-text-align-right">15%</td><td class="has-text-align-center">0.45</td></tr><tr><td class="has-text-align-center">F</td><td class="has-text-align-center">1111</td><td class="has-text-align-center">4</td><td class="has-text-align-right">5%</td><td class="has-text-align-center">0.20</td></tr></tbody></table></figure>



<p>あとは、A～Fごとに求めた「符号長 × 出現確率」をすべて足せば平均符号長 \( L \) があっという間に求まります。\[\begin{align*}<br>L &amp; = 0.50 + 0.20 + 0.60 + 0.40 + 0.45 + 0.20<br>\\ &amp; = 2.35<br>\end{align*}\]※ ハフマン符号で圧縮した場合も同じ平均符号長が求まります。</p>
<div class="speaker-mute footnotes_reference_container"> <div class="footnote_container_prepare"><p><span tabindex="0" class="footnote_reference_container_label pointer">注釈</span><span tabindex="0" class="footnote_reference_container_collapse_button" style="display: none;">[<a id="footnote_reference_container_collapse_button_18163_1">+</a>]</span></p></div> <div id="footnote_references_container_18163_1"><table class="footnotes_table footnote-reference-container"><caption class="accessibility">注釈</caption> <tbody> 

<tr class="footnotes_plugin_reference_row"> <th scope="row" class="footnote_plugin_index_combi pointer"  onclick="footnote_moveToAnchor_18163_1('footnote_plugin_tooltip_18163_1_1');"><a id="footnote_plugin_reference_18163_1_1" class="footnote_backlink"><span class="footnote_index_arrow">&#8593;</span>1</a></th> <td class="footnote_plugin_text">理由を簡単に説明すると、シャノン・ファノ符号化で作った二分木は必ず「全ての文字に対する各ノードがすべて葉ノードになっている」からです。</td></tr>

<tr class="footnotes_plugin_reference_row"> <th scope="row" class="footnote_plugin_index_combi pointer"  onclick="footnote_moveToAnchor_18163_1('footnote_plugin_tooltip_18163_1_2');"><a id="footnote_plugin_reference_18163_1_2" class="footnote_backlink"><span class="footnote_index_arrow">&#8593;</span>2</a></th> <td class="footnote_plugin_text"><mark style="background-color:rgba(0, 0, 0, 0);color:#0051ff" class="has-inline-color">C (30%)</mark> と<mark style="background-color:rgba(0, 0, 0, 0);color:#ff0071" class="has-inline-color">ADEBF (70%)</mark>  だと最も半分に近くなるわけでないのでNG。</td></tr>

<tr class="footnotes_plugin_reference_row"> <th scope="row" class="footnote_plugin_index_combi pointer"  onclick="footnote_moveToAnchor_18163_1('footnote_plugin_tooltip_18163_1_3');"><a id="footnote_plugin_reference_18163_1_3" class="footnote_backlink"><span class="footnote_index_arrow">&#8593;</span>3</a></th> <td class="footnote_plugin_text"><mark style="background-color:rgba(0, 0, 0, 0);color:#0051ff" class="has-inline-color">DE (35%)</mark> と<mark style="background-color:rgba(0, 0, 0, 0);color:#ff0071" class="has-inline-color">BF (10%)</mark>  だと最も半分に近くなるわけでないのでNG。</td></tr>

 </tbody> </table> </div></div>]]></content:encoded>
					
					<wfw:commentRss>https://www.momoyama-usagi.com/entry/info-joho4/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>[基本情報・応用情報] うさぎでもわかる情報理論　第3羽　ハフマン符号化</title>
		<link>https://www.momoyama-usagi.com/entry/info-joho3</link>
					<comments>https://www.momoyama-usagi.com/entry/info-joho3#respond</comments>
		
		<dc:creator><![CDATA[ももうさ]]></dc:creator>
		<pubDate>Wed, 23 Nov 2022 23:24:13 +0000</pubDate>
				<category><![CDATA[情報]]></category>
		<category><![CDATA[情報理論]]></category>
		<guid isPermaLink="false">https://www.momoyama-usagi.com/?p=17916</guid>

					<description><![CDATA[こんにちは、ももうさです。 前回では、「一意復号可能な符号」と「瞬時復号可能な符号」がどのような符号なのかについてみていきました。 今回は、文字列を瞬時復号可能な符号かつ瞬時復号可能な符号の中で平均符号長が最も短くなるよ [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>こんにちは、ももうさです。</p>



<p>前回では、「一意復号可能な符号」と「瞬時復号可能な符号」がどのような符号なのかについてみていきました。</p>



<figure class="wp-block-embed is-type-wp-embed is-provider-工業大学生ももやまのうさぎ塾 wp-block-embed-工業大学生ももやまのうさぎ塾"><div class="wp-block-embed__wrapper">
        <article class="pb p-id-17865 is-position-relative pb-embed">
            <a class="pb-contents" href="https://www.momoyama-usagi.com/entry/info-joho2">
                <div class="pb__thumb"><img width="300" height="177" src="https://www.momoyama-usagi.com/wp-content/uploads/joho1-11-300x177.gif" class="is-position-overlay wp-post-image" alt="" lazysizes="1" srcset="https://www.momoyama-usagi.com/wp-content/uploads/joho1-11-300x177.gif 300w, https://www.momoyama-usagi.com/wp-content/uploads/joho1-11-1024x603.gif 1024w, https://www.momoyama-usagi.com/wp-content/uploads/joho1-11-768x452.gif 768w" /></div><div class="pb__body l-column is-flex-1"><div class="pb-title is-omit-line:2">うさぎでもわかる情報理論　第2羽　符号化と一意復号可能・瞬時復号可能な符号</div><div class="pb-substr is-font-size:s is-omit-line:2">皆さんはパソコンやスマホなどのコンピュータ上で何事もなく、「日本語」や「アルファベット」などの文字を使ってやり取りしてい</div></div>            </a>
        </article>
        
</div></figure>


<p><span>今回は、文字列を<span  style="background-image:linear-gradient(to bottom,transparent 0%,#FFF387 0%);" class="dbp-e-marker-animation y">瞬時復号可能な符号</span>かつ<span  style="background-image:linear-gradient(to bottom,transparent 0%,#FFF387 0%);" class="dbp-e-marker-animation y">瞬時復号可能な符号の中で平均符号長が最も短くなるよう</span>に符号化をするハフマン符号化方式について、例題や練習問題を解きながら見ていきましょう。</span></p>


<p>さらに、実際に基本情報や応用情報でハフマン符号化がどのように出題され、どのように解いていけばよいのかについても、確認しましょう。</p>



<div style="height:71px" class="wp-block-spacer"></div>



<h2 class="wp-block-heading">1. まずは例題で確認</h2>



<p>まずは、例題でハフマン符号化の方法を見ていきましょう。</p>


<div class='wp-block-dbp-frame l-frame-float is-design-onframe is-frame-style-default dbp-frame has-bgcolor'><div class="dbp-frame-title">例題</div><div class="dbp-frame-content has-content-gap">
<p>つぎの表は、とある文字列中（情報源）に出てくる文字の出現確率を表にしたものである。</p>

<figure class="wp-block-table aligncenter"><table><thead><tr><th class="has-text-align-center">文字(記号)</th><th class="has-text-align-center">符号 (ビット表記)</th><th class="has-text-align-right">出現確率</th></tr></thead><tbody><tr><td class="has-text-align-center">A</td><td class="has-text-align-center">(ア)</td><td class="has-text-align-right">12%</td></tr><tr><td class="has-text-align-center">B</td><td class="has-text-align-center">(イ)</td><td class="has-text-align-right">56%</td></tr><tr><td class="has-text-align-center">C</td><td class="has-text-align-center">(ウ)</td><td class="has-text-align-right">4%</td></tr><tr><td class="has-text-align-center">D</td><td class="has-text-align-center">(エ)</td><td class="has-text-align-right">20%</td></tr><tr><td class="has-text-align-center">E</td><td class="has-text-align-center">(オ)</td><td class="has-text-align-right">8%</td></tr></tbody></table></figure>

<p>(1) この文字列をハフマン符号化法によって符号化し、ビット表記の (ア) ～ (オ) に当てはまるビット表記を答えなさい。<br>(2) (1)で符号化した符号の平均符号長 \( L \) を小数第2位まで答えなさい。（必要であれば小数第3位を四捨五入すること）</p>
</div></div>


<div style="height:51px" class="wp-block-spacer"></div>



<h3 class="wp-block-heading">Step1. 各文字を出現確率 (回数) の多い順に並べ、各文字ごとを独立したグループとする</h3>



<p>ハフマン符号化をする際にはまず、与えられた文字（記号・情報）をそれぞれ独立したグループとしてから、出現確率が大きい順に並び替えます。</p>



<figure class="wp-block-table aligncenter"><table><thead><tr><th class="has-text-align-center">グループ (文字)</th><th class="has-text-align-right">出現確率</th></tr></thead><tbody><tr><td class="has-text-align-center">B</td><td class="has-text-align-right">56%</td></tr><tr><td class="has-text-align-center">D</td><td class="has-text-align-right">20%</td></tr><tr><td class="has-text-align-center">A</td><td class="has-text-align-right">12%</td></tr><tr><td class="has-text-align-center">E</td><td class="has-text-align-right">8%</td></tr><tr><td class="has-text-align-center">C</td><td class="has-text-align-right">4%</td></tr></tbody></table></figure>



<p>今回の場合は5種類あるため、5つの独立したグループが出てきます。</p>



<p>※ 並び変える際に、文字と出現確率の対応を書き間違えないようにしましょう。</p>



<div style="height:52px" class="wp-block-spacer"></div>



<h3 class="wp-block-heading">Step2. 出現確率が低い2つのグループを1つにしていきながら、二分木を作る</h3>


<p><span>つぎに、<span  style="background-image:linear-gradient(to bottom,transparent 0%,#FFF387 0%);" class="dbp-e-marker-animation y">グループ数が1になるまで、各グループの中から出現確率が低い2つのグループを探し出し、その2つのグループをひとまとめにしていきます。</span></span></p>


<p><strong>Step2-1. 5グループ → 4グループ</strong></p>



<figure class="wp-block-table aligncenter"><table><thead><tr><th class="has-text-align-center">グループ (文字)</th><th class="has-text-align-right">出現確率</th></tr></thead><tbody><tr><td class="has-text-align-center">B</td><td class="has-text-align-right">56%</td></tr><tr><td class="has-text-align-center">D</td><td class="has-text-align-right">20%</td></tr><tr><td class="has-text-align-center">A</td><td class="has-text-align-right">12%</td></tr><tr><td class="has-text-align-center"><mark style="background-color:rgba(0, 0, 0, 0);color:#0051ff" class="has-inline-color">E</mark></td><td class="has-text-align-right"><mark style="background-color:rgba(0, 0, 0, 0);color:#0051ff" class="has-inline-color">8%</mark></td></tr><tr><td class="has-text-align-center"><mark style="background-color:rgba(0, 0, 0, 0);color:#ff0071" class="has-inline-color">C</mark></td><td class="has-text-align-right"><mark style="background-color:rgba(0, 0, 0, 0);color:#ff0071" class="has-inline-color">4%</mark></td></tr></tbody></table></figure>



<p>出現確率が低い2つのグループは、<mark style="background-color:rgba(0, 0, 0, 0);color:#0051ff" class="has-inline-color">E</mark>と<mark style="background-color:rgba(0, 0, 0, 0);color:#ff0071" class="has-inline-color">C</mark>なので、この2つをひとまとめにします。</p>



<p>（ひとまとめにしたグループの出現確率は、2つのグループの出現確率の合計です<span class="footnote_referrer"><a tabindex="0" onclick="footnote_moveToReference_17916_3('footnote_plugin_reference_17916_3_1');" onkeypress="footnote_moveToReference_17916_3('footnote_plugin_reference_17916_3_1');" ><sup id="footnote_plugin_tooltip_17916_3_1" class="footnote_plugin_tooltip_text">[1]</sup></a><span id="footnote_plugin_tooltip_text_17916_3_1" class="footnote_tooltip">今回の場合は、Eの出現確率が6%、Cの出現確率が6%なので、ひとまとめにしたグループの出現確率は、6% + 6% = 12% となります。</span></span>。）</p>



<figure class="wp-block-table aligncenter"><table><thead><tr><th class="has-text-align-center">グループ (文字)</th><th class="has-text-align-right">出現確率</th></tr></thead><tbody><tr><td class="has-text-align-center">B</td><td class="has-text-align-right">56%</td></tr><tr><td class="has-text-align-center">D</td><td class="has-text-align-right">20%</td></tr><tr><td class="has-text-align-center"><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-light-blue-color">A</mark></td><td class="has-text-align-right">12%</td></tr><tr><td class="has-text-align-center"><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-light-green-color">EC</mark></td><td class="has-text-align-right"><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-light-green-color">12%</mark></td></tr></tbody></table></figure>



<p>さらに、ひとまとめにした2つのグループを子とし、二分木をつくります<span class="footnote_referrer"><a tabindex="0" onclick="footnote_moveToReference_17916_3('footnote_plugin_reference_17916_3_2');" onkeypress="footnote_moveToReference_17916_3('footnote_plugin_reference_17916_3_2');" ><sup id="footnote_plugin_tooltip_17916_3_2" class="footnote_plugin_tooltip_text">[2]</sup></a><span id="footnote_plugin_tooltip_text_17916_3_2" class="footnote_tooltip">&nbsp;&#x2026; <span class="footnote_tooltip_continue"  onclick="footnote_moveToReference_17916_3('footnote_plugin_reference_17916_3_2');">Continue reading</span></span></span>。</p>



<figure class="wp-block-image aligncenter size-full is-resized"><img src="https://www.momoyama-usagi.com/wp-content/uploads/joho2-sub-1.jpg" alt="" class="wp-image-17941" width="470" height="359" srcset="https://www.momoyama-usagi.com/wp-content/uploads/joho2-sub-1.jpg 679w, https://www.momoyama-usagi.com/wp-content/uploads/joho2-sub-1-300x230.jpg 300w" /><figcaption class="wp-element-caption"><mark style="background-color:rgba(0, 0, 0, 0);color:#0051ff" class="has-inline-color">E</mark>, <mark style="background-color:rgba(0, 0, 0, 0);color:#ff0071" class="has-inline-color">C</mark>をひとまとめに</figcaption></figure>



<p><strong>Step2-2. 4グループ → 3グループ</strong></p>



<figure class="wp-block-table aligncenter"><table><thead><tr><th class="has-text-align-center">グループ (文字)</th><th class="has-text-align-right">出現確率</th></tr></thead><tbody><tr><td class="has-text-align-center">B</td><td class="has-text-align-right">56%</td></tr><tr><td class="has-text-align-center">D</td><td class="has-text-align-right">20%</td></tr><tr><td class="has-text-align-center"><mark style="background-color:rgba(0, 0, 0, 0);color:#0051ff" class="has-inline-color">A</mark></td><td class="has-text-align-right"><mark style="background-color:rgba(0, 0, 0, 0);color:#0051ff" class="has-inline-color">12%</mark></td></tr><tr><td class="has-text-align-center"><mark style="background-color:rgba(0, 0, 0, 0);color:#ff0071" class="has-inline-color">EC</mark></td><td class="has-text-align-right"><mark style="background-color:rgba(0, 0, 0, 0);color:#ff0071" class="has-inline-color">12%</mark></td></tr></tbody></table></figure>



<p>出現確率が低い2つのグループは、<mark style="background-color:rgba(0, 0, 0, 0);color:#0051ff" class="has-inline-color">A</mark>と<mark style="background-color:rgba(0, 0, 0, 0);color:#ff0071" class="has-inline-color">EC</mark>なので、この2つをひとまとめにします。</p>



<figure class="wp-block-table aligncenter"><table><thead><tr><th class="has-text-align-center">グループ (文字)</th><th class="has-text-align-right">出現確率</th></tr></thead><tbody><tr><td class="has-text-align-center">B</td><td class="has-text-align-right">56%</td></tr><tr><td class="has-text-align-center"><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-light-green-color">AEC</mark></td><td class="has-text-align-right"><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-light-green-color">24%</mark></td></tr><tr><td class="has-text-align-center">D</td><td class="has-text-align-right">20%</td></tr></tbody></table></figure>



<p>さらに、ひとまとめにした2つのグループを子とし、二分木をつくります。</p>



<figure class="wp-block-image aligncenter size-full is-resized"><img src="https://www.momoyama-usagi.com/wp-content/uploads/joho2-sub-2.jpg" alt="" class="wp-image-17942" width="604" height="440" srcset="https://www.momoyama-usagi.com/wp-content/uploads/joho2-sub-2.jpg 922w, https://www.momoyama-usagi.com/wp-content/uploads/joho2-sub-2-300x219.jpg 300w, https://www.momoyama-usagi.com/wp-content/uploads/joho2-sub-2-768x561.jpg 768w" /><figcaption class="wp-element-caption"><mark style="background-color:rgba(0, 0, 0, 0);color:#0051ff" class="has-inline-color">A</mark>, <mark style="background-color:rgba(0, 0, 0, 0);color:#ff0071" class="has-inline-color">EC</mark>をひとまとめに</figcaption></figure>



<p><strong>Step2-3. 3グループ → 2グループ</strong></p>



<figure class="wp-block-table aligncenter"><table><thead><tr><th class="has-text-align-center">グループ (文字)</th><th class="has-text-align-right">出現確率</th></tr></thead><tbody><tr><td class="has-text-align-center">B</td><td class="has-text-align-right">56%</td></tr><tr><td class="has-text-align-center"><mark style="background-color:rgba(0, 0, 0, 0);color:#0051ff" class="has-inline-color">AEC</mark></td><td class="has-text-align-right"><mark style="background-color:rgba(0, 0, 0, 0);color:#0051ff" class="has-inline-color">24%</mark></td></tr><tr><td class="has-text-align-center"><mark style="background-color:rgba(0, 0, 0, 0);color:#ff0071" class="has-inline-color">D</mark></td><td class="has-text-align-right"><mark style="background-color:rgba(0, 0, 0, 0);color:#ff0071" class="has-inline-color">20%</mark></td></tr></tbody></table></figure>



<p>出現確率が低い2つのグループは、AECとDなので、この2つをひとまとめにします。</p>



<figure class="wp-block-table aligncenter"><table><thead><tr><th class="has-text-align-center">グループ (文字)</th><th class="has-text-align-right">出現確率</th></tr></thead><tbody><tr><td class="has-text-align-center">B</td><td class="has-text-align-right">56%</td></tr><tr><td class="has-text-align-center"><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-light-green-color">AECD</mark></td><td class="has-text-align-right"><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-light-green-color">44%</mark></td></tr></tbody></table></figure>



<p>さらに、ひとまとめにした2つのグループを子とし、二分木をつくります。</p>



<figure class="wp-block-image aligncenter size-full is-resized"><img src="https://www.momoyama-usagi.com/wp-content/uploads/joho2-sub-3.jpg" alt="" class="wp-image-17943" width="566" height="566" srcset="https://www.momoyama-usagi.com/wp-content/uploads/joho2-sub-3.jpg 924w, https://www.momoyama-usagi.com/wp-content/uploads/joho2-sub-3-300x300.jpg 300w, https://www.momoyama-usagi.com/wp-content/uploads/joho2-sub-3-150x150.jpg 150w, https://www.momoyama-usagi.com/wp-content/uploads/joho2-sub-3-768x769.jpg 768w" /><figcaption class="wp-element-caption">A, ECをひとまとめに</figcaption></figure>



<p><strong>Step2-1. 2グループ → 1グループ</strong></p>



<figure class="wp-block-table aligncenter"><table><thead><tr><th class="has-text-align-center">グループ (文字)</th><th class="has-text-align-right">出現確率</th></tr></thead><tbody><tr><td class="has-text-align-center"><mark style="background-color:rgba(0, 0, 0, 0);color:#0051ff" class="has-inline-color">B</mark></td><td class="has-text-align-right"><mark style="background-color:rgba(0, 0, 0, 0);color:#0051ff" class="has-inline-color">56%</mark></td></tr><tr><td class="has-text-align-center"><mark style="background-color:rgba(0, 0, 0, 0);color:#ff0071" class="has-inline-color">AECD</mark></td><td class="has-text-align-right"><mark style="background-color:rgba(0, 0, 0, 0);color:#ff0071" class="has-inline-color">44%</mark></td></tr></tbody></table></figure>



<p>出現確率が低い2つのグループ(<mark style="background-color:rgba(0, 0, 0, 0);color:#0051ff" class="has-inline-color">B</mark>と<mark style="background-color:rgba(0, 0, 0, 0);color:#ff0071" class="has-inline-color">AECD</mark>)をひとまとめにします。<br>（残り2グループなので、その2グループが出現確率が低い2グループとなります。）</p>



<figure class="wp-block-table aligncenter"><table><thead><tr><th class="has-text-align-center">グループ (文字)</th><th class="has-text-align-right">出現確率</th></tr></thead><tbody><tr><td class="has-text-align-center"><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-light-green-color">BAECD</mark></td><td class="has-text-align-right"><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-light-green-color">100%</mark></td></tr></tbody></table></figure>



<p>いつものように、ひとまとめにした2つのグループを子とし、二分木をつくりましょう。</p>



<figure class="wp-block-image aligncenter size-large is-resized"><img src="https://www.momoyama-usagi.com/wp-content/uploads/joho2-sub-4-806x1024.jpg" alt="" class="wp-image-17944" width="699" height="888" srcset="https://www.momoyama-usagi.com/wp-content/uploads/joho2-sub-4-806x1024.jpg 806w, https://www.momoyama-usagi.com/wp-content/uploads/joho2-sub-4-236x300.jpg 236w, https://www.momoyama-usagi.com/wp-content/uploads/joho2-sub-4-768x976.jpg 768w, https://www.momoyama-usagi.com/wp-content/uploads/joho2-sub-4.jpg 924w" /></figure>



<div style="height:52px" class="wp-block-spacer"></div>



<h3 class="wp-block-heading">Step3. 作成した二分木から各文字(情報)ごとの符号を求める</h3>



<p>ここからは、作成した二分木を見ていくことで、各文字ごとの符号を求めていきましょう。</p>



<p>まず、下のように各節（ノード）の左側を0、右側を1として考えます。</p>



<figure class="wp-block-image aligncenter size-large is-resized"><img src="https://www.momoyama-usagi.com/wp-content/uploads/joho2-5-790x1024.jpg" alt="" class="wp-image-17926" width="651" height="844" srcset="https://www.momoyama-usagi.com/wp-content/uploads/joho2-5-790x1024.jpg 790w, https://www.momoyama-usagi.com/wp-content/uploads/joho2-5-231x300.jpg 231w, https://www.momoyama-usagi.com/wp-content/uploads/joho2-5-768x996.jpg 768w, https://www.momoyama-usagi.com/wp-content/uploads/joho2-5.jpg 820w" /></figure>



<p>あとは、各文字（A～E）に対応するノードごとに「木構造の一番上の部分から対応するノードまでたどっていく」という操作をし、たどっていく際に通った0, 1を左から順番に並べていったものが符号となります。</p>



<figure class="wp-block-image aligncenter size-full"><img width="1409" height="1258" src="https://www.momoyama-usagi.com/wp-content/uploads/nkk950VYYaTrDIN7aVYX1667344477-1667344710.gif" alt="" class="wp-image-17967"/></figure>



<p>よって、各文字A～Eごとの符号は下のように求まります。</p>



<figure class="wp-block-table aligncenter"><table><thead><tr><th class="has-text-align-center">文字(記号)</th><th class="has-text-align-center">符号 (ビット表記)</th><th class="has-text-align-right">出現確率</th></tr></thead><tbody><tr><td class="has-text-align-center">A</td><td class="has-text-align-center">100</td><td class="has-text-align-right">12%</td></tr><tr><td class="has-text-align-center">B</td><td class="has-text-align-center">0</td><td class="has-text-align-right">56%</td></tr><tr><td class="has-text-align-center">C</td><td class="has-text-align-center">1011</td><td class="has-text-align-right">4%</td></tr><tr><td class="has-text-align-center">D</td><td class="has-text-align-center">11</td><td class="has-text-align-right">20%</td></tr><tr><td class="has-text-align-center">E</td><td class="has-text-align-center">1010</td><td class="has-text-align-right">8%</td></tr></tbody></table></figure>


<p><span>結果を見てみると、<span  style="background-image:linear-gradient(to bottom,transparent 0%,#FFF387 0%);" class="dbp-e-marker-animation blue">出現確率が高い符号には短い符号</span>を、<span  style="background-image:linear-gradient(to bottom,transparent 0%,#FFF387 0%);" class="dbp-e-marker-animation red">出現確率が低い符号には長い符号</span>が付いていることがわかりますね。</span></p>
<p>このようにハフマン符号では、文字列の平均符号長がなるべく短くなるような符号の決め方を機械的に決めることができるのです！</p>


<div style="height:50px" class="wp-block-spacer"></div>



<p>(2) </p>



<p>平均符号長は、各文字ごとに「符号長（符号の文字数） × 出現確率」を求め、それらを足すことで求めることができます。</p>



<p>今回の場合は、各文字ごとの「符号長」、および「符号長 × 出現確率」を下のように求めることができます。</p>



<figure class="wp-block-table aligncenter"><table><thead><tr><th class="has-text-align-center">文字(記号)</th><th class="has-text-align-center">符号 (ビット表記)</th><th class="has-text-align-center">符号長</th><th class="has-text-align-right">出現確率</th><th class="has-text-align-center">符号長 × 出現確率</th></tr></thead><tbody><tr><td class="has-text-align-center">A</td><td class="has-text-align-center">100</td><td class="has-text-align-center">3</td><td class="has-text-align-right">12%</td><td class="has-text-align-center">0.36</td></tr><tr><td class="has-text-align-center">B</td><td class="has-text-align-center">0</td><td class="has-text-align-center">1</td><td class="has-text-align-right">56%</td><td class="has-text-align-center">0.56</td></tr><tr><td class="has-text-align-center">C</td><td class="has-text-align-center">1011</td><td class="has-text-align-center">4</td><td class="has-text-align-right">4%</td><td class="has-text-align-center">0.16</td></tr><tr><td class="has-text-align-center">D</td><td class="has-text-align-center">11</td><td class="has-text-align-center">2</td><td class="has-text-align-right">20%</td><td class="has-text-align-center">0.40</td></tr><tr><td class="has-text-align-center">E</td><td class="has-text-align-center">1010</td><td class="has-text-align-center">4</td><td class="has-text-align-right">8%</td><td class="has-text-align-center">0.32</td></tr></tbody></table></figure>



<p>よって、平均符号長 \( L \) は\[\begin{align*}<br>L &amp; = 0.36 + 0.56 + 0.16 + 0.40 + 0.32 <br>\\ &amp; = 1.80<br>\end{align*}\]と求まります。</p>


<div class='wp-block-dbp-frame l-frame-inner is-design-inline is-frame-style-default dbp-frame has-bgcolor'><div class="dbp-frame-title">ハフマン符号化手順まとめ</div><div class="dbp-frame-content has-content-gap">
<p>ある文字列 (情報) をハフマン符号化する場合、次の1-3を順にすればOK。</p>

<ol class="wp-block-list">
<li>各文字(情報)を出現確率（出現頻度）の高い順に並べ、それぞれを独立したグループと考える</li>



<li>各グループの中で、出現確率が低い2つのグループを1つにしていきながら、グループが1つになるまで二分木を作っていく。</li>



<li>作成した二分木から、各文字ごとの符号を求める</li>
</ol>
</div></div>


<div style="height:71px" class="wp-block-spacer"></div>



<h2 class="wp-block-heading">2. ハフマン符号化と瞬時復号可能性</h2>



<h4 class="wp-block-heading">(1) 瞬時復号可能な符号とは</h4>



<p>下のように、後戻りせずに符号化した文字列を復号することができる符号のことを、瞬時復号可能な符号と呼びます。</p>



<figure class="wp-block-image aligncenter size-full"><img width="1157" height="403" src="https://www.momoyama-usagi.com/wp-content/uploads/zhl1dYa4gERu0e9BcX3H1666181878-1666181916-1.gif" alt="" class="wp-image-17884"/><figcaption class="wp-element-caption">瞬時復号をしていく様子</figcaption></figure>



<p>瞬時復号可能であるためには、どの符号語に対しても、頭部分に自身以外の符号語が出てこないかどうかで判定をすることができます。</p>



<h4 class="wp-block-heading">(2) ハフマン符号化法で符号化した符号は必ず瞬時復号可能（かつ平均符号長が最小）！</h4>


<p>ハフマン符号法で符号化を行うと符号は、<span  style="background-image:linear-gradient(to bottom,transparent 0%,#FFF387 0%);" class="dbp-e-marker-animation y">必ず (平均符号長が最小の) 瞬時復号可能な符号になる</span>点が大きな特徴です。</p>
<p>ここで、ハフマン符号化により符号化すると<span>、必ず瞬時復号可能となることを二分木を使って確認しましょう。</span></p>


<p>まず、瞬時復号可能ではない符号を二分木で表すと、下のように各文字列が葉ではないノードが出てきますね。</p>



<p>つまり、葉ではないノードに対応する情報 (文字) があった時点で、何かしらの接頭語となっている符号が存在していることになります。</p>



<figure class="wp-block-image aligncenter size-large"><img width="1024" height="631" src="https://www.momoyama-usagi.com/wp-content/uploads/joho3-2-1-1024x631.jpg" alt="" class="wp-image-18084" srcset="https://www.momoyama-usagi.com/wp-content/uploads/joho3-2-1-1024x631.jpg 1024w, https://www.momoyama-usagi.com/wp-content/uploads/joho3-2-1-300x185.jpg 300w, https://www.momoyama-usagi.com/wp-content/uploads/joho3-2-1-768x473.jpg 768w, https://www.momoyama-usagi.com/wp-content/uploads/joho3-2-1-1536x946.jpg 1536w, https://www.momoyama-usagi.com/wp-content/uploads/joho3-2-1.jpg 1895w" /></figure>



<p>これを言い換えると、「全ての文字に対する各ノードがすべて葉ノードになっている」ことを確認できれば、接頭語となっている符号が存在しないこと、つまり符号が瞬時復号可能であることも確認ができます。</p>



<figure class="wp-block-image aligncenter size-large is-resized"><img src="https://www.momoyama-usagi.com/wp-content/uploads/joho3-1-1024x971.gif" alt="" class="wp-image-18094" width="607" height="575" srcset="https://www.momoyama-usagi.com/wp-content/uploads/joho3-1-1024x971.gif 1024w, https://www.momoyama-usagi.com/wp-content/uploads/joho3-1-300x284.gif 300w, https://www.momoyama-usagi.com/wp-content/uploads/joho3-1-768x728.gif 768w" /><figcaption class="wp-element-caption">瞬時復号可能な符号と二分木<br>（全ての文字列に対するノードが葉ノード）</figcaption></figure>


<p><span  style="background-image:linear-gradient(to bottom,transparent 0%,#FFF387 0%);" class="dbp-e-marker-animation y">ハフマン符号化法によって符号化した符号が必ず平均符号長最小の瞬時復号可能な符号となる</span>性質は、基本情報や応用情報の午前問題を解く際にかなり使えるので、必ず覚えておきましょう！！</p>


<p>※ 二分木を使って符号化をする方法には、ハフマン符号化のほかに<a rel="noreferrer noopener" href="https://www.momoyama-usagi.com/entry/info-joho4" data-type="URL" target="_blank">シャノン・ファノ符号化</a>もあります。シャノン・ファノ符号化はハフマン符号化とは異なるアルゴリズムで二分木を作成していきますが、瞬時復号可能となる理由はハフマン符号化と同じです<span class="footnote_referrer"><a tabindex="0" onclick="footnote_moveToReference_17916_3('footnote_plugin_reference_17916_3_3');" onkeypress="footnote_moveToReference_17916_3('footnote_plugin_reference_17916_3_3');" ><sup id="footnote_plugin_tooltip_17916_3_3" class="footnote_plugin_tooltip_text">[3]</sup></a><span id="footnote_plugin_tooltip_text_17916_3_3" class="footnote_tooltip"></span></span>。</p>



<div style="height:71px" class="wp-block-spacer"></div>



<h2 class="wp-block-heading">3. 練習問題</h2>


<div class='wp-block-dbp-frame l-frame-float is-design-onframe is-frame-style-default dbp-frame has-bgcolor'><div class="dbp-frame-title">問題</div><div class="dbp-frame-content has-content-gap">
<p>つぎの表は、とある文字列中（情報源）に出てくる文字の出現回数を表にしたものである。</p>

<figure class="wp-block-table aligncenter"><table><thead><tr><th class="has-text-align-center">文字(記号)</th><th class="has-text-align-center">符号 (ビット表記)</th><th class="has-text-align-right">出現回数</th></tr></thead><tbody><tr><td class="has-text-align-center">A</td><td class="has-text-align-center">(ア)</td><td class="has-text-align-right">5</td></tr><tr><td class="has-text-align-center">B</td><td class="has-text-align-center">(イ)</td><td class="has-text-align-right">1</td></tr><tr><td class="has-text-align-center">C</td><td class="has-text-align-center">(ウ)</td><td class="has-text-align-right">6</td></tr><tr><td class="has-text-align-center">D</td><td class="has-text-align-center">(エ)</td><td class="has-text-align-right">4</td></tr><tr><td class="has-text-align-center">E</td><td class="has-text-align-center">(オ)</td><td class="has-text-align-right">3</td></tr><tr><td class="has-text-align-center">F</td><td class="has-text-align-center">(カ)</td><td class="has-text-align-right">1</td></tr></tbody></table></figure>

<p>(1) この文字列をハフマン符号化法によって符号化し、ビット表記の (ア) ～ (カ) に当てはまるビット表記を答えなさい。<br>(2) (1)で符号化した符号の平均符号長 \( L \) を小数第2位まで答えなさい。（必要であれば小数第3位を四捨五入すること）</p>
</div></div>


<div style="height:71px" class="wp-block-spacer"></div>



<h2 class="wp-block-heading">4. 練習問題の答え</h2>



<p>(1)を解く前に各文字の出現回数から出現確率を求めましょう。（(2)で使うため）</p>



<p>各文字の出現確率は、( 各文字の出現回数 ) ÷ ( 文字全体の出現回数[今回の場合は20] ) で求めることができます。</p>



<figure class="wp-block-table aligncenter"><table><thead><tr><th class="has-text-align-center">文字(記号)</th><th class="has-text-align-center">符号 (ビット表記)</th><th class="has-text-align-right">出現回数</th><th class="has-text-align-right">出現確率</th></tr></thead><tbody><tr><td class="has-text-align-center">A</td><td class="has-text-align-center">(ア)</td><td class="has-text-align-right">5</td><td class="has-text-align-right">25%</td></tr><tr><td class="has-text-align-center">B</td><td class="has-text-align-center">(イ)</td><td class="has-text-align-right">1</td><td class="has-text-align-right">5%</td></tr><tr><td class="has-text-align-center">C</td><td class="has-text-align-center">(ウ)</td><td class="has-text-align-right">6</td><td class="has-text-align-right">30%</td></tr><tr><td class="has-text-align-center">D</td><td class="has-text-align-center">(エ)</td><td class="has-text-align-right">4</td><td class="has-text-align-right">20%</td></tr><tr><td class="has-text-align-center">E</td><td class="has-text-align-center">(オ)</td><td class="has-text-align-right">3</td><td class="has-text-align-right">15%</td></tr><tr><td class="has-text-align-center">F</td><td class="has-text-align-center">(カ)</td><td class="has-text-align-right">1</td><td class="has-text-align-right">5%</td></tr></tbody></table></figure>



<p><strong>(1) ハフマン符号による符号化</strong></p>



<h3 class="wp-block-heading">Step1. 各文字を出現確率 (回数) の多い順に並べ、各文字ごとを独立したグループとする</h3>



<p>まず、与えられた文字（記号・情報）をそれぞれ独立したグループとしてから、出現確率が大きい順に並び替えます。</p>



<figure class="wp-block-table aligncenter"><table><thead><tr><th class="has-text-align-center">グループ (文字)</th><th class="has-text-align-right">出現確率</th></tr></thead><tbody><tr><td class="has-text-align-center">C</td><td class="has-text-align-right">30%</td></tr><tr><td class="has-text-align-center">A</td><td class="has-text-align-right">25%</td></tr><tr><td class="has-text-align-center">D</td><td class="has-text-align-right">20%</td></tr><tr><td class="has-text-align-center">E</td><td class="has-text-align-right">15%</td></tr><tr><td class="has-text-align-center">B</td><td class="has-text-align-right">5%</td></tr><tr><td class="has-text-align-center">F</td><td class="has-text-align-right">5%</td></tr></tbody></table></figure>



<p>今回の場合は6種類あるため、6つの独立したグループが出てきます。</p>







<h3 class="wp-block-heading">Step2. 出現確率が低い2つのグループを1つにしていきながら、二分木を作る</h3>


<p>つぎに、1グループになるまで、「出現確率が低い2つのグループを1つにまとめる」という操作を繰り返します。</p>


<p><strong>Step2-1. 6グループ → 5グループ</strong></p>



<figure class="wp-block-table aligncenter"><table><thead><tr><th class="has-text-align-center">グループ (文字)</th><th class="has-text-align-right">出現確率</th></tr></thead><tbody><tr><td class="has-text-align-center">C</td><td class="has-text-align-right">30%</td></tr><tr><td class="has-text-align-center">A</td><td class="has-text-align-right">25%</td></tr><tr><td class="has-text-align-center">D</td><td class="has-text-align-right">20%</td></tr><tr><td class="has-text-align-center">E</td><td class="has-text-align-right">15%</td></tr><tr><td class="has-text-align-center"><mark style="background-color:rgba(0, 0, 0, 0);color:#0051ff" class="has-inline-color">B</mark></td><td class="has-text-align-right"><mark style="background-color:rgba(0, 0, 0, 0);color:#0051ff" class="has-inline-color">5%</mark></td></tr><tr><td class="has-text-align-center"><mark style="background-color:rgba(0, 0, 0, 0);color:#ff0071" class="has-inline-color">F</mark></td><td class="has-text-align-right"><mark style="background-color:rgba(0, 0, 0, 0);color:#ff0071" class="has-inline-color">5%</mark></td></tr></tbody></table></figure>



<p>まずは、出現確率が低い2つのグループは、<mark style="background-color:rgba(0, 0, 0, 0);color:#0051ff" class="has-inline-color">B</mark>と<mark style="background-color:rgba(0, 0, 0, 0);color:#ff0071" class="has-inline-color">F</mark>なので、この2つをひとまとめにします。</p>



<figure class="wp-block-table aligncenter"><table><thead><tr><th class="has-text-align-center">グループ (文字)</th><th class="has-text-align-right">出現確率</th></tr></thead><tbody><tr><td class="has-text-align-center">C</td><td class="has-text-align-right">30%</td></tr><tr><td class="has-text-align-center">A</td><td class="has-text-align-right">25%</td></tr><tr><td class="has-text-align-center">D</td><td class="has-text-align-right">20%</td></tr><tr><td class="has-text-align-center">E</td><td class="has-text-align-right">15%</td></tr><tr><td class="has-text-align-center"><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-light-green-color">BF</mark></td><td class="has-text-align-right"><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-light-green-color">10%</mark></td></tr></tbody></table></figure>



<p>さらに、ひとまとめにした2つのグループを子とし、二分木をつくります。</p>



<figure class="wp-block-image aligncenter size-full is-resized"><img src="https://www.momoyama-usagi.com/wp-content/uploads/joho2-sub-5.jpg" alt="" class="wp-image-17945" width="497" height="366" srcset="https://www.momoyama-usagi.com/wp-content/uploads/joho2-sub-5.jpg 698w, https://www.momoyama-usagi.com/wp-content/uploads/joho2-sub-5-300x221.jpg 300w" /></figure>



<p><strong>Step2-2. 5グループ → 4グループ</strong></p>



<figure class="wp-block-table aligncenter"><table><thead><tr><th class="has-text-align-center">グループ (文字)</th><th class="has-text-align-right">出現確率</th></tr></thead><tbody><tr><td class="has-text-align-center">C</td><td class="has-text-align-right">30%</td></tr><tr><td class="has-text-align-center">A</td><td class="has-text-align-right">25%</td></tr><tr><td class="has-text-align-center">D</td><td class="has-text-align-right">20%</td></tr><tr><td class="has-text-align-center"><mark style="background-color:rgba(0, 0, 0, 0);color:#0051ff" class="has-inline-color">E</mark></td><td class="has-text-align-right"><mark style="background-color:rgba(0, 0, 0, 0);color:#0051ff" class="has-inline-color">15%</mark></td></tr><tr><td class="has-text-align-center"><mark style="background-color:rgba(0, 0, 0, 0);color:#ff0071" class="has-inline-color">BF</mark></td><td class="has-text-align-right"><mark style="background-color:rgba(0, 0, 0, 0);color:#ff0071" class="has-inline-color">10%</mark></td></tr></tbody></table></figure>



<p>出現確率が低い2つのグループは、<mark style="background-color:rgba(0, 0, 0, 0);color:#0051ff" class="has-inline-color">B</mark>と<mark style="background-color:rgba(0, 0, 0, 0);color:#ff0071" class="has-inline-color">F</mark>なので、この2つをひとまとめにします。</p>



<figure class="wp-block-table aligncenter"><table><thead><tr><th class="has-text-align-center">グループ (文字)</th><th class="has-text-align-right">出現確率</th></tr></thead><tbody><tr><td class="has-text-align-center">C</td><td class="has-text-align-right">30%</td></tr><tr><td class="has-text-align-center">A</td><td class="has-text-align-right">25%</td></tr><tr><td class="has-text-align-center"><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-light-green-color">EBF</mark></td><td class="has-text-align-right"><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-light-green-color">25%</mark></td></tr><tr><td class="has-text-align-center">D</td><td class="has-text-align-right">20%</td></tr></tbody></table></figure>



<p>さらに、ひとまとめにした2つのグループを子とし、二分木をつくります。</p>



<figure class="wp-block-image aligncenter size-full is-resized"><img src="https://www.momoyama-usagi.com/wp-content/uploads/joho2-sub-6.jpg" alt="" class="wp-image-17946" width="313" height="220" srcset="https://www.momoyama-usagi.com/wp-content/uploads/joho2-sub-6.jpg 951w, https://www.momoyama-usagi.com/wp-content/uploads/joho2-sub-6-300x212.jpg 300w, https://www.momoyama-usagi.com/wp-content/uploads/joho2-sub-6-768x542.jpg 768w" /></figure>



<p><strong>Step2-3. 4グループ → 3グループ</strong></p>



<figure class="wp-block-table aligncenter"><table><thead><tr><th class="has-text-align-center">グループ (文字)</th><th class="has-text-align-right">出現確率</th></tr></thead><tbody><tr><td class="has-text-align-center">C</td><td class="has-text-align-right">30%</td></tr><tr><td class="has-text-align-center">A</td><td class="has-text-align-right">25%</td></tr><tr><td class="has-text-align-center"><mark style="background-color:rgba(0, 0, 0, 0);color:#0051ff" class="has-inline-color">EBF</mark></td><td class="has-text-align-right"><mark style="background-color:rgba(0, 0, 0, 0);color:#0051ff" class="has-inline-color">25%</mark></td></tr><tr><td class="has-text-align-center"><mark style="background-color:rgba(0, 0, 0, 0);color:#ff0071" class="has-inline-color">D</mark></td><td class="has-text-align-right"><mark style="background-color:rgba(0, 0, 0, 0);color:#ff0071" class="has-inline-color">20%</mark></td></tr></tbody></table></figure>



<p>まずは、出現確率が低い2つのグループは、<mark style="background-color:rgba(0, 0, 0, 0);color:#0051ff" class="has-inline-color">EBF</mark>と<mark style="background-color:rgba(0, 0, 0, 0);color:#ff0071" class="has-inline-color">D</mark>なので、この2つをひとまとめにします。</p>



<figure class="wp-block-table aligncenter"><table><thead><tr><th class="has-text-align-center">グループ (文字)</th><th class="has-text-align-right">出現確率</th></tr></thead><tbody><tr><td class="has-text-align-center"><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-light-green-color">EBFD</mark></td><td class="has-text-align-right"><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-light-green-color">45%</mark></td></tr><tr><td class="has-text-align-center">C</td><td class="has-text-align-right">30%</td></tr><tr><td class="has-text-align-center">A</td><td class="has-text-align-right">25%</td></tr></tbody></table></figure>



<p>さらに、ひとまとめにした2つのグループを子とし、二分木をつくります。</p>



<figure class="wp-block-image aligncenter size-full is-resized"><img src="https://www.momoyama-usagi.com/wp-content/uploads/joho2-sub-7.jpg" alt="" class="wp-image-17947" width="576" height="551" srcset="https://www.momoyama-usagi.com/wp-content/uploads/joho2-sub-7.jpg 951w, https://www.momoyama-usagi.com/wp-content/uploads/joho2-sub-7-300x287.jpg 300w, https://www.momoyama-usagi.com/wp-content/uploads/joho2-sub-7-768x735.jpg 768w" /></figure>



<p><strong>Step2-4. 3グループ → 2グループ</strong></p>



<figure class="wp-block-table aligncenter"><table><thead><tr><th class="has-text-align-center">グループ (文字)</th><th class="has-text-align-right">出現確率</th></tr></thead><tbody><tr><td class="has-text-align-center">EBFD</td><td class="has-text-align-right">45%</td></tr><tr><td class="has-text-align-center"><mark style="background-color:rgba(0, 0, 0, 0);color:#0051ff" class="has-inline-color">C</mark></td><td class="has-text-align-right"><mark style="background-color:rgba(0, 0, 0, 0);color:#0051ff" class="has-inline-color">30%</mark></td></tr><tr><td class="has-text-align-center"><mark style="background-color:rgba(0, 0, 0, 0);color:#ff0071" class="has-inline-color">A</mark></td><td class="has-text-align-right"><mark style="background-color:rgba(0, 0, 0, 0);color:#ff0071" class="has-inline-color">25%</mark></td></tr></tbody></table></figure>



<p>出現確率が低い2つのグループは、<mark style="background-color:rgba(0, 0, 0, 0);color:#0051ff" class="has-inline-color">C</mark>と<mark style="background-color:rgba(0, 0, 0, 0);color:#ff0071" class="has-inline-color">A</mark>なので、この2つをひとまとめにします。</p>



<figure class="wp-block-table aligncenter"><table><thead><tr><th class="has-text-align-center">グループ (文字)</th><th class="has-text-align-right">出現確率</th></tr></thead><tbody><tr><td class="has-text-align-center"><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-light-green-color">CA</mark></td><td class="has-text-align-right"><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-light-green-color">55%</mark></td></tr><tr><td class="has-text-align-center">EBFD</td><td class="has-text-align-right">45%</td></tr></tbody></table></figure>



<p>さらに、ひとまとめにした2つのグループを子とし、二分木をつくります。</p>



<figure class="wp-block-image aligncenter size-large"><img width="1024" height="587" src="https://www.momoyama-usagi.com/wp-content/uploads/joho2-sub-8-1024x587.jpg" alt="" class="wp-image-17948" srcset="https://www.momoyama-usagi.com/wp-content/uploads/joho2-sub-8-1024x587.jpg 1024w, https://www.momoyama-usagi.com/wp-content/uploads/joho2-sub-8-300x172.jpg 300w, https://www.momoyama-usagi.com/wp-content/uploads/joho2-sub-8-768x440.jpg 768w, https://www.momoyama-usagi.com/wp-content/uploads/joho2-sub-8-1536x880.jpg 1536w, https://www.momoyama-usagi.com/wp-content/uploads/joho2-sub-8.jpg 1594w" /></figure>



<p><strong>Step2-5. 2グループ → 1グループ</strong></p>



<p>残りの2つのグループ（<mark style="background-color:rgba(0, 0, 0, 0);color:#0051ff" class="has-inline-color">CA</mark>と<mark style="background-color:rgba(0, 0, 0, 0);color:#ff0071" class="has-inline-color">EBFD</mark>）をひとまとめにします。</p>



<figure class="wp-block-table aligncenter"><table><thead><tr><th class="has-text-align-center">グループ (文字)</th><th class="has-text-align-right">出現確率</th></tr></thead><tbody><tr><td class="has-text-align-center"><mark style="background-color:rgba(0, 0, 0, 0);color:#0051ff" class="has-inline-color">CA</mark></td><td class="has-text-align-right"><mark style="background-color:rgba(0, 0, 0, 0);color:#0051ff" class="has-inline-color">55%</mark></td></tr><tr><td class="has-text-align-center"><mark style="background-color:rgba(0, 0, 0, 0);color:#ff0071" class="has-inline-color">EBFD</mark></td><td class="has-text-align-right"><mark style="background-color:rgba(0, 0, 0, 0);color:#ff0071" class="has-inline-color">45%</mark></td></tr></tbody></table></figure>



<p>このグループを子とし、二分木をつくれば、二分木の完成です。</p>



<figure class="wp-block-image aligncenter size-large"><img width="1024" height="802" src="https://www.momoyama-usagi.com/wp-content/uploads/joho2-sub-9-1024x802.jpg" alt="" class="wp-image-17949" srcset="https://www.momoyama-usagi.com/wp-content/uploads/joho2-sub-9-1024x802.jpg 1024w, https://www.momoyama-usagi.com/wp-content/uploads/joho2-sub-9-300x235.jpg 300w, https://www.momoyama-usagi.com/wp-content/uploads/joho2-sub-9-768x602.jpg 768w, https://www.momoyama-usagi.com/wp-content/uploads/joho2-sub-9-1536x1204.jpg 1536w, https://www.momoyama-usagi.com/wp-content/uploads/joho2-sub-9.jpg 1594w" /></figure>



<h3 class="wp-block-heading">Step3. 作成した二分木から各文字(情報)ごとの符号を求める</h3>



<p>二分木が完成したら、つぎの方法で符号を求めていきます。</p>



<ul class="wp-block-list">
<li>二分木の各節(ノード)の左側を0、右側を1とする</li>



<li>各文字（A～F）ごとに、以下の操作を実施
<ul class="wp-block-list">
<li>木構造の一番上の部分から対応するノードまでたどっていく</li>



<li>たどった際に通った0, 1を左から順番に並べたものを符号にする</li>
</ul>
</li>
</ul>



<figure class="wp-block-image aligncenter size-full"><img width="1848" height="1351" src="https://www.momoyama-usagi.com/wp-content/uploads/Upy4NrioOEllQT9yE2va1667639749-1667640059.gif" alt="" class="wp-image-17968"/></figure>



<p>よって、各文字A～Fごとの符号は下のように求まります。</p>



<figure class="wp-block-table aligncenter"><table><thead><tr><th class="has-text-align-center">文字(記号)</th><th class="has-text-align-center">符号 (ビット表記)</th><th class="has-text-align-right">出現確率</th></tr></thead><tbody><tr><td class="has-text-align-center">A</td><td class="has-text-align-center">01</td><td class="has-text-align-right">25%</td></tr><tr><td class="has-text-align-center">B</td><td class="has-text-align-center">1010</td><td class="has-text-align-right">5%</td></tr><tr><td class="has-text-align-center">C</td><td class="has-text-align-center">00</td><td class="has-text-align-right">30%</td></tr><tr><td class="has-text-align-center">D</td><td class="has-text-align-center">11</td><td class="has-text-align-right">20%</td></tr><tr><td class="has-text-align-center">E</td><td class="has-text-align-center">100</td><td class="has-text-align-right">15%</td></tr><tr><td class="has-text-align-center">F</td><td class="has-text-align-center">1011</td><td class="has-text-align-right">5%</td></tr></tbody></table></figure>



<div style="height:50px" class="wp-block-spacer"></div>



<p><strong>(2) 平均符号長の計算</strong></p>



<p>まず、各文字ごとの「符号長」および「符号長 × 出現確率」を求めましょう。</p>



<figure class="wp-block-table aligncenter"><table><thead><tr><th class="has-text-align-center">文字(記号)</th><th class="has-text-align-center">符号 (ビット表記)</th><th class="has-text-align-center">符号長</th><th class="has-text-align-right">出現確率</th><th class="has-text-align-center">符号長 × 出現確率</th></tr></thead><tbody><tr><td class="has-text-align-center">A</td><td class="has-text-align-center">01</td><td class="has-text-align-center">2</td><td class="has-text-align-right">25%</td><td class="has-text-align-center">0.50</td></tr><tr><td class="has-text-align-center">B</td><td class="has-text-align-center">1010</td><td class="has-text-align-center">4</td><td class="has-text-align-right">5%</td><td class="has-text-align-center">0.20</td></tr><tr><td class="has-text-align-center">C</td><td class="has-text-align-center">00</td><td class="has-text-align-center">2</td><td class="has-text-align-right">30%</td><td class="has-text-align-center">0.60</td></tr><tr><td class="has-text-align-center">D</td><td class="has-text-align-center">11</td><td class="has-text-align-center">2</td><td class="has-text-align-right">20%</td><td class="has-text-align-center">0.40</td></tr><tr><td class="has-text-align-center">E</td><td class="has-text-align-center">100</td><td class="has-text-align-center">3</td><td class="has-text-align-right">15%</td><td class="has-text-align-center">0.45</td></tr><tr><td class="has-text-align-center">F</td><td class="has-text-align-center">1011</td><td class="has-text-align-center">4</td><td class="has-text-align-right">5%</td><td class="has-text-align-center">0.20</td></tr></tbody></table></figure>



<p>あとは、A～Fごとに求めた「符号長 × 出現確率」をすべて足すことで平均符号長 \( L \) を求めることができます。\[\begin{align*}<br>L &amp; = 0.50 + 0.20 + 0.60 + 0.40 + 0.45 + 0.20<br>\\ &amp; = 2.35<br>\end{align*}\]</p>



<div style="height:71px" class="wp-block-spacer"></div>



<h2 class="wp-block-heading">5. [問題] 基本情報・応用情報での問われ方</h2>



<p>最後に、実際に基本情報・応用情報でハフマン符号化はどのように問われるかを見ていきましょう。</p>



<h3 class="wp-block-heading">(1) 基本情報の午前問題の例</h3>


<div class='wp-block-dbp-frame l-frame-float is-design-onframe is-frame-style-default dbp-frame has-bgcolor'><div class="dbp-frame-title">基本情報での問われ方</div><div class="dbp-frame-content has-content-gap">
<p>出現頻度の異なるA、B、C、D、Eの5文字で構成される通信データを、ハフマン符号化を使って圧縮するために、符号表を作成した。aに入る符号として、適切なものはどれか。</p>

<figure class="wp-block-table aligncenter"><table><thead><tr><th class="has-text-align-center">文字</th><th class="has-text-align-center">出現頻度 (%)</th><th class="has-text-align-center">符号</th></tr></thead><tbody><tr><td class="has-text-align-center">A</td><td class="has-text-align-center">26</td><td class="has-text-align-center">00</td></tr><tr><td class="has-text-align-center">B</td><td class="has-text-align-center">25</td><td class="has-text-align-center">01</td></tr><tr><td class="has-text-align-center">C</td><td class="has-text-align-center">24</td><td class="has-text-align-center">10</td></tr><tr><td class="has-text-align-center">D</td><td class="has-text-align-center">13</td><td class="has-text-align-center">[　a　]</td></tr><tr><td class="has-text-align-center">E</td><td class="has-text-align-center">12</td><td class="has-text-align-center">111</td></tr></tbody></table></figure>

<p>ア: 001<br>イ: 010<br>ウ: 101<br>エ: 110</p>

<p class="has-text-align-right">[基本情報技術者　平成30年秋期　午前問4]</p>
</div></div>


<div style="height:50px" class="wp-block-spacer"></div>



<h3 class="wp-block-heading">(2) 応用情報の午前問題の例</h3>


<div class='wp-block-dbp-frame l-frame-float is-design-onframe is-frame-style-default dbp-frame has-bgcolor'><div class="dbp-frame-title">応用情報での問われ方</div><div class="dbp-frame-content has-content-gap">
<p>符号化方式に関する記述のうち、ハフマン方式はどれか。</p>

<p>ア: 0と1の数字で構成する符号の中で，0又は1の連なりを一つのブロックとし，このブロックに長さを表す符号を割り当てる。<br>イ: 10進数字の0～9を4ビット2進数の最初の10個に割り当てる。<br>ウ: 発生確率が分かっている記号群を符号化したとき，1記号当たりの平均符号長が最小になるように割り当てる。<br>エ: 連続した波を標本化と量子化によって0と1の数字で構成する符号に割り当てる。</p>

<p class="has-text-align-right">[応用情報技術者　平成30年秋期　午前問5]</p>
</div></div>


<div style="height:71px" class="wp-block-spacer"></div>



<h2 class="wp-block-heading">6. [解答] 基本情報・応用情報での問われ方</h2>



<h3 class="wp-block-heading">(1) 基本情報の午前問題の例</h3>



<p>解答: エ</p>



<p>基本情報では問題には必ず選択肢が与えられています。<br>（応用情報でも午前問題と一部の午後問題には与えられています。）</p>



<p>そのため、ハフマン符号化を行った符号の特徴である</p>



<ul class="wp-block-list">
<li>必ず瞬時復号可能となる</li>



<li>瞬時復号可能な符号の中でも平均符号長が最短となる</li>
</ul>



<p>を満たしていない選択肢を消去していくことで、ハフマン符号化をしなくても正解に導けることがあります。</p>



<p>今回の場合、</p>



<p>ア → Aの符号00の接頭語となるためNG<br>イ → Bの符号01の接頭語となるためNG<br>ウ → Cの符号10の接頭語となるためNG</p>



<p>となるため、ハフマン符号化をしなくても残った エ が正解とわかります。</p>



<div style="height:41px" class="wp-block-spacer"></div>



<p>また、「瞬時復号可能」かを調べるのであれば下のように図を書くのも有効です。</p>



<figure class="wp-block-image aligncenter size-large"><img width="1024" height="638" src="https://www.momoyama-usagi.com/wp-content/uploads/joho3-2-2-1024x638.jpg" alt="" class="wp-image-18085" srcset="https://www.momoyama-usagi.com/wp-content/uploads/joho3-2-2-1024x638.jpg 1024w, https://www.momoyama-usagi.com/wp-content/uploads/joho3-2-2-300x187.jpg 300w, https://www.momoyama-usagi.com/wp-content/uploads/joho3-2-2-768x479.jpg 768w, https://www.momoyama-usagi.com/wp-content/uploads/joho3-2-2-1536x957.jpg 1536w, https://www.momoyama-usagi.com/wp-content/uploads/joho3-2-2.jpg 2003w" /></figure>



<p>図を見ると、ア～ウのノードを追加すると、どこかしらのノードが葉ではなくなりますね。なので、ア～ウの選択肢は誤りであることがわかります。</p>



<figure class="wp-block-image aligncenter size-large"><img width="1024" height="638" src="https://www.momoyama-usagi.com/wp-content/uploads/joho3-2-3-1024x638.jpg" alt="" class="wp-image-18086" srcset="https://www.momoyama-usagi.com/wp-content/uploads/joho3-2-3-1024x638.jpg 1024w, https://www.momoyama-usagi.com/wp-content/uploads/joho3-2-3-300x187.jpg 300w, https://www.momoyama-usagi.com/wp-content/uploads/joho3-2-3-768x479.jpg 768w, https://www.momoyama-usagi.com/wp-content/uploads/joho3-2-3-1536x957.jpg 1536w, https://www.momoyama-usagi.com/wp-content/uploads/joho3-2-3.jpg 2003w" /></figure>



<h3 class="wp-block-heading">(2) 応用情報の午前問題の例</h3>



<p>解答: ウ</p>



<p>ハフマン符号に関する知識の問題です。ハフマン符号について知っているだけで、1問分の得点が得られるおいしい問題なので、必ず得点をしておきたいですね。</p>



<p>[他の選択肢]</p>



<p>ア: 不正解。ラングレス法に関する説明。<br>イ: 不正解。二進化十進数 (BCD、Binary-coded decimal) に関する説明。<br>ウ: 正解。ハフマン符号化に関する説明。<br>エ: 不正解。ディジタル化の説明。</p>
<div class="speaker-mute footnotes_reference_container"> <div class="footnote_container_prepare"><p><span tabindex="0" class="footnote_reference_container_label pointer">注釈</span><span tabindex="0" class="footnote_reference_container_collapse_button" style="display: none;">[<a id="footnote_reference_container_collapse_button_17916_3">+</a>]</span></p></div> <div id="footnote_references_container_17916_3"><table class="footnotes_table footnote-reference-container"><caption class="accessibility">注釈</caption> <tbody> 

<tr class="footnotes_plugin_reference_row"> <th scope="row" class="footnote_plugin_index_combi pointer"  onclick="footnote_moveToAnchor_17916_3('footnote_plugin_tooltip_17916_3_1');"><a id="footnote_plugin_reference_17916_3_1" class="footnote_backlink"><span class="footnote_index_arrow">&#8593;</span>1</a></th> <td class="footnote_plugin_text">今回の場合は、Eの出現確率が6%、Cの出現確率が6%なので、ひとまとめにしたグループの出現確率は、6% + 6% = 12% となります。</td></tr>

<tr class="footnotes_plugin_reference_row"> <th scope="row" class="footnote_plugin_index_combi pointer"  onclick="footnote_moveToAnchor_17916_3('footnote_plugin_tooltip_17916_3_2');"><a id="footnote_plugin_reference_17916_3_2" class="footnote_backlink"><span class="footnote_index_arrow">&#8593;</span>2</a></th> <td class="footnote_plugin_text">Eを左側、Cを右側にしていますが順不同です。ただ、本記事では「2番目に出現確率が低いもの」を左側、「1番出現確率が低いもの」を右側に固定しています。</td></tr>

 </tbody> </table> </div></div>]]></content:encoded>
					
					<wfw:commentRss>https://www.momoyama-usagi.com/entry/info-joho3/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>うさぎでもわかる情報理論　第2羽　符号化と一意復号可能・瞬時復号可能な符号</title>
		<link>https://www.momoyama-usagi.com/entry/info-joho2</link>
					<comments>https://www.momoyama-usagi.com/entry/info-joho2#respond</comments>
		
		<dc:creator><![CDATA[ももうさ]]></dc:creator>
		<pubDate>Wed, 19 Oct 2022 15:30:48 +0000</pubDate>
				<category><![CDATA[まとめシリーズ]]></category>
		<category><![CDATA[情報]]></category>
		<category><![CDATA[情報理論]]></category>
		<guid isPermaLink="false">https://www.momoyama-usagi.com/?p=17865</guid>

					<description><![CDATA[皆さんはパソコンやスマホなどのコンピュータ上で何事もなく、「日本語」や「アルファベット」などの文字を使ってやり取りしていますね。 しかし、コンピュータ上では0, 1の2進数のみで情報を記録されているのでしたね。言い換える [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>皆さんはパソコンやスマホなどのコンピュータ上で何事もなく、「日本語」や「アルファベット」などの文字を使ってやり取りしていますね。</p>



<p>しかし、コンピュータ上では0, 1の2進数のみで情報を記録されているのでしたね。言い換えると、「日本語」や「アルファベット」などの情報はそのままコンピュータ上で保存されているわけではなく、2進数に変換されて保存されています。</p>



<p>そこで今回は、コンピュータ上で情報を読み出したり書きだしたりする際に使われる符号化についてみていきましょう。</p>



<div style="height:80px" class="wp-block-spacer"></div>



<h2 class="wp-block-heading">1. 符号化とは</h2>


<p><span>文字などの情報を2進数（0と1だけで表す）に置き換え、コンピュータ上で扱えるデータに変換することを符号化と言います。</span></p>


<p>例えば、「あ」・「い」・「う」・「え」の文字列を、下の2進数で置き換える（＝符号化する）ことにします。</p>



<figure class="wp-block-image aligncenter size-full is-resized"><img src="https://www.momoyama-usagi.com/wp-content/uploads/joho1-6.gif" alt="" class="wp-image-17872" width="363" height="463"/><figcaption class="wp-element-caption">2進数置き換えルールと呼ぶことにしますか</figcaption></figure>



<p>ここで、置き換えた2進数（今回の場合は "00", "01", "10", "11"）のことを符号語と呼びます。</p>



<p>すると、文字列「あいうえ」は「00011011」と変換されます。</p>



<figure class="wp-block-image aligncenter size-large is-resized"><img src="https://www.momoyama-usagi.com/wp-content/uploads/joho1-1-1024x307.gif" alt="" class="wp-image-17866" width="800" height="239" srcset="https://www.momoyama-usagi.com/wp-content/uploads/joho1-1-1024x307.gif 1024w, https://www.momoyama-usagi.com/wp-content/uploads/joho1-1-300x90.gif 300w, https://www.momoyama-usagi.com/wp-content/uploads/joho1-1-768x230.gif 768w" /><figcaption class="wp-element-caption">符号化の例</figcaption></figure>



<div style="height:40px" class="wp-block-spacer"></div>


<p><span>また、符号化された文字列を元の情報 (文字など) に戻すことを復号化と呼びます。</span></p>


<figure class="wp-block-image aligncenter size-large"><img width="1024" height="307" src="https://www.momoyama-usagi.com/wp-content/uploads/joho1-2-1024x307.gif" alt="" class="wp-image-17867" srcset="https://www.momoyama-usagi.com/wp-content/uploads/joho1-2-1024x307.gif 1024w, https://www.momoyama-usagi.com/wp-content/uploads/joho1-2-300x90.gif 300w, https://www.momoyama-usagi.com/wp-content/uploads/joho1-2-768x230.gif 768w" /><figcaption class="wp-element-caption">復号化の例</figcaption></figure>



<div style="height:51px" class="wp-block-spacer"></div>










<div class='wp-block-dbp-frame l-frame-float is-design-onframe is-frame-style-default dbp-frame has-bgcolor'><div class="dbp-frame-title">例題</div><div class="dbp-frame-content has-content-gap">
<p>アルファベットのA～Dを次のように符号化する。</p>

<ul class="wp-block-list">
<li>A → 0</li>



<li>B → 10</li>



<li>C → 110</li>



<li>D → 111</li>
</ul>

<p>このとき、(1), (2)の問いに答えなさい。</p>

<p>(1) 文字列「BDCA」を符号化しなさい。<br>(2) 「11001111010」を復号化しなさい。</p>
</div></div>


<p>[解説]</p>



<p>符号化ルール</p>



<ul class="wp-block-list">
<li><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-red-color">A → 0</mark></li>



<li><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-light-blue-color">B → 10</mark></li>



<li><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-light-green-color">C → 110</mark></li>



<li><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-light-orange-color">D → 111</mark></li>
</ul>



<p>に従って、符号化・復号化をしていきましょう。</p>



<p>(1)</p>



<p class="has-text-align-center has-large-font-size"><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-light-blue-color">B</mark><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-light-orange-color">D</mark><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-light-green-color">C</mark><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-red-color">A</mark> → <mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-light-blue-color">10</mark><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-light-orange-color">111</mark><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-light-green-color">110</mark><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-red-color">0</mark></p>



<p>より、101111100と符号化できる。</p>



<p>(2)</p>



<p class="has-text-align-center has-large-font-size"><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-light-green-color">110</mark><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-red-color">0</mark><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-light-orange-color">111</mark><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-light-blue-color">1010</mark> → <mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-light-green-color">C</mark><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-red-color">A</mark><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-light-orange-color">D</mark><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-light-blue-color">BB</mark></p>



<p>より、CADBBと復号化できる。</p>



<div style="height:80px" class="wp-block-spacer"></div>



<h2 class="wp-block-heading">2. 符号化のための条件</h2>



<p>やみくもに符号化のルールを決めると、復号する際に</p>



<ul class="wp-block-list">
<li>復号ができない</li>



<li>復号ができたとしても復号に時間がかかる</li>
</ul>



<p>といった問題が発生します。</p>



<p>そこで、符号化の際には、下のルールを守って符号化をする必要があります。</p>



<p><strong>[必須条件]</strong></p>



<ul class="wp-block-list">
<li>符号化した文字列を一意に復号できること <br>→ 一意復号可能な符号であること</li>
</ul>



<p><strong>[推奨条件] (満たしてなくてもいいけど満たして)</strong></p>



<ul class="wp-block-list">
<li>符号化した文字列を後戻りせず（かつ一意）に復号できること → 瞬時復号可能な符号</li>



<li>出来る限り短い符号 (0, 1) で符号化すること</li>
</ul>



<h3 class="wp-block-heading">(1) 一意復号可能な符号 [必須条件]</h3>



<h4 class="wp-block-heading">(i) 一意復号可能とは</h4>



<p>一意復号可能な符号とは、符号化した文字列を復号した際にその結果が1通りだけになる符号のことを表します。言い換えて、「元の情報を符号化し、それを復号すると100%元の情報に戻るような符号」と思っていただいてもOKです。</p>



<p>符号化は、一意復号可能な符号で行うことが必須です。「符号化された情報を復号したら、元の情報と違うものが出てきた」なんてことがあったら困りますよね。</p>



<div style="height:41px" class="wp-block-spacer"></div>



<h4 class="wp-block-heading">(ii) 一意復号可能な符号の条件</h4>


<p><span>ある符号が一意復号可能であるかを瞬時に見分ける方法は基本的にはありません。<br />（ただし、元の文字列への戻し方が2パターン以上存在する符号列を1つでも見つけることができれば、一意復号不可能であることは確認できます。）</span></p>


<div style="height:41px" class="wp-block-spacer"></div>



<h4 class="wp-block-heading">(ii) 一意復号不可能な符号の例</h4>



<p>下の例の符号を考えてみましょう。</p>



<ul class="wp-block-list">
<li><mark style="background-color:rgba(0, 0, 0, 0);color:#ff00a5" class="has-inline-color">あ → 0</mark></li>



<li><mark style="background-color:rgba(0, 0, 0, 0);color:#008eff" class="has-inline-color">い → 01</mark> </li>



<li><mark style="background-color:rgba(0, 0, 0, 0);color:#4cc13a" class="has-inline-color">う → 001</mark></li>
</ul>



<p>この場合、出てくる符号語は <mark style="background-color:rgba(0, 0, 0, 0);color:#ff00a5" class="has-inline-color">"0"</mark>, <mark style="background-color:rgba(0, 0, 0, 0);color:#008eff" class="has-inline-color">"01"</mark>, <mark style="background-color:rgba(0, 0, 0, 0);color:#4cc13a" class="has-inline-color">"001"</mark> の3つですね。ここで、<mark style="background-color:rgba(0, 0, 0, 0);color:#ff00a5" class="has-inline-color">"0"</mark>, <mark style="background-color:rgba(0, 0, 0, 0);color:#008eff" class="has-inline-color">"01"</mark> をそれぞれ復号化すると、</p>



<ul class="wp-block-list">
<li><mark style="background-color:rgba(0, 0, 0, 0);color:#ff00a5" class="has-inline-color">0 → あ</mark></li>



<li><mark style="background-color:rgba(0, 0, 0, 0);color:#008eff" class="has-inline-color">01 → い</mark></li>
</ul>



<p>の1通りだけ得られます。一方、<mark style="background-color:rgba(0, 0, 0, 0);color:#4cc13a" class="has-inline-color">"001"</mark> は復号化すると、下のように2つの復号結果が出てきてしまいます<span class="footnote_referrer"><a tabindex="0" onclick="footnote_moveToReference_17865_5('footnote_plugin_reference_17865_5_1');" onkeypress="footnote_moveToReference_17865_5('footnote_plugin_reference_17865_5_1');" ><sup id="footnote_plugin_tooltip_17865_5_1" class="footnote_plugin_tooltip_text">[1]</sup></a><span id="footnote_plugin_tooltip_text_17865_5_1" class="footnote_tooltip">"001" を復号すると「<mark style="background-color:rgba(0, 0, 0, 0);color:#ff00a5" class="has-inline-color">あ</mark><mark style="background-color:rgba(0, 0, 0, 0);color:#008eff" class="has-inline-color">い</mark>」or「<mark style="background-color:rgba(0, 0, 0, 0);color:#4cc13a" class="has-inline-color">う</mark>」のどちらがわからなくなるということですね。</span></span>。そのため、例1の符号は一意復号不可能です。</p>



<figure class="wp-block-image aligncenter size-large"><img width="1024" height="461" src="https://www.momoyama-usagi.com/wp-content/uploads/joho1-3-1024x461.gif" alt="" class="wp-image-17868" srcset="https://www.momoyama-usagi.com/wp-content/uploads/joho1-3-1024x461.gif 1024w, https://www.momoyama-usagi.com/wp-content/uploads/joho1-3-300x135.gif 300w, https://www.momoyama-usagi.com/wp-content/uploads/joho1-3-768x346.gif 768w" /></figure>



<div style="height:41px" class="wp-block-spacer"></div>



<h3 class="wp-block-heading">(2) 瞬時復号可能な符号 [推奨条件]</h3>



<p>瞬時復号可能な符号とは、符号化した文字列を復号していく際に、後戻りせずに復号ができる符号のことを表します。言い換えて、「先頭から順番に見ていくだけで、復号ができる符号」と考えてもOKです。</p>



<figure class="wp-block-image aligncenter size-full"><img width="1157" height="403" src="https://www.momoyama-usagi.com/wp-content/uploads/zhl1dYa4gERu0e9BcX3H1666181878-1666181916-1.gif" alt="" class="wp-image-17884"/><figcaption class="wp-element-caption">瞬時復号をしていく様子</figcaption></figure>



<div style="height:41px" class="wp-block-spacer"></div>



<h4 class="wp-block-heading">(ii) 瞬時復号可能な符号の条件</h4>



<p>一意復号のときと異なり、瞬時復号可能な符号は見分ける方法があります。</p>


<p>ある符号が瞬時復号可能であるかは、符号化した文字列を左から読んでいくだけで、後戻りせずに各符号語を判別できるような符号化ルールをつかって符号化をする必要がありますね。</p>


<figure class="wp-block-image aligncenter size-full"><img width="1157" height="403" src="https://www.momoyama-usagi.com/wp-content/uploads/zhl1dYa4gERu0e9BcX3H1666181878-1666181916-1.gif" alt="" class="wp-image-17884"/><figcaption class="wp-element-caption">後戻りせずに符号化ができる例</figcaption></figure>



<p>ここで、後戻りしないと各符号語を判別できない（＝瞬時復号不可能な）符号を見ていきましょう。</p>


<p><span>例えば下の符号化ルールの場合、「0」が出てきたときは、次の文字を先読みしないと「あ → 0」か「い → 01」のどちらかが確定できません。</span></p>


<figure class="wp-block-image aligncenter size-large"><img width="1024" height="335" src="https://www.momoyama-usagi.com/wp-content/uploads/joho1-8-1024x335.gif" alt="" class="wp-image-17885" srcset="https://www.momoyama-usagi.com/wp-content/uploads/joho1-8-1024x335.gif 1024w, https://www.momoyama-usagi.com/wp-content/uploads/joho1-8-300x98.gif 300w, https://www.momoyama-usagi.com/wp-content/uploads/joho1-8-768x251.gif 768w" /></figure>



<p>もう少し詳しく符号化ルールを見ていくと、<mark style="background-color:rgba(0, 0, 0, 0);color:#008eff" class="has-inline-color"> 01</mark>の頭部分には、<mark style="background-color:rgba(0, 0, 0, 0);color:#ff00a5" class="has-inline-color">「あ → 0」</mark>の<mark style="background-color:rgba(0, 0, 0, 0);color:#ff00a5" class="has-inline-color">0</mark>が含まれていますね。そのため、<mark style="background-color:rgba(0, 0, 0, 0);color:#008eff" class="has-inline-color">「い → 01」</mark>を復号する際に冒頭の1文字目0を読んだだけでは、<mark style="background-color:rgba(0, 0, 0, 0);color:#ff00a5" class="has-inline-color">「あ → 0」</mark>なのか、<mark style="background-color:rgba(0, 0, 0, 0);color:#008eff" class="has-inline-color">「い → 01」</mark>に出てくる0なのかがわかりません。</p>


<p>これを言い換えると、瞬時復号可能かどうかは<span  style="background-image:linear-gradient(to bottom,transparent 0%,#FFF387 0%);" class="dbp-e-marker-animation y">符号化ルールに出てくるどの符号語に対しても、頭部分に自身以外の符号語が出てこないかどうか</span>で判定ができますね。</p>


<div style="height:41px" class="wp-block-spacer"></div>



<h4 class="wp-block-heading">(iii) 例で確認</h4>



<p><strong>例1) 瞬時復号不可能な符号</strong></p>



<p>「い」の符号化ルールにおいて、<mark style="background-color:rgba(0, 0, 0, 0);color:#008eff" class="has-inline-color">「い → <mark style="background-color:rgba(0, 0, 0, 0);color:#ff00a5" class="has-inline-color">0</mark>1」</mark>のように、頭部分に<mark style="background-color:rgba(0, 0, 0, 0);color:#ff00a5" class="has-inline-color">「あ → 0」</mark>の<mark style="background-color:rgba(0, 0, 0, 0);color:#ff00a5" class="has-inline-color">0</mark>が含まれているため、瞬時復号不可能。</p>



<figure class="wp-block-image aligncenter size-large"><img width="1024" height="533" src="https://www.momoyama-usagi.com/wp-content/uploads/joho1-9-1024x533.gif" alt="" class="wp-image-17886" srcset="https://www.momoyama-usagi.com/wp-content/uploads/joho1-9-1024x533.gif 1024w, https://www.momoyama-usagi.com/wp-content/uploads/joho1-9-300x156.gif 300w, https://www.momoyama-usagi.com/wp-content/uploads/joho1-9-768x400.gif 768w" /></figure>



<p><strong>例2) 瞬時復号可能な符号</strong></p>



<figure class="wp-block-image aligncenter size-large"><img width="1024" height="518" src="https://www.momoyama-usagi.com/wp-content/uploads/joho1-5-1024x518.gif" alt="" class="wp-image-17870" srcset="https://www.momoyama-usagi.com/wp-content/uploads/joho1-5-1024x518.gif 1024w, https://www.momoyama-usagi.com/wp-content/uploads/joho1-5-300x152.gif 300w, https://www.momoyama-usagi.com/wp-content/uploads/joho1-5-768x389.gif 768w" /></figure>



<p>「あ → 0」：他の符号化ルールに出てくる符号 10, 11 の頭部分に0は出てこないのでOK<br>「い → 10」：「あ → 0」の符号は1文字、「う → 11」の符号は2文字と、自身の符号の文字数(2文字) 以下なのでOK。</p>



<p>より瞬時復号可能。</p>



<p>※ 各符号を確認する際は、自身の符号の文字数以下のものは「頭文字に来ることがないことが明らか」なため、確認を省略できます<span class="footnote_referrer"><a tabindex="0" onclick="footnote_moveToReference_17865_5('footnote_plugin_reference_17865_5_2');" onkeypress="footnote_moveToReference_17865_5('footnote_plugin_reference_17865_5_2');" ><sup id="footnote_plugin_tooltip_17865_5_2" class="footnote_plugin_tooltip_text">[2]</sup></a><span id="footnote_plugin_tooltip_text_17865_5_2" class="footnote_tooltip">&nbsp;&#x2026; <span class="footnote_tooltip_continue"  onclick="footnote_moveToReference_17865_5('footnote_plugin_reference_17865_5_2');">Continue reading</span></span></span>。</p>


<div class='wp-block-dbp-frame l-frame-inner is-design-inline is-frame-style-default dbp-frame has-bgcolor'><div class="dbp-frame-title">一意復号可能な符号と瞬時復号可能な符号</div><div class="dbp-frame-content has-content-gap">
<p><strong>[一意復号可能な符号の判定<strong>法</strong>]</strong></p>

<p>基本的に瞬時に見分ける方法はない。地道に試して2通り以上の復号パターンが得られるか確認するしかない。</p>

<p>（1つでも2通り以上復号パターンが得られる場合は、一意復号不可能）</p>

<p><strong>[瞬時復号可能な符号の判定法]</strong></p>

<p>符号化ルール内にあるどの文字(情報)を符号化しても、頭部分に自分以外の符号語が出てこなければOK。</p>

<p>（符号語を確認する際には、各符号化ルールの中から符号語の文字数が少ない順に行うことをおすすめします。また、自身の符号の文字数以下のものは確認を省略できます。）</p>
<p><span>※ <span  style="background-image:linear-gradient(to bottom,transparent 0%,#FFF387 0%);" class="dbp-e-marker-animation blue">瞬時復号可能な符号は必ず一意復号可能な符号となる</span>ため、<span  style="background-image:linear-gradient(to bottom,transparent 0%,#FFF387 0%);" class="dbp-e-marker-animation blue"> 瞬時復号可能な符号を満たすことを確認できれば一意復号可能な符号かどうかは確認しなくても一意復号可能であることを確認できる</span>。</span></p></div></div>


<div style="height:80px" class="wp-block-spacer"></div>



<h2 class="wp-block-heading">3. 練習問題</h2>



<p>それでは、実際に「一意復号可能な符号」、「瞬時復号可能な符号」の判定法が理解できているかを練習問題で確認しましょう。</p>


<div class='wp-block-dbp-frame l-frame-float is-design-onframe is-frame-style-default dbp-frame has-bgcolor'><div class="dbp-frame-title">練習問題</div><div class="dbp-frame-content has-content-gap">
<p>次の(1)～(3)の符号のうち、瞬時可能な符号は(1), (2), (3)の中からすべて選びなさい。</p>

<figure class="wp-block-image aligncenter size-large"><img width="1024" height="388" src="https://www.momoyama-usagi.com/wp-content/uploads/joho1-10-1024x388.gif" alt="" class="wp-image-17893" srcset="https://www.momoyama-usagi.com/wp-content/uploads/joho1-10-1024x388.gif 1024w, https://www.momoyama-usagi.com/wp-content/uploads/joho1-10-300x114.gif 300w, https://www.momoyama-usagi.com/wp-content/uploads/joho1-10-768x291.gif 768w" /></figure>
</div></div>


<p><strong>[略解]</strong></p>



<p>(1) </p>



<p><strong>[解説]</strong></p>



<p>(1): 瞬時復号可能</p>



<p>まずは、瞬時復号可能な符号かどうかの判定。</p>



<p>「あ → 00」、「い → 01」、「う → 10」、「え → 00」いずれも2文字の符号語である。</p>



<p>よって、完全一致しない限り自身以外の符号語の接頭語となる符号は存在しない。</p>



<p>よって、瞬時復号可能である。</p>



<div style="height:30px" class="wp-block-spacer"></div>



<p>(2): 瞬時復号可能ではない</p>



<p>「あ → 0」については、他の符号語 10, 11, 101 の接頭語になっていないためOK。</p>



<p>しかし、<mark style="background-color:rgba(0, 0, 0, 0);color:#008eff" class="has-inline-color">「い → 10」</mark>については、「え → <mark style="background-color:rgba(0, 0, 0, 0);color:#008eff" class="has-inline-color">10</mark>1」の符号 <mark style="background-color:rgba(0, 0, 0, 0);color:#008eff" class="has-inline-color">10</mark>1 の接頭語になってしまっているため、瞬時復号可能な符号ではない。</p>



<div style="height:30px" class="wp-block-spacer"></div>



<p>(3): 瞬時復号可能ではない</p>



<p><mark style="background-color:rgba(0, 0, 0, 0);color:#ff00a5" class="has-inline-color">「あ → 0」</mark>については、「え → <mark style="background-color:rgba(0, 0, 0, 0);color:#ff00a5" class="has-inline-color">0</mark>10」の符号語 <mark style="background-color:rgba(0, 0, 0, 0);color:#ff00a5" class="has-inline-color">0</mark>10 の接頭語になっていないためNG。よって、瞬時復号可能な符号ではない。</p>



<div style="height:80px" class="wp-block-spacer"></div>



<h2 class="wp-block-heading">4. さいごに</h2>



<p>今回は、コンピュータ上で文字などの情報を扱う際に使われる符号化について学んでいきました。</p>



<p>最後に、一意復号可能な符号と瞬時復号可能な符号の関係を図にて、確認しておきましょう。</p>



<figure class="wp-block-image aligncenter size-large"><img width="1024" height="603" src="https://www.momoyama-usagi.com/wp-content/uploads/joho1-11-1024x603.gif" alt="" class="wp-image-17894" srcset="https://www.momoyama-usagi.com/wp-content/uploads/joho1-11-1024x603.gif 1024w, https://www.momoyama-usagi.com/wp-content/uploads/joho1-11-300x177.gif 300w, https://www.momoyama-usagi.com/wp-content/uploads/joho1-11-768x452.gif 768w" /></figure>



<p>次回からは、実際に符号化する際に使われるハフマン符号やシャノンファノ符号についてみていきたいと思います。</p>



<div style="height:41px" class="wp-block-spacer"></div>



<p><strong>[余談1] 符号化と文字コード</strong></p>



<p>コンピュータをよく使う人や、情報系の人なら文字コード（<a rel="noreferrer noopener" href="https://www.momoyama-usagi.com/entry/info-c-char#ASCII" data-type="URL" target="_blank">ASCIIコード</a>、Unicode、Shift-JISなど）というのを聞いたことがあると思います。この文字コードというのは、「どの符号化のルールが適用されているか」というのを表しています。</p>



<p>例えば、ASCIIコードであれば、各種文字とその符号（16進数に変換して記載している）は下のようになります。</p>



<figure class="wp-block-image aligncenter"><img src="https://www.momoyama-usagi.com/wp-content/uploads/2021/05/20190731112523.gif" alt="f:id:momoyama1192:20190731112523g:plain" title="f:id:momoyama1192:20190731112523g:plain"/></figure>







<div style="height:41px" class="wp-block-spacer"></div>



<p><strong>[余談2] 符号化と<strong>文字化け</strong></strong></p>



<p>実際にWebサイトやドキュメントなどを見ていて、「文字化け」に出会ったことはありませんか？</p>



<p>実は、文字化けというのは「Webサイトやドキュメントを作成する際のコード設定」と「閲覧時の文字コード設定」がそろっていないために発生する現象なのです。</p>



<figure class="wp-block-image aligncenter size-large"><img width="1024" height="205" src="https://www.momoyama-usagi.com/wp-content/uploads/joho1-12-1024x205.gif" alt="" class="wp-image-17907" srcset="https://www.momoyama-usagi.com/wp-content/uploads/joho1-12-1024x205.gif 1024w, https://www.momoyama-usagi.com/wp-content/uploads/joho1-12-300x60.gif 300w, https://www.momoyama-usagi.com/wp-content/uploads/joho1-12-768x154.gif 768w, https://www.momoyama-usagi.com/wp-content/uploads/joho1-12-1536x308.gif 1536w" /><figcaption class="wp-element-caption">文字化けの例</figcaption></figure>
<div class="speaker-mute footnotes_reference_container"> <div class="footnote_container_prepare"><p><span tabindex="0" class="footnote_reference_container_label pointer">注釈</span><span tabindex="0" class="footnote_reference_container_collapse_button" style="display: none;">[<a id="footnote_reference_container_collapse_button_17865_5">+</a>]</span></p></div> <div id="footnote_references_container_17865_5"><table class="footnotes_table footnote-reference-container"><caption class="accessibility">注釈</caption> <tbody> 

<tr class="footnotes_plugin_reference_row"> <th scope="row" class="footnote_plugin_index_combi pointer"  onclick="footnote_moveToAnchor_17865_5('footnote_plugin_tooltip_17865_5_1');"><a id="footnote_plugin_reference_17865_5_1" class="footnote_backlink"><span class="footnote_index_arrow">&#8593;</span>1</a></th> <td class="footnote_plugin_text">"001" を復号すると「<mark style="background-color:rgba(0, 0, 0, 0);color:#ff00a5" class="has-inline-color">あ</mark><mark style="background-color:rgba(0, 0, 0, 0);color:#008eff" class="has-inline-color">い</mark>」or「<mark style="background-color:rgba(0, 0, 0, 0);color:#4cc13a" class="has-inline-color">う</mark>」のどちらがわからなくなるということですね。</td></tr>

<tr class="footnotes_plugin_reference_row"> <th scope="row" class="footnote_plugin_index_combi pointer"  onclick="footnote_moveToAnchor_17865_5('footnote_plugin_tooltip_17865_5_2');"><a id="footnote_plugin_reference_17865_5_2" class="footnote_backlink"><span class="footnote_index_arrow">&#8593;</span>2</a></th> <td class="footnote_plugin_text">例えば「0の頭部分は10ですか？」と聞かれても絶対違うじゃん、となりますよね。また、同じ文字数の場合は完全一致していない場合は100%頭部分は異なるため、こちらもチェックしなくてOK。</td></tr>

 </tbody> </table> </div></div>]]></content:encoded>
					
					<wfw:commentRss>https://www.momoyama-usagi.com/entry/info-joho2/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>うさぎでもわかる画像処理　Part03　画像処理とフィルタ1（線形フィルタ編）</title>
		<link>https://www.momoyama-usagi.com/entry/info-img03</link>
					<comments>https://www.momoyama-usagi.com/entry/info-img03#respond</comments>
		
		<dc:creator><![CDATA[ももうさ]]></dc:creator>
		<pubDate>Sun, 16 Oct 2022 14:07:31 +0000</pubDate>
				<category><![CDATA[コンピュータビジョン]]></category>
		<category><![CDATA[情報]]></category>
		<category><![CDATA[画像処理]]></category>
		<category><![CDATA[フィルタ]]></category>
		<guid isPermaLink="false">https://www.momoyama-usagi.com/?p=17641</guid>

					<description><![CDATA[こんにちは、ももやまです。 前回の「うさぎでもわかる画像処理　Part02」では、画像処理の中でも最も基本的な画像内の各画素値を自身の画素値のみを使って、一定のルールを用いて変換していく方法（トーンカーブ）について説明し [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>こんにちは、ももやまです。</p>



<p>前回の「<a href="https://www.momoyama-usagi.com/entry/info-img02" data-type="URL" target="_blank" rel="noreferrer noopener">うさぎでもわかる画像処理　Part02</a>」では、画像処理の中でも最も基本的な<strong><span style="text-decoration: underline;">画像内の各画素値を自身の画素値のみを使って、一定のルールを用いて変換していく</span></strong>方法（トーンカーブ）について説明していきました。</p>



<figure class="wp-block-image aligncenter size-large"><img width="1024" height="402" src="https://www.momoyama-usagi.com/wp-content/uploads/gazo3-1-1024x402.jpg" alt="" class="wp-image-17626" srcset="https://www.momoyama-usagi.com/wp-content/uploads/gazo3-1-1024x402.jpg 1024w, https://www.momoyama-usagi.com/wp-content/uploads/gazo3-1-300x118.jpg 300w, https://www.momoyama-usagi.com/wp-content/uploads/gazo3-1-768x301.jpg 768w, https://www.momoyama-usagi.com/wp-content/uploads/gazo3-1-1536x603.jpg 1536w, https://www.momoyama-usagi.com/wp-content/uploads/gazo3-1.jpg 1842w" /><figcaption>画像内の各画素値を自身の画素値を用いて変換していく画像処理<br>（トーンカーブ）</figcaption></figure>



<p>トーンカーブを用いた画像処理でも、様々な画像処理ができるのですが、自身の画素値のみを書き換えていく画像処理では出来ることに限りがあります。</p>



<p>そこで今回と次回の2回にわたって、画像内の各画素値を変換していく際に<strong><span style="text-decoration: underline;">自身の画素値だけでなく、周りの画素の画素値を利用しながら画像処理をしていく</span></strong>方法（フィルタ、空間フィルタリングなどと呼ばれます）について学習していきましょう。</p>



<figure class="wp-block-image aligncenter size-large"><img width="1024" height="402" src="https://www.momoyama-usagi.com/wp-content/uploads/gazo3-2-1024x402.jpg" alt="" class="wp-image-17627" srcset="https://www.momoyama-usagi.com/wp-content/uploads/gazo3-2-1024x402.jpg 1024w, https://www.momoyama-usagi.com/wp-content/uploads/gazo3-2-300x118.jpg 300w, https://www.momoyama-usagi.com/wp-content/uploads/gazo3-2-768x301.jpg 768w, https://www.momoyama-usagi.com/wp-content/uploads/gazo3-2-1536x603.jpg 1536w, https://www.momoyama-usagi.com/wp-content/uploads/gazo3-2.jpg 1842w" /><figcaption>まわりの画像も利用した画像処理<br>（フィルタ・空間フィルタリング）</figcaption></figure>



<p>今回の記事では、フィルタの中でも線形フィルタに着目してみていきます。</p>



<div style="height:100px" class="wp-block-spacer"></div>



<h2 class="wp-block-heading">1. 線形フィルタのいろは</h2>



<h3 class="wp-block-heading">(1) 線形フィルタとは</h3>



<p>画像処理の世界で出てくるフィルタは、</p>



<ul class="wp-block-list"><li>線形フィルタ</li><li>非線形フィルタ</li></ul>



<p>の2つに分けることができます。</p>



<p>さらに、入力画像 \( A \) の \( i \) 行 \( j \) 列の画素値を \( A_{i,j} \)、出力画像 \( B \) の \( i \) 行 \( j \) 列の画素値を \( B_{i,j} \) としたときに\[<br>B_{m,n} = \sum^{N}_{n = -N} \sum^{M}_{m = -M} A_{i+m,j+n} H_{m,n}<br>\]の式（たたみこみ演算）で表されるようなフィルタのことを線形フィルタとよび、このときの \( H_{m,n} \) がフィルタを表す \( 2M+1 \) × \( 2N+1 \) 行列 \( H \) の \( m \) 行 \( n \) 列の係数を表します。</p>



<p>例えば、下のフィルタは3×3行列で表されていますね。</p>



<figure class="wp-block-image aligncenter size-full is-resized"><img src="https://www.momoyama-usagi.com/wp-content/uploads/img3-1.gif" alt="" class="wp-image-17654" width="384" height="459"/></figure>



<h3 class="wp-block-heading">(2) 線形フィルタの計算の様子を見てみよう</h3>



<p>では、(1)の例で出したフィルタ\[<br>\left( \begin{array}{ccc} \frac{1}{23} &amp; \frac{2}{23} &amp; \frac{5}{23} \\ \frac{3}{23} &amp; \frac{1}{23} &amp; \frac{2}{23} \\ \frac{2}{23} &amp; \frac{3}{23} &amp; \frac{4}{23}  \end{array} \right)<br>\]を使って、たたみこみ式\[<br>B_{m,n} = \sum^{N}_{n = -N} \sum^{M}_{m = -M} A_{i+m,j+n} H_{m,n}<br>\]でどんな計算をしているかを下のアニメーションで確認してみましょう。</p>



<figure class="wp-block-image aligncenter size-full"><img width="1797" height="958" src="https://www.momoyama-usagi.com/wp-content/uploads/X0MhFIqM257J5PZecniX1665582452-1665582488.gif" alt="" class="wp-image-17640"/></figure>


<p>このように線形フィルタでは、<span  style="background-image:linear-gradient(to bottom,transparent 0%,#FFF387 0%);" class="dbp-e-marker-animation y">着目した画素とその周囲の各画素値ごとに対応するフィルタの係数を掛け、それらをすべて足したものを着目した画素の新たな画素値とする計算</span>を各画素ごとに行っているのです！</p>


<figure class="wp-block-image aligncenter size-full"><img width="1783" height="975" src="https://www.momoyama-usagi.com/wp-content/uploads/PeU2i13yNMvwUSxpJeET1665671987-1665672022-1.gif" alt="" class="wp-image-17656"/><figcaption>たたみ込み計算を各画素に適用していく様子</figcaption></figure>



<p>※ 端の画素をどうするかについては、様々な考え方がありますが、本記事では端の画素は画像処理をしない（＝画素値0）としたいと思います。</p>



<h3 class="wp-block-heading">(3) 例題で確認！</h3>






<div class='wp-block-dbp-frame l-frame-float is-design-onframe is-frame-style-default dbp-frame has-bgcolor'><div class="dbp-frame-title">例題</div><div class="dbp-frame-content has-content-gap">
<p>図1で表される元画像、および図2で示されるフィルタ(a), (b)がある。</p>

<p>(1), (2)の問いに答えなさい。</p>

<figure class="wp-block-image aligncenter size-full is-resized"><img src="https://www.momoyama-usagi.com/wp-content/uploads/img3-3.gif" alt="" class="wp-image-17663" width="435" height="437"/><figcaption>図1. 元画像の画素値</figcaption></figure>

<figure class="wp-block-image aligncenter size-large"><img width="1024" height="617" src="https://www.momoyama-usagi.com/wp-content/uploads/img3-2-1024x617.gif" alt="" class="wp-image-17662" srcset="https://www.momoyama-usagi.com/wp-content/uploads/img3-2-1024x617.gif 1024w, https://www.momoyama-usagi.com/wp-content/uploads/img3-2-300x181.gif 300w, https://www.momoyama-usagi.com/wp-content/uploads/img3-2-768x463.gif 768w" /><figcaption>図2. フィルタ (a), (b)</figcaption></figure>

<p>(1) フィルタ (a) を適用したときの、図3のアに当てはまる画素値を答えなさい。ただし、小数点以下を四捨五入し、整数値で答えること。<br>(2) フィルタ (b) を適用したときの、図3のイに当てはまる画素値を答えなさい。ただし、小数点以下を四捨五入し、整数値で答えること。</p>

<figure class="wp-block-image aligncenter size-full is-resized"><img src="https://www.momoyama-usagi.com/wp-content/uploads/img3-4.gif" alt="" class="wp-image-17664" width="575" height="578"/><figcaption>図3. 適用後の画素値</figcaption></figure>
</div></div>


<p>[解説]</p>



<p>(1)</p>



<p>フィルタ (a) \[<br>\left( \begin{array}{ccc} \frac{1}{5} &amp; 0 &amp; \frac{2}{5} \\ 0 &amp; \frac{1}{5} &amp; 0 \\ 0 &amp; 0 &amp; \frac{1}{5}  \end{array} \right)<br>\]を適用した場合の [ア] の画素値を求めればOK。</p>



<figure class="wp-block-image aligncenter size-full"><img width="1805" height="1380" src="https://www.momoyama-usagi.com/wp-content/uploads/ssmuun71RT3wtB86BA9Y1665797683-1665797769-1.gif" alt="" class="wp-image-17675"/></figure>



<p>よって [ ア ] の画素値は181となる。</p>



<p>(2)</p>



<p>フィルタ (b) \[<br>\left( \begin{array}{ccc} \frac{1}{25} &amp; \frac{1}{25} &amp; \frac{1}{25} &amp; \frac{1}{25} &amp; \frac{1}{25}  \\ \frac{1}{25} &amp; \frac{1}{25} &amp; \frac{1}{25} &amp; \frac{1}{25} &amp; \frac{1}{25}  \\ \frac{1}{25} &amp; \frac{1}{25} &amp; \frac{1}{25} &amp; \frac{1}{25} &amp; \frac{1}{25} \\ \frac{1}{25} &amp; \frac{1}{25} &amp; \frac{1}{25} &amp; \frac{1}{25} &amp; \frac{1}{25}  \\ \frac{1}{25} &amp; \frac{1}{25} &amp; \frac{1}{25} &amp; \frac{1}{25} &amp; \frac{1}{25}   \end{array} \right)<br>\]を適用した場合の [イ] の画素値を求めればOK。</p>



<figure class="wp-block-image aligncenter size-large"><img width="1024" height="533" src="https://www.momoyama-usagi.com/wp-content/uploads/bandicam-2022-10-15-10-37-22-975-1024x533.jpg" alt="" class="wp-image-17676" srcset="https://www.momoyama-usagi.com/wp-content/uploads/bandicam-2022-10-15-10-37-22-975-1024x533.jpg 1024w, https://www.momoyama-usagi.com/wp-content/uploads/bandicam-2022-10-15-10-37-22-975-300x156.jpg 300w, https://www.momoyama-usagi.com/wp-content/uploads/bandicam-2022-10-15-10-37-22-975-768x400.jpg 768w, https://www.momoyama-usagi.com/wp-content/uploads/bandicam-2022-10-15-10-37-22-975-1536x799.jpg 1536w, https://www.momoyama-usagi.com/wp-content/uploads/bandicam-2022-10-15-10-37-22-975.jpg 1785w" /></figure>



<figure class="wp-block-image size-large"><img width="1024" height="472" src="https://www.momoyama-usagi.com/wp-content/uploads/bandicam-2022-10-15-10-37-58-973-1024x472.jpg" alt="" class="wp-image-17677" srcset="https://www.momoyama-usagi.com/wp-content/uploads/bandicam-2022-10-15-10-37-58-973-1024x472.jpg 1024w, https://www.momoyama-usagi.com/wp-content/uploads/bandicam-2022-10-15-10-37-58-973-300x138.jpg 300w, https://www.momoyama-usagi.com/wp-content/uploads/bandicam-2022-10-15-10-37-58-973-768x354.jpg 768w, https://www.momoyama-usagi.com/wp-content/uploads/bandicam-2022-10-15-10-37-58-973-1536x709.jpg 1536w, https://www.momoyama-usagi.com/wp-content/uploads/bandicam-2022-10-15-10-37-58-973.jpg 1810w" /></figure>



<p>よって [ イ ] の画素値は149となる。</p>



<h3 class="wp-block-heading">(4) 線形フィルタの演算をする関数（ソースコード）</h3>



<p>実際に入力画像と線形フィルタを設定すると、画像処理を行う関数をPythonとMATLABで作成しました。</p>



<h4 class="wp-block-heading">Python</h4>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: python; title: ; notranslate">
def applyFilter(img,filt):
    # 入力画像のサイズ取得
    img_row    = img.shape&#x5B;0]
    img_col    = img.shape&#x5B;1]

    # フィルタのサイズ取得 (適さないフィルタサイズの場合はエラーを返す)
    filt_row = filt.shape&#x5B;0]
    filt_col = filt.shape&#x5B;1]
    if (filt_row % 2 == 0) or (filt_col % 2 == 0):
        print(&quot;フィルタサイズ設定に誤りがあります。&quot;)
        return img

    # 結果画像初期化
    result_img = np.zeros( (img_row,img_col) )

    # フィルタの中心部分算出
    filt_mid = int(filt_row / 2)

    # フィルタ適用
    for row in range(img_row):
        for col in range(img_col):
            if (row - filt_mid &lt; 0) or (col - filt_mid &lt; 0) or ( (row + filt_mid &gt;= img_row) ) or ( (col+ filt_mid &gt;= img_col) ):
                continue # 端の画素は無視 (画素値0)
            tmp_result = img&#x5B;row - filt_mid:row + filt_mid + 1,col - filt_mid:col + filt_mid + 1] # 計算に使う周りの画素取得
            
            tmp_result = tmp_result * filt
            result_img&#x5B;row,col] = round(np.sum(tmp_result))

    return result_img
</pre></div>


<h4 class="wp-block-heading">MATLAB</h4>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: matlabkey; title: ; notranslate">
function &#x5B;result_img] = applyFilter(img,filt)
    img_row = size(img,1);
    img_col = size(img,2);

    filt_row = size(filt,1);
    filt_col = size(filt,2);
    if mod(filt_row,2) == 0 || mod(filt_col,2) == 0
        disp(&quot;フィルタサイズ設定に誤りがあります。&quot;);
        result_img = img;
        return
    end

    result_img = zeros(img_row,img_col,&#039;uint8&#039;);

    filt_mid = uint32(filt_row / 2) - 1; % MATLABは要素が1スタートなのでPythonに慣れている人は注意！

    for row = 1:img_row
        for col = 1:img_col
            if (row - filt_mid &lt; 1) || (col - filt_mid &lt; 1) || (row + filt_mid &gt; img_row) || (col + filt_mid &gt; img_col)
                continue % 端は無視 (画素値0とする)
            end

            tmp_result = img(row - filt_mid:row + filt_mid,col - filt_mid:col + filt_mid); % 計算に使う周りの画素取得
            tmp_result = double(tmp_result) .* filt;
            result_img(row,col) = uint8(sum(tmp_result,&#039;all&#039;));
        end
    end
end
</pre></div>


<div style="height:49px" class="wp-block-spacer"></div>



<p>フィルタについての確認ができたところで、ここからは画像処理の世界によく出てくる代表的なフィルタを見ていきましょう。</p>



<div style="height:100px" class="wp-block-spacer"></div>



<h2 class="wp-block-heading">2. 平滑化</h2>



<p>ここでは、元の画像の画素値変化（濃淡変化）を小さくするフィルタを紹介します。</p>



<p>平滑化フィルタを適用することで、画像の濃淡変化を小さくした画像（＝元画像をぼかした画像）を生成することができます。</p>



<h3 class="wp-block-heading">(1) 平均化フィルタ (移動平均フィルタ)</h3>



<p>各画素を「自分自身とその周りの画素値の平均値」を新たな画素値とするフィルタです。\[\left( \begin{array}{ccc} \frac{1}{9} &amp;  \frac{1}{9} &amp;  \frac{1}{9} \\ \frac{1}{9} &amp;  \frac{1}{9} &amp;  \frac{1}{9} \\\frac{1}{9} &amp;  \frac{1}{9} &amp;  \frac{1}{9} \end{array} \right), \ \ \ <br>\left( \begin{array}{ccc} \frac{1}{25} &amp; \frac{1}{25} &amp; \frac{1}{25} &amp; \frac{1}{25} &amp; \frac{1}{25}  \\ \frac{1}{25} &amp; \frac{1}{25} &amp; \frac{1}{25} &amp; \frac{1}{25} &amp; \frac{1}{25}  \\ \frac{1}{25} &amp; \frac{1}{25} &amp; \frac{1}{25} &amp; \frac{1}{25} &amp; \frac{1}{25} \\ \frac{1}{25} &amp; \frac{1}{25} &amp; \frac{1}{25} &amp; \frac{1}{25} &amp; \frac{1}{25}  \\ \frac{1}{25} &amp; \frac{1}{25} &amp; \frac{1}{25} &amp; \frac{1}{25} &amp; \frac{1}{25}   \end{array} \right)<br>\]</p>



<p>「自分自身とその周りの画素値の平均」をとるため、隣り合う画素同士の画素値の差が減り、濃淡変化が緩やかになるため、元画像をぼかした画像が生成されます。</p>



<div style="height:36px" class="wp-block-spacer"></div>



<p>例えば下の変換は、自分＋周り1画素の平均値をとった3×3の平均化フィルタを表します。</p>



<figure class="wp-block-image aligncenter size-large"><img width="1024" height="568" src="https://www.momoyama-usagi.com/wp-content/uploads/gazo3-24-1024x568.jpg" alt="" class="wp-image-17712" srcset="https://www.momoyama-usagi.com/wp-content/uploads/gazo3-24-1024x568.jpg 1024w, https://www.momoyama-usagi.com/wp-content/uploads/gazo3-24-300x167.jpg 300w, https://www.momoyama-usagi.com/wp-content/uploads/gazo3-24-768x426.jpg 768w, https://www.momoyama-usagi.com/wp-content/uploads/gazo3-24-1536x853.jpg 1536w, https://www.momoyama-usagi.com/wp-content/uploads/gazo3-24.jpg 1704w" /></figure>



<div style="height:36px" class="wp-block-spacer"></div>



<p>「自分＋周り2画素」をとった5×5のフィルタを使った平均化も見てみましょう。</p>



<figure class="wp-block-image aligncenter size-full"><img width="1704" height="1016" src="https://www.momoyama-usagi.com/wp-content/uploads/gazo3-25.jpg" alt="" class="wp-image-17713" srcset="https://www.momoyama-usagi.com/wp-content/uploads/gazo3-25.jpg 1704w, https://www.momoyama-usagi.com/wp-content/uploads/gazo3-25-300x179.jpg 300w, https://www.momoyama-usagi.com/wp-content/uploads/gazo3-25-1024x611.jpg 1024w, https://www.momoyama-usagi.com/wp-content/uploads/gazo3-25-768x458.jpg 768w, https://www.momoyama-usagi.com/wp-content/uploads/gazo3-25-1536x916.jpg 1536w" /></figure>



<div style="height:36px" class="wp-block-spacer"></div>



<p>2つの変換を比べてみると、より広い周囲の画素値の平均をとった5×5フィルタの方が、よりぼかされた画像が生成されているのが特徴です。</p>



<figure class="wp-block-image aligncenter size-full"><img width="2176" height="1433" src="https://www.momoyama-usagi.com/wp-content/uploads/gazo3-8.jpg" alt="" class="wp-image-17633" srcset="https://www.momoyama-usagi.com/wp-content/uploads/gazo3-8.jpg 2176w, https://www.momoyama-usagi.com/wp-content/uploads/gazo3-8-300x198.jpg 300w, https://www.momoyama-usagi.com/wp-content/uploads/gazo3-8-1024x674.jpg 1024w, https://www.momoyama-usagi.com/wp-content/uploads/gazo3-8-768x506.jpg 768w, https://www.momoyama-usagi.com/wp-content/uploads/gazo3-8-1536x1012.jpg 1536w, https://www.momoyama-usagi.com/wp-content/uploads/gazo3-8-2048x1349.jpg 2048w" /></figure>



<div style="height:50px" class="wp-block-spacer"></div>



<h3 class="wp-block-heading">(2) 加重平均化フィルタ [重み付き平均化]</h3>



<p>平均化をする際に単純に平均化するのではなく、下のように「自分自身の画素（フィルタの中心）に近いほど重み大、遠いほど重み小」なフィルタを使って平均化をすることがあります。</p>



<figure class="wp-block-image aligncenter size-full"><img width="1707" height="961" src="https://www.momoyama-usagi.com/wp-content/uploads/bandicam-2022-10-16-09-26-44-543.jpg" alt="" class="wp-image-17718" srcset="https://www.momoyama-usagi.com/wp-content/uploads/bandicam-2022-10-16-09-26-44-543.jpg 1707w, https://www.momoyama-usagi.com/wp-content/uploads/bandicam-2022-10-16-09-26-44-543-300x169.jpg 300w, https://www.momoyama-usagi.com/wp-content/uploads/bandicam-2022-10-16-09-26-44-543-1024x576.jpg 1024w, https://www.momoyama-usagi.com/wp-content/uploads/bandicam-2022-10-16-09-26-44-543-768x432.jpg 768w, https://www.momoyama-usagi.com/wp-content/uploads/bandicam-2022-10-16-09-26-44-543-1536x865.jpg 1536w" /></figure>



<p>このようなフィルタのことを加重平均化フィルタと呼び、加重平均化フィルタを使って平均化をすることを重み付き平均化と呼びます。</p>



<p>また、フィルタの重みをガウス分布（正規分布）\[<br>h_{x,y} = \frac{1}{2 \pi \alpha^2} e^{ - \frac{x^2 + y^2}{2 \alpha^2} }<br>\]に近づけたフィルタのことをガウシアンフィルタと呼びます。</p>



<div style="height:50px" class="wp-block-spacer"></div>



<h3 class="wp-block-heading">(3) 特定方向への平滑化</h3>



<p>特定方向へ画像をぼかすことができるフィルタもあります。</p>



<h4 class="wp-block-heading">(i) 横方向へ平滑化</h4>



<p>横方向のみに対して画素値の平均を取っていきます。</p>



<figure class="wp-block-image aligncenter size-full"><img width="1717" height="1021" src="https://www.momoyama-usagi.com/wp-content/uploads/gazo3-10.jpg" alt="" class="wp-image-17635" srcset="https://www.momoyama-usagi.com/wp-content/uploads/gazo3-10.jpg 1717w, https://www.momoyama-usagi.com/wp-content/uploads/gazo3-10-300x178.jpg 300w, https://www.momoyama-usagi.com/wp-content/uploads/gazo3-10-1024x609.jpg 1024w, https://www.momoyama-usagi.com/wp-content/uploads/gazo3-10-768x457.jpg 768w, https://www.momoyama-usagi.com/wp-content/uploads/gazo3-10-1536x913.jpg 1536w" /></figure>



<p>例えば上の例の場合、自分自身の画素と横±10画素の画素値の平均\[<br>B_{x,y} = \frac{1}{21} \left( A_{x-10,y} + A_{x-9,y} + \cdots + A_{x,y} + \cdots + A_{x+9,y} + A_{x+10,y}   \right)<br>\]を取っています。</p>



<p>※注意（以後同様）</p>



<ul class="wp-block-list"><li>\( A_{x,y} \) が元画像、\( B_{x,y} \) が変換後の \( x \) 行 \( y \) 列の画素値を表しています。</li><li>横方向を \( x \)、縦方向を \( y \) としています。</li></ul>



<h4 class="wp-block-heading">(ii) 縦方向へ平滑化</h4>



<p>縦方向のみに対して画素値の平均を取っていきます。</p>



<figure class="wp-block-image aligncenter size-full"><img width="1717" height="1021" src="https://www.momoyama-usagi.com/wp-content/uploads/gazo3-9.jpg" alt="" class="wp-image-17634" srcset="https://www.momoyama-usagi.com/wp-content/uploads/gazo3-9.jpg 1717w, https://www.momoyama-usagi.com/wp-content/uploads/gazo3-9-300x178.jpg 300w, https://www.momoyama-usagi.com/wp-content/uploads/gazo3-9-1024x609.jpg 1024w, https://www.momoyama-usagi.com/wp-content/uploads/gazo3-9-768x457.jpg 768w, https://www.momoyama-usagi.com/wp-content/uploads/gazo3-9-1536x913.jpg 1536w" /></figure>



<p>例えば上の例の場合、自分自身の画素と縦±10画素の画素値の平均\[<br>B_{x,y} = \frac{1}{21} \left( A_{x,y-10} + A_{x,y-9} + \cdots + A_{x,y} + \cdots + A_{x,y+9} + A_{x,y+10}   \right)<br>\]を取っています。</p>



<h4 class="wp-block-heading">(iii) 斜め方向へ平滑化</h4>



<p>左上方向から右下方向に対して画素値の平均を取っていきます。</p>



<figure class="wp-block-image aligncenter size-full"><img width="1717" height="1021" src="https://www.momoyama-usagi.com/wp-content/uploads/gazo3-11.jpg" alt="" class="wp-image-17636" srcset="https://www.momoyama-usagi.com/wp-content/uploads/gazo3-11.jpg 1717w, https://www.momoyama-usagi.com/wp-content/uploads/gazo3-11-300x178.jpg 300w, https://www.momoyama-usagi.com/wp-content/uploads/gazo3-11-1024x609.jpg 1024w, https://www.momoyama-usagi.com/wp-content/uploads/gazo3-11-768x457.jpg 768w, https://www.momoyama-usagi.com/wp-content/uploads/gazo3-11-1536x913.jpg 1536w" /></figure>



<p>例えば上の例の場合、基準に左上方向から右下方向に向かって±自分自身の画素10画素の画素値の平均\[<br>B_{x,y} = \frac{1}{21} \left( A_{x-10,y-10} + A_{x-9,y-9} + \cdots + A_{x,y} + \cdots + A_{x+9,y+9} + A_{x+10,y+10}   \right)<br>\]を取っています。</p>



<div style="height:100px" class="wp-block-spacer"></div>



<h2 class="wp-block-heading">3. 鮮鋭化</h2>



<p>「3. 平滑化」で出てきたフィルタ、 元の画像の画素値変化（濃淡変化）を小さくすることで、元画像をぼかした画像を生成するフィルタでしたね。</p>



<p>鮮鋭化は、「3. 平滑化」とは反対に元の画像の画素値変化（濃淡変化）を大きくする変換をするフィルタです。</p>



<p>鮮鋭化フィルタを適用することで、画像の濃淡変化を大きくした画像（＝元画像のエッジを強調した画像）を生成することができます。</p>



<div style="height:65px" class="wp-block-spacer"></div>



<p>具体的には、各画素ごとに、「<mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-red-color"><strong>自分自身の画素を定数倍（＝強調）</strong></mark>し、<mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-blue-color"><strong>周りの画素値を一定量引いたもの</strong></mark>」を新たな画素値にしていきます。\[\left( \begin{array}{ccc} \textcolor{blue}{-1} &amp; \textcolor{blue}{-1} &amp; \textcolor{blue}{-1} \\ \textcolor{blue}{-1} &amp; \textcolor{red}{9} &amp; \textcolor{blue}{-1} \\ \textcolor{blue}{-1} &amp; \textcolor{blue}{-1} &amp; \textcolor{blue}{-1} \end{array} \right), \ \ \ <br>\left( \begin{array}{ccc}  \textcolor{blue}{-1} &amp; \textcolor{blue}{-1} &amp; \textcolor{blue}{-1} &amp; \textcolor{blue}{-1} &amp; \textcolor{blue}{-1} \\ \textcolor{blue}{-1} &amp; \textcolor{blue}{-1} &amp; \textcolor{blue}{-1} &amp; \textcolor{blue}{-1} &amp; \textcolor{blue}{-1}  \\ \textcolor{blue}{-1} &amp; \textcolor{blue}{-1} &amp; \textcolor{red}{25} &amp; \textcolor{blue}{-1} &amp; \textcolor{blue}{-1}  \\ \textcolor{blue}{-1} &amp; \textcolor{blue}{-1} &amp; \textcolor{blue}{-1} &amp; \textcolor{blue}{-1} &amp; \textcolor{blue}{-1}  \\ \textcolor{blue}{-1} &amp; \textcolor{blue}{-1} &amp; \textcolor{blue}{-1} &amp; \textcolor{blue}{-1} &amp; \textcolor{blue}{-1}   \end{array} \right)<br>\]</p>



<p>「自分自身の画素値を定数倍＋周りの画素値を一定値引く」ため隣り合う画素同士の画素値の差が増え、濃淡変化が大きくなるため、元画像のエッジを強調した画像が生成されます。</p>



<figure class="wp-block-image aligncenter size-full is-resized"><img src="https://www.momoyama-usagi.com/wp-content/uploads/gazo3-33.jpg" alt="" class="wp-image-17841" width="800" height="355" srcset="https://www.momoyama-usagi.com/wp-content/uploads/gazo3-33.jpg 1999w, https://www.momoyama-usagi.com/wp-content/uploads/gazo3-33-300x133.jpg 300w, https://www.momoyama-usagi.com/wp-content/uploads/gazo3-33-1024x455.jpg 1024w, https://www.momoyama-usagi.com/wp-content/uploads/gazo3-33-768x342.jpg 768w, https://www.momoyama-usagi.com/wp-content/uploads/gazo3-33-1536x683.jpg 1536w" /><figcaption>鮮鋭化フィルタの適用</figcaption></figure>







<p>なお、「3. 平滑化」のときと同じように、範囲が広いフィルタの方が、よりフィルタが強く作用します。</p>



<figure class="wp-block-image aligncenter size-full"><img width="2117" height="1297" src="https://www.momoyama-usagi.com/wp-content/uploads/gazo3-32.jpg" alt="" class="wp-image-17840" srcset="https://www.momoyama-usagi.com/wp-content/uploads/gazo3-32.jpg 2117w, https://www.momoyama-usagi.com/wp-content/uploads/gazo3-32-300x184.jpg 300w, https://www.momoyama-usagi.com/wp-content/uploads/gazo3-32-1024x627.jpg 1024w, https://www.momoyama-usagi.com/wp-content/uploads/gazo3-32-768x471.jpg 768w, https://www.momoyama-usagi.com/wp-content/uploads/gazo3-32-1536x941.jpg 1536w, https://www.momoyama-usagi.com/wp-content/uploads/gazo3-32-2048x1255.jpg 2048w" /><figcaption>3×3より5×5のフィルタの方が鮮鋭化されている</figcaption></figure>



<div style="height:100px" class="wp-block-spacer"></div>



<h2 class="wp-block-heading">4. 1次微分によるエッジ抽出</h2>



<p>皆さんは高校時代に「微分」について学びましたね。</p>



<p>ここで、「画像処理の世界でも微分って出てくるの？」と思った人も多いと思います。実は、微分</p>



<h3 class="wp-block-heading">(1) 画素の微分とは</h3>



<p>ある関数 \( f(x) \) を微分したもの（導関数） \( f'(x) \) は\[<br>f'(x) = \lim_{h \to 0} \frac{f(x+h) - f(x)}{h}<br>\]で計算できるのでしたね。</p>



<p>日本語でいうと、「\( x \) をほんの少し増やしたときの、\( f(x) \) の変化の度合い」を表したのが導関数ですね。</p>


<p><span>なので、画像を微分すると「画素値の変化の度合い」が得られそうな感じがしますね。さらに、「画素値の変化の度合い」を得ることで、<span  style="background-image:linear-gradient(to bottom,transparent 0%,#FFF387 0%);" class="dbp-e-marker-animation y">特に画素値が変化している部分（＝エッジ）を得ることができます</span>。</span></p>


<div style="height:36px" class="wp-block-spacer"></div>



<p>しかし、微分をフィルタとして取り入れるためには、以下の2つの問題を解決する必要があります。</p>



<ul class="wp-block-list"><li>画像 \( A_{x,y} \) を関数として見る場合、1変数 \( f(x) \) ではなく、横方向 \( x \)、縦方向 \( y \) の2変数関数 \( f(x,y) \) で表現する必要があること</li><li>\( h \to 0 \) という極限操作が画像処理の世界ではできないこと</li></ul>



<p>というわけで、1つずつ順番に解決していきましょう。</p>



<h4 class="wp-block-heading">(i) 2変数関数の微分とは</h4>



<p>2変数関数 \( f(x,y) \) の微分ですが、下のように<mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-blue-color">「\( x \) での微分」</mark>と<mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-red-color">「\( y \) での微分」</mark>のように、微分する変数を1つ指定し、それ以外の変数を定数として考えることで、高校時代で習った1変数の微分と同じような感覚で微分ができます。\[<br>\textcolor{blue}{ f_x(x,y)  = \lim_{h \to 0} \frac{f(x+h,y) - f(x,y)}{h} } <br>\]\[<br>\textcolor{red}{ f_y(x,y)  = \lim_{h \to 0} \frac{f(x,y+h) - f(x,y)}{h} } <br>\]この方法のことを、偏微分と呼びます。</p>



<p>※ 偏微分についてもっと知りたい人は、偏微分についての記事のリンクを貼っているので是非こちらのリンクをご覧ください。</p>



<figure class="wp-block-embed is-type-wp-embed is-provider-工業大学生ももやまのうさぎ塾 wp-block-embed-工業大学生ももやまのうさぎ塾"><div class="wp-block-embed__wrapper">
        <article class="pb p-id-203 is-position-relative pb-embed">
            <a class="pb-contents" href="https://www.momoyama-usagi.com/entry/math-analysis14">
                <div class="pb__thumb is-blank-thumb"></div><div class="pb__body l-column is-flex-1"><div class="pb-title is-omit-line:2">うさぎでもわかる解析　Part14　偏微分（偏導関数・偏微分係数の計算方法）</div><div class="pb-substr is-font-size:s is-omit-line:2">今回は、解析学において特に大切な要素である偏微分についてのまとめを書きました。偏微分のやり方、偏導関数・高次偏導関数・偏</div></div>            </a>
        </article>
        
</div></figure>



<p><strong>[注意]</strong></p>



<p>単に \( f'(x,y) \) と表すと \( x \), \( y \) どちらの変数で微分したかわからなくなるので、</p>



<ul class="wp-block-list"><li>\( f(x,y) \) を \( x \) で微分した場合 → \( f_x (x,y) \)</li><li>\( f(x,y) \) を \( y \) で微分した場合 → \( f_y (x,y) \)</li></ul>



<p>と表記することにします<span class="footnote_referrer"><a tabindex="0" onclick="footnote_moveToReference_17641_7('footnote_plugin_reference_17641_7_1');" onkeypress="footnote_moveToReference_17641_7('footnote_plugin_reference_17641_7_1');" ><sup id="footnote_plugin_tooltip_17641_7_1" class="footnote_plugin_tooltip_text">[1]</sup></a><span id="footnote_plugin_tooltip_text_17641_7_1" class="footnote_tooltip">なお、偏微分を正式に表す場合は、\[<br>f_x (x,y) = \frac{ \partial }{ \partial x } f(x,y) , \ \ \ f_y (x,y) = \frac{ \partial }{ \partial y } f(x,y) <br>\]と表記します。</span></span>。</p>



<h4 class="wp-block-heading">(ii) 画像処理での微分の表現</h4>



<p>画像処理は、1画素単位での処理となるため、\( h \to 0 \) のように「0に近づける」のような操作ができません。</p>



<p>そこで、画像処理で微分を表現する場合は\[<br>f_x = \frac{f(x+h,y) - f(x,y)}{h} <br>\]\[<br>f_y = \frac{f(x,y+h) - f(x,y)}{h} <br>\]に対し、\( h = 1 \) を代入し、「隣り合う画素の差分を取る」ことで微分を表現します。</p>



<p>実際に \( h = 1 \) を代入すると、<mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-blue-color">\( x \) 方向（横方向）</mark>・<mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-red-color">\( y \) 方向（縦方向）</mark>の微分は下の式で表されます。</p>



<p><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-blue-color">[\( x \) 方向（横方向）の微分]\[<br>f_x(x,y)  = f(x+1,y) - f(x,y)<br>\]</mark></p>



<p><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-red-color">[\( y \) 方向（横方向）の微分]\[<br>f_y(x,y)  = f(x,y+1) - f(x,y)<br>\]</mark></p>



<h3 class="wp-block-heading">(2) 1次微分フィルタ</h3>



<p>(1)で導出した式\[<br>f_x(x,y) = f(x+1,y) - f(x,y)<br>\]\[<br>f_y(x,y)  = f(x,y+1) - f(x,y)<br>\]をフィルタの形に書き換えることで、1次微分フィルタを導出できます。</p>



<figure class="wp-block-table aligncenter"><table><thead><tr><th class="has-text-align-center">方向</th><th class="has-text-align-center">式</th><th class="has-text-align-center">フィルタ</th></tr></thead><tbody><tr><td class="has-text-align-center">横方向（\( x \) 方向）</td><td class="has-text-align-center">\( f_x(x,y) = \textcolor{deepskyblue}{f(x+1,y)} - \textcolor{magenta}{f(x,y)} \)</td><td class="has-text-align-center">\(<br>\left( \begin{array}{ccc} 0 &amp; 0 &amp; 0 \\ 0 &amp; \textcolor{magenta}{-1} &amp; \textcolor{deepskyblue}{1} \\ 0 &amp; 0 &amp; 0 \end{array} \right)<br>\)</td></tr><tr><td class="has-text-align-center">縦方向（\( y \) 方向）</td><td class="has-text-align-center">\( f_y (x,y) = \textcolor{deepskyblue}{f(x,y+1)} - \textcolor{magenta}{f(x,y)} \)</td><td class="has-text-align-center">\(<br>\left( \begin{array}{ccc} 0 &amp; 0 &amp; 0 \\  0 &amp; \textcolor{magenta}{-1} &amp; 0  \\ 0 &amp; \textcolor{deepskyblue}{1} &amp; 0 \end{array} \right)<br>\)</td></tr></tbody></table></figure>



<p><strong>[横方向 (\( x \) 方向) のフィルタ適用例]</strong></p>



<figure class="wp-block-image aligncenter size-large"><img width="1024" height="518" src="https://www.momoyama-usagi.com/wp-content/uploads/gazo3-28-1024x518.jpg" alt="" class="wp-image-17811" srcset="https://www.momoyama-usagi.com/wp-content/uploads/gazo3-28-1024x518.jpg 1024w, https://www.momoyama-usagi.com/wp-content/uploads/gazo3-28-300x152.jpg 300w, https://www.momoyama-usagi.com/wp-content/uploads/gazo3-28-768x388.jpg 768w, https://www.momoyama-usagi.com/wp-content/uploads/gazo3-28-1536x777.jpg 1536w, https://www.momoyama-usagi.com/wp-content/uploads/gazo3-28.jpg 1976w" /></figure>



<p>横方向の1次微分フィルタを適用すると、横方向の画素値変化が可視化されるため、出力画像には縦方向のエッジが強く出てきます。</p>



<p>一方、縦方向の画素値変化は可視化されないため、横方向のエッジは出力画像にあまり出てきません。</p>



<figure class="wp-block-image aligncenter size-large"><img width="1024" height="876" src="https://www.momoyama-usagi.com/wp-content/uploads/gazo3-30-1024x876.jpg" alt="" class="wp-image-17813" srcset="https://www.momoyama-usagi.com/wp-content/uploads/gazo3-30-1024x876.jpg 1024w, https://www.momoyama-usagi.com/wp-content/uploads/gazo3-30-300x257.jpg 300w, https://www.momoyama-usagi.com/wp-content/uploads/gazo3-30-768x657.jpg 768w, https://www.momoyama-usagi.com/wp-content/uploads/gazo3-30.jpg 1383w" /></figure>



<p><strong>[縦方向 (\( y \) 方向) のフィルタ適用例]</strong></p>



<figure class="wp-block-image aligncenter size-large"><img width="1024" height="518" src="https://www.momoyama-usagi.com/wp-content/uploads/gazo3-29-1024x518.jpg" alt="" class="wp-image-17812" srcset="https://www.momoyama-usagi.com/wp-content/uploads/gazo3-29-1024x518.jpg 1024w, https://www.momoyama-usagi.com/wp-content/uploads/gazo3-29-300x152.jpg 300w, https://www.momoyama-usagi.com/wp-content/uploads/gazo3-29-768x388.jpg 768w, https://www.momoyama-usagi.com/wp-content/uploads/gazo3-29-1536x777.jpg 1536w, https://www.momoyama-usagi.com/wp-content/uploads/gazo3-29.jpg 1976w" /></figure>



<p>縦方向の1次微分フィルタを適用することで、縦方向の画素値変化が可視化されるため、出力される画像には横方向のエッジが強く出てきます。</p>



<p>一方、横方向の画素値変化は可視化されないため、縦方向のエッジは出力画像にあまり出てきません。</p>



<figure class="wp-block-image aligncenter size-large"><img width="1024" height="876" src="https://www.momoyama-usagi.com/wp-content/uploads/gazo3-31-1024x876.jpg" alt="" class="wp-image-17814" srcset="https://www.momoyama-usagi.com/wp-content/uploads/gazo3-31-1024x876.jpg 1024w, https://www.momoyama-usagi.com/wp-content/uploads/gazo3-31-300x257.jpg 300w, https://www.momoyama-usagi.com/wp-content/uploads/gazo3-31-768x657.jpg 768w, https://www.momoyama-usagi.com/wp-content/uploads/gazo3-31.jpg 1383w" /></figure>



<h3 class="wp-block-heading">(3) 様々な1次微分フィルタ</h3>



<p>画像の微分は、各画素ごとに「隣り合う画素の差分を取る」ことで求めることができるのですが、差分を取り方として、\[<br>f_x(x,y) = f(x+1,y) - f(x,y)<br>\]\[<br>f_y(x,y) = f(x,y+1) - f(x,y)<br>\]というとり方以外にも以外にも¥[<br>f_x(x,y) = f(x,y) - f(x-1,y)<br>\]\[<br>f_y(x,y) = f(x,y) - f(x,y-1)<br>\]で差分を取ることもできますね。</p>



<p>そのため、1次微分フィルタを下のように書くこともできます。</p>



<figure class="wp-block-table aligncenter"><table><thead><tr><th class="has-text-align-center">方向</th><th class="has-text-align-center">式</th><th class="has-text-align-center">フィルタ</th></tr></thead><tbody><tr><td class="has-text-align-center">横方向（\( x \) 方向）</td><td class="has-text-align-center">\( f_x(x,y) = \textcolor{deepskyblue}{f(x,y)} - \textcolor{magenta}{f(x-1,y)} \)</td><td class="has-text-align-center">\(<br>\left( \begin{array}{ccc} 0 &amp; 0 &amp; 0 \\  \textcolor{magenta}{-1} &amp; \textcolor{deepskyblue}{1} &amp; 0 \\ 0 &amp; 0 &amp; 0 \end{array} \right)<br>\)</td></tr><tr><td class="has-text-align-center">縦方向（\( y \) 方向）</td><td class="has-text-align-center">\( f_y (x,y) = \textcolor{deepskyblue}{f(x,y)} - \textcolor{magenta}{f(x,y-1)} \)</td><td class="has-text-align-center">\(<br>\left( \begin{array}{ccc} 0 &amp; \textcolor{magenta}{-1} &amp; 0 \\ 0 &amp; \textcolor{deepskyblue}{1} &amp; 0 \\ 0 &amp; 0 &amp; 0 \end{array} \right)<br>\)</td></tr></tbody></table></figure>



<p>また、2つの差分のとり方\[<br>f_x(x,y) = f(x+1,y) - f(x,y) , \ \ \ f_x(x,y) = f(x,y) - f(x-1,y)<br>\]\[<br>f_y(x,y) = f(x,y+1) - f(x,y) , \ \ \ f_y(x,y) = f(x,y) - f(x,y-1)<br>\]の平均をとって、\[\begin{align*}<br>f_x(x,y) &amp; = \frac{1}{2} \left[ \left\{ f(x+1,y) - f(x,y) \right\} + \left\{ f(x,y) - f(x-1,y) \right\} \right]<br>\\ &amp; = \frac{1}{2} \left\{ f(x+1,y) - f(x-1,y) \right\}<br>\end{align*}\]</p>



<p>\[\begin{align*}<br>f_y(x,y) &amp; = \frac{1}{2} \left[ \left\{ f(x,y+1) - f(x,y) \right\} + \left\{ f(x,y) - f(x,y-1) \right\} \right]<br>\\ &amp; = \frac{1}{2} \left\{ f(x,y+1) - f(x,y-1) \right\}<br>\end{align*}\]とする方法もあります。</p>



<p>この方法の場合の1次フィルタは、下のようになります。</p>



<figure class="wp-block-table aligncenter"><table><thead><tr><th class="has-text-align-center">方向</th><th class="has-text-align-center">式</th><th class="has-text-align-center">フィルタ</th></tr></thead><tbody><tr><td class="has-text-align-center">横方向（\( x \) 方向）</td><td class="has-text-align-center">\( f_x(x,y) = \textcolor{deepskyblue}{\frac{1}{2} f(x+1,y)}  \textcolor{magenta}{\frac{-1}{2} f(x-1,y)} \)</td><td class="has-text-align-center">\(<br>\left( \begin{array}{ccc} 0 &amp; 0 &amp; 0 \\  \textcolor{magenta}{-\frac{1}{2} } &amp; 0 &amp; \textcolor{deepskyblue}{ \frac{1}{2} } \\ 0 &amp; 0 &amp; 0 \end{array} \right)<br>\)</td></tr><tr><td class="has-text-align-center">縦方向（\( y \) 方向）</td><td class="has-text-align-center">\( f_y(x,y) = \textcolor{deepskyblue}{\frac{1}{2} f(x,y+1)}  \textcolor{magenta}{\frac{-1}{2} f(x,y-1)} \)</td><td class="has-text-align-center">\(<br>\left( \begin{array}{ccc} 0 &amp; \textcolor{magenta}{- \frac{1}{2} } &amp; 0 \\  0 &amp; 0 &amp;  0 \\ 0 &amp; \textcolor{deepskyblue}{ \frac{1}{2} } &amp; 0 \end{array} \right)<br>\)</td></tr></tbody></table><figcaption>※ フィルタの係数 1/2 は省略されることもあり。</figcaption></figure>



<p>このように、同じ「横(縦)方向の1次微分」でも、フィルタの書き方が3通りもあるのです。</p>



<figure class="wp-block-image aligncenter size-full"><img width="2002" height="1080" src="https://www.momoyama-usagi.com/wp-content/uploads/gazo3-14.jpg" alt="" class="wp-image-17701" srcset="https://www.momoyama-usagi.com/wp-content/uploads/gazo3-14.jpg 2002w, https://www.momoyama-usagi.com/wp-content/uploads/gazo3-14-300x162.jpg 300w, https://www.momoyama-usagi.com/wp-content/uploads/gazo3-14-1024x552.jpg 1024w, https://www.momoyama-usagi.com/wp-content/uploads/gazo3-14-768x414.jpg 768w, https://www.momoyama-usagi.com/wp-content/uploads/gazo3-14-1536x829.jpg 1536w" /><figcaption>様々な微分フィルタのとり方</figcaption></figure>



<p>※ 3番目のフィルタの係数 \( \frac{1}{2} \) は省略して、\[<br>\left( \begin{array}{ccc} 0 &amp; 0 &amp; 0 \\  \textcolor{magenta}{- 1 } &amp; 0 &amp; \textcolor{deepskyblue}{ 1 } \\ 0 &amp; 0 &amp; 0 \end{array} \right) , \ \ \ \left( \begin{array}{ccc} 0 &amp; 0 &amp; 0 \\  \textcolor{magenta}{- 1 } &amp; 0 &amp;  \textcolor{deepskyblue}{ 1 } \\ 0 &amp; 0 &amp; 0 \end{array} \right)<br>\]と表現することも多いです。（ただし出力される画像の画素値は2倍になる）</p>



<div style="height:100px" class="wp-block-spacer"></div>



<h2 class="wp-block-heading">5. プレヴィットフィルタ</h2>



<h3 class="wp-block-heading">(1) 1次微分フィルタの欠点</h3>



<p>「5. 1次微分フィルタ」では、エッジ（＝画素値が特に変化している部分）を得ることができるのでしたね。</p>



<p>しかし、同時に画像に含まれるノイズも1次微分フィルタにより強調されてしまいます。</p>



<p>そこで、</p>



<h3 class="wp-block-heading">(2) プレヴィットフィルタの仕組み [横方向]</h3>



<p>1次微分フィルタと同じようにプレヴィットフィルタにも横方向（\( x \) 方向）、縦方向（\( y \) 方向）それぞれのフィルタがありますが、まず横方向のプレヴィットフィルタから見ていきましょう。</p>



<p>横方向の1次微分フィルタでは、次の2つの式の\[<br>f(x+1,y) - f(x,y) , \ \ \ f(x,y) - f(x-1,y)<br>\]の平均値を出力画素値（＝偏導関数）とするのでしたね。</p>



<p>プレヴィットフィルタでは、この2つの式に加え、縦方向の前後の画素 \( y \pm 1 \) に対しても\[<br>f(x+1,y-1) - f(x,y-1) , \ \ \ f(x,y-1) - f(x-1,y-1)<br>\]\[<br>f(x+1,y+1) - f(x,y+1) , \ \ \ f(x,y+1) - f(x-1,y+1)<br>\]のように「隣り合う画素の差分を取る」ということをします。</p>



<p>これら6つの式の平均</p>



<p class="has-small-font-size">\[\begin{align*}<br>g(x,y) &amp; = \frac{1}{6} \left\{ f(x+1,y) - f(x,y) \right\} + \frac{1}{6} \left\{ f(x,y) - f(x-1,y) \right\}<br>\\ &amp; + \frac{1}{6} \left\{ f(x+1,y-1) - f(x,y-1) \right\} + \frac{1}{6} \left\{ f(x,y-1) - f(x-1,y-1) \right\}<br>\\ &amp; + \frac{1}{6} \left\{ f(x+1,y) - f(x,y) \right\} + \frac{1}{6} \left\{ f(x,y) - f(x-1,y) \right\}<br>\\ &amp; = \frac{1}{6} \left\{ \textcolor{red}{f(x-1,y-1)} +  \textcolor{blue}{f(x+1,y-1)} + \textcolor{deepskyblue}{f(x-1,y)} +  \textcolor{magenta}{f(x+1,y)} +  \textcolor{orange}{f(x-1,y+1)} +  \textcolor{green}{f(x+1,y+1)} \right\}<br>\end{align*}\]</p>



<p>をとったフィルタが、プレヴィットフィルタ\[ \frac{1}{6}<br>\left( \begin{array}{ccc} \textcolor{red}{- 1 } &amp; 0 &amp; \textcolor{blue}{ 1 }\\ \textcolor{magenta}{- 1 } &amp; 0 &amp; \textcolor{deepskyblue}{ 1 } \\ \textcolor{orange}{- 1 } &amp; 0 &amp; \textcolor{green}{ 1 } \end{array} \right)<br>\]となります。</p>







<figure class="wp-block-image aligncenter size-full"><img width="1982" height="1008" src="https://www.momoyama-usagi.com/wp-content/uploads/gazo3-17.jpg" alt="" class="wp-image-17704" srcset="https://www.momoyama-usagi.com/wp-content/uploads/gazo3-17.jpg 1982w, https://www.momoyama-usagi.com/wp-content/uploads/gazo3-17-300x153.jpg 300w, https://www.momoyama-usagi.com/wp-content/uploads/gazo3-17-1024x521.jpg 1024w, https://www.momoyama-usagi.com/wp-content/uploads/gazo3-17-768x391.jpg 768w, https://www.momoyama-usagi.com/wp-content/uploads/gazo3-17-1536x781.jpg 1536w" /></figure>



<h3 class="wp-block-heading">(3) プレヴィットフィルタの仕組み [縦方向]</h3>



<p>縦方向のプレヴィットフィルタも、横方向のときと同じように1次微分で使った2つの式\[<br>f(x,y+1) - f(x,y) , \ \ \ f(x,y) - f(x,y-1)<br>\]に加え、横方向の前後の画素 \( x \pm 1 \) に対しても\[<br>f(x-1,y+1) - f(x,y) , \ \ \ f(x-1,y) - f(x,y-1)<br>\]\[<br>f(x+1,y+1) - f(x,y) , \ \ \ f(x+1,y) - f(x,y-1)<br>\]のように「隣り合う画素の差分を取った」式を作ります。</p>



<p>合計6つの式の平均</p>



<p class="has-small-font-size">\[\begin{align*}<br>g(x,y) &amp; = \frac{1}{6} \left\{ f(x,y+1) - f(x,y) \right\} + \frac{1}{6} \left\{ f(x,y) - f(x,y-1) \right\}<br>\\ &amp; + \frac{1}{6} \left\{ f(x-1,y+1) - f(x-1,y) \right\} + \frac{1}{6} \left\{ f(x-1,y) - f(x-1,y-1) \right\}<br>\\ &amp; + \frac{1}{6} \left\{ f(x+1,y+1) - f(x+1,y) \right\} + \frac{1}{6} \left\{ f(x+1,y) - f(x+1,y-1)  \right\}<br>\\ &amp; = \frac{1}{6} \left\{ \textcolor{red}{f(x-1,y-1)} + \textcolor{magenta}{f(x,y-1)} + \textcolor{orange}{f(x+1,y-1)} +  \textcolor{blue}{f(x-1,y+1)} + \textcolor{deepskyblue}{f(x,y+1)} +    \textcolor{green}{f(x+1,y+1)} \right\}<br>\end{align*}\]</p>



<p>をとったものが縦方向のプレヴィットフィルタとなります。</p>



<p>\[ \frac{1}{6}<br>\left( \begin{array}{ccc} \textcolor{red}{- 1 } &amp; \textcolor{magenta}{ -1 } &amp; \textcolor{orange}{- 1 } \\ 0 &amp; 0 &amp; 0 \\ \textcolor{blue}{ 1 } &amp; \textcolor{deepskyblue}{ 1 } &amp; \textcolor{green}{ 1 } \end{array} \right)<br>\]</p>



<figure class="wp-block-image aligncenter size-full"><img width="1982" height="1008" src="https://www.momoyama-usagi.com/wp-content/uploads/gazo3-18.jpg" alt="" class="wp-image-17705" srcset="https://www.momoyama-usagi.com/wp-content/uploads/gazo3-18.jpg 1982w, https://www.momoyama-usagi.com/wp-content/uploads/gazo3-18-300x153.jpg 300w, https://www.momoyama-usagi.com/wp-content/uploads/gazo3-18-1024x521.jpg 1024w, https://www.momoyama-usagi.com/wp-content/uploads/gazo3-18-768x391.jpg 768w, https://www.momoyama-usagi.com/wp-content/uploads/gazo3-18-1536x781.jpg 1536w" /></figure>



<div style="height:100px" class="wp-block-spacer"></div>



<h2 class="wp-block-heading">6. ソーベルフィルタ</h2>



<p>横/縦方向のブレットフィルタでは、下の6種類の方法で「隣り合う画素の差分を取る」ことをし、それらの平均をとっていましたね。</p>



<p class="has-text-align-center">横方向ブレットフィルタ：平均化する数式一覧</p>



<figure class="wp-block-table"><table><thead><tr><th>着目する \( y \) </th><th>数式</th></tr></thead><tbody><tr><td>\( y - 1 \) に対して</td><td> \( f(x+1,y-1) - f(x,y-1) \) と \( f(x,y-1) - f(x-1,y-1) \)</td></tr><tr><td>\( y  \) に対して</td><td>\( f(x+1,y) - f(x,y-1) \) と \( f(x,y) - f(x-1,y-1) \)</td></tr><tr><td>\( y + 1 \) に対して</td><td>\( f(x+1,y+1) - f(x,y-1) \) と \( f(x,y+1) - f(x-1,y-1) \)</td></tr></tbody></table></figure>







<p class="has-text-align-center">縦方向ブレットフィルタ：平均化する数式一覧</p>



<figure class="wp-block-table"><table><thead><tr><th>着目する \( x \) </th><th>数式</th></tr></thead><tbody><tr><td>\( x - 1 \) に対して</td><td>\( f(x-1,y+1) - f(x-1,y) \) と \( f(x-1,y) - f(x,y-1) \)</td></tr><tr><td>\( x  \) に対して</td><td>\( f(x,y+1) - f(x,y) \) と \( f(x,y) - f(x,y-1) \)</td></tr><tr><td>\( x + 1 \) に対して</td><td>\( f(x+1,y+1) - f(x+1,y) \) と \( f(x+1,y) - f(x+1,y-1) \)</td></tr></tbody></table></figure>







<p>ソーベルフィルタでも、同じように6種類の方法で「隣り合う画素の差分を取る」のですが、ソーベルフィルタの場合は、<strong><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-red-color">着目している画素と同じ方向に対して2倍の重みをつけて</mark></strong>から平均化をします。</p>



<p class="has-text-align-center">横方向ソーベルフィルタ：平均化する数式一覧</p>



<figure class="wp-block-table aligncenter"><table><thead><tr><th class="has-text-align-center">着目する \( y \) </th><th class="has-text-align-center">数式</th></tr></thead><tbody><tr><td class="has-text-align-center">\( y - 1 \) に対して</td><td class="has-text-align-center"> \( f(x+1,y-1) - f(x,y-1)\) と \( f(x,y-1) - f(x-1,y-1) \)</td></tr><tr><td class="has-text-align-center"><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-red-color">\( y  \) に対して</mark></td><td class="has-text-align-center"><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-red-color">\( 2 f(x+1,y) - 2 f(x,y-1) \) と \( 2f(x,y) - 2 f(x-1,y-1) \)</mark></td></tr><tr><td class="has-text-align-center">\( y + 1 \) に対して</td><td class="has-text-align-center">\( f(x+1,y+1) - f(x,y-1) \) と \( f(x,y+1) - f(x-1,y-1) \)</td></tr></tbody></table></figure>







<p class="has-text-align-center">縦方向ブレットフィルタ：平均化する数式一覧</p>



<figure class="wp-block-table aligncenter"><table><thead><tr><th class="has-text-align-center">着目する \( x \) </th><th class="has-text-align-center">数式</th></tr></thead><tbody><tr><td class="has-text-align-center">\( x - 1 \) に対して</td><td class="has-text-align-center">\( f(x-1,y+1) - f(x-1,y) \) と \( f(x-1,y) - f(x,y-1) \)</td></tr><tr><td class="has-text-align-center"><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-red-color">\( x  \) に対して</mark></td><td class="has-text-align-center"><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-red-color">\( 2 f(x,y+1) - 2 f(x,y) \) と \( 2 f(x,y) - 2 f(x,y-1) \)</mark></td></tr><tr><td class="has-text-align-center">\( x + 1 \) に対して</td><td class="has-text-align-center">\( f(x+1,y+1) - f(x+1,y) \) と \( f(x+1,y) - f(x+1,y-1) \)</td></tr></tbody></table></figure>



<div style="height:40px" class="wp-block-spacer"></div>



<p>2倍の重みをつけたあとは、平均を取ればOKです。</p>



<p><strong>[横方向ソーベルフィルタ]</strong></p>



<p>導出)</p>



<p class="has-small-font-size">\[\begin{align*}<br>g(x,y) &amp; = \frac{2}{8} \left\{ f(x+1,y) - f(x,y) \right\} + \frac{2}{8} \left\{ f(x,y) - f(x-1,y) \right\}<br>\\ &amp; + \frac{1}{8} \left\{ f(x+1,y-1) - f(x,y-1) \right\} + \frac{1}{8} \left\{ f(x,y-1) - f(x-1,y-1) \right\}<br>\\ &amp; + \frac{1}{8} \left\{ f(x+1,y) - f(x,y) \right\} + \frac{1}{8} \left\{ f(x,y) - f(x-1,y) \right\}<br>\\ &amp; = \frac{1}{8} \left\{ \textcolor{red}{f(x-1,y-1)} +  \textcolor{blue}{f(x+1,y-1)} + \textcolor{magenta}{2 f(x-1,y)} +  \textcolor{deepskyblue}{2 f(x+1,y)} +  \textcolor{orange}{f(x-1,y+1)} +  \textcolor{green}{f(x+1,y+1)} \right\}<br>\end{align*}\]</p>



<p>結果)\[ \frac{1}{8}<br>\left( \begin{array}{ccc} \textcolor{red}{- 1 } &amp; 0 &amp; \textcolor{blue}{ 1 }\\ \textcolor{magenta}{- 2 } &amp; 0 &amp; \textcolor{deepskyblue}{ 2 } \\ \textcolor{orange}{- 1 } &amp; 0 &amp; \textcolor{green}{ 1 } \end{array} \right)<br>\]</p>



<p>変換例)</p>



<figure class="wp-block-image aligncenter size-full"><img width="1982" height="1008" src="https://www.momoyama-usagi.com/wp-content/uploads/gazo3-19.jpg" alt="" class="wp-image-17706" srcset="https://www.momoyama-usagi.com/wp-content/uploads/gazo3-19.jpg 1982w, https://www.momoyama-usagi.com/wp-content/uploads/gazo3-19-300x153.jpg 300w, https://www.momoyama-usagi.com/wp-content/uploads/gazo3-19-1024x521.jpg 1024w, https://www.momoyama-usagi.com/wp-content/uploads/gazo3-19-768x391.jpg 768w, https://www.momoyama-usagi.com/wp-content/uploads/gazo3-19-1536x781.jpg 1536w" /></figure>



<p><strong>[縦方向ソーベルフィルタ導出]</strong></p>



<p class="has-small-font-size">\[\begin{align*}<br>g(x,y) &amp; = \frac{2}{8} \left\{ f(x,y+1) - f(x,y) \right\} + \frac{2}{8} \left\{ f(x,y) - f(x,y-1) \right\}<br>\\ &amp; + \frac{1}{8} \left\{ f(x-1,y+1) - f(x-1,y) \right\} + \frac{1}{8} \left\{ f(x-1,y) - f(x-1,y-1) \right\}<br>\\ &amp; + \frac{1}{8} \left\{ f(x+1,y+1) - f(x+1,y) \right\} + \frac{1}{8} \left\{ f(x+1,y) - f(x+1,y-1)  \right\}<br>\\ &amp; = \frac{1}{8}  \left\{ \textcolor{red}{f(x-1,y-1)} + \textcolor{magenta}{2 f(x,y-1)} + \textcolor{orange}{f(x+1,y-1)} +  \textcolor{blue}{f(x-1,y+1)} + \textcolor{deepskyblue}{2 f(x,y+1)} +    \textcolor{green}{f(x+1,y+1)} \right\}<br>\end{align*}\]</p>



<p>結果)\[<br>\frac{1}{8}<br>\left( \begin{array}{ccc} \textcolor{red}{- 1 } &amp; \textcolor{magenta}{ -2 } &amp; \textcolor{orange}{- 1 } \\ 0 &amp; 0 &amp; 0 \\ \textcolor{blue}{ 1 } &amp; \textcolor{deepskyblue}{ 2 } &amp; \textcolor{green}{ 1 } \end{array} \right)<br>\]</p>



<p>変換例)</p>



<figure class="wp-block-image aligncenter size-full"><img width="1982" height="1008" src="https://www.momoyama-usagi.com/wp-content/uploads/gazo3-20.jpg" alt="" class="wp-image-17707" srcset="https://www.momoyama-usagi.com/wp-content/uploads/gazo3-20.jpg 1982w, https://www.momoyama-usagi.com/wp-content/uploads/gazo3-20-300x153.jpg 300w, https://www.momoyama-usagi.com/wp-content/uploads/gazo3-20-1024x521.jpg 1024w, https://www.momoyama-usagi.com/wp-content/uploads/gazo3-20-768x391.jpg 768w, https://www.momoyama-usagi.com/wp-content/uploads/gazo3-20-1536x781.jpg 1536w" /></figure>



<div style="height:100px" class="wp-block-spacer"></div>



<h2 class="wp-block-heading">7. 2次微分フィルタ</h2>



<h3 class="wp-block-heading">(1) 2次微分が表すものとは</h3>



<p>2次微分は、微分したもの \( f'(x) \) に対してさらに微分をすることをいいます。数式で書くと、\[<br>f''(x) = \lim_{h \to 0} \frac{f'(x+h) - f'(x)}{h}<br>\]となります。</p>



<p>日本語で説明すると</p>



<ul class="wp-block-list"><li>\( x \) の変化量を表したものが \( f'(x) \) → 1次微分</li><li>\( f'(x) \) の変化量を表したものが \( f''(x) \) → 2次微分</li></ul>



<p>といえますね。</p>


<p><span>そのため、画像を2次微分すると「画素値の変化度合いの大小」が得られそうな感じがしますね。「画素値の変化度合いの大小」を得ることで、<span  style="background-image:linear-gradient(to bottom,transparent 0%,#FFF387 0%);" class="dbp-e-marker-animation y">特に画素値が変化している部分（＝エッジ）を1次微分に比べて正確に得ることができます</span>。</span></p>


<h3 class="wp-block-heading">(2) 2次微分フィルタの導出</h3>



<p>ここからは、（3×3の）2次微分フィルタを導出してみましょう。</p>



<h4 class="wp-block-heading">\( x \) 方向 (縦方向) の2次微分</h4>



<p>2変数関数の \( x \) に関する1次微分は、\[<br>f_x(x,y) = \lim_{h \to 0} \frac{f(x+h,y) - f(x,y)}{h}<br>\]で計算できるのでしたね。</p>



<p>\( x \) に関する2次微分は、\( x \) で1次微分した関数 \( f_x (x,y) \) に対して、さらにもう1度微分することで求めることができます。\[<br>f_{xx} (x,y) = \lim_{h \to 0} \frac{f_x(x+h,y) - f_x(x,y)}{h}<br>\]※ \( x \) に関する2次微分を適用した関数を \( f_{xx} \) で表記します<span class="footnote_referrer"><a tabindex="0" onclick="footnote_moveToReference_17641_7('footnote_plugin_reference_17641_7_2');" onkeypress="footnote_moveToReference_17641_7('footnote_plugin_reference_17641_7_2');" ><sup id="footnote_plugin_tooltip_17641_7_2" class="footnote_plugin_tooltip_text">[2]</sup></a><span id="footnote_plugin_tooltip_text_17641_7_2" class="footnote_tooltip">\( \frac{ \partial^2}{ \partial x^2} \) と表記されることもあります。</span></span>。</p>



<p>ただし、画像処理の世界では極限計算 \( h \to 0 \) ができないので、代わりに \( h = 1 \) とし、\[<br>f_{xx} (x,y) = f_x(x+1,y) - f_x(x,y)<br>\]を求めることで \( x \) に関する2次微分を求めます。</p>



<p>ここで、1次微分 \( f_x(x+1,y) \), \( f_x(x,y) \) は\[<br>f_x (x+1,y) = f(x+1,y) - f(x,y)<br>\]\[<br>f_x(x,y) = f(x,y) - f(x-1,y)<br>\]と書き換えることができますね<span class="footnote_referrer"><a tabindex="0" onclick="footnote_moveToReference_17641_7('footnote_plugin_reference_17641_7_3');" onkeypress="footnote_moveToReference_17641_7('footnote_plugin_reference_17641_7_3');" ><sup id="footnote_plugin_tooltip_17641_7_3" class="footnote_plugin_tooltip_text">[3]</sup></a><span id="footnote_plugin_tooltip_text_17641_7_3" class="footnote_tooltip">1階微分の法則 \( f_x (x,y) = f_x (x+1,y) - f_x (x,y) \), \( f_x (x,y) = f_x (x,y) - f_x (x-1,y) \) より</span></span>。</p>



<p>よって、2次微分を\[\begin{align*}<br>f_{xx} (x,y) &amp; =  f_x(x+1,y) - f_x(x,y)<br>\\ &amp; = \left\{ f(x+1,y) - f(x,y) \right\} + \left\{ f(x,y) - f(x-1,y) \right\} <br>\\ &amp; = \textcolor{magenta}{f(x+1,y)} \textcolor{green}{-2 f(x,y)} + \textcolor{deepskyblue}{f(x-1,y)}<br>\end{align*}\]と変形できるため、2次微分フィルタは\[<br>\left( \begin{array}{ccc} 0 &amp; 0 &amp; 0 \\  \textcolor{deepskyblue}{1} &amp; \textcolor{green}{-2} &amp; \textcolor{magenta}{1} \\ 0 &amp; 0 &amp; 0 \end{array} \right)<br>\]と導出できます。</p>



<p><strong>[実際に横方向の2次微分フィルタを適用すると…？]</strong></p>



<figure class="wp-block-image aligncenter size-full"><img width="1982" height="1008" src="https://www.momoyama-usagi.com/wp-content/uploads/gazo3-21.jpg" alt="" class="wp-image-17708" srcset="https://www.momoyama-usagi.com/wp-content/uploads/gazo3-21.jpg 1982w, https://www.momoyama-usagi.com/wp-content/uploads/gazo3-21-300x153.jpg 300w, https://www.momoyama-usagi.com/wp-content/uploads/gazo3-21-1024x521.jpg 1024w, https://www.momoyama-usagi.com/wp-content/uploads/gazo3-21-768x391.jpg 768w, https://www.momoyama-usagi.com/wp-content/uploads/gazo3-21-1536x781.jpg 1536w" /></figure>



<p>横方向の2次微分フィルタを適用することで、横方向の画素値変化が可視化されます。可視化された画像には縦方向のエッジが入っているのが特徴です。</p>



<h4 class="wp-block-heading">\( y \) 方向 (横方向) の2次微分</h4>



<p>\( x \) 方向のときと同じように、\( y \) に関する2次微分は、\( y \) で1次微分した関数 \( f_y (x,y) \) に対して、さらにもう1度微分することで求めることができます。\[<br>f_{yy} (x,y) = \lim_{h \to 0} \frac{f_y(x,y+h) - f_y(x,y)}{h}<br>\]※ \( y \) に関する2次微分を適用した関数を \( f_{yy} \) で表記します<span class="footnote_referrer"><a tabindex="0" onclick="footnote_moveToReference_17641_7('footnote_plugin_reference_17641_7_4');" onkeypress="footnote_moveToReference_17641_7('footnote_plugin_reference_17641_7_4');" ><sup id="footnote_plugin_tooltip_17641_7_4" class="footnote_plugin_tooltip_text">[4]</sup></a><span id="footnote_plugin_tooltip_text_17641_7_4" class="footnote_tooltip">\( \frac{ \partial^2}{ \partial y^2} \) と表記されることもあります。</span></span>。</p>



<p>ただし、先程も言った通り画像処理の世界では極限計算 \( h \to 0 \) ができないので、代わりに \( h = 1 \) とし、\[<br>f_{yy} (x,y) = f_y(x,y+1) - f_y(x,y)<br>\]を求めることで \( y \) に関する2次微分を求めます。</p>



<p>ここで、1次微分 \( f_y(x,y+1) \), \( f_y(x,y) \) は\[<br>f_y (x,y+1) = f(x,y+1) - f(x,y)<br>\]\[<br>f_y(x,y) = f(x,y) - f(x,y-1)<br>\]と書き換えられますね<span class="footnote_referrer"><a tabindex="0" onclick="footnote_moveToReference_17641_7('footnote_plugin_reference_17641_7_5');" onkeypress="footnote_moveToReference_17641_7('footnote_plugin_reference_17641_7_5');" ><sup id="footnote_plugin_tooltip_17641_7_5" class="footnote_plugin_tooltip_text">[5]</sup></a><span id="footnote_plugin_tooltip_text_17641_7_5" class="footnote_tooltip">1階微分の法則 \( f_y (x,y) = f_y (x,y+1) - f_y(x,y) \), \( f_y (x,y) = f_y (x,y) - f_y(x,y-1) \) より</span></span>。</p>



<p>よって、2次微分を\[\begin{align*}<br>f_{yy} (x,y) = f_y(x,y+1) - f_y(x,y)<br>\\ &amp; = \left\{ f(x,y+1) - f(x,y) \right\} + \left\{ f(x,y) - f(x,y-1) \right\} <br>\\ &amp; = \textcolor{magenta}{f(x,y+1)} \textcolor{green}{-2 f(x,y)} + \textcolor{deepskyblue}{f(x,y-1)}<br>\end{align*}\]と変形できるため、2次微分フィルタは\[<br>\left( \begin{array}{ccc} 0 &amp; \textcolor{deepskyblue}{1} &amp; 0 \\  0 &amp; \textcolor{green}{-2} &amp; 0 \\ 0 &amp; \textcolor{magenta}{1} &amp; 0 \end{array} \right)<br>\]と導出できます。</p>



<figure class="wp-block-image aligncenter size-full"><img width="1982" height="1008" src="https://www.momoyama-usagi.com/wp-content/uploads/gazo3-22.jpg" alt="" class="wp-image-17709" srcset="https://www.momoyama-usagi.com/wp-content/uploads/gazo3-22.jpg 1982w, https://www.momoyama-usagi.com/wp-content/uploads/gazo3-22-300x153.jpg 300w, https://www.momoyama-usagi.com/wp-content/uploads/gazo3-22-1024x521.jpg 1024w, https://www.momoyama-usagi.com/wp-content/uploads/gazo3-22-768x391.jpg 768w, https://www.momoyama-usagi.com/wp-content/uploads/gazo3-22-1536x781.jpg 1536w" /></figure>



<p>縦方向の2次微分フィルタを適用することで、縦方向の画素値変化が可視化されます。可視化された画像には横方向のエッジが入っているのが特徴です。</p>



<div style="height:100px" class="wp-block-spacer"></div>



<h2 class="wp-block-heading">8. ラプラシアンフィルタ</h2>



<p>「7. 2次微分フィルタ」では、横方向・縦方向それぞれの画素値変化の度合いを可視化することができますが、一度に「横方向と縦方向両方」の画素値の度合いを可視化することができます。</p>



<p>そこで、\( x \) に関する2次微分 \( f_{xx} (x,y) \) と、\( y \) に関する2次微分 \( f_{yy} (x,y) \) を足したフィルタを考えましょう。（ラプラシアンフィルタと呼ばれます<span class="footnote_referrer"><a tabindex="0" onclick="footnote_moveToReference_17641_7('footnote_plugin_reference_17641_7_6');" onkeypress="footnote_moveToReference_17641_7('footnote_plugin_reference_17641_7_6');" ><sup id="footnote_plugin_tooltip_17641_7_6" class="footnote_plugin_tooltip_text">[6]</sup></a><span id="footnote_plugin_tooltip_text_17641_7_6" class="footnote_tooltip">2変数関数 \( f(x,y) \) のラプラシアンが\[ f_{xx} (x,y) + f_{yy} (x,y) \]で定義されることから名前が付けられています。</span></span>。）</p>



<p>ここで、\[<br>f_{xx} = f(x+1,y) - 2 f(x,y) + f(x-1,y)<br>\]\[<br>f_{yy} = f(x,y+1) - 2 f(x,y) + f(x,y-1)<br>\]なので、\( f_{xx} (x,y) \) と \( f_{yy} (x,y) \) を足した和 \( g(x,y) \) は\[\begin{align*}<br>g(x,y) &amp; = f_{xx} (x,y) + f_{yy} (x,y)<br>\\ &amp; = \left\{ f(x+1,y) - 2 f(x,y) + f(x-1,y) \right\} + \left\{ f(x,y+1) - 2 f(x,y) + f(x,y-1) \right\} <br>\\ &amp; = \textcolor{red}{f(x-1,y)} + \textcolor{orange}{f(x,y-1)} \textcolor{green}{-4 f(x,y)} + \textcolor{deepskyblue}{ f(x, y+1) } + \textcolor{blue}{ f(x+1,y) }<br>\end{align*}\]となるため、ラプラシアンフィルタは\[<br>\left( \begin{array}{ccc} 0 &amp;\textcolor{red}{1}  &amp; 0 \\  \textcolor{orange}{1} &amp; \textcolor{green}{-4} &amp; \textcolor{deepskyblue}{1} \\ 0 &amp; \textcolor{blue}{1} &amp; 0 \end{array} \right)<br>\]と求められます。</p>



<figure class="wp-block-image aligncenter size-full"><img width="1982" height="1008" src="https://www.momoyama-usagi.com/wp-content/uploads/gazo3-23.jpg" alt="" class="wp-image-17710" srcset="https://www.momoyama-usagi.com/wp-content/uploads/gazo3-23.jpg 1982w, https://www.momoyama-usagi.com/wp-content/uploads/gazo3-23-300x153.jpg 300w, https://www.momoyama-usagi.com/wp-content/uploads/gazo3-23-1024x521.jpg 1024w, https://www.momoyama-usagi.com/wp-content/uploads/gazo3-23-768x391.jpg 768w, https://www.momoyama-usagi.com/wp-content/uploads/gazo3-23-1536x781.jpg 1536w" /></figure>



<div style="height:100px" class="wp-block-spacer"></div>



<h2 class="wp-block-heading">9. 練習問題</h2>



<p>最後に、練習問題で軽くフィルタについておさらいしておきましょう。</p>


<div class='wp-block-dbp-frame l-frame-float is-design-onframe is-frame-style-default dbp-frame has-bgcolor'><div class="dbp-frame-title">練習問題</div><div class="dbp-frame-content has-content-gap">
<p>ある画像に対して、次の(1)～(3)で示されるフィルタを加えたときの出力画像を表した説明として、正しいものを1つずつ選び番号で答えなさい。</p>

<figure class="wp-block-image aligncenter size-large"><img width="1024" height="355" src="https://www.momoyama-usagi.com/wp-content/uploads/img3-7-1024x355.gif" alt="" class="wp-image-17832" srcset="https://www.momoyama-usagi.com/wp-content/uploads/img3-7-1024x355.gif 1024w, https://www.momoyama-usagi.com/wp-content/uploads/img3-7-300x104.gif 300w, https://www.momoyama-usagi.com/wp-content/uploads/img3-7-768x266.gif 768w, https://www.momoyama-usagi.com/wp-content/uploads/img3-7-1536x532.gif 1536w" /></figure>

<p><strong>[選択肢]</strong></p>

<ol class="wp-block-list"><li>元画像のエッジが強調された画像が出力された。</li><li>元画像がぼやけた画像が出力された。</li><li>元画像のエッジ部分だけが出力された。</li></ol>
</div></div>


<p><strong>[解説]</strong></p>



<p>(1) 2 → 平滑化<br>(2) 1 → 鮮鋭化<br>(3) 3 → ラプラシアンフィルタ</p>



<div class="speaker-mute footnotes_reference_container"> <div class="footnote_container_prepare"><p><span tabindex="0" class="footnote_reference_container_label pointer">注釈</span><span tabindex="0" class="footnote_reference_container_collapse_button" style="display: none;">[<a id="footnote_reference_container_collapse_button_17641_7">+</a>]</span></p></div> <div id="footnote_references_container_17641_7"><table class="footnotes_table footnote-reference-container"><caption class="accessibility">注釈</caption> <tbody> 

<tr class="footnotes_plugin_reference_row"> <th scope="row" class="footnote_plugin_index_combi pointer"  onclick="footnote_moveToAnchor_17641_7('footnote_plugin_tooltip_17641_7_1');"><a id="footnote_plugin_reference_17641_7_1" class="footnote_backlink"><span class="footnote_index_arrow">&#8593;</span>1</a></th> <td class="footnote_plugin_text">なお、偏微分を正式に表す場合は、\[<br>f_x (x,y) = \frac{ \partial }{ \partial x } f(x,y) , \ \ \ f_y (x,y) = \frac{ \partial }{ \partial y } f(x,y) <br>\]と表記します。</td></tr>

<tr class="footnotes_plugin_reference_row"> <th scope="row" class="footnote_plugin_index_combi pointer"  onclick="footnote_moveToAnchor_17641_7('footnote_plugin_tooltip_17641_7_2');"><a id="footnote_plugin_reference_17641_7_2" class="footnote_backlink"><span class="footnote_index_arrow">&#8593;</span>2</a></th> <td class="footnote_plugin_text">\( \frac{ \partial^2}{ \partial x^2} \) と表記されることもあります。</td></tr>

<tr class="footnotes_plugin_reference_row"> <th scope="row" class="footnote_plugin_index_combi pointer"  onclick="footnote_moveToAnchor_17641_7('footnote_plugin_tooltip_17641_7_3');"><a id="footnote_plugin_reference_17641_7_3" class="footnote_backlink"><span class="footnote_index_arrow">&#8593;</span>3</a></th> <td class="footnote_plugin_text">1階微分の法則 \( f_x (x,y) = f_x (x+1,y) - f_x (x,y) \), \( f_x (x,y) = f_x (x,y) - f_x (x-1,y) \) より</td></tr>

<tr class="footnotes_plugin_reference_row"> <th scope="row" class="footnote_plugin_index_combi pointer"  onclick="footnote_moveToAnchor_17641_7('footnote_plugin_tooltip_17641_7_4');"><a id="footnote_plugin_reference_17641_7_4" class="footnote_backlink"><span class="footnote_index_arrow">&#8593;</span>4</a></th> <td class="footnote_plugin_text">\( \frac{ \partial^2}{ \partial y^2} \) と表記されることもあります。</td></tr>

<tr class="footnotes_plugin_reference_row"> <th scope="row" class="footnote_plugin_index_combi pointer"  onclick="footnote_moveToAnchor_17641_7('footnote_plugin_tooltip_17641_7_5');"><a id="footnote_plugin_reference_17641_7_5" class="footnote_backlink"><span class="footnote_index_arrow">&#8593;</span>5</a></th> <td class="footnote_plugin_text">1階微分の法則 \( f_y (x,y) = f_y (x,y+1) - f_y(x,y) \), \( f_y (x,y) = f_y (x,y) - f_y(x,y-1) \) より</td></tr>

<tr class="footnotes_plugin_reference_row"> <th scope="row" class="footnote_plugin_index_combi pointer"  onclick="footnote_moveToAnchor_17641_7('footnote_plugin_tooltip_17641_7_6');"><a id="footnote_plugin_reference_17641_7_6" class="footnote_backlink"><span class="footnote_index_arrow">&#8593;</span>6</a></th> <td class="footnote_plugin_text">2変数関数 \( f(x,y) \) のラプラシアンが\[ f_{xx} (x,y) + f_{yy} (x,y) \]で定義されることから名前が付けられています。</td></tr>

 </tbody> </table> </div></div>]]></content:encoded>
					
					<wfw:commentRss>https://www.momoyama-usagi.com/entry/info-img03/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>うさぎでもわかるコンパイラ　第4羽　左再帰の除去</title>
		<link>https://www.momoyama-usagi.com/entry/info-compiler4</link>
					<comments>https://www.momoyama-usagi.com/entry/info-compiler4#respond</comments>
		
		<dc:creator><![CDATA[ももうさ]]></dc:creator>
		<pubDate>Tue, 20 Sep 2022 11:51:09 +0000</pubDate>
				<category><![CDATA[コンパイラ(言語処理系)]]></category>
		<category><![CDATA[まとめシリーズ]]></category>
		<category><![CDATA[情報]]></category>
		<category><![CDATA[コンパイラ]]></category>
		<category><![CDATA[言語処理系]]></category>
		<guid isPermaLink="false">https://www.momoyama-usagi.com/?p=17270</guid>

					<description><![CDATA[こんにちは、ももやまです。 前回は1文字だけの先読みで構文解析ができる文法であるLL(1)文法について説明していきました。 しかし、文法の中に左再帰な規則が入ってしまうと、文法内の他の規則に関わらず、絶対にLL(1)文法 [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>こんにちは、ももやまです。</p>



<p>前回は1文字だけの先読みで構文解析ができる文法であるLL(1)文法について説明していきました。</p>



<figure class="wp-block-embed is-type-wp-embed is-provider-工業大学生ももやまのうさぎ塾 wp-block-embed-工業大学生ももやまのうさぎ塾"><div class="wp-block-embed__wrapper">
        <article class="pb p-id-16248 is-position-relative pb-embed">
            <a class="pb-contents" href="https://www.momoyama-usagi.com/entry/info-compiler3">
                <div class="pb__thumb"><img width="300" height="211" src="https://www.momoyama-usagi.com/wp-content/uploads/bandicam-2022-09-19-09-38-10-080-300x211.jpg" class="is-position-overlay wp-post-image" alt="" lazysizes="1" srcset="https://www.momoyama-usagi.com/wp-content/uploads/bandicam-2022-09-19-09-38-10-080-300x211.jpg 300w, https://www.momoyama-usagi.com/wp-content/uploads/bandicam-2022-09-19-09-38-10-080-1024x721.jpg 1024w, https://www.momoyama-usagi.com/wp-content/uploads/bandicam-2022-09-19-09-38-10-080-768x541.jpg 768w, https://www.momoyama-usagi.com/wp-content/uploads/bandicam-2022-09-19-09-38-10-080-1536x1081.jpg 1536w, https://www.momoyama-usagi.com/wp-content/uploads/bandicam-2022-09-19-09-38-10-080.jpg 1553w" /></div><div class="pb__body l-column is-flex-1"><div class="pb-title is-omit-line:2">うさぎでもわかるコンパイラ　第3羽　First・Follow・Director集合とLL(1)文法の判定</div><div class="pb-substr is-font-size:s is-omit-line:2">こんにちは、ももやまです。 コンパイラ（言語処理系）の勉強をしていると、 LL(1)文法First集合Follow集合Director集合 などの不思議な用</div></div>            </a>
        </article>
        
</div></figure>



<p>しかし、文法の中に左再帰な規則が入ってしまうと、文法内の他の規則に関わらず、絶対にLL(1)文法となることはありません。言い換えると、左再帰な規則は先読みしながらの構文解析の壁の1つといえます。</p>



<p>そこで今回は、</p>



<ul class="wp-block-list"><li>そもそも左再帰とは？</li><li>左再帰な規則が入るとLL(1)文法でなくなる理由</li><li>左再帰の除去（例題・練習問題あり）</li></ul>



<p>について、お勉強していきましょう。</p>


<div class='wp-block-dbp-frame l-frame-inner is-design-inline is-frame-style-default dbp-frame has-bgcolor'><div class="dbp-frame-title">文字表記に関する注意</div><div class="dbp-frame-content has-content-gap">
<p>本記事では特に指示がない限り、文章中に出てくる小文字・大文字・ギリシャ文字は</p>

<ul class="wp-block-list"><li>小文字 \( a \), \( b \), \( c \), \( d \), … → 終端記号</li><li>大文字 \( S \), \( A \), \( B \), \( C \), … → 非終端記号</li><li>\( \varepsilon \) を除くギリシャ文字 \( \alpha \), \( \beta \), … → 終端記号と非終端記号から出来る文字列<br>（例: \( abAb \), \( AbC \), \( ABC \), \( abc \) など…）</li><li>\( \varepsilon \) → 空文字</li></ul>

<p>を表します。</p>
</div></div>


<p>※ </p>



<h2 class="wp-block-heading">1. 左再帰・左再帰文法とは？</h2>



<p>左再帰(規則)とは、生成規則の中に<span style="text-decoration: underline;"><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-red-color"><strong>生成元の非終端記号</strong></mark></span>と<strong><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-blue-color"><span style="text-decoration: underline;">生成先の文字列の1文字目(先頭)</span></mark></strong>が同じになっている規則、つまり規則中に \( \textcolor{red}{A} \to \textcolor{blue}{A} \alpha \) となる規則のことをさします。</p>


<p><span>また、左再帰 \( \textcolor{red}{A} \to \textcolor{red}{A} \alpha \) が含まれている文法のことを<span  style="background-image:linear-gradient(to bottom,transparent 0%,#FFF387 0%);" class="dbp-e-marker-animation blue">左再帰文法</span>と呼びます。（ただし \( \alpha \not = \varepsilon \)）</span></p>


<p>例えば、生成規則が\[\begin{align*}<br>P = \{ \ \ \ \ S  &amp;  \to aA \\ \textcolor{red}{A} &amp;  \textcolor{red}{\to Aba} \ | \ cd \\ B &amp;  \to Sc \ | \ a \ \ \ \ \ \ \ \}<br>\end{align*}<br>\]で表される文法は、左再帰 \( \textcolor{red}{A \to Aba  } \) が含まれていますね。そのため、この文法は左再帰文法です。</p>



<div style="height:47px" class="wp-block-spacer"></div>



<p>左再帰文法には、左再帰の核部分 \( \textcolor{red}{A} \to \textcolor{red}{A} \alpha \) に加えて再帰をストップする規則の形 \( A \to \beta \) が含まれているのが特徴です。</p>



<div style="height:30px" class="wp-block-spacer"></div>



<h3 class="wp-block-heading">[余談1] 右再帰とは？</h3>



<p>「左再帰があるなら、右再帰な文法もあるんじゃね？」と思った人もいると思います。</p>



<p>想像の通り、右再帰もあります。具体的には、\( \textcolor{red}{A} \to \alpha \textcolor{blue}{A} \) の形の規則を右再帰と呼び<span class="footnote_referrer"><a tabindex="0" onclick="footnote_moveToReference_17270_9('footnote_plugin_reference_17270_9_1');" onkeypress="footnote_moveToReference_17270_9('footnote_plugin_reference_17270_9_1');" ><sup id="footnote_plugin_tooltip_17270_9_1" class="footnote_plugin_tooltip_text">[1]</sup></a><span id="footnote_plugin_tooltip_text_17270_9_1" class="footnote_tooltip">日本語で説明すると、<strong><span style="text-decoration: underline;"><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-red-color">生成元の非終端記号</mark></span></strong>と<strong><span style="text-decoration: underline;"><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-blue-color">生成先の文字列の終端</mark></span></strong>が同じになっている規則が右再帰です。</span></span>、右再帰な規則が含まれている文法のことを右再帰文法と呼びます。（左再帰の時と同じく \( \alpha \not = \varepsilon \)）</p>



<p>右再帰文法も、左再帰文法と同じように規則の核部分に加えて再帰をストップする規則の形 \( A \to \beta \) が含まれているのが特徴です。</p>



<h3 class="wp-block-heading">[余談2] 間接的な左(右)再帰</h3>



<p>下の文法\[<br>\textcolor{red}{A \to Bb, \ \ \ B \to Aa} , \ \ \  A \to \alpha<br>\]のように、見た目的には左再帰になっていないものの、規則を適用していくと、\[<br>\textcolor{red}{A} \xrightarrow{A \to Bb} Bb \xrightarrow{B \to Aa} \textcolor{red}{A}ab<br>\]のように左再帰な形が出てくる規則のことを、<strong><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-red-color">間接左再帰</mark></strong>と呼びます<span class="footnote_referrer"><a tabindex="0" onclick="footnote_moveToReference_17270_9('footnote_plugin_reference_17270_9_2');" onkeypress="footnote_moveToReference_17270_9('footnote_plugin_reference_17270_9_2');" ><sup id="footnote_plugin_tooltip_17270_9_2" class="footnote_plugin_tooltip_text">[2]</sup></a><span id="footnote_plugin_tooltip_text_17270_9_2" class="footnote_tooltip">一方、見た目的に明らかな左再帰の形 \( \textcolor{red}{A} \to \textcolor{red}{A} \alpha \) をしている左再帰のことを、直接左再帰と呼ぶこともあります。</span></span>。</p>



<p>同じように下の文法\[<br>\textcolor{blue}{A \to bB, \ \ \ B \to aA} , \ \ \  A \to \alpha<br>\]のように、見た目的には右再帰になっていないものの、規則を適用していくと、\[<br>\textcolor{blue}{A} \xrightarrow{A \to bB} bB \xrightarrow{B \to aA} ba \textcolor{blue}{A}<br>\]のように右再帰な形が出てくる規則のことを、<strong><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-blue-color">間接右再帰</mark></strong>と呼びます<span class="footnote_referrer"><a tabindex="0" onclick="footnote_moveToReference_17270_9('footnote_plugin_reference_17270_9_3');" onkeypress="footnote_moveToReference_17270_9('footnote_plugin_reference_17270_9_3');" ><sup id="footnote_plugin_tooltip_17270_9_3" class="footnote_plugin_tooltip_text">[3]</sup></a><span id="footnote_plugin_tooltip_text_17270_9_3" class="footnote_tooltip">一方、見た目的に明らかな右再帰の形 \( \textcolor{blue}{A} \to \alpha \textcolor{blue}{A}  \) が含まれている場合、直接右再帰と呼ぶこともあります。</span></span>。</p>



<p>※ 今回の記事では、\( A \to A \alpha \) の形が出てくる直接的な左再帰の除去だけについて説明します。（間接的な左再帰の除去は本記事では割愛します。）</p>







<div style="height:50px" class="wp-block-spacer"></div>



<h2 class="wp-block-heading">2. 左再帰文法の問題点</h2>


<p><span>左再帰が含まれている文法（左再帰文法）の最大の問題点は、絶対にLL(1)文法とはならないからです。</span>言い換えると、左再帰が含まれている文法は、<span  style="background-image:linear-gradient(to bottom,transparent 0%,#FFF387 0%);" class="dbp-e-marker-animation red">1文字先読みすることで後戻りなしに構文解析することができません</span>。</p>


<p>LL(1)文法にならない理由を具体例を踏まえてみていきましょう。</p>



<p>例えば、次の左再帰規則\[<br>A \to Aa , \ \ A \to b<br>\]を持つ文法があったとします。（出発記号 \( A \)）</p>



<p>ここで、もしLL(1)文法であれば、1文字先読みするだけで \( A \to Aa \), \( A \to b \) のどちかを判別することができますよね。</p>



<p>しかしこの2つの規則は、</p>



<ul class="wp-block-list"><li>\( A \to \textcolor{red}{A} a \)：生成先の先頭 \( A \) は最終的に \( A \to b \) により \( b \) になる</li><li>\( A \to \textcolor{ded}{b} \) ：生成先の先頭 \( \textcolor{red}{b} \) である</li></ul>



<p>ため、1文字先読みしたとしても、どちらの規則を適用すればよいかわかりません。</p>



<h3 class="wp-block-heading">厳密に証明してみる</h3>



<p>[お知らせ] 証明で使うDirector集合・First集合・Follow集合の解説は<a rel="noreferrer noopener" href="https://www.momoyama-usagi.com/entry/info-compiler3" data-type="URL" target="_blank">こちら</a>で行っています。</p>



<p>もっと厳密に、Director集合を使って左再帰規則\[<br>A \to A \alpha , \ \ A \to \beta<br>\]がLL(1)文法でないことを示してみましょう。</p>



<p>まず、生成規則 \( \textcolor{magenta}{A} \to \textcolor{deepskyblue}{Aa} \) に関するDirector集合 \( \mathrm{Director} ( \textcolor{magenta}{A} , \textcolor{deepskyblue}{A \alpha} ) \) は、\[\begin{align*}<br>\mathrm{Director} ( \textcolor{magenta}{A} , \textcolor{deepskyblue}{A \alpha} ) &amp; = \mathrm<br>{First} (  \textcolor{deepskyblue}{A \alpha} )<br>\\ &amp; =  \mathrm{First} (  A  ) <br>\\ &amp; =  \mathrm{First} (  \beta  ) <br>\end{align*}\]と計算できます。</p>



<p>※ \( \varepsilon \notin \mathrm{First} ( A \alpha) = \mathrm{First} ( \beta ) \) の条件を仮定</p>



<div style="height:26px" class="wp-block-spacer"></div>



<p>また、 \( \textcolor{magenta}{A} \to \textcolor{deepskyblue}{ \beta } \) に関するDirector集合は、 \( \varepsilon  \notin  \mathrm{First} ( \beta ) \) のとき\[\begin{align*}<br>&amp; = \mathrm{First} (\textcolor{deepskyblue}{A \alpha} )<br>\\ &amp; = \mathrm{First} (A)<br>\\ &amp; = \mathrm{First} ( \beta )<br>\end{align*}\]と計算できます。</p>



<p>※ \( \varepsilon \notin \mathrm{First} ( \beta ) \) の条件を仮定</p>



<div style="height:33px" class="wp-block-spacer"></div>



<p>よって、\( \varepsilon \notin \mathrm{First} ( \beta ) \) のときに\[<br>\mathrm{Director} ( A , A \alpha ) \cap \mathrm{Director} ( A , \beta ) = \mathrm{First} ( \beta )<br>\]が成立するため、LL(1)文法ではない。</p>



<p>※ ほんの一部の条件に対してでもDirector集合の積集合が \( \phi \) 以外になったらLL(1)文法ではない。</p>



<h3 class="wp-block-heading">右再帰文法は大丈夫なの？</h3>



<p>右再帰文法（生成規則に右再帰が含まれている）だからといって絶対にLL(1)文法ではなくなるとは限りません。</p>



<p>例えば、\[<br>A \to a A , \ \ \ A \to b<br>\]のような文法は \( A \to aA \) が含まれているため右再帰文法ですが、</p>



<ul class="wp-block-list"><li>\( A \to \textcolor{red}{a} A  \)：生成先の先頭 \( A \) は \( a \) である</li><li>\( A \to \textcolor{blue}{b}  \) ：生成先の先頭 \( A \) は \( b \) である</li></ul>



<p>のため、生成先の先頭文字を見るだけで \( A \to aA \), \( A \to b \) のどちらを適用すべきかが一意に定まりますね。そのため、LL(1)文法と言えます<span class="footnote_referrer"><a tabindex="0" onclick="footnote_moveToReference_17270_9('footnote_plugin_reference_17270_9_4');" onkeypress="footnote_moveToReference_17270_9('footnote_plugin_reference_17270_9_4');" ><sup id="footnote_plugin_tooltip_17270_9_4" class="footnote_plugin_tooltip_text">[4]</sup></a><span id="footnote_plugin_tooltip_text_17270_9_4" class="footnote_tooltip">厳密に示したい場合は\[\begin{align*}\mathrm{Director} ( A, aA) \cap  \mathrm{Director} (A, b) &amp; = \mathrm{First} (a) \cap \mathrm{First} (b)\\ &amp; = \{ a \} \cap \{ b \}\\ &amp; =&nbsp;&#x2026; <span class="footnote_tooltip_continue"  onclick="footnote_moveToReference_17270_9('footnote_plugin_reference_17270_9_4');">Continue reading</span></span></span>。</p>



<div style="height:50px" class="wp-block-spacer"></div>



<h2 class="wp-block-heading">3. 左再帰の除去</h2>



<h3 class="wp-block-heading">(1) 左再帰除去の手順</h3>



<p>左再帰文法は、次の公式を使うことによって簡単に左再帰ではない文法に書き換えることができます。</p>


<div class='wp-block-dbp-frame l-frame-inner is-design-inline is-frame-style-default dbp-frame has-bgcolor'><div class="dbp-frame-title">左再帰の除去 (左再帰が1つの場合)</div><div class="dbp-frame-content has-content-gap">
<p>左再帰が含まれる規則\[<br>A \to A \textcolor{red}{\alpha} \ | \ \textcolor{blue}{\beta}<br>\]は、以下のように変形をすることで左再帰ではない等価な規則に変形できる。\[\begin{align*}<br>A &amp; \to\textcolor{blue}{\beta} \textcolor{green}{A'}  \\<br>\textcolor{green}{A'} &amp; \to \textcolor{red}{\alpha} \textcolor{green}{A'} \ | \ \varepsilon<br>\end{align*}\]※ 新たな非終端記号 \( \textcolor{green}{A'} \) を追加している。</p>

<p>ここで、 \( \textcolor{red}{\alpha} \), \( \textcolor{blue}{\beta} \) は下の3つの条件を満たす非終端記号と終端記号が並んだ文字列である。</p>

<ul class="wp-block-list"><li>\( \textcolor{red}{\alpha} \not = \varepsilon \)</li><li>\( \textcolor{blue}{\beta} \) の先頭文字は \( B \) 以外である。<br>（先頭以外であれば \( \textcolor{blue}{\beta} \) の中に \( B \) が含まれていてもOK）</li><li>\( \textcolor{red}{\alpha}\), \( \textcolor{blue}{\beta}\) は非終端記号だけ、終端記号だけで構成されていてもOK</li></ul>

<div style="height:37px" class="wp-block-spacer"></div>

<p>[注意]</p>

<p>※1. 左再帰に関係がない非終端記号（上の例の場合は \( A \) 以外）から始まる生成規則からはそのままでOK。<br>※2. 変形後は非終端記号 \( A' \) が増える点に注意！<br>※3. \( \beta = \varepsilon \) の場合は\[<br>A \to \alpha A \ | \ \varepsilon<br>\]と置き換えるだけで左再帰の除去が可能。（非終端記号が増えない）</p>
</div></div>


<p><strong>[公式導出]</strong> (やみくもに丸暗記するのではなく、導出過程を理解してから覚えましょう！)</p>



<p>まず最初に左再帰が含まれる規則\[<br>A \to A \alpha \ | \ \beta<br>\]にはどのような文字列が含まれるかを書きだしてみましょう。</p>



<figure class="wp-block-image aligncenter size-large"><img width="1024" height="366" src="https://www.momoyama-usagi.com/wp-content/uploads/konpai4-2-1024x366.gif" alt="" class="wp-image-17413" srcset="https://www.momoyama-usagi.com/wp-content/uploads/konpai4-2-1024x366.gif 1024w, https://www.momoyama-usagi.com/wp-content/uploads/konpai4-2-300x107.gif 300w, https://www.momoyama-usagi.com/wp-content/uploads/konpai4-2-768x275.gif 768w, https://www.momoyama-usagi.com/wp-content/uploads/konpai4-2-1536x549.gif 1536w" /></figure>



<p>すると、</p>



<ul class="wp-block-list"><li>\( \beta \)</li><li>\( \beta \alpha \)</li><li>\( \beta \alpha \alpha \)</li><li>\( \beta \alpha \alpha \alpha \)</li></ul>



<p>のように、\( \beta \) が1文字来たあとに \( \alpha \) が連続するような文字列\[<br>\beta \underbrace{ \alpha \alpha \alpha \cdots }_{\mathrm{0 \ 回以上繰り返し}}<br>\]が当てはまることがわかりますね。</p>



<p>つまり、左再帰の規則を書き換える際には、左再帰ではない規則で\[<br>\beta \underbrace{ \alpha \alpha \alpha \cdots }_{\mathrm{0 \ 回以上繰り返し}}<br>\]となる文字列を表せればOKです。</p>



<div style="height:43px" class="wp-block-spacer"></div>



<p>ここからは、左再帰規則\[<br>A \to A \alpha \ | \ \beta<br>\]を左再帰でない規則に書き換えるために文字列\[<br>\textcolor{red}{\beta} \textcolor{blue}{ \underbrace{ \alpha \alpha \alpha \cdots }_{\mathrm{0 \ 回以上繰り返し}} }<br>\]を <mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-red-color">[ア] \( \beta \) の部分</mark>と <mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-blue-color">[イ] \( \alpha \) の繰り返し部分</mark>に分けます。</p>



<p><strong><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-red-color">[ア] \( \beta \) の部分</mark></strong></p>



<p>\( \beta \) の部分は1回だけ \( \beta \) を出力するために新しい非終端記号 \( A' \) を使って\[<br>\textcolor{red}{A \to \beta A'}<br>\]とします。</p>



<div style="height:21px" class="wp-block-spacer"></div>



<p><strong><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-blue-color">[イ] 0回以上の \( \alpha \) 繰り返しの部分</mark></strong></p>


<p><span>つぎに、\( A' \) の部分で0回以上の \( \alpha \) の繰り返しを左再帰を使わずに表します。ここで<span  style="background-image:linear-gradient(to bottom,transparent 0%,#FFF387 0%);" class="dbp-e-marker-animation red">左再帰は使ったらダメ</span>だけど、<span  style="background-image:linear-gradient(to bottom,transparent 0%,#FFF387 0%);" class="dbp-e-marker-animation blue">右再帰を使ったらダメとは一言も言っていない</span>点が重要です。</span></p>


<p>そのため、0回以上の \( \alpha \) の繰り返しは右再帰\[<br>\textcolor{blue}{ A' \to \alpha A' \ | \ \varepsilon }<br>\]を使って表現します。</p>



<p>※ \( \alpha \) は0回以上の繰り返し（＝空文字も含める）なので、右再帰をストップする条件は \( A' \to \varepsilon \) となります。</p>



<div style="height:21px" class="wp-block-spacer"></div>



<p><strong>(a), (b)をまとめる</strong></p>



<p>あとは <mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-red-color">[ア]</mark> と<mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-blue-color"> [イ]</mark> の規則を合わせるだけで、左再帰の除去をした（元の文法と等価な）文法の完成です！\[\begin{align*}<br>\textcolor{red}{A} &amp; \textcolor{red}{\to \beta A'}  \\<br>\textcolor{blue}{A'} &amp; \textcolor{blue}{\to \alpha A' \ | \ \varepsilon}<br>\end{align*}\]</p>



<div style="height:21px" class="wp-block-spacer"></div>



<h3 class="wp-block-heading">(2) 例題で確認 [左再帰の除去]</h3>


<div class='wp-block-dbp-frame l-frame-float is-design-onframe is-frame-style-default dbp-frame has-bgcolor'><div class="dbp-frame-title">例題1</div><div class="dbp-frame-content has-content-gap">
<p>次の文法 \( G \) がある。\[<br>G = \left( \ \{ S,A,B \} \ , \  \{ a,b,c,d \} \ , \  P \ , \ S \ \right)<br>\]\[\begin{align*}<br>P = \{ \ \ \ \ S  &amp;  \to AaB \\ A &amp;  \to Acb \ | \ b \\ B &amp;  \to Sc \ | \ d \ \ \ \ \ \ \ \}<br>\end{align*}<br>\]つぎの(1), (2)の問いに答えなさい。</p>

<p>(1) \( G \) は左再帰文法である。その理由を答えなさい。<br>(2) \( G \) に対して左再帰の除去を適用し、左再帰ではない文法 \( G' \) に書き換えなさい。</p>
</div></div>


<p><strong>[解説1]</strong></p>



<p>(1)</p>



<p>生成規則 \( \textcolor{red}{A} \to \textcolor{blue}{A}cb \) において、<strong><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-red-color">生成元の非終端記号</mark></strong>と<mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-blue-color"><strong>生成先の1文字目(先頭文字)</strong></mark>が一致しているため。</p>



<div style="height:50px" class="wp-block-spacer"></div>



<p>(2)</p>



<p>左再帰が発生している部分について、下のように \( \textcolor{red}{\alpha} \), \( \textcolor{blue}{\beta} \) をおきます。\[<br>A \to A \textcolor{red}{ \underbrace{ cb }_{\alpha} } \ | \ \textcolor{blue}{ \underbrace{ b }_{ \beta } }<br>\]</p>



<p>あとは、左再帰の除去規則を使って規則を書き換えればOKです。\[\begin{align*}<br>A &amp; \to \textcolor{blue}{ \underbrace{ b }_{ \beta } }   A' \\<br>A' &amp; \to \textcolor{red}{ \underbrace{ cb }_{\alpha} } A' \ | \ \varepsilon<br>\end{align*}\]</p>



<p>左再帰の発生に関係のない非終端記号（今回の場合は \( A \) 以外）の生成規則\[<br>S \to AaB , \ \ \ B \to Sc \ | \ d<br>\]はそのままでOKなので、文法 \( G \) と等価な左再帰ではない文法 \( G' \) は、\[<br>G' = \left( \ \{ S,A, \textcolor{magenta}{A'} ,B \} \ , \  \{ a,b,c,d \} \ , \  \textcolor{magenta}{P'} \ , \ S \ \right)<br>\]\[\begin{align*}<br>\textcolor{magenta}{P'} = \{ \ \ \ \ S  &amp;  \to AaB \\ <br>A &amp; \to \textcolor{blue}{ b }  A' \\<br>A' &amp; \to \textcolor{red}{ cb } A' \ | \ \varepsilon<br>\\  B &amp;  \to Sc \ | \ d \ \ \ \ \ \ \ \}<br>\end{align*}<br>\]となります。</p>



<p>※ <strong><mark style="background-color:rgba(0, 0, 0, 0);color:#f05bff" class="has-inline-color">ピンク色を付けて書いた部分</mark></strong>は忘れがちなので要注意！</p>



<div style="height:21px" class="wp-block-spacer"></div>



<h3 class="wp-block-heading">(3) 左再帰が複数含まれる場合</h3>



<p>下のように左再帰が複数含まれる規則\[\begin{align*}<br>\textcolor{magenta}{A} &amp; \textcolor{magenta}{\to A \alpha_1 \ | \ A \alpha_2 \ | \ \cdots} \\\<br>\textcolor{deepskyblue}{A} &amp; \textcolor{deepskyblue}{\to \beta_1 \ | \ \beta_2 \ | \ \cdots}<br>\end{align*}\]であっても、左再帰の適用が可能です。</p>



<p><strong>[色の意味]</strong></p>



<p><mark style="background-color:rgba(0, 0, 0, 0);color:#fb46ff" class="has-inline-color">桃色の規則 … 左再帰の核となる \( A \to A \alpha_k \) が含まれた規則</mark><br><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-light-blue-color">水色の規則 … 左再帰をストップする規則 \( A \to \beta_k \) が含まれた規則</mark><span class="footnote_referrer"><a tabindex="0" onclick="footnote_moveToReference_17270_9('footnote_plugin_reference_17270_9_5');" onkeypress="footnote_moveToReference_17270_9('footnote_plugin_reference_17270_9_5');" ><sup id="footnote_plugin_tooltip_17270_9_5" class="footnote_plugin_tooltip_text">[5]</sup></a><span id="footnote_plugin_tooltip_text_17270_9_5" class="footnote_tooltip">\( A \) が生成元で、生成先の先頭が \( A \) で始まらない（つまり桃色の規則に当てはまらない）規則は全て水色の規則に含まれる。（ \( A \to bA \)&nbsp;&#x2026; <span class="footnote_tooltip_continue"  onclick="footnote_moveToReference_17270_9('footnote_plugin_reference_17270_9_5');">Continue reading</span></span></span></p>



<p>左再帰が含まれていない \( A \to A \alpha_k \) が含まれた規則</p>


<div class='wp-block-dbp-frame l-frame-inner is-design-inline is-frame-style-default dbp-frame has-bgcolor'><div class="dbp-frame-title">左再帰の除去 (左再帰が複数出てくる場合)</div><div class="dbp-frame-content has-content-gap">
<p>左再帰が複数含まれる規則\[\begin{align*}<br>\textcolor{magenta}{A} &amp; \textcolor{magenta}{\to A \alpha_1 \ | \ A \alpha_2 \ | \ \cdots \ | \ A \alpha_m } \\\<br>\textcolor{deepskyblue}{A} &amp; \textcolor{deepskyblue}{\to \beta_1 \ | \ \beta_2 \ | \ \cdots \ | \ \beta_n }<br>\end{align*}\]でも、以下のように変形をすることで左再帰ではない等価な規則に変形できる。\[\begin{align*}<br>\textcolor{deepskyblue}{A} &amp; \textcolor{deepskyblue}{ \to \beta_1 A' \ | \ \beta_2 A' \ | \ \cdots \ |  \ \beta_n A'}  \\<br>\textcolor{magenta}{A'} &amp; \textcolor{magenta}{ \to \alpha_1 A' \ | \ \alpha_2 A'  \  | \  \cdots \  |  \ \alpha_m A'  \  |   \ \varepsilon }<br>\end{align*}\]</p>

<p>ここで、 \( \alpha_1 \), \( \alpha_2 \), …, \( \beta_1 \) , \( \beta_2 \), … は下の3つの条件を満たす非終端記号と終端記号が並んだ文字列である。</p>

<ul class="wp-block-list"><li>\( \alpha_1 \) , \( \alpha_2 \), … は空文字以外であれば何でもOK </li><li>\( \beta_1 \), \( \beta_2 \), … の先頭文字は \( B \) 以外である。<br>（先頭以外であれば \( \beta \) の中に \( B \) が含まれていてもOK）</li><li>\( \alpha_1 \), \( \alpha_2 \), …, \( \beta_1 \) , \( \beta_2 \), … は非終端記号だけ、終端記号だけで構成されていてもOK</li></ul>

<div style="height:37px" class="wp-block-spacer"></div>

<p>[注意]</p>

<p>※1. 左再帰に関係がない非終端記号（上の例の場合は \( A \) 以外）から始まる生成規則からはそのままでOK。<br>※2. 変形後は非終端記号 \( A' \) が増える点に注意！</p>
</div></div>


<div style="height:21px" class="wp-block-spacer"></div>



<h3 class="wp-block-heading">(4) 例題で確認  [左再帰が複数含まれる場合]</h3>


<div class='wp-block-dbp-frame l-frame-float is-design-onframe is-frame-style-default dbp-frame has-bgcolor'><div class="dbp-frame-title">例題2</div><div class="dbp-frame-content has-content-gap">
<p>次の文法 \( G \) がある。\[<br>G = \left( \ \{ S,A,B, C \} \ , \  \{ a,b,c,d \} \ , \  P \ , \ S \ \right)<br>\]\[\begin{align*}<br>P = \{ \ \ \ \ <br>S  &amp;  \to aBc \\ <br>A &amp;  \to bB \ | \ aA \\ <br>B &amp;  \to BaA \ | \ BS \ | \ aa \ | \ dBa \ | \ Cd  \\ <br>C &amp; \to cc \ | \ ccc <br>\ \ \ \ \ \ \ \ \ \  \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \}<br>\end{align*}<br>\]この文法 \( G \) に対して、左再帰の除去を適用することで、\( G \) と等価な左再帰ではない文法 \( G' \) に書き換えなさい。</p>
</div></div>


<p>左再帰の直接的な原因は \( \textcolor{magenta}{B \to BaA} \), \( \textcolor{magenta}{B \to BS}  \) の2つ（共に \( B \) が生成元の規則）ですね。</p>



<p>ここで、\( B \) が生成元の規則は先ほどの2つのほかに \( \textcolor{deepskyblue}{B \to aa} \), \( \textcolor{deepskyblue}{B \to dBa} \), \( \textcolor{deepskyblue}{B \to Cd} \) の3つがあります。</p>



<p>なので、文字列を\[\begin{align*}<br>B &amp; \to B \underbrace{ aA }_{ \alpha_1 } \ | \ B  \underbrace{ S }_{ \alpha_2 } \\ <br>B &amp; \to  \underbrace{ aa }_{ \beta_1 } \ | \ \underbrace{ dBa }_{ \beta_2 } \ | \ \underbrace{ Cd }_{ \beta_3 }<br>\end{align*}\]とおきましょう。</p>



<p>あとは、左再帰の除去公式で置き換えてあげればOKです！\[\begin{align*}<br>B &amp; \to \underbrace{ aa }_{ \beta_1 } B' \ | \ \underbrace{ dBa }_{ \beta_2 } B' \ | \ \underbrace{ Cd }_{ \beta_3 } B'  \\<br>B' &amp; \to \underbrace{ aA }_{ \alpha_1 } B' \ | \  \underbrace{ S }_{ \alpha_2 } B' \ | \ \varepsilon<br>\end{align*}\]</p>



<p>左再帰の発生に関係のない非終端記号（今回の場合は \( A \) 以外）の生成規則はそのままでOKなので、文法 \( G \) と等価かつ左再帰ではない文法 \( G' \) は、\[<br>G' = \left( \ \{ S,A, B, \textcolor{magenta}{B'} \} \ , \  \{ a,b,c,d \} \ , \  P' \ , \ S \ \right)<br>\]\[\begin{align*}<br>P' = \{ \ \ \ \ <br>S  &amp;  \to aBc \\ <br>A &amp;  \to bB \ | \ aA \\ <br>\textcolor{magenta}{B} &amp; \textcolor{magenta}{\to aa B' \ | \ dBaB' \ | \ CdB'}  \\<br>\textcolor{magenta}{B'} &amp; \textcolor{magenta}{ \to aAB' \ | \ S B' \ | \ \varepsilon } \\<br>C &amp; \to cc \ | \ ccc <br>\ \ \ \ \ \ \ \ \ \  \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \}<br>\end{align*}<br>\]となります。（<strong><mark style="background-color:rgba(0, 0, 0, 0);color:#f05bff" class="has-inline-color">ピンク色を付けて書いた部分</mark></strong>が変更箇所）</p>



<div style="height:99px" class="wp-block-spacer"></div>



<h2 class="wp-block-heading">5. 練習問題</h2>



<p>それでは、今回習った左再帰の除去について2問の練習問題を用意しました。</p>



<h3 class="wp-block-heading">練習1. 左再帰が1つの場合</h3>


<div class='wp-block-dbp-frame l-frame-float is-design-onframe is-frame-style-default dbp-frame has-bgcolor'><div class="dbp-frame-title">練習1</div><div class="dbp-frame-content has-content-gap">
<p>次の文法 \( G \) がある。\[<br>G = \left( \ \{ S,A,B \} \ , \  \{ a,b,c \} \ , \  P \ , \ S \ \right)<br>\]\[\begin{align*}<br>P = \{ \ \ \ \ <br>S  &amp;  \to Sab \ | \ c \\ <br>A &amp;  \to BaA \ | \ a \\ <br>B &amp;  \to cA \ | \ bb <br>\ \ \ \ \ \ \ \}<br>\end{align*}<br>\]つぎの(1), (2)の問いに答えなさい。</p>

<p>(1) \( G \) は左再帰文法である。その理由を答えなさい。<br>(2) \( G \) に対して左再帰の除去を適用し、左再帰ではない文法 \( G' \) に書き換えなさい。</p>
</div></div>


<div style="height:42px" class="wp-block-spacer"></div>



<h3 class="wp-block-heading">練習2. 左再帰が複数ある場合</h3>


<div class='wp-block-dbp-frame l-frame-float is-design-onframe is-frame-style-default dbp-frame has-bgcolor'><div class="dbp-frame-title">練習2</div><div class="dbp-frame-content has-content-gap">
<p>次の文法 \( G \) がある。\[<br>G = \left( \ \{ S,A,B, C \} \ , \  \{ a,b,c,d \} \ , \  P \ , \ S \ \right)<br>\]\[\begin{align*}<br>P = \{ \ \ \ \ <br>S  &amp;  \to dS \ | \ bbab \\ <br>A &amp;  \to aA \ | \ bB \ | \ cC \ | \ d \\ <br>B &amp;  \to b \ | \ Sb \\<br>C &amp; \to Cab \ | \ Cb \ | \ CBS \ | \ cc \ | \ Ad <br>\ \ \ \ \ \}<br>\end{align*}<br>\]この文法 \( G \) に対して、左再帰の除去を適用することで、\( G \) と等価な左再帰ではない文法 \( G' \) に書き換えなさい。</p>
</div></div>


<div style="height:99px" class="wp-block-spacer"></div>



<h2 class="wp-block-heading">6. 練習問題の答え</h2>



<h3 class="wp-block-heading">解答1. 左再帰が1つの場合</h3>



<p>(1)</p>



<p>生成規則 \( \textcolor{red}{S} \to \textcolor{blue}{S} ab \) において、<strong><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-red-color">生成元の非終端記号</mark></strong>と<mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-blue-color"><strong>生成先の1文字目(先頭文字)</strong></mark>が一致しているため。</p>



<div style="height:40px" class="wp-block-spacer"></div>



<p>(2)</p>



<p>まず、左再帰が発生している \( S \) が生成元の規則に対して、\( \textcolor{red}{\alpha} \), \( \textcolor{blue}{\beta} \) を以下のようにおく。\[<br>S   \to S \textcolor{red}{ \underbrace{ ab }_{\alpha} } \ | \ \textcolor{blue}{ \underbrace{ c }_{\beta} } <br>\]</p>



<p>あとは、左再帰の除去規則を使って規則を書き換えればOK。\[\begin{align*}<br>S &amp; \to \textcolor{blue}{ \underbrace{  c  }_{ \beta } }   S' \\<br>S' &amp; \to \textcolor{red}{ \underbrace{ ab }_{\alpha} } S' \ | \ \varepsilon<br>\end{align*}\]</p>



<p>左再帰の発生に関係のない非終端記号（今回の場合は \( S \) 以外）の生成規則はそのままでOKなので、文法 \( G \) と等価な左再帰ではない文法 \( G' \) は、\[<br>G' = \left( \ \{ S,A, \textcolor{magenta}{A'} ,B \} \ , \  \{ a,b,c,d \} \ , \  \textcolor{magenta}{P'} \ , \ S \ \right)<br>\]\[<br>\begin{align*}<br>P' = \{ \ \ \ \ <br>S &amp; \to \textcolor{blue}{ c } S' \\<br>S' &amp; \to \textcolor{red}{ ab } S' \ | \ \varepsilon \\<br>A &amp;  \to BaA \ | \ a \\ <br>B &amp;  \to cA \ | \ bb <br>\ \ \ \ \ \ \ \}<br>\end{align*}<br>\]となる。</p>



<div style="height:42px" class="wp-block-spacer"></div>



<h3 class="wp-block-heading">解答2. 左再帰が複数の場合</h3>



<p>左再帰の直接的な原因は \( \textcolor{magenta}{C \to Cab} \), \( \textcolor{magenta}{C \to Cb}  \), \( \textcolor{magenta}{C \to CBS}  \) の3つ（共に \( C \) が生成元の規則）。</p>



<p>また、\( C \) が生成元の規則は先ほどの3つのほかに \( \textcolor{deepskyblue}{C \to cc} \), \( \textcolor{deepskyblue}{C \to Ad} \) の2つがある。</p>



<p>なので、\( \alpha_1 \), \( \alpha_2 \), \( \alpha_3 \), \( \beta_1 \), \( \beta_2 \) を用いて文字列を\[\begin{align*}<br>C &amp; \to C \underbrace{ ab }_{ \alpha_1 } \ | \ C  \underbrace{ b }_{ \alpha_2 } \ | \ C  \underbrace{ BS }_{ \alpha_3 } \\ <br>C &amp; \to  \underbrace{ cc }_{ \beta_1 } \ | \ \underbrace{ Ad }_{ \beta_2 } <br>\end{align*}\]とおく。</p>



<p>あとは、左再帰の除去公式で置き換えるだけ。\[\begin{align*}<br>C &amp; \to \underbrace{ cc }_{ \beta_1 } C' \ | \ \underbrace{ Ad }_{ \beta_2 } C'  \\<br>C' &amp; \to \underbrace{ ab }_{ \alpha_1 } C' \ | \  \underbrace{ b }_{ \alpha_2 } C' \ | \   \underbrace{ BS }_{ \alpha_3 } C' \ | \ \varepsilon<br>\end{align*}\]</p>



<p>左再帰の発生に関係のない非終端記号（今回の場合は \( S \) 以外）の生成規則はそのままでOKなので、文法 \( G \) と等価かつ左再帰ではない文法 \( G' \) は、\[<br>G' = \left( \ \{ S,A, B, C,  \textcolor{magenta}{C'} \} \ , \  \{ a,b,c,d \} \ , \  P' \ , \ S \ \right)<br>\]\[\begin{align*}<br>P' = \{ \ \ \ \ <br>S  &amp;  \to dS \ | \ bbab \\ <br>A &amp;  \to aA \ | \ bB \ | \ cC \ | \ d \\ <br>B &amp;  \to b \ | \ Sb \\<br>C &amp; \to cc C' \ | \ Ad C'  \\<br>C' &amp; \to ab  C' \ | \  b C' \ | \   BS C' \ | \ \varepsilon<br>\ \ \ \ \ \}<br>\end{align*}\]となります。</p>



<div style="height:99px" class="wp-block-spacer"></div>



<h2 class="wp-block-heading">7. さいごに</h2>



<p>今回は、左再帰が含まれる文法（左再帰文法）と、左再帰の除去について説明していきました。</p>



<p>最後に左再帰の除去公式をおさらいしておきましょう！</p>



<figure class="wp-block-image aligncenter size-large"><img width="1024" height="322" src="https://www.momoyama-usagi.com/wp-content/uploads/konpai4-3-1024x322.gif" alt="" class="wp-image-17594" srcset="https://www.momoyama-usagi.com/wp-content/uploads/konpai4-3-1024x322.gif 1024w, https://www.momoyama-usagi.com/wp-content/uploads/konpai4-3-300x94.gif 300w, https://www.momoyama-usagi.com/wp-content/uploads/konpai4-3-768x242.gif 768w, https://www.momoyama-usagi.com/wp-content/uploads/konpai4-3-1536x483.gif 1536w" /><figcaption>左再帰除去の公式確認</figcaption></figure>



<p>左再帰文法の問題点や、左再帰の除去について少しでも理解していただけたのであれば本当にうれしいです！</p>
<div class="speaker-mute footnotes_reference_container"> <div class="footnote_container_prepare"><p><span tabindex="0" class="footnote_reference_container_label pointer">注釈</span><span tabindex="0" class="footnote_reference_container_collapse_button" style="display: none;">[<a id="footnote_reference_container_collapse_button_17270_9">+</a>]</span></p></div> <div id="footnote_references_container_17270_9"><table class="footnotes_table footnote-reference-container"><caption class="accessibility">注釈</caption> <tbody> 

<tr class="footnotes_plugin_reference_row"> <th scope="row" class="footnote_plugin_index_combi pointer"  onclick="footnote_moveToAnchor_17270_9('footnote_plugin_tooltip_17270_9_1');"><a id="footnote_plugin_reference_17270_9_1" class="footnote_backlink"><span class="footnote_index_arrow">&#8593;</span>1</a></th> <td class="footnote_plugin_text">日本語で説明すると、<strong><span style="text-decoration: underline;"><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-red-color">生成元の非終端記号</mark></span></strong>と<strong><span style="text-decoration: underline;"><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-blue-color">生成先の文字列の終端</mark></span></strong>が同じになっている規則が右再帰です。</td></tr>

<tr class="footnotes_plugin_reference_row"> <th scope="row" class="footnote_plugin_index_combi pointer"  onclick="footnote_moveToAnchor_17270_9('footnote_plugin_tooltip_17270_9_2');"><a id="footnote_plugin_reference_17270_9_2" class="footnote_backlink"><span class="footnote_index_arrow">&#8593;</span>2</a></th> <td class="footnote_plugin_text">一方、見た目的に明らかな左再帰の形 \( \textcolor{red}{A} \to \textcolor{red}{A} \alpha \) をしている左再帰のことを、直接左再帰と呼ぶこともあります。</td></tr>

<tr class="footnotes_plugin_reference_row"> <th scope="row" class="footnote_plugin_index_combi pointer"  onclick="footnote_moveToAnchor_17270_9('footnote_plugin_tooltip_17270_9_3');"><a id="footnote_plugin_reference_17270_9_3" class="footnote_backlink"><span class="footnote_index_arrow">&#8593;</span>3</a></th> <td class="footnote_plugin_text">一方、見た目的に明らかな右再帰の形 \( \textcolor{blue}{A} \to \alpha \textcolor{blue}{A}  \) が含まれている場合、直接右再帰と呼ぶこともあります。</td></tr>

<tr class="footnotes_plugin_reference_row"> <th scope="row" class="footnote_plugin_index_combi pointer"  onclick="footnote_moveToAnchor_17270_9('footnote_plugin_tooltip_17270_9_4');"><a id="footnote_plugin_reference_17270_9_4" class="footnote_backlink"><span class="footnote_index_arrow">&#8593;</span>4</a></th> <td class="footnote_plugin_text">厳密に示したい場合は\[\begin{align*}<br>\mathrm{Director} ( A, aA) \cap  \mathrm{Director} (A, b) &amp; = \mathrm{First} (a) \cap \mathrm{First} (b)<br>\\ &amp; = \{ a \} \cap \{ b \}<br>\\ &amp; = \phi<br>\end{align*}\]とすればOK。</td></tr>

<tr class="footnotes_plugin_reference_row"> <th scope="row" class="footnote_plugin_index_combi pointer"  onclick="footnote_moveToAnchor_17270_9('footnote_plugin_tooltip_17270_9_5');"><a id="footnote_plugin_reference_17270_9_5" class="footnote_backlink"><span class="footnote_index_arrow">&#8593;</span>5</a></th> <td class="footnote_plugin_text">\( A \) が生成元で、生成先の先頭が \( A \) で始まらない（つまり桃色の規則に当てはまらない）規則は全て水色の規則に含まれる。（ \( A \to bA \) のように、自身を生成する規則であっても生成先の先頭が \( A \) でない文法であれば当てはまるので注意。）</td></tr>

 </tbody> </table> </div></div>]]></content:encoded>
					
					<wfw:commentRss>https://www.momoyama-usagi.com/entry/info-compiler4/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>うさぎでもわかるコンパイラ　第3羽　First・Follow・Director集合とLL(1)文法の判定</title>
		<link>https://www.momoyama-usagi.com/entry/info-compiler3</link>
					<comments>https://www.momoyama-usagi.com/entry/info-compiler3#respond</comments>
		
		<dc:creator><![CDATA[ももうさ]]></dc:creator>
		<pubDate>Sun, 18 Sep 2022 17:42:54 +0000</pubDate>
				<category><![CDATA[コンパイラ(言語処理系)]]></category>
		<category><![CDATA[まとめシリーズ]]></category>
		<category><![CDATA[情報]]></category>
		<category><![CDATA[コンパイラ]]></category>
		<category><![CDATA[言語処理系]]></category>
		<guid isPermaLink="false">https://www.momoyama-usagi.com/?p=16248</guid>

					<description><![CDATA[こんにちは、ももやまです。 コンパイラ（言語処理系）の勉強をしていると、 LL(1)文法 First集合 Follow集合 Director集合 などの不思議な用語が出てきますよね。しかも、これらの定義（特にFirst集 [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>こんにちは、ももやまです。</p>



<p>コンパイラ（言語処理系）の勉強をしていると、</p>



<ul class="wp-block-list"><li>LL(1)文法</li><li>First集合</li><li>Follow集合</li><li>Director集合</li></ul>



<p>などの不思議な用語が出てきますよね。しかも、これらの定義（特にFirst集合やFollow集合）の定義は少し難解です。</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow"><p>文法 \( G = ( V_N, V_T, P, S ) \)に関して、記号列 \( \alpha \in ( V_N \cup V_T )^* \)、非終端記号 \(A \in V_T \) について、\( \mathrm{First} \ ( \alpha ) \), および \( \mathrm{Follow} \) は次のように定義される。\[<br>\mathrm{First} \ ( \alpha ) = \left\{  a \mid a \in V_T , \alpha  \overset{*}{\Rightarrow} a \cdots  \right\}<br>\]\[<br>\mathrm{Follow} \ ( A ) = \left\{  a \mid a \in V_T ,  S  \overset{*}{\Rightarrow} \cdots Aa \cdots \right\}<br>\]ただし \( \alpha \overset{*}{\Rightarrow} \varepsilon \) なら \( \varepsilon \in \mathrm{First} \ ( \alpha ) \) とする。</p><cite><a rel="noreferrer noopener" href="https://asasaki.cis.k.hosei.ac.jp/lect/compiler/2009A/Ex07-2.pdf" data-type="URL" target="_blank">コンパイラ補助資料　佐々木晃</a> より</cite></blockquote>



<div style="height:24px" class="wp-block-spacer"></div>



<p>そこで今回は、</p>



<ul class="wp-block-list"><li>LL(1)文法とはそもそも何か？</li><li>First, Follow, Director集合を求めて何がうれしいのか</li><li>First, Follow, Director集合の求め方</li></ul>



<p>の3点を中心に、LL(1)文法とFirst・Follow・Director集合のお勉強をしていきましょう。</p>


<div class='wp-block-dbp-frame l-frame-inner is-design-inline is-frame-style-default dbp-frame has-bgcolor'><div class="dbp-frame-title">文字表記に関する注意</div><div class="dbp-frame-content has-content-gap">
<p>本記事では特に指示がない限り、文章中に出てくる小文字・大文字・ギリシャ文字は</p>

<ul class="wp-block-list"><li>小文字 \( a \), \( b \), \( c \), \( d \), … → 終端記号</li><li>大文字 \( S \), \( A \), \( B \), \( C \), … → 非終端記号</li><li>\( \varepsilon \) → 空文字</li></ul>

<p>を表します。</p>
</div></div>


<div style="height:51px" class="wp-block-spacer"></div>



<h2 class="wp-block-heading">1. LL(1)文法とは</h2>



<p>ある文字列 \( \alpha \) が文法規則を満たすかどうかを一番単純に調べる方法は、下のように「出発記号 \( S \) から変換規則を総当たりで試していき、試した中に \( \alpha \) が含まれるか」を調べることです。</p>



<figure class="wp-block-image aligncenter"><img src="https://www.momoyama-usagi.com/wp-content/uploads/2021/05/20190906161619.gif" alt="f:id:momoyama1192:20190906161619g:plain" title="f:id:momoyama1192:20190906161619g:plain"/><figcaption>一番単純に文字列が文法規則を満たすか調べる方法</figcaption></figure>



<p>しかし、やみくもに総当たりで試す方法は、処理的にかなり無駄が発生してしまいます<span class="footnote_referrer"><a tabindex="0" onclick="footnote_moveToReference_16248_11('footnote_plugin_reference_16248_11_1');" onkeypress="footnote_moveToReference_16248_11('footnote_plugin_reference_16248_11_1');" ><sup id="footnote_plugin_tooltip_16248_11_1" class="footnote_plugin_tooltip_text">[1]</sup></a><span id="footnote_plugin_tooltip_text_16248_11_1" class="footnote_tooltip">&nbsp;&#x2026; <span class="footnote_tooltip_continue"  onclick="footnote_moveToReference_16248_11('footnote_plugin_reference_16248_11_1');">Continue reading</span></span></span>。</p>


<p>そこで、<span  style="background-image:linear-gradient(to bottom,transparent 0%,#FFF387 0%);" class="dbp-e-marker-animation y">構文解析をする際に1文字だけ先読みし、どの生成規則を使えばよいかを決めてから実際に変換していく</span>方法が考えられました。</p>
<p>このように、<span  style="background-image:linear-gradient(to bottom,transparent 0%,#FFF387 0%);" class="dbp-e-marker-animation blue">1文字だけ先読みすれば、文字列を後戻りすることなく構文解析ができる（文法を満たすか確認できる）文法</span>からなる文法のことを<span  style="background-image:linear-gradient(to bottom,transparent 0%,#FFF387 0%);" class="dbp-e-marker-animation blue">LL(1)文法</span>と呼びます<span class="footnote_referrer"><a tabindex="0" onclick="footnote_moveToReference_16248_11('footnote_plugin_reference_16248_11_2');" onkeypress="footnote_moveToReference_16248_11('footnote_plugin_reference_16248_11_2');" ><sup id="footnote_plugin_tooltip_16248_11_2" class="footnote_plugin_tooltip_text">[2]</sup></a><span id="footnote_plugin_tooltip_text_16248_11_2" class="footnote_tooltip">&nbsp;&#x2026; <span class="footnote_tooltip_continue"  onclick="footnote_moveToReference_16248_11('footnote_plugin_reference_16248_11_2');">Continue reading</span></span></span>。</p>


<div style="height:50px" class="wp-block-spacer"></div>



<p>LL(1)文法とは言えない文法（＝1文字だけ先読みするだけでは文字列を後戻りせずに構文解析ができない）文法の例も見てみましょう。</p>



<p>例えば、非終端記号（かつ出発記号） \( S \)、終端記号 \( a \), \( b \)、生成規則\[<br> S \to aaS , \ \ S \to abS , \ \ S \to b  <br>\]からなる文法規則があるとします。</p>



<p>この文法規則に \( \textcolor{red}{a} bab \) という文字列が当てはまるかどうかを1文字先読みで見ていきましょう。</p>



<p>しかし、1文字目 \( \textcolor{red}{a} \) が出てくる生成規則には、</p>



<ul class="wp-block-list"><li>\( S \to \textcolor{red}{a} aS \)</li><li>\( S \to \textcolor{red}{a} b S \)</li></ul>



<p>の2つがあるため、1文字先読みしただけでは \( S \to aaS \), \( S \to abS \) どちらの生成規則を適用すればいいかわかりません。 </p>



<div style="height:50px" class="wp-block-spacer"></div>


<p><span>この例から分かる通り、LL(1)文法かどうかは<span  style="background-image:linear-gradient(to bottom,transparent 0%,#FFF387 0%);" class="dbp-e-marker-animation y">文法の生成規則のみ</span>で決まります。</span></p>
<p><span>ここで、LL(1)文法を満たす生成規則であるかを機械的に確認する手法として導入されたのが</span>First・Follow・Director集合という概念なのです！</p>


<div style="height:50px" class="wp-block-spacer"></div>



<p>つぎの第2章からは、</p>



<ul class="wp-block-list"><li>実際にFirst, Follow, Director集合の求め方の解説</li><li>なぜ機械的にLL(1)文法を満たすのかがわかるのか</li></ul>



<p>の2点について解説していきます。</p>



<div style="height:50px" class="wp-block-spacer"></div>



<h2 class="wp-block-heading">2. First集合</h2>



<h3 class="wp-block-heading">(1) First 集合とはなにか</h3>



<p>First集合 \( \mathrm{First} ( \alpha ) \) は、「ある文字列 \( \textcolor{magenta}{\alpha} \) に対して<mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-light-blue-color">生成規則を適用して（複数回適用OK）</mark>全て<mark style="background-color:rgba(0, 0, 0, 0);color:#298e1a" class="has-inline-color">終端記号</mark>にした際に、<mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-light-orange-color">先頭（1文字目）に出てくる可能性がある文字</mark>を集めた集合」を表します。</p>



<p>数式で書くと、\[<br>\mathrm{First}  ( \textcolor{magenta}{\alpha} ) = \left\{  \textcolor{orange}{a} \mid \textcolor{orange}{a} \in \textcolor{green}{V_T} , \textcolor{magenta}{\alpha} \textcolor{deepskyblue}{\overset{*}{\Rightarrow}} \textcolor{orange}{a} \cdots  \right\}<br>\]となります。（色部分を日本語の説明に対応させています）</p>



<figure class="wp-block-image aligncenter size-full is-resized"><img src="https://www.momoyama-usagi.com/wp-content/uploads/konpai3-1.gif" alt="" class="wp-image-16277" width="421" height="424"/><figcaption>First集合のイメージ</figcaption></figure>



<p>例えば、\( \mathrm{First}  ( \alpha ) = \{ a, b, c\} \) の場合、\( \alpha \) に生成規則を適用していった際に出来る文字列の先頭（1文字目）が \( a \), \( b \), \( c \) のいずれかであることを表します。</p>



<div style="height:50px" class="wp-block-spacer"></div>



<h3 class="wp-block-heading">(2) First 集合で頭にいれておくべき公式</h3>



<p>※ 公式を丸暗記するのではなく、理屈を理解してから頭に入れましょう。</p>



<h4 class="wp-block-heading">規則1[R1]  First(a) … 終端記号1文字 \( a \) の場合 </h4>



<p>終端記号 \( a \) は、これ以上生成規則を適用することが出来ない文字を表すのでしたね。そのため、\( a \) はどう頑張っても他の文字に変換されることはありません。</p>



<p>よって、終端記号1文字 \( a \) のFirst集合の要素は終端記号 \( a \) だけとなります。\[<br>\mathrm{First} ( a ) = a<br>\]※ 空文字 \( \varepsilon \) のFirst集合は、\( \mathrm{First}  ( \varepsilon ) = \{ \varepsilon \} \) となります。言い換えると、\( \mathrm{First}  ( \alpha ) = \{ \varepsilon \} \) は、\( \alpha \) が空文字であることを表します。</p>



<p>※ 以後、この規則を用いた変換をする場合は  \( \overset{ \mathrm{R1} }{=} \) と = の上にR1（規則1）を用いていることを示します。</p>



<div style="height:40px" class="wp-block-spacer"></div>



<h4 class="wp-block-heading">規則2[R2] First(A) … 非終端記号1文字の場合</h4>



<p>非終端記号 \( A \) のFirst集合 \( \mathrm{First}  ( A ) \) を求める際、下のように樹形図を書いていって先頭1文字目に出てる文字を地味に探しても正しい答えは出てきますが、列挙ミスが発生する場合があります。</p>



<figure class="wp-block-image aligncenter size-large"><img width="1024" height="428" src="https://www.momoyama-usagi.com/wp-content/uploads/konpai3-2-1024x428.gif" alt="" class="wp-image-16299" srcset="https://www.momoyama-usagi.com/wp-content/uploads/konpai3-2-1024x428.gif 1024w, https://www.momoyama-usagi.com/wp-content/uploads/konpai3-2-300x126.gif 300w, https://www.momoyama-usagi.com/wp-content/uploads/konpai3-2-768x321.gif 768w, https://www.momoyama-usagi.com/wp-content/uploads/konpai3-2-1536x643.gif 1536w, https://www.momoyama-usagi.com/wp-content/uploads/konpai3-2-2048x857.gif 2048w" /><figcaption>一番単純な \( \mathrm{First}  A \) の求め方</figcaption></figure>



<p>なのでもう少し機械的に \( \mathrm{First}  ( A ) \) を求めてみましょう。</p>



<p>例えば、\( A \to BC \) という生成規則があったとします。これを言い換えると、「\( BC \) に対して生成規則を適用し、すべて終端記号に変換した際に出てくる文字列」は、必ず「\( A \) に対して生成規則を適用し、すべて終端記号に変換した際に出てくる文字列」 として出てきますね。</p>



<p>言い換えると、「\( BC \) に生成先を適用してすべて終端記号にした際に出てくる先頭文字 \( \mathrm{First}  (BC) \) の集合」の要素に、「\( A \) に生成先を適用してすべて終端記号にした際に出てくる先頭文字 \( \mathrm{First}  (A) \) の集合」が含まれますね。</p>



<p>つまり、 \( \mathrm{First}  ( A ) \) を機械的に求める手順としては、\( A \) から生成規則 \( A \to \alpha \), \( A \to \beta \), … を探していき、その生成先の文字列 \( \alpha \), \( \beta \), … のFirst集合 \( \mathrm{First}  ( \alpha ) \), \( \mathrm{First}  ( \beta ) \) の要素をすべてFirst集合 \( \mathrm{First}  (A) \) の要素とすればOKです。</p>



<div style="height:30px" class="wp-block-spacer"></div>



<p>1つ例を見てみましょう。\( A \) から始まる生成規則 \( A \to \textcolor{red}{\varepsilon} \), \( A \to \textcolor{blue}{aB} \), \( A \to \textcolor{green}{Cb} \) が3つあったとします。</p>



<p>この場合、\( \mathrm{First}  (A) \) の要素は、\( \mathrm{First}  ( \textcolor{red}{ \varepsilon } ) \), \( \mathrm{First}  ( \textcolor{blue}{ aB } ) \), \( \mathrm{First}  ( \textcolor{green}{ Cb } ) \) の和\[<br>\mathrm{First}  ( A ) = \underbrace{ \mathrm{First}  ( \textcolor{red}{\varepsilon} ) }_{  A \to \textcolor{red}{\varepsilon} } \cup \underbrace{ \mathrm{First}  ( \textcolor{blue}{a B} ) }_{ A \to \textcolor{blue}{ aB } } \cup \underbrace{ \mathrm{First}  ( \textcolor{green}{Cb} ) }_{ A \to \textcolor{green}{Cb} }<br>\]となります。</p>


<p><span>ここで1点注意が必要です<span  style="background-image:linear-gradient(to bottom,transparent 0%,#FFF387 0%);" class="dbp-e-marker-animation red">非終端記号 \( A \) から空文字 \( \varepsilon \) が生成される可能性があるときには、\( \mathrm{First}&nbsp; ( A ) \) の要素に \( \varepsilon \) が加わる点に注意</span>してください。</span></p>


<p>※ 以後、この規則を用いた変換をする場合は  \( \overset{ \mathrm{R2} }{=} \) と = の上にR2（規則2）を用いていることを示します。</p>



<div style="height:40px" class="wp-block-spacer"></div>



<h4 class="wp-block-heading">規則3[R3] First(αβ…) … 2文字以上の場合</h4>



<p>First集合は、「文字列に生成規則を加えて全て終端記号にした際に、先頭に来る可能性がある終端記号」を表しているのでしたね。</p>



<div style="height:50px" class="wp-block-spacer"></div>



<p>そのため、（First集合を求めるだけであれば）最初の1文字さえわかってしまえば、（最初の1文字が空文字とはならない限り）残りの後ろは何が来ようが関係ありません。</p>



<p>よって、文字列 \( \alpha \beta \cdots \) のFirst集合 \( \mathrm{First}  ( \alpha \beta \cdots ) \) は、\( \alpha \) に空文字が来ない限り（＝ \( \varepsilon \notin \mathrm{First}  (\alpha )   \) の場合）は \( \mathrm{First}  ( \alpha ) \) と等しくなります。</p>



<p>一方、\( \alpha \) に空文字が来る可能性があるとき（＝ \( \varepsilon \in  \mathrm{First}  (\alpha )  \) の場合）は、2文字目が先頭になる可能性があるため、1文字目に加えて2文字目 \( \beta \cdots \) の先頭文字 \( \mathrm{First}  ( \beta \cdots ) \) も追加で調べます。つまり、\[<br>\mathrm{First}  ( \alpha \beta \cdots ) = \left( \mathrm{First}  ( \alpha ) - \{ \varepsilon \} \right) \cup \mathrm{First} ( \beta \cdots )<br>\]が成立します。</p>



<p>※ \( \varepsilon \) を引いた理由は、2文字目 \( \beta \) の先頭に空文字 \( \varepsilon \) が来ない場合、文字列 \( \alpha \beta \cdots \) に \( \beta \) の文字列が残り、文字列  \( \alpha \beta \cdots \) が空文字 \( \varepsilon \) になることはないからです。</p>



<div style="height:24px" class="wp-block-spacer"></div>



<p>まとめると、2文字以上の文字列 \( \alpha \beta \cdots \) のFirst集合 \( \mathrm{First}  ( \alpha \beta \cdots ) \) は、\[<br>\mathrm{First}  ( \alpha \beta \cdots ) = \left\{ \begin{array}{ccc} \mathrm{First}  ( \alpha ) &amp; \varepsilon \notin \mathrm{First}  ( \alpha )  \\ \left( \mathrm{First}  ( \alpha ) - \{ \varepsilon \} \right) \cup \mathrm{First}  ( \beta \cdots ) &amp; \varepsilon \in \mathrm{First}  ( \alpha )  \end{array} \right.<br>\]で求めることができます。</p>



<p>※ 以後、この規則を用いた変換をする場合は  \( \overset{ \mathrm{R3} }{=} \) と = の上にR3（規則3）を用いていることを示します。</p>



<div style="height:30px" class="wp-block-spacer"></div>



<h4 class="wp-block-heading">注意: 左再帰 A → Aα が含まれる場合のFirst集合</h4>



<p>\( \textcolor{red}{A} \to \textcolor{blue}{A} bc \) のように「<mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-blue-color">生成先の文字列の先頭</mark>が<mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-red-color">生成元の文字列</mark>になっている」場合、First集合を求めていくと\[\begin{align*}<br>\mathrm{First} (A) &amp; \overset{ \mathrm{R2} }{=} \mathrm{First} (Abc)<br>\\ &amp; \overset{ \mathrm{R3} }{=} \mathrm{First} (A)<br>\end{align*}\]となり、求めたい集合 \( \mathrm{First} (A) \) が計算途中に出てくるというよくわからないことが起こります。</p>



<p>この形になった場合は、計算途中に出てくる \( \mathrm{First} (A) \) は無視してOKです。例えば、\[<br> \mathrm{First} (A) = \underbrace{ \mathrm{First} (A) }_{ \mathrm{無視} } \cup \mathrm{First} (b)<br>\]となった場合は、左辺にも右辺にも出てくる \(  \mathrm{First} (A) \) を無視し、\[<br>\mathrm{First} (A) = \mathrm{First} (b)<br>\]として計算してください<span class="footnote_referrer"><a tabindex="0" onclick="footnote_moveToReference_16248_11('footnote_plugin_reference_16248_11_3');" onkeypress="footnote_moveToReference_16248_11('footnote_plugin_reference_16248_11_3');" ><sup id="footnote_plugin_tooltip_16248_11_3" class="footnote_plugin_tooltip_text">[3]</sup></a><span id="footnote_plugin_tooltip_text_16248_11_3" class="footnote_tooltip"> \( A \to Ab \) のように左再帰文法となる規則を適用しても、先頭文字列は \( A \) のまま変わらないため、無視しても問題ない。</span></span>。</p>



<p>また、\[<br>\textcolor{red}{A \to Bb, \ \ \ B \to Aa} , \ \ \  A \to c<br>\]のように、見た目に左再帰になる生成規則は含まれてはいないものの、変形していくと、\[<br>\textcolor{red}{A} \to Bb \to \textcolor{red}{A}ab<br>\]のように間接的に左再帰の形が出てくる場合、\[\begin{align*}<br>\mathrm{First} ( A ) &amp; = \mathrm{First} (B) \cup \mathrm{First} (c) \\ <br>\mathrm{First} (B) &amp; =  \mathrm{First} (A)<br>\end{align*}\]のように、一意には答えを決定できないような形が出てくることがあります。</p>



<p>しかし、左再帰になる規則の部分だけに着目してみると、\( \mathrm{First} (A) = \mathrm{First} (B) \), \( \mathrm{First} (B) = \mathrm{First} (A) \) 以外の式が出てこず、特に新しい要素が足される気配（例えば  \( \mathrm{First} (c) \) はありません。</p>



<figure class="wp-block-image aligncenter size-large"><img width="1024" height="170" src="https://www.momoyama-usagi.com/wp-content/uploads/konpai3-7-1024x170.gif" alt="" class="wp-image-16592" srcset="https://www.momoyama-usagi.com/wp-content/uploads/konpai3-7-1024x170.gif 1024w, https://www.momoyama-usagi.com/wp-content/uploads/konpai3-7-300x50.gif 300w, https://www.momoyama-usagi.com/wp-content/uploads/konpai3-7-768x128.gif 768w, https://www.momoyama-usagi.com/wp-content/uploads/konpai3-7-1536x255.gif 1536w" /></figure>


<p><span>そのため、間接的な左再帰が出てきた際（＝一意に答えが決定できないような形が出てきた場合）には、<span  style="background-image:linear-gradient(to bottom,transparent 0%,#FFF387 0%);" class="dbp-e-marker-animation y">間接的な左再帰が出てくる式（例えば \( A \to B b \), \( B \to Aa \)）をすべて無視し、残りの生成規則からFirst集合を求めてください</span>。ただし、<span  style="background-image:linear-gradient(to bottom,transparent 0%,#FFF387 0%);" class="dbp-e-marker-animation red">間接的な左再帰に寄与している非終端記号（今回の例だと \(A \), \( B \)）同士のFirst集合は等しくなる</span>点は忘れないでください。</span></p>


<p>今回の場合は、\( A \to Bb \), \( B \to Aa \), \( A \to c \) のうちの赤文字部分が間接的な左再帰なため、まずは間接的な左再帰とは関係ない生成規則 \( A \to c \) から\[\begin{align*}<br>\mathrm{First} (A) &amp; \overset{ \mathrm{R1} }{=} \mathrm{First} (c)<br>\\ &amp; = \{ c \}<br>\end{align*}\]と求めます。さらに、間接的な左再帰に寄与している \(A \), \( B \) のFirst集合は等しくなるため、\[<br>\mathrm{First} (B) = \mathrm{First} (A) = \{ c \}<br>\]と求めることができます<span class="footnote_referrer"><a tabindex="0" onclick="footnote_moveToReference_16248_11('footnote_plugin_reference_16248_11_4');" onkeypress="footnote_moveToReference_16248_11('footnote_plugin_reference_16248_11_4');" ><sup id="footnote_plugin_tooltip_16248_11_4" class="footnote_plugin_tooltip_text">[4]</sup></a><span id="footnote_plugin_tooltip_text_16248_11_4" class="footnote_tooltip">いったん\[\begin{align*}\mathrm{First} (A) &amp; = \mathrm{First} (B) \cup \mathrm{First} (c)\\ &amp; = \underbrace{ \mathrm{First} (A) }_{ \mathrm{無視} } \cup \mathrm{First} (c)\\ &amp; =&nbsp;&#x2026; <span class="footnote_tooltip_continue"  onclick="footnote_moveToReference_16248_11('footnote_plugin_reference_16248_11_4');">Continue reading</span></span></span>。</p>



<div style="height:50px" class="wp-block-spacer"></div>


<div class='wp-block-dbp-frame l-frame-inner is-design-inline is-frame-style-default dbp-frame has-bgcolor'><div class="dbp-frame-title">First集合を求める際に使う3つの公式まとめ</div><div class="dbp-frame-content has-content-gap">
<p><strong>公式1[R1]</strong>  終端記号1文字 \( a \) のFirst集合の要素はそのまま \( a \) \[<br>\mathrm{First} ( a ) \overset{ \mathrm{R1} }{=} \{ a \}<br>\]</p>

<p>※1: 例題・練習問題で公式1を適用する場合は \( \overset{ \mathrm{R1} }{=} \) と表記<br>※2: \( \mathrm{First} ( \varepsilon ) = \{ \varepsilon \} \) である。<br>※3: \( \mathrm{First} ( \alpha ) = \{ \varepsilon \} \) は、\( \alpha \) が空文字であることを表す( \( \alpha = \varepsilon \) ) </p>

<div style="height:30px" class="wp-block-spacer"></div>

<p><strong>公式2[R2]</strong>  非終端記号1文字 \( A \) のFirst集合の要素は、\( A \) から生成される生成規則 \( A \to \textcolor{red}{\alpha} \),  \( A \to \textcolor{blue}{\beta} \),  \( A \to \textcolor{green}{\gamma} \), … の生成先(右辺)のFirst集合の和\[<br>\mathrm{First} ( A ) \overset{ \mathrm{R2} }{=} \underbrace{ \mathrm{First} ( \alpha ) }_{A \to \textcolor{red}{\alpha}} \cup \underbrace{ \mathrm{First} ( \beta ) }_{A \to \textcolor{blue}{\beta}} \cup \underbrace{ \mathrm{First} ( \gamma ) }_{A \to \textcolor{gamma}{\gamma}} \cup \cdots<br>\]</p>

<p>※1. 例題・練習問題で公式2を適用する場合は \( \overset{ \mathrm{R2} }{=} \) と表記<br>※2. \( \textcolor{magenta}{A} \to \textcolor{magenta}{A} \alpha  \) のような左再帰が含まれる文法が出てきた場合は無視する（間接的な左再帰、例えば \( A \to B \alpha \), \( B \to A \beta \) など）が出てきた場合も無視するが、間接的な左再帰に寄与する非終端記号（例の場合だと \( A \), \( B \)）同士のFirst集合は等しくなる。）。</p>

<div style="height:30px" class="wp-block-spacer"></div>

<p><strong>公式3[R3]</strong>  2文字以上の文字列 \( \alpha \beta \) のFirst集合の要素は、<mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-red-color">1文字目 \( \alpha \) に空文字の可能性がなければ</mark>1文字目のFirst集合、<mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-blue-color">1文字目 \( \alpha \) に空文字の可能性があれば</mark>1文字目 \( \alpha \) と2文字目 \( \beta \) のFirst集合\[<br>\mathrm{First}  ( \alpha \beta \cdots ) \overset{ \mathrm{R3} }{=} \left\{ \begin{array}{ccc} \mathrm{First}  ( \alpha ) &amp; ( \textcolor{red}{ \varepsilon \notin \mathrm{First}  ( \alpha ) } ) \\ \mathrm{First}  ( \alpha ) \cup \mathrm{First}  ( \beta \cdots ) &amp; ( \textcolor{blue}{ \varepsilon \in \mathrm{First}  ( \alpha )  }  )\end{array} \right.<br>\]</p>

<p>※1: 例題・練習問題で公式3を適用する場合は \( \overset{ \mathrm{R3} }{=} \) と表記<br>※2: 1文字目も2文字目も空文字の可能性があれば、1文字目～3文字目のFirst集合の和を取ればOK<span class="footnote_referrer"><a tabindex="0" onclick="footnote_moveToReference_16248_11('footnote_plugin_reference_16248_11_5');" onkeypress="footnote_moveToReference_16248_11('footnote_plugin_reference_16248_11_5');" ><sup id="footnote_plugin_tooltip_16248_11_5" class="footnote_plugin_tooltip_text">[5]</sup></a><span id="footnote_plugin_tooltip_text_16248_11_5" class="footnote_tooltip">一般化すると、1文字目からn文字目までの文字すべてに空文字があれば、1文字目～n+1文字目の和を取ればOK。</span></span>。</p>
</div></div>


<h3 class="wp-block-heading">(3) 例題で確認！</h3>



<p>ここからは、1題例題を実際に解いてみましょう。</p>


<div class='wp-block-dbp-frame l-frame-float is-design-onframe is-frame-style-default dbp-frame has-bgcolor'><div class="dbp-frame-title">例題1</div><div class="dbp-frame-content has-content-gap">
<p>次の文法 \( G \) がある。\[<br>G = \left( \ \{ S,A,B \} \ , \  \{ a,b,c,d \} \ , \  P \ , \ S \ \right)<br>\]\[\begin{align*}<br>P = \{ \ \ \ \ S  &amp;  \to aA \\ A &amp;  \to bBa \ | \ \varepsilon \\ B &amp;  \to Sc \ | \ d \ \ \ \ \ \ \ \}<br>\end{align*}<br>\]この文法 \( G \) に対し、</p>

<p>(1) \( \mathrm{First} (S) \)<br>(2) \( \mathrm{First} (A) \)<br>(3) \( \mathrm{First} (B) \)</p>

<p>をそれぞれ求めなさい。</p>
</div></div>


<p>解説の前に、First集合を求める手順について確認しておきましょう。</p>


<div class='wp-block-dbp-frame l-frame-inner is-design-inline is-frame-style-default dbp-frame has-bgcolor'><div class="dbp-frame-title">First集合求める手順</div><div class="dbp-frame-content has-content-gap">
<p>ある非終端記号 \( A \) のFirst集合 \( \mathrm{First} (A) \) は次の手順で求める。</p>

<p>Step1. \( A \) が生成元となる規則\[\begin{align*}<br>A &amp; \to \alpha \\ A &amp; \to \beta \\ A &amp; \to \gamma \\  &amp; \ \ \vdots<br>\end{align*}\]をすべて探す。</p>

<p>Step2. Step1で探したすべての生成規則の生成先（右辺）\( \alpha \), \( \beta \), \( \gamma \) のFirst集合 \( \mathrm{First} ( \alpha ) \), \( \mathrm{First} ( \beta ) \), \( \mathrm{First} ( \gamma ) \) を求める。</p>

<p>Step3. Step2で求めたFirst集合の和を取る。\[<br>\mathrm{First} (A) = \underbrace{ \mathrm{First} (\alpha) }_{A \to \alpha} \cup \underbrace{ \mathrm{First} (\beta) }_{A \to \beta} \cup \underbrace{ \mathrm{First} (\gamma) }_{A \to \gamma} \cup \cdots<br>\]</p>
</div></div>


<h4 class="wp-block-heading">First(S) の求め方</h4>



<p>\( S \) が生成元になる規則は、\( S \to \textcolor{red}{ aA } \) ただ1つですね。</p>



<p>そのため、\[\begin{align*}<br>\mathrm{First} (S) &amp; \overset{ \mathrm{R2} }{=} \underbrace{ \mathrm{First} ( \textcolor{red}{aA} ) }_{S \to \textcolor{red}{aA} }<br>\\ &amp; \overset{ \mathrm{R3} }{=}  \mathrm{First} (a)<br>\\ &amp; \overset{ \mathrm{R1} }{=} \{ a \}<br>\end{align*}\]で計算できます。</p>



<h4 class="wp-block-heading">First(A) の求め方</h4>



<p>\( A \) が生成元になる規則は、\( A \to bBa \ | \ \varepsilon \)、つまり \( A \to \textcolor{red}{bBa} \) と \( A \to \textcolor{blue}{\varepsilon} \) の2つですね。</p>



<p>そのため、\[\begin{align*}<br>\mathrm{First} (A) &amp; \overset{ \mathrm{R2} }{=} \underbrace{ \mathrm{First} ( \textcolor{red}{bBa}  ) }_{A \to \textcolor{red}{bBa} } \cup \underbrace{ \mathrm{First} (\textcolor{blue}{\varepsilon}) }_{A \to \textcolor{blue}{\varepsilon}}<br>\end{align*}\]を求めればＯＫです。</p>



<p>ここで、それぞれのFirst集合は、\[\begin{align*}<br>\mathrm{First} (bBa) &amp; \overset{ \mathrm{R3} }{=} \mathrm{First} (b)<br>\\ &amp; \overset{ \mathrm{R1} }{=} \{ b \}<br>\end{align*}\]\[\begin{align*}<br>\mathrm{First} ( \varepsilon ) &amp; \overset{ \mathrm{R1} }{=} \{ \varepsilon \}<br>\end{align*}\]となるため、求めたいFirst集合は\[\begin{align*}<br>\mathrm{First} (A) &amp; \overset{ \mathrm{R2} }{=} \mathrm{First} (bBa) \cup \mathrm{First} (\varepsilon )<br>\\ &amp; = \{ b \} \cup \{ \varepsilon \}<br>\\ &amp; = \{ b, \varepsilon \}<br>\end{align*}\]と計算できます。</p>



<h4 class="wp-block-heading">First(B) の求め方</h4>



<p>\( B \) が生成元になる規則は、\( B  \to Sc \ | \ d \)、つまり \( B \to \textcolor{red}{Sc} \) と \( B \to \textcolor{blue}{d} \) の2つですね。</p>



<p>そのため、\[\begin{align*}<br>\mathrm{First} (B) &amp; \overset{ \mathrm{R2} }{=} \underbrace{ \mathrm{First} ( \textcolor{red}{Sc} ) }_{B \to \textcolor{red}{Sc}} \cup \underbrace{ \mathrm{First} ( \textcolor{blue}{d} ) }_{B \to \textcolor{blue}{d}}<br>\end{align*}\]を求めればＯＫです。</p>



<p>ここで、それぞれのFirst集合は、\[\begin{align*}<br>\mathrm{First} (Sc) &amp; \overset{ \mathrm{R3} }{=} \mathrm{First} (S)<br>\\ &amp; \overset{(1) }{=} \{ a \}<br>\end{align*}\]\[\begin{align*}<br>\mathrm{First} ( d ) &amp; \overset{ \mathrm{R1} }{=} \{ d \}<br>\end{align*}\]となるため、求めたいFirst集合は\[\begin{align*}<br>\mathrm{First} (B) &amp; \overset{ \mathrm{R2} }{=} \mathrm{First} (Sc) \cup \mathrm{First} ( d )<br>\\ &amp; = \{ a \} \cup \{ d \}<br>\\ &amp; = \{ a,d \}<br>\end{align*}\]と計算できます。</p>



<p>※ \( \overset{(1) }{=}\) は、(1)の答え \( \mathrm{First} \ (S) = \{ a \} \) を使っていることを表しています。</p>



<div style="height:100px" class="wp-block-spacer"></div>



<h2 class="wp-block-heading">3. Follow集合</h2>



<h3 class="wp-block-heading">(1) Follow 集合とはなにか</h3>



<p>Follow集合 \( \mathrm{Follow} ( A ) \) は、「ある非終端記号1文字 \( \textcolor{magenta}{A} \) 以降の文字をの<mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-light-orange-color">直後に来る可能性がある文字</mark>（<mark style="background-color:rgba(0, 0, 0, 0);color:#298e1a" class="has-inline-color">終端記号</mark>）の候補を集めた集合」を表します。</p>



<p>数式で書くと、\[<br>\mathrm{Follow}  ( \textcolor{magenta}{A} ) = \left\{  \textcolor{orange}{a} \mid \textcolor{orange}{a} \in \textcolor{green}{V_T} , \textcolor{magenta}{\alpha} \overset{*}{\Rightarrow}  \cdots A \textcolor{orange}{a} \cdots  \right\}<br>\]となります。（色部分を日本語の説明に対応させています）</p>



<figure class="wp-block-image aligncenter size-full is-resized"><img src="https://www.momoyama-usagi.com/wp-content/uploads/konpai3-3.gif" alt="" class="wp-image-16432" width="577" height="416"/><figcaption>Follow集合のイメージ<br>（水色の丸部分に来る終端記号の文字の候補を表す）</figcaption></figure>







<p>例えば、\( \mathrm{Follow}  ( A ) = \{ a, b \} \) の場合、\( A \) の後ろの文字列をすべて終端記号にした際、\( A \) の直後に来る文字列が \( a \), \( b \) のいずれかであることを表します。</p>



<div style="height:32px" class="wp-block-spacer"></div>



<p>1点注意が必要なのは、Follow集合の要素に「空文字 \( \varepsilon \)」が出てくることは絶対にありません。</p>



<p>その代わりに、「\( A \) の直後に来る文字はありません（＝\( A \) が文字列の終端になりますよ）」というのを表す記号 \( \$ \) がFollow集合の要素で使われます。</p>



<div style="height:100px" class="wp-block-spacer"></div>



<h3 class="wp-block-heading">(2) Follow 集合で頭にいれておくべき3つの公式</h3>



<p>各非終端記号に対してFollow集合を求めていくときには、公式1～公式3で出てきた要素すべての和を取ることで求めます。</p>



<p>そこで、この「(2) Follow集合で頭にいれておくべき3つの公式」では、公式1～公式3の式の紹介だけでなく、何故この式でFollow集合が求められるのかまで説明していきます。</p>



<h4 class="wp-block-heading">公式1. 出発記号 S の直後は必ず文字列の終端 $ </h4>



<p>文脈自由文法では、下のようにどの文字列も出発記号 \( S \) から与えられた生成規則により変換されていき、導出されます。\[<br>S \xrightarrow{S \to AaB} AaB \xrightarrow{A \to aA} aAaB \xrightarrow{A \to a} aaaB \xrightarrow{B \to b} aaab <br>\]</p>



<p>そのため、出発記号の後ろは必ず文字列の終端となりますね。</p>



<figure class="wp-block-image aligncenter size-full"><img width="853" height="228" src="https://www.momoyama-usagi.com/wp-content/uploads/konpai3-5.gif" alt="" class="wp-image-16528"/></figure>



<p>そのため、最初に出発記号に対するFollow集合 \( \mathrm{Follow} (S) \) に対しては、文字列の終端を表す \( \$ \) を要素に追加します。\[<br>\mathrm{Follow} (S) + = \{ \$ \}<br>\]</p>



<figure class="wp-block-image aligncenter size-full"><img width="788" height="189" src="https://www.momoyama-usagi.com/wp-content/uploads/konpai3-13.gif" alt="" class="wp-image-16931"/><figcaption>本記事では、Follow集合の要素追加をこんな感じに図でも記します！</figcaption></figure>



<p>※1: 出発記号ではない非終端記号に対しては何もしなくてOKです。<br>※2: \( X += Y \) は、（集合 \( X \) に含まれない）集合 \( Y \) の要素を集合 \( X \) に加えることを表します。数式で書くと、\( X = X \cup Y \) です。</p>



<h4 class="wp-block-heading">公式2.  直後の文字が空文字にならない場合</h4>



<p>Follow集合は、「ある非終端記号の直後に来る（終端記号の）文字の候補」を表すため、Follow集合を求める際には、まずは生成規則の生成元ではなく、生成先側の文字列に着目します。</p>



<p>例えば、\( S \to a \textcolor{magenta}{A} \textcolor{blue}{c} B \) という規則があったとします。この規則を適用すると、\( \textcolor{magenta}{A}   \) の直後には必ず \( \textcolor{blue}{c} B \) という文字が来ますよね。</p>



<p>このように、\( S \to a \textcolor{magenta}{A}  \textcolor{blue}{c} B \) のような求めたい非終端記号 \( \textcolor{magenta}{A}  \) が生成されている規則を見つけ、<mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-blue-color">その直後に来る文字（今回は \( c \)）</mark>を見つけ出す（＋非終端記号であれば終端記号に変換する）ことでFollow集合を求められそうですね。</p>



<div style="height:32px" class="wp-block-spacer"></div>



<p>もう少し一般化して、\( \mathrm{Follow} (A) \) の求め方を公式化していきましょう。</p>



<p>まず、求めたい非終端記号 \( \textcolor{magenta}{A}  \) が生成されている規則を探し出し、生成先の文字列を \( \textcolor{magenta}{A} \) より前にある文字列 \( \textcolor{gray}{\alpha} \) と \( \textcolor{magenta}{A} \) より後ろにある文字列 \( \textcolor{blue}{\beta} \) に分け、\( S \to \textcolor{gray}{\alpha} \textcolor{magenta}{A} \textcolor{blue}{\beta} \) の形にします。</p>



<p>例えば、\( S \to a  \textcolor{magenta}{A} cB \) であれば、\[<br>S \to \textcolor{gray}{ \underbrace{a}_{\alpha}} \textcolor{magenta}{A} \textcolor{blue}{\underbrace{cB}_{\beta}}<br>\]より、\( \textcolor{gray}{\alpha = a} \), \( \textcolor{blue}{\beta = cB} \) となります。</p>



<p>※1 \( \textcolor{gray}{\alpha} \) はFollow集合の計算ではいらない子なので、求めなくてもOK。<br>※2 \( \alpha \), \( \beta \) に空文字が来てもOK。例えば、\( S \to \textcolor{gray}{a} \textcolor{magenta}{A} \) であれば、\( \textcolor{gray}{\alpha = a } \), \( \textcolor{blue}{\beta = \varepsilon} \) となる。</p>



<div style="height:49px" class="wp-block-spacer"></div>



<p>ここで、\( \mathrm{Follow} (A) \) というのは、\( A \) の直後に出てくる文字列でしたね。</p>



<p>また、先ほど生成規則を \( S \to \textcolor{gray}{\alpha} \textcolor{magenta}{A} \textcolor{blue}{\beta} \) と書き換えましたね。つまり、「 \( \textcolor{magenta}{A}  \) の直後に出てくる文字列」というのは、「\( \textcolor{blue}{\beta} \) の先頭に来る文字列」と言い換えることができますね。さらにもう1段階言い換えると、「\( \textcolor{blue}{\beta} \) の先頭に来る文字列」は \( \mathrm{First} ( \textcolor{blue}{\beta} ) \) と書くことができますね。</p>



<figure class="wp-block-image aligncenter size-full is-resized"><img src="https://www.momoyama-usagi.com/wp-content/uploads/konpai3-38.gif" alt="" class="wp-image-17162" width="465" height="389"/></figure>



<p>そのため、生成規則 \( S \to \alpha \textcolor{magenta}{A} \textcolor{blue}{\beta} \) に対して、Follow集合に\[<br>\mathrm{Follow} ( \textcolor{magenta}{A} ) + = \mathrm{First} ( \textcolor{blue}{\beta} )<br>\]と \( \mathrm{First} ( \textcolor{blue}{\beta} ) \) を追加します。</p>



<figure class="wp-block-image aligncenter size-full"><img width="980" height="185" src="https://www.momoyama-usagi.com/wp-content/uploads/konpai3-14.gif" alt="" class="wp-image-16932"/><figcaption>注意: 追加時に \( \varepsilon \) を無視すること</figcaption></figure>



<div style="height:32px" class="wp-block-spacer"></div>


<p><span>ただし、</span><span>First集合の要素に \( \varepsilon \) が含まれる場合は、<span  style="background-image:linear-gradient(to bottom,transparent 0%,#FFF387 0%);" class="dbp-e-marker-animation red">\( \varepsilon \) を無視してから</span>Follow集合に追加してください。例えば、\( S \to \alpha A \beta \) に対して、\( \mathrm{First} ( \beta ) = \{ b, c, \varepsilon \} \) であれば、\[\begin{align*}<br>\mathrm{Follow} ( A) + &amp; = \mathrm{First} ( \beta )<br>\\ &amp; =&nbsp; \{ b,c \}&nbsp;<br>\end{align*}\]と、Follow集合に \( b \), \( c \) の要素を加えます。そのため、\( S \to \alpha A \) のように \( A \) の直後の文字列 \( \beta \) がそもそも存在しない場合は、この公式でFollow集合の追加は行われません<span class="footnote_referrer"><a tabindex="0" onclick="footnote_moveToReference_16248_11('footnote_plugin_reference_16248_11_6');" onkeypress="footnote_moveToReference_16248_11('footnote_plugin_reference_16248_11_6');" ><sup id="footnote_plugin_tooltip_16248_11_6" class="footnote_plugin_tooltip_text">[6]</sup></a><span id="footnote_plugin_tooltip_text_16248_11_6" class="footnote_tooltip">\( \beta \) がそもそも存在しない、つまり \( \beta = \varepsilon \) のときは、\( \mathrm{First} ( \beta ) = \mathrm{First} ( \varepsilon ) &nbsp;\overset{ \mathrm{R1} }{=} \{&nbsp;&#x2026; <span class="footnote_tooltip_continue"  onclick="footnote_moveToReference_16248_11('footnote_plugin_reference_16248_11_6');">Continue reading</span></span></span>。</span></p>


<p>さらに、\( \mathrm{First} ( \beta ) \) に \( \varepsilon \) が含まれる（＝ \( \beta \) が空文字になる可能性がある）場合や、\( S \to \alpha A \) のように、 そもそも \( A \) が生成先の文字列の末尾になる場合は公式2を確認します。</p>



<div style="height:52px" class="wp-block-spacer"></div>



<h4 class="wp-block-heading">公式3.  直後の文字が空文字になる可能性がある場合</h4>



<p>生成規則 \( S \to \alpha A \textcolor{blue}{\beta} \) において、</p>



<ul class="wp-block-list"><li> \( \textcolor{blue}{\beta} \) 部分がそもそも存在しない<br>（つまり \( A \to \alpha A \) となるとき）</li><li> \( \textcolor{blue}{\beta} \) 部分が存在していた場合でも \( S \to \alpha \alpha A \textcolor{blue}{B} \), \( B \to \varepsilon \) のように \( \textcolor{blue}{\beta} \) に空文字が来る可能性がある場合<br>（つまり \( \varepsilon \in \mathrm{First} ( \beta ) \) となる場合）</li></ul>



<p>は、生成先 \( \alpha A \textcolor{blue}{\beta} \) に着目するだけでは、\( A \) の直後に来る文字列（＝ \( \mathrm{Follow} (A) \)）がわかりません。</p>



<p>ここで、\( S \) の直後の文字を \( \textcolor{blue}{X} \) としてから、\( S \textcolor{magenta}{X}  \) に生成規則 \( \textcolor{purple}{S \to aA} \) を適用することを考えましょう。すると、\[ \textcolor{purple}{S}  \textcolor{blue}{X}   \to \textcolor{purple}{aA} \textcolor{blue}{X} \]となり、「\( A \) の直後の文字」が「\( S \) の直後の文字」と同じになっていることがわかりますね。</p>



<figure class="wp-block-image aligncenter size-large is-resized"><img src="https://www.momoyama-usagi.com/wp-content/uploads/konpai3-4-1024x312.gif" alt="" class="wp-image-16504" width="711" height="216" srcset="https://www.momoyama-usagi.com/wp-content/uploads/konpai3-4-1024x312.gif 1024w, https://www.momoyama-usagi.com/wp-content/uploads/konpai3-4-300x91.gif 300w, https://www.momoyama-usagi.com/wp-content/uploads/konpai3-4-768x234.gif 768w" /><figcaption>青丸部分が空文字なら、\( A \) の直後の文字列は \( S \) の直後の文字列となる。</figcaption></figure>


<p><span>つまり、\( S \to \varepsilon \in \mathrm{First} ( \beta ) \) 、つまり \( \beta \) 部分が空文字になる（つまり \( \textcolor{blue}{S} \to a \textcolor{magenta}{A} \) となる）可能性がある場合は\[<br>\mathrm{Follow} ( \textcolor{magenta}{A} ) += \mathrm{Follow} ( \textcolor{blue}{S} )<br>\]と、生成元 \( \textcolor{blue}{S} \) の非終端記号の直後の文字、つまり \( \mathrm{Follow} (\textcolor{blue}{S}) \) を \( \mathrm{Follow} (\textcolor{blue}{A}) \) に追加します。</span></p>


<figure class="wp-block-image aligncenter size-large"><img width="1024" height="403" src="https://www.momoyama-usagi.com/wp-content/uploads/konpai3-15-1024x403.gif" alt="" class="wp-image-16933" srcset="https://www.momoyama-usagi.com/wp-content/uploads/konpai3-15-1024x403.gif 1024w, https://www.momoyama-usagi.com/wp-content/uploads/konpai3-15-300x118.gif 300w, https://www.momoyama-usagi.com/wp-content/uploads/konpai3-15-768x302.gif 768w" /><figcaption>\( \varepsilon \in \mathrm{First} ( \beta \) \) のとき、で1つにまとめてもOK<br>（本記事では分かりやすさ重視のため、2つに分けています）</figcaption></figure>



<h4 class="wp-block-heading">注意: 右再帰 A → αAが含まれる場合</h4>



<p>\( \textcolor{red}{A} \to ab \textcolor{blue}{A} \) のように「<mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-blue-color">生成先の文字列の終端</mark>が<mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-red-color">生成元の文字列</mark>になっている」生成規則の場合、\[\begin{align*}<br>\mathrm{Follow} (A) + &amp; = \mathrm{Follow} (A)<br>\\ &amp; = \mathrm{Follow} (A) \cup \mathrm{Follow} (A) <br>\end{align*}\]となるため、\( \mathrm{Follow} (A) \) に要素が一切追加されません。</p>



<p>そのため、右再帰 \( A \to \alpha A \) となる文法に対しては、Follow集合を求める際には無視してください。</p>



<div style="height:50px" class="wp-block-spacer"></div>



<p>特に注意が必要なのが、\[<br>A \to aB , \ \ \ B \to bA<br>\]のように見た目は右再帰な規則は含まれていないものの、変形してみると\[<br>A \to aB \to abA<br>\]のように間接的に右再帰な規則が含まれる場合です。</p>



<p>この場合、生成規則 \( A \to aB \) に対しては\( \textcolor{blue}{A} \to a \textcolor{magenta}{B} \) より\[\begin{align*}<br>\mathrm{Follow} ( \textcolor{magenta}{B} ) + &amp; = \mathrm{Follow} ( \textcolor{blue}{A} )<br>\\ &amp; = \mathrm{Follow} (B) \cup \mathrm{Follow} (A)<br>\end{align*}\]が成立するため、\( \mathrm{Follow} (B) \) に対して、\( \mathrm{Follow} (A) \) の要素を追加されるような式が出てきます。</p>



<p>さらに、\( \mathrm{Follow} (A) \) を求めていきましょう。\( \textcolor{blue}{B} \to b \textcolor{magenta}{A} \) より\[\begin{align*}<br>\mathrm{Follow} ( \textcolor{magenta}{A} ) + &amp; = \mathrm{Follow} ( \textcolor{blue}{B} )<br>\\ &amp; = \mathrm{Follow} (A) \cup \mathrm{Follow} (B)<br>\end{align*}\] なり、\( \mathrm{Follow} (A) \) に対して \( \mathrm{Follow} (B) \) を追加するような式が出てきます。</p>



<p>すると、</p>



<ul class="wp-block-list"><li>\( \mathrm{Follow} (A) \) を求めるためには追加される要素である \( \mathrm{Follow} (B) \) を求める必要がある</li><li>\( \mathrm{Follow} (B) \) を求めるためには追加される要素である \( \mathrm{Follow} (A) \) を求める必要がある</li></ul>



<p>という「無限ループ」が発生し、訳が分からないことが起こってしまいます。 </p>



<p>ここで、式ではなく意味的に考えてみましょう。ある非終端記号 \( A \) Follow集合 \( \mathrm{Follow} (A) \) とは、「\( A \) の直後に来る非終端記号の候補を集めた集合」でしたね。</p>



<p>そこで、ある非終端記号 \( A \) を間接的な右再帰規則 \( A \to aB \), \( B \to bA \) だけで変換していくことで、Follow集合がどうなるかを見てみましょう。</p>



<figure class="wp-block-image aligncenter size-large"><img width="1024" height="181" src="https://www.momoyama-usagi.com/wp-content/uploads/konpai3-6-1024x181.gif" alt="" class="wp-image-16584" srcset="https://www.momoyama-usagi.com/wp-content/uploads/konpai3-6-1024x181.gif 1024w, https://www.momoyama-usagi.com/wp-content/uploads/konpai3-6-300x53.gif 300w, https://www.momoyama-usagi.com/wp-content/uploads/konpai3-6-768x136.gif 768w" /></figure>



<p>すると、\( A \to aB \) の変化から、\( A \) の直後の非終端記号（\( \mathrm{Follow} (A) \)）と \( B \) の直後の非終端記号（\( \mathrm{Follow} (B) \) には変化がないことがわかりますね。また\( aB \to abA \) の変化から、\( B \) の直後の非終端記号（\( \mathrm{Follow} (B) \)）と \( A \) の直後の非終端記号（\( \mathrm{Follow} (A) \) にも変化がないことがわかりますね。</p>



<p>よって、\( A \to aB \), \( B \to bA \) のような間接的な右再帰規則が含まれている場合、Follow集合に追加されるような要素は存在しないこと、および \( \mathrm{Follow} (A) \),  \( \mathrm{Follow} (B) \) が等しくなることがわかりますね<span class="footnote_referrer"><a tabindex="0" onclick="footnote_moveToReference_16248_11('footnote_plugin_reference_16248_11_7');" onkeypress="footnote_moveToReference_16248_11('footnote_plugin_reference_16248_11_7');" ><sup id="footnote_plugin_tooltip_16248_11_7" class="footnote_plugin_tooltip_text">[7]</sup></a><span id="footnote_plugin_tooltip_text_16248_11_7" class="footnote_tooltip">\( \textcolor{blue}{A} \to a \textcolor{magenta}{B} \) より、\[\begin{align*}\mathrm{Follow} ( \textcolor{magenta}{B} ) + &amp; = \mathrm{Follow} ( \textcolor{magenta}{A} )\\ &amp; =&nbsp;&#x2026; <span class="footnote_tooltip_continue"  onclick="footnote_moveToReference_16248_11('footnote_plugin_reference_16248_11_7');">Continue reading</span></span></span>。</p>


<p><span>そのため、Follow集合を求める際には、直接的な右再帰規則 \( A \to \alpha A \) だけでなく、間接的な右再帰規則 \( A \to aB \), \( B \to bA \) が含まれている場合（＝一意に答えが決定できないような形が出てきた場合）でも、<span  style="background-image:linear-gradient(to bottom,transparent 0%,#FFF387 0%);" class="dbp-e-marker-animation y">間接的な左再帰が出てくる式（例えば \( A \to aB \), \( B \to bA \) ）をすべて無視し、残りの生成規則からFollow集合を求めてください</span>。ただし、<span  style="background-image:linear-gradient(to bottom,transparent 0%,#FFF387 0%);" class="dbp-e-marker-animation red">間接的な左再帰に寄与している非終端記号（今回の例だと \(A \), \( B \)）同士のFirst集合は等しくなる</span>点は忘れないでください。</span></p>


<figure class="wp-block-image aligncenter size-full is-resized"><img src="https://www.momoyama-usagi.com/wp-content/uploads/konpai3-35.gif" alt="" class="wp-image-16954" width="505" height="423"/><figcaption>間接的な左再帰に寄与している非終端記号同士の<br>Follow集合は等しくなる（＝一心同体）</figcaption></figure>


<div class='wp-block-dbp-frame l-frame-inner is-design-inline is-frame-style-default dbp-frame has-bgcolor'><div class="dbp-frame-title">Follow集合を求める際に使う3つの公式まとめ</div><div class="dbp-frame-content has-content-gap">
<p>Follow集合は[公式1]～[公式3]で出てきた要素の和で求められる。</p>

<p>※ ただし、\( X += Y \) は、\[<br>X = X \cup Y<br>\]を表す。（集合 \( Y \) の要素を集合 \( X \) に加える）</p>

<div style="height:30px" class="wp-block-spacer"></div>

<p><strong>[公式1]</strong>  出発記号 \( S \) の場合は文字列の終端を表す \( \$ \) を追加する。\[\begin{align*}<br>\mathrm{Follow} (S) += \{ \$ \} \end{align*}\]</p>

<figure class="wp-block-image aligncenter size-full"><img width="788" height="189" src="https://www.momoyama-usagi.com/wp-content/uploads/konpai3-13.gif" alt="" class="wp-image-16931"/><figcaption>公式1</figcaption></figure>

<div style="height:30px" class="wp-block-spacer"></div>

<p>[公式1]適用後、各非終端記号 \( \textcolor{magenta}{A} \) ごとに、生成先に \( \textcolor{magenta}{A} \) が含まれる生成規則を</p>

<ul class="wp-block-list"><li><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-gray-color">\( A \) より前の文字列 \( \alpha \)</mark></li><li><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-blue-color">\( A \) より後ろの文字列 \( \beta \)</mark></li></ul>

<p>に分けて \( S \to \textcolor{gray}{\alpha} \textcolor{magenta}{A} \textcolor{blue}{\beta} \) の形に分けたあと、公式1・公式2のどちらか（もしくは両方）を適用し、\( \mathrm{Follow} (\textcolor{magenta}{A}) \) に集合を追加する。</p>

<p>※ \( \textcolor{gray}{\alpha} \) と <mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-blue-color">\( \beta \)</mark> は空文字でもOK。</p>

<p>例1: \( B \to \textcolor{magenta}{A} \textcolor{blue}{c} \) のとき： \( \textcolor{gray}{\alpha = \varepsilon} \), \( \textcolor{blue}{\beta = c} \)<br>例2: \( B \to \textcolor{gray}{d} \textcolor{magenta}{A} \) のとき： \( \textcolor{gray}{\alpha = d} \), \( \textcolor{blue}{\beta = \varepsilon} \)<br>例3: \( B \to\textcolor{magenta}{A} \) のとき： \( \textcolor{gray}{\alpha = \varepsilon} \), \( \textcolor{blue}{\beta = \varepsilon} \)</p>

<p><strong>[公式2]</strong></p>

<p>\( \textcolor{blue}{\beta} \) (空文字ではない)何かしらの文字列があれば、\( \mathrm{First} ( \beta) \) を除くすべての集合を \( \mathrm{Follow} (\textcolor{magenta}{A}) \) に加える。\[<br>\mathrm{Follow} (\textcolor{magenta}{A}) +=  \mathrm{First} ( \textcolor{blue}{\beta}) - \{ \varepsilon \} <br>\]※ \( \beta \) がそもそも空文字（つまり \( S \to \alpha A \)）の場合はこの公式を適用しない。</p>

<figure class="wp-block-image aligncenter size-full"><img width="980" height="185" src="https://www.momoyama-usagi.com/wp-content/uploads/konpai3-14.gif" alt="" class="wp-image-16932"/><figcaption>公式2（First集合を足す際には \( \varepsilon \) を無視！）</figcaption></figure>

<div style="height:30px" class="wp-block-spacer"></div>

<p><strong>[公式3]</strong></p>

<p>\( \beta \) がそもそも空文字（つまり \( \textcolor{blue}{S} \to \alpha \textcolor{magenta}{A} \)）もしくは空文字ではないが \( \mathrm{First} ( \beta ) \) の要素に \( \varepsilon \) が含まれる場合は、集合 \( S \) のFollow集合 \( \mathrm{Follow} (\textcolor{blue}{S}) \) を \( \mathrm{Follow} (\textcolor{magenta}{A}) \) に加える。 \[<br>\mathrm{Follow} (\textcolor{magenta}{A}) += \mathrm{Follow} (\textcolor{blue}{S})<br>\]</p>

<figure class="wp-block-image aligncenter size-large"><img width="1024" height="403" src="https://www.momoyama-usagi.com/wp-content/uploads/konpai3-15-1024x403.gif" alt="" class="wp-image-16933" srcset="https://www.momoyama-usagi.com/wp-content/uploads/konpai3-15-1024x403.gif 1024w, https://www.momoyama-usagi.com/wp-content/uploads/konpai3-15-300x118.gif 300w, https://www.momoyama-usagi.com/wp-content/uploads/konpai3-15-768x302.gif 768w" /><figcaption>公式3</figcaption></figure>

<p>※ \( \textcolor{red}{A} \to  \alpha \textcolor{red}{A} \) のような→再帰が含まれる文法が出てきた場合は無視する（間接的な右再帰、例えば \( A \to \alpha B \), \( B \to \beta A \) など）が出てきた場合も無視するが、間接的な左再帰に寄与する非終端記号（例の場合だと \( A \), \( B \)）同士のFollow集合は等しくなる。）。</p>
</div></div>


<h3 class="wp-block-heading">(3) 例題で確認！</h3>



<p>ここからは、例題1でも出てきた文法を使って、実際にFollow集合を求め方を見ていきましょう。</p>


<div class='wp-block-dbp-frame l-frame-float is-design-onframe is-frame-style-default dbp-frame has-bgcolor'><div class="dbp-frame-title">例題2</div><div class="dbp-frame-content has-content-gap">
<p>次の文法 \( G \) がある。\[<br>G = \left( \ \{ S, A, B \} \ , \  \{ a,b,c,d \} \ , \  P \ , \ S \ \right)<br>\]\[\begin{align*}<br>P = \{ \ \ \ \ S  &amp;  \to aA \\ A &amp;  \to bBa \ | \ \varepsilon \\ B &amp;  \to Sc \ | \ d \ \ \ \ \ \ \ \}<br>\end{align*}<br>\]この文法 \( G \) に対し、</p>

<p>(1) \( \mathrm{Follow} (S) \)<br>(2) \( \mathrm{Follow} (A) \)<br>(3) \( \mathrm{Follow} (B) \)</p>

<p>をそれぞれ求めなさい。</p>

<p>※ 必要であれば例題1で求めた\[\begin{align*}<br>\mathrm{First} (S) &amp; =  \{ a \}<br>\\ \mathrm{First} (A) &amp; = \{ b, \varepsilon \}<br>\\ \mathrm{First} (B) &amp; =  \{ a,d \}<br>\end{align*}\]を用いてもよい。</p>
</div></div>


<p>解説の前に、もう1度Follow集合を求める手順について確認しておきましょう。</p>


<div class='wp-block-dbp-frame l-frame-inner is-design-inline is-frame-style-default dbp-frame has-bgcolor'><div class="dbp-frame-title">Follow集合を求める手順</div><div class="dbp-frame-content has-content-gap">
<p>ある非終端記号 \( A \) のFollow集合 \( \mathrm{Follow} (A) \) はつぎの「準備」の後、下に示す公式[R1]と公式[R2]で出てくる要素を全て追加することで求められる。</p>

<p><strong>[公式1]</strong> 出発記号かどうかの確認</p>

<p>\( A \) が出発記号であるか確認し、出発記号であれば要素に \( \$ \) を加えた状態でスタート。それ以外の場合は要素なしでスタート。</p>

<ul class="wp-block-list"><li>\( A \) が出発記号である: \( \mathrm{Follow} (A) += \{ \$ \} \) </li><li>\( A \) が出発記号でない: なにもしない</li></ul>

<figure class="wp-block-image aligncenter size-full"><img width="788" height="189" src="https://www.momoyama-usagi.com/wp-content/uploads/konpai3-13.gif" alt="" class="wp-image-16931"/><figcaption>公式1</figcaption></figure>

<div style="height:50px" class="wp-block-spacer"></div>

<p><strong>[公式2]</strong>, <strong>[公式3]</strong> では \( S \to \textcolor{gray}{ab} \textcolor{magenta}{A} \textcolor{blue}{Bc} \) のような生成先に \( \textcolor{blue}{S} \) が出てくる規則それぞれに対し、\( S \to \textcolor{gray}{\alpha} \textcolor{magenta}{A} \textcolor{blue}{\beta} \) のように \( \textcolor{magenta}{A} \) の前の文字列 \( \textcolor{gray}{\alpha} \) と \( \textcolor{magenta}{A} \) の後の文字列 \( \textcolor{blue}{\beta} \) に分けてから考える。</p>

<p>※ \( \textcolor{gray}{\alpha} \), \( \textcolor{blue}{\beta} \) は空文字OK。例えば、\( S \to A \) であれば、\(  \textcolor{gray}{\alpha}  \), \( \textcolor{blue}{\beta}  \) ともに空文字 \( \varepsilon \) となる。</p>

<p><strong>[公式2]</strong> \( \beta \not =  \varepsilon \) であれば適用</p>

<p>生成規則 \( S \to \textcolor{gray}{\alpha} \textcolor{magenta}{A} \textcolor{blue}{\beta} \)  に対し、\( \textcolor{blue}{\beta} \) が空文字ではない場合、\( \mathrm{First} ( \textcolor{blue}{\beta} ) \) の要素を加える。ただし \( \varepsilon \) は加えない。\[<br>\mathrm{Follow} ( \textcolor{magenta}{A}  ) += \mathrm{First}  ( \textcolor{blue}{\beta} ) - \{ \varepsilon \}<br>\]</p>

<figure class="wp-block-image aligncenter size-full"><img width="980" height="185" src="https://www.momoyama-usagi.com/wp-content/uploads/konpai3-14.gif" alt="" class="wp-image-16932"/><figcaption>公式2</figcaption></figure>

<div style="height:40px" class="wp-block-spacer"></div>

<p><strong>[公式3]</strong> \(  \varepsilon \in \mathrm{First} ( \beta ) \) であれば適用</p>

<p>\( \textcolor{blue}{S} \to \alpha \textcolor{magenta}{A} \) のように \( \beta = \varepsilon \) となる場合や、\( \textcolor{blue}{S} \to \alpha \textcolor{magenta}{A} \beta \) の形だが \( \varepsilon \in  \mathrm{First} ( \textcolor{blue}{\beta} ) \) となる場合は、\( \mathrm{Follow} ( \textcolor{blue}{S} ) \) の要素を加える。\[<br>\mathrm{Follow} (  \textcolor{magenta}{A}  ) += \mathrm{Follow}  ( \textcolor{blue}{S})<br>\]</p>

<figure class="wp-block-image aligncenter size-large"><img width="1024" height="403" src="https://www.momoyama-usagi.com/wp-content/uploads/konpai3-15-1024x403.gif" alt="" class="wp-image-16933" srcset="https://www.momoyama-usagi.com/wp-content/uploads/konpai3-15-1024x403.gif 1024w, https://www.momoyama-usagi.com/wp-content/uploads/konpai3-15-300x118.gif 300w, https://www.momoyama-usagi.com/wp-content/uploads/konpai3-15-768x302.gif 768w" /></figure>
</div></div>


<h4 class="wp-block-heading">(1) Follow(S) の求め方</h4>



<p>まず、\( S \) は出発記号なので、初期状態として要素 \( \$ \) を加えます。</p>



<div style="height:26px" class="wp-block-spacer"></div>



<p>つぎに、\( \textcolor{magenta}{S} \) が生成先に出てくる規則は、\( B \to \textcolor{magenta}{S} c \) 1つだけなので、この生成規則に着目しましょう。</p>



<p>着目した生成規則の生成先 \( \textcolor{magenta}{S} \textcolor{blue}{c} \) において、\( \textcolor{magenta}{S} \) より後の文字列は \( \textcolor{blue}{c} \) ですね。よって、\( \textcolor{blue}{\beta} = \textcolor{blue}{c} \) となります。</p>



<div style="height:48px" class="wp-block-spacer"></div>



<p><strong>[公式2]</strong> \(  \textcolor{blue}{ \beta = c } \not = \varepsilon  \) なので〇</p>



<p>生成規則 \( B \to \textcolor{magenta}{S} \textcolor{blue}{ \underbrace{ c }_{ \beta } } \) より、\( \mathrm{Follow} ( \textcolor{magenta}{S} )  \) に追加される要素は、\[\begin{align*}<br>\mathrm{Follow} ( \textcolor{magenta}{S} ) + &amp; = \mathrm{First} ( \textcolor{blue}{c} ) - \{ \varepsilon \}<br>\\ &amp; \overset{ \mathrm{R1} }{=} \{ c \} - \{ \varepsilon \}<br>\\ &amp; = \{ c \}<br>\end{align*}\]と求められます。よって、\( \mathrm{Follow} ( \textcolor{magenta}{S} )  \) に \( c \) が追加されます。</p>



<div style="height:26px" class="wp-block-spacer"></div>



<p><strong>[公式3]</strong> \( \varepsilon \notin \mathrm{First} ( \textcolor{blue}{c} ) = \{ c \} \) なので×</p>



<div style="height:48px" class="wp-block-spacer"></div>



<p>よって、\[\begin{align*}<br>\mathrm{Follow} (S) &amp; = \{ $ \} \cup \{ c \}<br>\\ &amp; = \{ c, \$ \}<br>\end{align*}\]となります。</p>



<figure class="wp-block-image aligncenter size-full"><img width="953" height="418" src="https://www.momoyama-usagi.com/wp-content/uploads/konpai3-16.gif" alt="" class="wp-image-16934"/><figcaption>\( \mathrm{Follow} (S) \) の計算過程</figcaption></figure>



<div style="height:51px" class="wp-block-spacer"></div>



<h4 class="wp-block-heading">(2) Follow(A) の求め方</h4>



<p><strong>[公式1]</strong> \( A \) は出発記号ではないため×</p>



<div style="height:26px" class="wp-block-spacer"></div>



<p>つぎに、\( \textcolor{magenta}{A} \) が生成先に出てくる規則は、\( S \to aA \), \( A \to bBA \) の2つがありますが、\( \textcolor{deepskyblue}{A} \to bB \textcolor{deepskyblue}{A} \) は<mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-light-blue-color">右再帰</mark>なので無視します。そのため、<strong>[公式2]</strong>, <strong>[公式3]</strong> に当てはめる生成規則は \( S \to aA \) だけでOKです。</p>



<p>着目した規則の生成先 \( a \textcolor{magenta}{A} \) において、\( \textcolor{magenta}{A} \) より後の文字列はありません（＝空文字です）ね。よって、 \( \textcolor{blue}{\beta} = \textcolor{blue}{\varepsilon} \) です。</p>



<p><strong>[公式2]</strong> \(  \textcolor{blue}{ \beta = \varepsilon } \) なので×</p>



<div style="height:26px" class="wp-block-spacer"></div>



<p><strong>[公式3]</strong> \( \varepsilon \in \mathrm{First} ( \textcolor{blue}{ \varepsilon } ) = \{ \varepsilon \} \) なので〇</p>



<p>生成規則 \( \textcolor{blue}{S} \to  a \textcolor{magenta}{A}  \) より、\( \mathrm{Follow} ( \textcolor{magenta}{A} )  \) に追加される要素は、</p>



<p>\[\begin{align*}<br>\mathrm{Follow} ( \textcolor{magenta}{A} ) + &amp; = \mathrm{Follow} ( \textcolor{blue}{S} ) <br>\\ &amp; \overset{ \mathrm{(1)} }{=} \{ c, \$ \}<br>\end{align*}\]と求められます。よって、\( \mathrm{Follow} ( \textcolor{magenta}{A} )  \) に \( c, \$ \) が追加されます。</p>



<div style="height:48px" class="wp-block-spacer"></div>



<p>したがって、\( \mathrm{Follow} (A) \) は\[\begin{align*}<br>\mathrm{Follow} (A) &amp; = \{ c, \$ \}<br>\end{align*}\]と計算できます。</p>



<figure class="wp-block-image aligncenter size-full"><img width="772" height="194" src="https://www.momoyama-usagi.com/wp-content/uploads/konpai3-36.gif" alt="" class="wp-image-16961"/><figcaption>\( \mathrm{Follow} (A) \) の計算過程</figcaption></figure>



<div style="height:51px" class="wp-block-spacer"></div>



<h4 class="wp-block-heading">(3) Follow(B) の求め方</h4>



<p><strong>[公式1]</strong> \( B \) は出発記号ではないため×</p>



<div style="height:51px" class="wp-block-spacer"></div>



<p>ここで、\( \textcolor{magenta}{B} \) が生成先に出てくる規則は、\( A \to b \textcolor{magenta}{B} A \) の1つだけですね。なので <strong>[公式2]</strong>, <strong>[公式3]</strong> に当てはめる生成規則は \( A \to b \textcolor{magenta}{B} A \) だけです。</p>



<p>着目した生成規則の生成先 \(  b \textcolor{magenta}{B} A \) において、\( \textcolor{magenta}{B} \) より後の文字列は \( \textcolor{blue}{A} \) ですね。よって、\( \textcolor{blue}{\beta} = \textcolor{blue}{A} \) となります。</p>



<p><strong>[公式2]</strong> \(  \textcolor{blue}{ \beta = A } \not = \varepsilon \) なので〇</p>



<p>生成規則 \( A  \to \textcolor{gray}{b} \textcolor{magenta}{B} \textcolor{blue}{ \underbrace{ A }_{ \beta } } \) より、\( \mathrm{Follow} ( \textcolor{magenta}{B} )  \) に追加される要素は、\[\begin{align*}<br>\mathrm{Follow} ( \textcolor{magenta}{B} ) + &amp; = \mathrm{First} ( \textcolor{blue}{A} ) - \{  \varepsilon \}<br>\\ &amp; =  \{ b, \varepsilon \} - \{ \varepsilon \}<br>\\ &amp; = \{ b \}<br>\end{align*}\]と求められます。よって、\( \mathrm{Follow} ( \textcolor{magenta}{B} )  \) に \( b \) が追加されます。</p>



<div style="height:51px" class="wp-block-spacer"></div>



<p><strong>[公式3]</strong> \( \varepsilon \in \mathrm{First} ( \textcolor{blue}{ A } ) = \{ b, \varepsilon \} \) なので〇</p>



<p>生成規則 \( \textcolor{blue}{A} \to  b \textcolor{magenta}{B} A  \) より、\( \mathrm{Follow} ( \textcolor{magenta}{B} )  \) に追加される要素は、</p>



<p>\[\begin{align*}<br>\mathrm{Follow} ( \textcolor{magenta}{B} ) + &amp; = \mathrm{Follow} ( \textcolor{blue}{A} ) <br>\\ &amp; \overset{ \mathrm{(2)} }{=} \{ c, \$ \}<br>\end{align*}\]と求められます。よって、\( \mathrm{Follow} ( \textcolor{magenta}{B} )  \) に \( c, \$ \) が追加されます。</p>



<div style="height:48px" class="wp-block-spacer"></div>



<p>したがって、\( \mathrm{Follow} (B) \) は\[\begin{align*}<br>\mathrm{Follow} (B) &amp; = \{ b \} \cup \{ c, \$ \}<br>\\ &amp; = \{ b, c, \$ \}<br>\end{align*}\]と計算できます。</p>



<figure class="wp-block-image aligncenter size-full"><img width="956" height="421" src="https://www.momoyama-usagi.com/wp-content/uploads/konpai3-37.gif" alt="" class="wp-image-16960"/><figcaption>\( \mathrm{Follow} (B) \) の計算過程</figcaption></figure>



<div style="height:100px" class="wp-block-spacer"></div>



<h3 class="wp-block-heading">(4) Follow集合の計算ミスを防ぐコツ：図を書く</h3>



<p>※ このアイデアは、国島 丈生様のこちらのサイトを参考にさせていただきました。<br>（<a href="https://knsm.net/follow-%E3%81%AE%E8%A8%88%E7%AE%97%E3%82%92%E9%96%93%E9%81%95%E3%81%88%E3%81%AB%E3%81%8F%E3%81%8F%E3%81%99%E3%82%8B%E5%B7%A5%E5%A4%AB-d1d978ce96ec" data-type="URL" target="_blank" rel="noreferrer noopener">FOLLOW()の計算を間違えにくくする工夫</a>）</p>



<div style="height:47px" class="wp-block-spacer"></div>



<p>Follow集合は、First集合に比べて計算が複雑になるため、計算ミスがかなり出てきます<span class="footnote_referrer"><a tabindex="0" onclick="footnote_moveToReference_16248_11('footnote_plugin_reference_16248_11_8');" onkeypress="footnote_moveToReference_16248_11('footnote_plugin_reference_16248_11_8');" ><sup id="footnote_plugin_tooltip_16248_11_8" class="footnote_plugin_tooltip_text">[8]</sup></a><span id="footnote_plugin_tooltip_text_16248_11_8" class="footnote_tooltip">実際に私もよく計算ミスします。</span></span>。</p>



<p>そこで、今回の記事では下の図ように「Follow集合にどの集合の要素が追加されているか」を図で表現しています<span class="footnote_referrer"><a tabindex="0" onclick="footnote_moveToReference_16248_11('footnote_plugin_reference_16248_11_9');" onkeypress="footnote_moveToReference_16248_11('footnote_plugin_reference_16248_11_9');" ><sup id="footnote_plugin_tooltip_16248_11_9" class="footnote_plugin_tooltip_text">[9]</sup></a><span id="footnote_plugin_tooltip_text_16248_11_9" class="footnote_tooltip">下の図の場合「\( \mathrm{Follow} (S) \) を求めるためには \( \mathrm{First} (c) \) と \( \{ \$ \} \) の要素を追加すればOK」ということを表しています。</span></span>。</p>



<figure class="wp-block-image aligncenter size-large"><img width="1024" height="477" src="https://www.momoyama-usagi.com/wp-content/uploads/konpai3-8-1024x477.gif" alt="" class="wp-image-16720" srcset="https://www.momoyama-usagi.com/wp-content/uploads/konpai3-8-1024x477.gif 1024w, https://www.momoyama-usagi.com/wp-content/uploads/konpai3-8-300x140.gif 300w, https://www.momoyama-usagi.com/wp-content/uploads/konpai3-8-768x358.gif 768w" /><figcaption>\( \mathrm{Follow} (S) \) の計算図示化<br>(例題2の(1)に相当)</figcaption></figure>


<p><span>さらに、各非終端記号ごとに書いたFollow集合の計算図示を下のように<span  style="background-image:linear-gradient(to bottom,transparent 0%,#FFF387 0%);" class="dbp-e-marker blue">1つにまとめる</span>ことで、Follow集合同士の関係（どのFollow集合の要素がどのFollow集合に加えられているのか）も明確にすることができます。</span></p>


<figure class="wp-block-image aligncenter size-large"><img width="1024" height="578" src="https://www.momoyama-usagi.com/wp-content/uploads/konpai3-11-1024x578.gif" alt="" class="wp-image-16728" srcset="https://www.momoyama-usagi.com/wp-content/uploads/konpai3-11-1024x578.gif 1024w, https://www.momoyama-usagi.com/wp-content/uploads/konpai3-11-300x169.gif 300w, https://www.momoyama-usagi.com/wp-content/uploads/konpai3-11-768x434.gif 768w, https://www.momoyama-usagi.com/wp-content/uploads/konpai3-11-1536x867.gif 1536w" /></figure>



<p>図を書くことで、「矢印に従って集合を追加していく」するだけで簡単にFollow集合を求めることができます！</p>



<p>※ 追加時に \( \varepsilon \) が出てくる場合は無視してください。</p>



<figure class="wp-block-image aligncenter size-full"><img width="1609" height="1009" src="https://www.momoyama-usagi.com/wp-content/uploads/tCoGIcyoDOdpRXj2vLfJ1663404758-1663404848-1.gif" alt="" class="wp-image-16722"/></figure>



<p>さらに図を書くもう1つメリットは<strong><span style="text-decoration: underline;">検算が容易にできる</span></strong>ことです。</p>



<p>理由は、「ある集合 \( A \) の要素を集合 \( B \) に追加」した場合、集合の包含関係 \( A \subseteq B \) は必ず成立するからです<span class="footnote_referrer"><a tabindex="0" onclick="footnote_moveToReference_16248_11('footnote_plugin_reference_16248_11_10');" onkeypress="footnote_moveToReference_16248_11('footnote_plugin_reference_16248_11_10');" ><sup id="footnote_plugin_tooltip_16248_11_10" class="footnote_plugin_tooltip_text">[10]</sup></a><span id="footnote_plugin_tooltip_text_16248_11_10" class="footnote_tooltip">集合 \( B \) に集合 \( A \) の要素を追加したのに、集合 \( B \) の要素の中に集合 \( A \)&nbsp;&#x2026; <span class="footnote_tooltip_continue"  onclick="footnote_moveToReference_16248_11('footnote_plugin_reference_16248_11_10');">Continue reading</span></span></span>。</p>



<p>例えば、下の図は \( \mathrm{First} (c) \) の要素を \( \mathrm{Follow} (S) \) に追加しているため、\( \mathrm{First} (c) \subseteq \mathrm{Follow} (S) \) が必ず成立します。</p>



<figure class="wp-block-image aligncenter size-full"><img width="936" height="250" src="https://www.momoyama-usagi.com/wp-content/uploads/konpai3-9.gif" alt="" class="wp-image-16725"/></figure>



<p>この包含関係を、書いた図の中に出てくる矢印それぞれ（下の図の場合は5か所）でチェックします<span class="footnote_referrer"><a tabindex="0" onclick="footnote_moveToReference_16248_11('footnote_plugin_reference_16248_11_11');" onkeypress="footnote_moveToReference_16248_11('footnote_plugin_reference_16248_11_11');" ><sup id="footnote_plugin_tooltip_16248_11_11" class="footnote_plugin_tooltip_text">[11]</sup></a><span id="footnote_plugin_tooltip_text_16248_11_11" class="footnote_tooltip">具体的には、\( \{ $ \} \subseteq \mathrm{Follow} (S)  \), \( \mathrm{First} (c) \subseteq \mathrm{Follow} (S) \), \( \mathrm{Follow} (S) \subseteq \mathrm{Follow} (A) \), \( \mathrm{First} (A)&nbsp;&#x2026; <span class="footnote_tooltip_continue"  onclick="footnote_moveToReference_16248_11('footnote_plugin_reference_16248_11_11');">Continue reading</span></span></span>。矢印すべての箇所で包含関係が成り立っていればOKです。</p>



<p>※ 1つでも成り立っていないものがあれば、計算ミスをしています。</p>



<figure class="wp-block-image aligncenter size-large"><img width="1024" height="578" src="https://www.momoyama-usagi.com/wp-content/uploads/konpai3-12-1-1024x578.gif" alt="" class="wp-image-16732" srcset="https://www.momoyama-usagi.com/wp-content/uploads/konpai3-12-1-1024x578.gif 1024w, https://www.momoyama-usagi.com/wp-content/uploads/konpai3-12-1-300x169.gif 300w, https://www.momoyama-usagi.com/wp-content/uploads/konpai3-12-1-768x434.gif 768w, https://www.momoyama-usagi.com/wp-content/uploads/konpai3-12-1-1536x867.gif 1536w" /><figcaption>5つの矢印 → それぞれで包含関係を調べれば検算完了！</figcaption></figure>



<div style="height:100px" class="wp-block-spacer"></div>



<h2 class="wp-block-heading">4. Director集合とLL(1)文法の判定</h2>



<h3 class="wp-block-heading">(1) Director集合とは</h3>



<p>ある文法がLL(1)文法、つまり「1文字の先読みをするだけで、与えられた文字列を構文解析できる文法」とはどのような文法なのかをもう少し詳しく見ていきましょう。</p>



<p>例えば、文字列 \( baba \) が生成規則\[\begin{align*}<br>S &amp; \to aS \\<br>S &amp; \to bA \\<br>S &amp; \to bAb \\<br>A &amp; \to a<br>\end{align*}\]の文法を満たすか「1文字の先読み」で判定することを考えましょう。</p>



<p>まず、1文字目を先読みすると \( b \) となりますね。出発記号 \( S \) から \( \textcolor{blue}{b} \) で始まる規則を探そうとしますが、\( S \to \textcolor{blue}{b} A \) と \( S \to \textcolor{blue}{b} Ab \) の2つが存在してしまっているため、どちらの文法規則を使っていいかわかりません。</p>



<p>このように、同じ非終端記号から生成される文字列を終端記号にした文字列の先頭が\[<br>S \to \textcolor{blue}{b}A , \ \ \ S \to \textcolor{blue}{b} A b<br>\]のように重複していると、「1文字の先読みだけでは、どの構文規則を適用すればよいかわからなくなるため、与えられた文字列を構文解析できない」ことがわかりますね。</p>


<p><span>言い換えると、LL(1)文法であるかを判定するためには、<span  style="background-image:linear-gradient(to bottom,transparent 0%,#FFF387 0%);" class="dbp-e-marker-animation blue">同一非終端記号から生成されるすべての生成規則に対し、生成される可能性がある「終端記号の文字列の先頭文字」がすべて異なっていればOK</span>ですね。</span>&nbsp;</p>


<div style="height:36px" class="wp-block-spacer"></div>



<h3 class="wp-block-heading">(2) Director集合の定義と計算公式</h3>



<p>LL(1)文法であるかを機械的に判定するために登場したのがDirector集合です。</p>



<p>Director集合は、生成規則 \( \textcolor{magenta}{A} \to \textcolor{deepskyblue}{\alpha} \) に対し、「\( \textcolor{magenta}{A} \) から生成される文字列 \( \textcolor{deepskyblue}{\alpha} \) をすべて終端記号にしたときの先頭に来る文字の候補」を表しており、\[<br>\mathrm{Director} ( \textcolor{magenta}{A} , \textcolor{deepskyblue}{\alpha} )<br>\]と表記します。</p>



<h4 class="wp-block-heading">[Director集合の計算公式1] αに空文字が来ない場合</h4>



<p>ここで、生成規則 \( A \to \alpha \) の生成先 \( \textcolor{deepskyblue}{\alpha} \) をすべて終端記号にしたときの先頭に来る文字の候補というのは、\( \alpha \) に空文字が来ない限り \( \mathrm{First} (  \textcolor{deepskyblue}{\alpha} \) と書き換えることができます。</p>



<p>よって、\( \alpha \) に空文字が来ない場合（\( = \varepsilon \notin \mathrm{First} ( \alpha ) \)）は、\[<br>\mathrm{Director} ( \textcolor{magenta}{A} , \textcolor{deepskyblue}{\alpha} ) = \mathrm{First} ( \textcolor{deepskyblue}{\alpha} )<br>\]でDirector集合を求めることが可能です。</p>



<h4 class="wp-block-heading">[Director集合の計算公式2] αに空文字が来る可能性がある場合</h4>



<p>しかし、\( A \to \varepsilon \) が代入される可能性がある（\( = \varepsilon \in \mathrm{First} ( \alpha ) \)）場合、下のように \( A \to \varepsilon \) が適用されることで \( A \) のつぎの文字列 \( X \) が先頭に出てくる可能性があります。\[<br>A \textcolor{blue}{X}  \xrightarrow{A \to \varepsilon} \textcolor{blue}{X} <br>\]そのため、\(  \varepsilon \in \mathrm{First}  (  \textcolor{deepskyblue}{\alpha}  ) \) となる場合は \( \mathrm{First} (  \textcolor{deepskyblue}{\alpha} ) \) に加えて \( A \) の直後に来る終端記号の文字を表す \( \mathrm{Follow} (  \textcolor{magenta}{A} ) \) もDirector集合に加えます。</p>



<p>よって、\( \alpha \) に空文字が来る場合（\( = \varepsilon \in \mathrm{First} ( \alpha ) \)）は、\[<br>\mathrm{Director} ( \textcolor{magenta}{A} , \textcolor{deepskyblue}{\alpha} ) = \mathrm{Follow} ( \textcolor{magenta}{A} )<br>\]でDirector集合を求めることが可能です。</p>


<div class='wp-block-dbp-frame l-frame-inner is-design-inline is-frame-style-default dbp-frame has-bgcolor'><div class="dbp-frame-title">Director集合の定義</div><div class="dbp-frame-content has-content-gap">
<p>ある生成規則 \( \textcolor{magenta}{A} \to \textcolor{deepskyblue}{ \alpha } \) に対し、\( \textcolor{magenta}{A} \) を変形した際に先頭に来る文字列の候補をDirector集合と呼び、\( \mathrm{Director} ( \textcolor{magenta}{A} , \textcolor{deepskyblue}{\alpha} )  \) で記す。</p>

<p>ここで、Director集合はつぎのように計算ができる。</p>

<p>[公式1] \( \alpha \) が空文字とならない場合（ \( \varepsilon \notin \mathrm{First} ( \alpha ) \) ）\[<br>\mathrm{Director} ( \textcolor{magenta}{A} , \textcolor{deepskyblue}{\alpha} ) = \mathrm{First} ( \textcolor{deepskyblue}{\alpha} ) - \{ \varepsilon \}<br>\]</p>

<p>[公式2] \( \alpha \) が空文字となりうる場合（ \( \varepsilon \in \mathrm{First} ( \alpha ) \) ）\[<br>\mathrm{Director} ( \textcolor{magenta}{A} , \textcolor{deepskyblue}{\alpha} ) = \mathrm{First} ( \textcolor{deepskyblue}{\alpha} ) \cup \mathrm{Follow}  ( \textcolor{magenta}{A}  ) - \{ \varepsilon \}<br>\]</p>

<p>※ 特に \( A \to \varepsilon \) の場合、\[<br>\mathrm{Director} ( \textcolor{magenta}{A} , \textcolor{deepskyblue}{\alpha} ) = \mathrm{Follow}  ( \textcolor{magenta}{A} )<br>\]と計算できる。（[公式2]の変形）</p>
</div></div>


<div style="height:36px" class="wp-block-spacer"></div>



<h3 class="wp-block-heading">(3) Director集合を用いたLL(1)文法の判定</h3>


<p><span>LL(1)文法であるかどうかは、<span  style="background-image:linear-gradient(to bottom,transparent 0%,#FFF387 0%);" class="dbp-e-marker y">同一非終端記号から生成されるすべての生成規則に対し、生成される可能性がある「非終端記号の文字列の先頭文字」がすべて異なっていればOK</span>でしたね。</span></p>


<p>このLL(1)文法であるかの判定をDirector集合を用いて書くと下のようになります。</p>


<div class='wp-block-dbp-frame l-frame-inner is-design-inline is-frame-style-default dbp-frame has-bgcolor'><div class="dbp-frame-title">Director集合を用いたLL(1)文法の判定法</div><div class="dbp-frame-content has-content-gap">
<p>ある文法がLL(1)文法であることを確認するためには、2つ以上の生成元を持つすべての非終端記号に対し、同じ生成元 \( A \) のどの2つの規則 \( A \to \alpha_i \), \( A \to \alpha_j \) を選んでも\[<br>\mathrm{Director} ( A , \alpha_i)  \cap \mathrm{Director} ( A , \alpha_j ) = \phi<br>\]が成立すればLL(1)文法である。（1つでも成り立たないものがあった時点でLL(1)文法ではない。）</p>
</div></div>


<p>[例]</p>



<p>生成規則\[\begin{align*}<br>A &amp; \to \alpha_1 | \ \alpha_2  \\ <br>B &amp; \to \beta_1 \\<br>C &amp; \to \gamma_1 | \ \gamma_2 \ | \ \gamma_3 <br>\end{align*}\]からなる文法の場合、2つ以上の生成元を持つ非終端記号は \( A \)（2つ）と \( C \)（3つ）である。</p>



<p>(i) \( A \) で確認する内容\[<br>\mathrm{Director} ( A , \alpha_1 ) \cap \mathrm{Director} ( A , \alpha_2 ) = \phi<br>\]</p>



<div style="height:21px" class="wp-block-spacer"></div>



<p>(ii) \( C \) で確認する内容\[\begin{align*}<br>\mathrm{Director} ( C , \gamma_1 ) \cap \mathrm{Director} ( C , \gamma_2 ) &amp; = \phi \\<br>\mathrm{Director} ( C , \gamma_1 ) \cap \mathrm{Director} ( C , \gamma_3 ) &amp; = \phi \\<br>\mathrm{Director} ( C , \gamma_2 ) \cap \mathrm{Director} ( C , \gamma_3 ) &amp; = \phi <br>\end{align*}\]※ 3つの生成規則の中から2つを選ぶ組み合わせは、(生成規則1, 生成規則2), (生成規則1, 生成規則3), (生成規則2, 生成規則3) の3通りあるので、3通りとも調べる必要あり。</p>



<div style="height:21px" class="wp-block-spacer"></div>



<p>この(i), (ii)で出てきた式（合計4つ）がすべて成立すればLL(1)文法であることが言えます。一方、どれか1つでも成立しなかった時点でLL(1)文法ではありません。</p>



<div style="height:36px" class="wp-block-spacer"></div>



<h3 class="wp-block-heading">(4) 例題で確認してみよう</h3>



<p>Director集合の算出、およびLL(1)文法の確認を例題で確認していきましょう。</p>


<div class='wp-block-dbp-frame l-frame-float is-design-onframe is-frame-style-default dbp-frame has-bgcolor'><div class="dbp-frame-title">例題3</div><div class="dbp-frame-content has-content-gap">
<p>次の文法 \( G \) がある。\[<br>G = \left( \ \{ S, A, B \} \ , \  \{ a,b,c,d \} \ , \  P \ , \ S \ \right)<br>\]\[\begin{align*}<br>P = \{ \ \ \ \ S  &amp;  \to aA \\ A &amp;  \to bBa \ | \ \varepsilon \\ B &amp;  \to Sc \ | \ d \ \ \ \ \ \ \ \}<br>\end{align*}<br>\]この文法 \( G \) がLL(1)文法であることを確認しなさい。</p>

<p>※ 必要であれば例題1, 例題2で求めた\[\begin{align*}<br>\mathrm{First} (S) &amp; =  \{ a \}<br>\\ \mathrm{First} (A) &amp; = \{ b, \varepsilon \}<br>\\ \mathrm{First} (B) &amp; =  \{ a,d \} <br>\\ \mathrm{Follow} (S) &amp; =   \{ c, \$ \}<br>\\ \mathrm{Follow} (A) &amp; =  \{ c, \$ \}<br>\\ \mathrm{Follow} (B) &amp; =   \{ b. c, \$ \}<br>\end{align*}\]を用いてもよい。</p>
</div></div>


<p><strong>[解説]</strong></p>



<p>LL(1)文法であるか判定するためには、2つ以上の生成規則を持つ各非終端記号に対して、Director集合を取り、その積を確認します。</p>



<p>(i) \( A \) が生成元の生成規則 \( A \to bBa \), \( A \to \varepsilon \) に対してDirector集合確認</p>



<p>\( \textcolor{magenta}{A} \to \textcolor{deepskyblue}{bBa} \) のDirector集合\[\begin{align*}<br>\mathrm{Director} ( \textcolor{magenta}{A} , \textcolor{deepskyblue}{bBa} ) &amp; = \mathrm{First} ( \textcolor{deepskyblue}{bBa})<br>\\ &amp;  \overset{ \mathrm{R3} }{=} \mathrm{First} ( b )<br>\\ &amp;  \overset{ \mathrm{R1} }{=} \{ b \}<br>\end{align*}\]</p>



<p>\( \textcolor{magenta}{A} \to \textcolor{gray}{\varepsilon} \) のDirector集合\[\begin{align*}<br>\mathrm{Director} ( \textcolor{magenta}{A} , \textcolor{gray}{\varepsilon}  ) &amp; = \mathrm{Follow} ( \textcolor{magenta}{A} )<br>\\ &amp; =  \{ c, \$ \}<br>\end{align*}\]</p>



<div style="height:32px" class="wp-block-spacer"></div>



<p>\( A \) に関する各Director集合の積を取ると、\[\begin{align*}<br>\mathrm{Director} ( A, bBa  ) \cap \mathrm{Director} ( A, \varepsilon ) &amp; = \{ b \} \cap \{ c , \$ \}<br>\\ &amp; = \phi <br>\end{align*}\]となるためOK。</p>



<div style="height:48px" class="wp-block-spacer"></div>



<p>(ii) \( B \) が生成元の生成規則 \( B \to Sc \), \( B \to d \) に対してDirector集合確認</p>



<p>\( \textcolor{magenta}{B} \to \textcolor{deepskyblue}{Sc} \) のDirector集合\[\begin{align*}<br>\mathrm{Director} ( \textcolor{magenta}{B} , \textcolor{deepskyblue}{Sc}  ) &amp; = \mathrm{First} ( \textcolor{deepskyblue}{Sc} )<br>\\ &amp;  \overset{ \mathrm{R3} }{=} \mathrm{First} (S)<br>\\ &amp;  = \{ a \}<br>\end{align*}\]</p>



<p>\( \textcolor{magenta}{B} \to \textcolor{deepskyblue}{d} \) のDirector集合\[\begin{align*}<br>\mathrm{Director} ( \textcolor{magenta}{B} , \textcolor{deepskyblue}{d}  ) &amp; = \mathrm{First} ( \textcolor{deepskyblue}{d} )<br>\\ &amp;  \overset{ \mathrm{R1} }{=} \{ d \}<br>\end{align*}\]</p>



<div style="height:32px" class="wp-block-spacer"></div>



<p>\( B \) に関する各Director集合の積を取ると、\[\begin{align*}<br>\mathrm{Director} ( B, Sc  ) \cap \mathrm{Director} ( B,  d ) &amp; = \{ a \} \cap \{ d \}<br>\\ &amp; = \phi <br>\end{align*}\]となるためOK。</p>



<div style="height:32px" class="wp-block-spacer"></div>



<p>(i), (ii)よりLL(1)文法であることが確認できた。</p>



<p>※ \( S \) に対しては、\( S \to a A \) の1つの生成規則しかないため、Director集合は求めなくてOK。</p>



<div style="height:100px" class="wp-block-spacer"></div>



<h2 class="wp-block-heading">5. 練習問題</h2>



<p>それでは、ここまでの学習内容を練習問題を通じておさらいしていきましょう。</p>



<p>今回は、2問の練習問題を用意しています。</p>



<h3 class="wp-block-heading">練習1. </h3>


<div class='wp-block-dbp-frame l-frame-float is-design-onframe is-frame-style-default dbp-frame has-bgcolor'><div class="dbp-frame-title">練習1</div><div class="dbp-frame-content has-content-gap">
<p>次の文法 \( G \) がある。\[<br>G = \left( \ \{ S, A, B \} \ , \  \{ a,b,c,d \} \ , \  P \ , \ S \ \right)<br>\]\[\begin{align*}<br>P = \{ \ \ \ S  &amp;  \to aAa \\ A &amp;  \to bB \ | \ SB \\ B &amp;  \to cB \ | \ dAb \ | \ \varepsilon \ \ \}<br>\end{align*}<br>\]つぎの(1)～(3)の問いに答えなさい。</p>

<p>(1) \( \mathrm{First} (S) \), \( \mathrm{First} (A) \), \( \mathrm{First} (B) \) を求めなさい。<br>(2) \( \mathrm{Follow} (S) \), \( \mathrm{Follow} (A) \), \( \mathrm{Follow} (B) \) を求めなさい。<br>(3) この文法 \( G \) はLL(1)文法かどうかを理由を踏まえて答えなさい。</p>
</div></div>


<div style="height:51px" class="wp-block-spacer"></div>



<h3 class="wp-block-heading">練習2. </h3>


<div class='wp-block-dbp-frame l-frame-float is-design-onframe is-frame-style-default dbp-frame has-bgcolor'><div class="dbp-frame-title">練習2</div><div class="dbp-frame-content has-content-gap">
<p>次の文法 \( G \) がある。\[<br>G = \left( \ \{ S, A, B, C \} \ , \  \{ a,b,c,d \} \ , \  P \ , \ S \ \right)<br>\]\[\begin{align*}<br>P = \{ \ \ \ S  &amp;  \to AaB \\ A &amp;  \to cCA \ | \ c \\ B &amp;  \to S \ | \ BA \ |  \  \varepsilon \\ C &amp; \to Bc \ \ \ \ \ \ \ \ \ \ \ \ \ \ \}<br>\end{align*}<br>\]つぎの(1)～(4)の問いに答えなさい。</p>

<p>(1) \( \mathrm{First} (S) \), \( \mathrm{First} (A) \), \( \mathrm{First} (B) \), \( \mathrm{First} (C) \) を求めなさい。<br>(2) \( \mathrm{Follow} (S) \), \( \mathrm{Follow} (A) \), \( \mathrm{Follow} (B) \), \( \mathrm{Follow} (C) \) を求めなさい。<br>(3) この文法 \( G \) はLL(1)文法かどうかを理由を踏まえて答えなさい。</p>
</div></div>






<h2 class="wp-block-heading">6. 練習問題の答え</h2>



<h3 class="wp-block-heading">解答1. </h3>



<p>規則\[\begin{align*}<br>P = \{ \ \ \ S  &amp;  \to aAa \\ A &amp;  \to bB \ | \ SB \\ B &amp;  \to cB \ | \ dAb \ | \ \varepsilon \ \ \}<br>\end{align*}<br>\]で表される文法に対してFirst集合、Follow集合、Director集合を求めてLL(1)文法を判定する。</p>



<h4 class="wp-block-heading">(1) First集合の算出</h4>



<p>[略解]\[\begin{align*}<br>\mathrm{First} (S) &amp; = \{ a \} \\ <br>\mathrm{First} (A) &amp; = \{ a,b \} \\ <br>\mathrm{First} (B) &amp; = \{ c,d, \varepsilon \} <br>\end{align*}\]</p>



<div style="height:22px" class="wp-block-spacer"></div>



<p><strong>(i) \( \mathrm{First} (S) \) の計算</strong></p>



<p>\( S \) が生成元の規則は \( S \to \textcolor{red}{aAa} \) の1つだけなので、\( S \to \textcolor{red}{aAa} \) だけに着目すればOK。</p>



<p>\[\begin{align*}<br>\mathrm{First} (S) &amp;  \overset{ \mathrm{R2} }{=} \underbrace { \mathrm{First} (\textcolor{red}{aAa}) }_{S \to \textcolor{red}{aAa}}<br>\\ &amp; \overset{ \mathrm{R3} }{=} \mathrm{First} (a)<br>\\ &amp; \overset{ \mathrm{R1} }{=} \{ a \}<br>\end{align*}\]</p>



<div style="height:36px" class="wp-block-spacer"></div>



<p><strong>(ii) \( \mathrm{First} (A) \) の計算</strong></p>



<p>\( A \) が生成元の規則は \( A \to bB \) と \( A \to SB \) の2つがある。</p>



<p>そのため、\( \mathrm{First} (A) \) を求める際には  \( A \to \textcolor{red}{bB}\) と \( A \to \textcolor{blue}{SB} \) の2つの規則に着目すればOK。\[<br>\mathrm{First} (A)   \overset{ \mathrm{R2} }{=} \underbrace{ \mathrm{First} (\textcolor{red}{bB}) }_{ A \to \textcolor{red}{bB} } \cup \underbrace{ \mathrm{First} (\textcolor{blue}{SB}) }_{ A \to \textcolor{blue}{SB} } <br>\]</p>



<p>ここでそれぞれの項のFirst集合は以下のように計算できる。</p>



<p>\[\begin{align*}<br>\mathrm{First} (bB) &amp; \overset{ \mathrm{R3} }{=} \mathrm{First} (b)<br>\\ &amp; \overset{ \mathrm{R1} }{=} \{ b \}<br>\end{align*}\]</p>



<p>\[\begin{align*}<br>\mathrm{First} (SB) &amp; \overset{ \mathrm{R3} }{=} \mathrm{First} (S)<br>\\ &amp; \overset{ \mathrm{(1)} }{=} \{ a \}<br>\end{align*}\]</p>



<p>よって、\[\begin{align*}<br>\mathrm{First} (A) &amp;   \overset{ \mathrm{R2} }{=} \underbrace{ \mathrm{First} (bB) }_{ A \to bB } \cup \underbrace{ \mathrm{First} (SB) }_{ A \to SB } <br>\\ &amp; = \{ b \} \cup \{ a \}<br>\\ &amp; = \{ a, b \}<br>\end{align*}\]となる。</p>



<div style="height:36px" class="wp-block-spacer"></div>



<p><strong>(iii) \( \mathrm{First} (B) \) の計算</strong></p>



<p>\( B \) が生成元の規則は \( B \to cB \), \( B \to dAb \), \( B \to \varepsilon \) の3つがある。</p>



<p>そのため、\( \mathrm{First} (B) \) を求める際には   \( B \to \textcolor{red}{cB} \), \( B \to \textcolor{blue}{dAb} \), \( B \to \textcolor{green}{\varepsilon} \)  の3つの規則に着目すればOK。\[<br>\mathrm{First} (B)   \overset{ \mathrm{R2} }{=} \underbrace{ \mathrm{First} (\textcolor{red}{cB}) }_{ B \to \textcolor{red}{cB} } \cup \underbrace{ \mathrm{First} (\textcolor{blue}{dAb}) }_{B \to \textcolor{blue}{dAb}}  \cup \underbrace{ \mathrm{First} (\textcolor{green}{\varepsilon}) }_{B \to \textcolor{green}{\varepsilon}}<br>\]</p>



<p>ここでそれぞれの項のFirst集合は以下のように計算できる。</p>



<p>\[\begin{align*}<br>\mathrm{First} (cB) &amp; \overset{ \mathrm{R3} }{=} \mathrm{First} (c)<br>\\ &amp; \overset{ \mathrm{R1} }{=} \{ c \}<br>\end{align*}\]</p>



<p>\[\begin{align*}<br>\mathrm{First} (dAb) &amp; \overset{ \mathrm{R3} }{=} \mathrm{First} (d)<br>\\ &amp; \overset{ \mathrm{(1)} }{=} \{ d \}<br>\end{align*}\]</p>



<p>\[\begin{align*}<br>\mathrm{First} (\varepsilon) \overset{ \mathrm{R1} }{=} \{ \varepsilon \}<br>\end{align*}\]</p>



<p>よって、\[\begin{align*}<br>\mathrm{First} (B) &amp;  \overset{ \mathrm{R2} }{=} \mathrm{First} (cB) \cup \mathrm{First} (dAb)  \cup \mathrm{First} (\varepsilon) <br>\\ &amp; = \{ c \} \cup \{ d \} \cup \{ \varepsilon \} <br>\\ &amp; = \{ c,d, \varepsilon \}<br>\end{align*}\]となる。</p>



<div style="height:61px" class="wp-block-spacer"></div>



<h4 class="wp-block-heading">(2) Follow集合の算出</h4>



<p>[略解]\[\begin{align*}<br>\mathrm{Follow} (S) &amp; = \{ a,b,c,d, \$ \} \\ <br>\mathrm{Follow} (A) &amp; = \{ a,b \} \\ <br>\mathrm{Follow} (B) &amp; = \{ a,b \} <br>\end{align*}\]</p>



<div style="height:22px" class="wp-block-spacer"></div>



<p><strong>(i) \( \mathrm{Follow} (S) \) の算出式</strong></p>



<p>[公式1] \( S \) は出発記号？ → Yes。なので、\( \mathrm{Follow} (S) \) に \( \$  \) を追加。\[<br>\mathrm{Follow} (S)  += \{ \$ \}<br>\]</p>



<div style="height:23px" class="wp-block-spacer"></div>



<p>\( \textcolor{magenta}{S} \) が生成先に含まれる規則は、\( A \to \textcolor{magenta}{S} B \) のみなので、\( A \to \textcolor{magenta}{S} B \) にのみ着目すればOK。</p>



<p>ここで、\( A \to \textcolor{magenta}{ S } \textcolor{blue}{ \underbrace{B}_{ \beta } } \) より、\( \textcolor{blue}{\beta = B} \) とおく。</p>



<p>[公式2] \( \beta \not =  \varepsilon \)？ → \( \beta = B \not = \varepsilon \) なのでYes。</p>



<p>なので、\( A \to \textcolor{magenta}{S} \textcolor{blue}{ B } \) に対し、以下の集合の要素を追加。\( A\[\begin{align*}<br>\mathrm{Follow} ( \textcolor{magenta}{S} ) + &amp; = \mathrm{First} ( \textcolor{blue}{B} ) - \{ \varepsilon \}<br>\\ &amp; = \{ c,d, \varepsilon \} - \{ \varepsilon \}<br>\\ &amp; = \{ c,d \}<br>\end{align*}\]</p>



<div style="height:23px" class="wp-block-spacer"></div>



<p>[公式3] \( \varepsilon \in \mathrm{First} ( \beta ) \)？ → \( \mathrm{First} ( \beta ) = \{ c,d, \varepsilon \} \) なのでYes。</p>



<p>なので、\( \textcolor{blue}{A} \to \textcolor{magenta}{S} B \) に対し、以下の集合の要素を追加。\[\begin{align*}<br>\mathrm{Follow} ( \textcolor{magenta}{S} ) + &amp; = \mathrm{Follow} ( \textcolor{blue}{A} ) <br>\end{align*}\]</p>



<p>よって、\( \mathrm{Follow} (S) \) に追加される要素は以下の図で示す通り。</p>



<figure class="wp-block-image aligncenter size-full"><img width="987" height="628" src="https://www.momoyama-usagi.com/wp-content/uploads/konpai3-19.gif" alt="" class="wp-image-16937"/><figcaption>\( \mathrm{Follow} (S) \) で追加される要素の図示</figcaption></figure>



<div style="height:42px" class="wp-block-spacer"></div>



<p><strong>(ii) \( \mathrm{Follow} (A) \) の算出式</strong></p>



<p>[公式1] \( A \) は出発記号？ → No。</p>



<div style="height:23px" class="wp-block-spacer"></div>



<p>\( \textcolor{magenta}{A} \) が生成先に含まれる規則は、\( S \to a \textcolor{magenta}{A} a \), \( B \to d \textcolor{magenta}{A} b \) の2つなので、この2つの規則に着目すればOK。</p>



<p><strong>[a] \( S \to a \textcolor{magenta}{A} a \) に着目したとき</strong></p>



<p>\( S \to a \textcolor{magenta}{ A } \textcolor{blue}{ \underbrace{a}_{ \beta } } \) とおく。（つまり \( \textcolor{blue}{\beta = a} \)）</p>



<p>[公式2] \( \beta \not =  \varepsilon \)？ → \( \textcolor{blue}{\beta = a} \not = \varepsilon \) なのでYes。</p>



<p>なので、\( S \to a \textcolor{magenta}{A} \textcolor{blue}{ a } \) に対し、以下の集合の要素を追加。\[\begin{align*}<br>\mathrm{Follow} ( \textcolor{magenta}{A} ) + &amp; = \mathrm{First} ( \textcolor{blue}{a} ) <br>\\ &amp; = \{ a \}<br>\end{align*}\]</p>



<div style="height:23px" class="wp-block-spacer"></div>



<p>[公式3] \( \varepsilon \in \mathrm{First} ( \textcolor{blue}{\beta} ) \)？ → \( \mathrm{First} ( \textcolor{blue}{\beta} ) = \mathrm{First} ( \textcolor{blue}{a} ) = \{ a \} \) なのでNo。</p>



<div style="height:23px" class="wp-block-spacer"></div>



<p><strong>[b] \( B \to d \textcolor{magenta}{A} b \) に着目したとき</strong></p>



<p>[公式2] \( \beta \not =  \varepsilon \)？ → \( \textcolor{blue}{\beta = b} \not = \varepsilon \) なのでYes。</p>



<p>なので、\( S \to d \textcolor{magenta}{A} \textcolor{blue}{ b } \) に対し、以下の集合の要素を追加。\[\begin{align*}<br>\mathrm{Follow} ( \textcolor{magenta}{A} ) + &amp; = \mathrm{First} ( \textcolor{blue}{b} ) <br>\\ &amp; = \{ b \}<br>\end{align*}\]</p>



<div style="height:23px" class="wp-block-spacer"></div>



<p>[公式3] \( \varepsilon \in \mathrm{First} ( \beta ) \)？ → \( \mathrm{First} ( \textcolor{blue}{\beta} ) = \mathrm{First} ( \textcolor{blue}{b} )  = \{ b \} \) なのでNo。</p>



<p>よって、\( \mathrm{Follow} (A) \) に追加される要素は以下の図で示す通り。</p>



<figure class="wp-block-image aligncenter size-full"><img width="939" height="403" src="https://www.momoyama-usagi.com/wp-content/uploads/konpai3-20.gif" alt="" class="wp-image-16938"/></figure>



<div style="height:42px" class="wp-block-spacer"></div>



<p><strong>(iii) \( \mathrm{Follow} (B) \) の算出式</strong></p>



<p>[公式1] \( B \) は出発記号？ → No。</p>



<div style="height:23px" class="wp-block-spacer"></div>



<p>\( \textcolor{magenta}{B} \) が生成先に含まれる規則は、\( A \to b \textcolor{magenta}{B} \),  , \( A \to S \textcolor{magenta}{B} \)  ,\( B \to c \textcolor{magenta}{B} \) の3つ。ただし、\( B \to c \textcolor{magenta}{B} \) は右再帰規則のため無視。なので、\( A \to b \textcolor{magenta}{B} \),  \( A \to S \textcolor{magenta}{B} \) の2つの規則に着目すればOK。</p>



<p><strong>[a] \(  A \to b \textcolor{magenta}{B} \) に着目したとき</strong></p>



<p>\( A \to b \textcolor{magenta}{ B } \) の \( \textcolor{magenta}{B} \) の後ろの文字が存在しない。そのため、\( \textcolor{blue}{\beta = \varepsilon} \) である。</p>



<p>[公式2] \( \beta \not =  \varepsilon \)？ → \( \textcolor{blue}{\beta = \varepsilon} \) なのでNo。</p>



<div style="height:23px" class="wp-block-spacer"></div>



<p>[公式3] \( \varepsilon \in \mathrm{First} ( \beta ) \)？ → \( \mathrm{First} ( \textcolor{blue}{\beta} ) = \mathrm{First} ( \textcolor{blue}{ \varepsilon } )  = \{ \varepsilon \} \) なのでYes。</p>



<p>なので、\( \textcolor{blue}{A} \to b \textcolor{magenta}{B} \) に対し、以下の集合の要素を追加。\[\begin{align*}<br>\mathrm{Follow} ( \textcolor{magenta}{B} ) + &amp; = \mathrm{Follow} ( \textcolor{blue}{A} ) <br>\end{align*}\]</p>



<div style="height:23px" class="wp-block-spacer"></div>



<p><strong>[b] \(  A \to S \textcolor{magenta}{B}\) に着目したとき</strong></p>



<p>\( A \to S \textcolor{magenta}{ B } \) の \( \textcolor{magenta}{B} \) の後ろの文字が存在しない。そのため、\( \textcolor{blue}{\beta = \varepsilon} \) である。</p>



<p>[公式2] \( \beta \not =  \varepsilon \)？ → \( \textcolor{blue}{\beta = \varepsilon} \) なのでNo。</p>



<div style="height:23px" class="wp-block-spacer"></div>



<p>[公式3] \( \varepsilon \in \mathrm{First} ( \beta ) \)？ → \( \mathrm{First} ( \textcolor{blue}{\beta} ) = \mathrm{First} ( \textcolor{blue}{ \varepsilon } ) = \{ \varepsilon \} \) なのでYes。</p>



<p>なので、\( \textcolor{blue}{A} \to S \textcolor{magenta}{B} \) に対し、以下の集合の要素を追加。\[\begin{align*}<br>\mathrm{Follow} ( \textcolor{magenta}{B} ) + &amp; = \mathrm{Follow} ( \textcolor{blue}{A} ) <br>\end{align*}\]</p>



<p>※ 式から察している人もいるかもしれませんが、[a] の生成式と全く同じ結果が出てきます。</p>



<p>よって、\( \mathrm{Follow} (B) \) に追加される要素は以下の図で示す通り。</p>



<figure class="wp-block-image aligncenter size-large"><img width="1024" height="164" src="https://www.momoyama-usagi.com/wp-content/uploads/konpai3-21-1024x164.gif" alt="" class="wp-image-16939" srcset="https://www.momoyama-usagi.com/wp-content/uploads/konpai3-21-1024x164.gif 1024w, https://www.momoyama-usagi.com/wp-content/uploads/konpai3-21-300x48.gif 300w, https://www.momoyama-usagi.com/wp-content/uploads/konpai3-21-768x123.gif 768w" /><figcaption>\( \mathrm{Follow} (A) \) で追加される要素の図示<br>（代表として \( A \to SB \) を選択）</figcaption></figure>



<p><strong>それぞれの計算結果をまとめてFollow集合を算出</strong></p>



<p>先ほど出した \( \mathrm{Follow} (S) \), \( \mathrm{Follow} (A) \), \( \mathrm{Follow} (B) \) の計算過程を1つの図に表すと、下のようになる。</p>



<figure class="wp-block-image aligncenter size-large"><img width="1024" height="587" src="https://www.momoyama-usagi.com/wp-content/uploads/konpai3-22-1024x587.gif" alt="" class="wp-image-16940" srcset="https://www.momoyama-usagi.com/wp-content/uploads/konpai3-22-1024x587.gif 1024w, https://www.momoyama-usagi.com/wp-content/uploads/konpai3-22-300x172.gif 300w, https://www.momoyama-usagi.com/wp-content/uploads/konpai3-22-768x440.gif 768w, https://www.momoyama-usagi.com/wp-content/uploads/konpai3-22-1536x881.gif 1536w" /></figure>



<p>あとは、求められるFollow集合から順にFollow集合を求めていけばOK。</p>



<p>※ 今回の場合は、\( \mathrm{Follow} (A) \) を求めてから、\( \mathrm{Follow} (S) \) と \( \mathrm{Follow} (B) \) を求めていく流れになりますね（\( \mathrm{Follow} (S) \) と \( \mathrm{Follow} (B) \) はどっちから求めてもOK）。</p>



<p>(ii) \( \mathrm{Follow} (A) \) の計算結果</p>



<figure class="wp-block-image aligncenter size-large"><img width="1024" height="587" src="https://www.momoyama-usagi.com/wp-content/uploads/konpai3-23-1024x587.gif" alt="" class="wp-image-16941" srcset="https://www.momoyama-usagi.com/wp-content/uploads/konpai3-23-1024x587.gif 1024w, https://www.momoyama-usagi.com/wp-content/uploads/konpai3-23-300x172.gif 300w, https://www.momoyama-usagi.com/wp-content/uploads/konpai3-23-768x440.gif 768w, https://www.momoyama-usagi.com/wp-content/uploads/konpai3-23-1536x881.gif 1536w" /></figure>



<p>[計算式]\[\begin{align*}<br>\mathrm{Follow} (A) &amp; = \mathrm{First} (a) \cup \mathrm{First} (b) - \{ \varepsilon \}<br>\\ &amp; = \{ a \} \cup \{ b \}<br>\\ &amp; = \{ a, b \}<br>\end{align*}\]</p>



<div style="height:32px" class="wp-block-spacer"></div>



<p>(i) \( \mathrm{Follow} (S) \) の計算結果</p>



<figure class="wp-block-image aligncenter size-large"><img width="1024" height="587" src="https://www.momoyama-usagi.com/wp-content/uploads/konpai3-24-1024x587.gif" alt="" class="wp-image-16942" srcset="https://www.momoyama-usagi.com/wp-content/uploads/konpai3-24-1024x587.gif 1024w, https://www.momoyama-usagi.com/wp-content/uploads/konpai3-24-300x172.gif 300w, https://www.momoyama-usagi.com/wp-content/uploads/konpai3-24-768x440.gif 768w, https://www.momoyama-usagi.com/wp-content/uploads/konpai3-24-1536x881.gif 1536w" /></figure>



<p>[計算式]\[\begin{align*}<br>\mathrm{Follow} (S) &amp; = \mathrm{First} (B) \cup \mathrm{Follow} (A) \cup \{ \$ \}  - \{ \varepsilon \}<br>\\ &amp; = \{ c, d, \varepsilon \} \cup \{ a,b \} \cup \{ \$ \} - \{ \varepsilon \}<br>\\ &amp; = \{ a, b, c, d, \$ \}<br>\end{align*}\]※ \( \varepsilon \) を無視するのを忘れずに</p>



<div style="height:32px" class="wp-block-spacer"></div>



<p>(iii) \( \mathrm{Follow} (B) \) の計算結果</p>



<figure class="wp-block-image aligncenter size-large"><img width="1024" height="587" src="https://www.momoyama-usagi.com/wp-content/uploads/konpai3-25-1024x587.gif" alt="" class="wp-image-16943" srcset="https://www.momoyama-usagi.com/wp-content/uploads/konpai3-25-1024x587.gif 1024w, https://www.momoyama-usagi.com/wp-content/uploads/konpai3-25-300x172.gif 300w, https://www.momoyama-usagi.com/wp-content/uploads/konpai3-25-768x440.gif 768w, https://www.momoyama-usagi.com/wp-content/uploads/konpai3-25-1536x881.gif 1536w" /></figure>



<p>[計算式]\[\begin{align*}<br>\mathrm{Follow} (B) &amp; = \mathrm{Follow} (A)<br>\\ &amp; = \{ a, b \}<br>\end{align*}\]※Follow集合の要素には \( \varepsilon \) が出てこないので、\( \varepsilon \) を引いていません。（引いてもOKです。）</p>



<div style="height:61px" class="wp-block-spacer"></div>



<h4 class="wp-block-heading">(3) Director集合の算出とLL(1)文法の判定</h4>



<p>各非終端記号に対して、生成元から2つ以上の生成規則を持つものは、</p>



<ol class="wp-block-list"><li>\( A \) が生成元となる規則：\( A \to bB \), \( A \to SB \)</li><li>\( B \) が生成元となる規則：\( B \to cB \), \( B \to dAb \), \( B \to \varepsilon \)</li></ol>



<p>である。あとは、非終端記号ごとに「どの生成規則同士の積をとっても、Director集合が空集合になること」を確認すればOK。</p>



<p>1) \( A \) が生成元の生成規則 \( A \to bB \), \( A \to SB \) に対してDirector集合確認</p>



<p>\( \textcolor{magenta}{A} \to \textcolor{deepskyblue}{bB}  \) のDirector集合\[\begin{align*}<br>\mathrm{Director} ( \textcolor{magenta}{A} , \textcolor{deepskyblue}{bB}  ) &amp; = \mathrm{First} ( \textcolor{deepskyblue}{bB} )<br>\\ &amp;  \overset{ \mathrm{R3} }{=} \mathrm{First} ( b )<br>\\ &amp;  \overset{ \mathrm{R1} }{=} \{ b \}<br>\end{align*}\]</p>



<p>\( \textcolor{magenta}{A} \to \textcolor{deepskyblue}{SB}  \) のDirector集合\[\begin{align*}<br>\mathrm{Director} ( \textcolor{magenta}{A} , \textcolor{deepskyblue}{SB}  ) &amp; = \mathrm{First} ( \textcolor{deepskyblue}{SB} )<br>\\ &amp;  \overset{ \mathrm{R3} }{=} \mathrm{First} ( S )<br>\\ &amp;  = \{ a \}<br>\end{align*}\]</p>



<p>\( A \) に関する各Director集合同士の積を取ると、\[\begin{align*}<br>\mathrm{Director} ( A, bB  ) \cap \mathrm{Director} ( A, SB ) &amp; = \{ b \} \cap \{ a \}<br>\\ &amp; = \phi <br>\end{align*}\]となるためOK。</p>



<div style="height:49px" class="wp-block-spacer"></div>



<p>2) \( B \) が生成元の生成規則 \( B \to cB \), \( B \to dAb \), \( B \to \varepsilon \)に対してDirector集合確認</p>



<p>\( \textcolor{magenta}{B} \to \textcolor{deepskyblue}{cB}  \) のDirector集合\[\begin{align*}<br>\mathrm{Director} ( \textcolor{magenta}{B} , \textcolor{deepskyblue}{cB}  ) &amp; = \mathrm{First} ( \textcolor{deepskyblue}{cB} )<br>\\ &amp;  \overset{ \mathrm{R3} }{=} \mathrm{First} ( c )<br>\\ &amp;  \overset{ \mathrm{R1} }{=} \{ c \}<br>\end{align*}\]</p>



<p>\( \textcolor{magenta}{B} \to \textcolor{deepskyblue}{dAb} \) のDirector集合\[\begin{align*}<br>\mathrm{Director} ( \textcolor{magenta}{B} , \textcolor{deepskyblue}{dAb}  ) &amp; = \mathrm{First} ( \textcolor{deepskyblue}{dAb} )<br>\\ &amp;  \overset{ \mathrm{R3} }{=} \mathrm{First} ( d )<br>\\ &amp;  \overset{ \mathrm{R1} }{=} \{ d \}<br>\end{align*}\]</p>



<p>\( \textcolor{magenta}{B} \to \textcolor{gray}{\varepsilon} \) のDirector集合\[\begin{align*}<br>\mathrm{Director} ( \textcolor{magenta}{B} , \textcolor{gray}{\varepsilon}  ) &amp; = \mathrm{Follow} ( \textcolor{magenta}{B} )<br>\\ &amp; =  \{ a, b \}<br>\end{align*}\]</p>



<p>\( B \) に関する各Director集合同士の積を取ると、\[\begin{align*}<br>\mathrm{Director} ( B, cB  ) \cap \mathrm{Director} ( B, dAb ) &amp; = \{ c \} \cap \{ d \}<br>= \phi  \\<br>\mathrm{Director} ( B, cB  ) \cap \mathrm{Director} ( B, \varepsilon ) &amp; = \{ c \} \cap \{ a,b \}<br>= \phi  \\<br>\mathrm{Director} ( B, dAb  ) \cap \mathrm{Director} ( B, \varepsilon ) &amp; = \{ d \} \cap \{ a,b \}<br>= \phi  <br>\end{align*}\]となるためOK。</p>



<div style="height:49px" class="wp-block-spacer"></div>



<p>1), 2) より、題意の文法はLL(1)文法である。</p>



<div style="height:90px" class="wp-block-spacer"></div>



<h3 class="wp-block-heading">解答2.  </h3>



<p>規則\[\begin{align*}<br>P = \{ \ \ \ S  &amp;  \to AaB \\ A &amp;  \to cCA \ | \ c \\ B &amp;  \to S \ | \ BA \ |  \  \varepsilon \\ C &amp; \to Bc \ \ \ \ \ \ \ \ \ \ \ \ \ \ \}<br>\end{align*}<br>\]で表される文法に対してFirst集合、Follow集合、Director集合を求めてLL(1)文法を判定する。</p>



<h4 class="wp-block-heading">(1) First集合の算出</h4>



<p>[略解]\[\begin{align*}<br>\mathrm{First} (S) &amp; = \{ c \} \\ <br>\mathrm{First} (A) &amp; = \{ c \} \\ <br>\mathrm{First} (B) &amp; = \{ c, \varepsilon \} \\<br>\mathrm{First} (C) &amp; = \{ c \} <br>\end{align*}\]</p>



<p><strong>(i) \( \mathrm{First} (S) \) の計算</strong> (途中まで)</p>



<p>\( S \) が生成元の規則は \( S \to \textcolor{red}{AaB} \) の1つだけなので、\( S \to \textcolor{red}{AaB} \) だけに着目すればOK。</p>



<p>\[\begin{align*}<br>\mathrm{First} (S) &amp;  \overset{ \mathrm{R2} }{=} \underbrace{ \mathrm{First} ( \textcolor{red}{AaB} ) }_{S \to \textcolor{red}{AaB}}<br>\\ &amp; \overset{ \mathrm{R3} }{=} \mathrm{First} (A)<br>\end{align*}\]※ まだ \( \mathrm{First} (A) \) が求まっていないため保留</p>



<div style="height:36px" class="wp-block-spacer"></div>



<p><strong>(ii) \( \mathrm{First} (A) \) の計算</strong>（と \( \mathrm{First} (S) \) の計算再開）</p>



<p>\( A \) が生成元の規則は \( A \to cCA \) と \( A \to c \) の2つがある。</p>



<p>そのため、\( \mathrm{First} (A) \) を求める際には  \( A \to \textcolor{red}{cCA} \) と \( A \to \textcolor{blue}{c} \) の2つの規則に着目すればOK。\[<br>\mathrm{First} (A)   \overset{ \mathrm{R2} }{=} \underbrace{ \mathrm{First} (\textcolor{red}{cCA}) }_{A \to \textcolor{red}{cCA}} \cup \underbrace{ \mathrm{First} ( \textcolor{blue}{c}) }_{A \to \textcolor{blue}{c}}<br>\]</p>



<p>ここでそれぞれの項のFirst集合は以下のように計算できる。</p>



<p>\[\begin{align*}<br>\mathrm{First} (cCA) &amp; \overset{ \mathrm{R3} }{=} \mathrm{First} (c)<br>\\ &amp; \overset{ \mathrm{R1} }{=} \{ c \}<br>\end{align*}\]</p>



<p>\[\begin{align*}<br>\mathrm{First} (c) &amp; \overset{ \mathrm{R1} }{=} \{ c \}<br>\end{align*}\]</p>



<p>よって、\[\begin{align*}<br>\mathrm{First} (A) &amp;  \overset{ \mathrm{R2} }{=} \mathrm{First} (cCA) \cup \mathrm{First} (c) <br>\\ &amp; = \{ c \} \cup \{ c \}<br>\\ &amp; = \{ c \}<br>\end{align*}\]となる。また、\( \mathrm{First} (S) \) も</p>



<p>\[\begin{align*}<br>\mathrm{First} (S) &amp;  \overset{ \mathrm{R2} }{=} \mathrm{First} (AaB)<br>\\ &amp; \overset{ \mathrm{R3} }{=} \mathrm{First} (A)<br>\\ &amp; = \{ c \}<br>\end{align*}\]と求められる。</p>



<div style="height:36px" class="wp-block-spacer"></div>



<p><strong>(iii) \( \mathrm{First} (B) \) の計算</strong></p>



<p>\( B \) が生成元の規則は \( B \to S \), \( B \to BA \), \( B \to \varepsilon \) の3つがある。</p>



<p>ただし、\( B \to B A \) は左再帰の文法なので無視する。そのため、\( \mathrm{First} (B) \) を求める際には   \( B \to \textcolor{red}{cB} \), \( B \to \textcolor{blue}{dAb} \) の2つの規則に着目すればOK。\[<br>\mathrm{First} (B)   \overset{ \mathrm{R2} }{=} \underbrace{ \mathrm{First} (\textcolor{red}{cB}) }_{B \to \textcolor{red}{ cB }} \cup \underbrace{ \mathrm{First} ( \textcolor{blue}{dAb} ) }_{B \to \textcolor{blue}{dAb} }<br>\]</p>



<p>ここで、\[\begin{align*}<br>\mathrm{First} (\varepsilon) \overset{ \mathrm{R1} }{=} \{ \varepsilon \}<br>\end{align*}\]なので、\( \mathrm{First} (B) \) は\[\begin{align*}<br>\mathrm{First} (B) &amp;  \overset{ \mathrm{R2} }{=} \mathrm{First} (S) \cup \mathrm{First} (\varepsilon) <br>\\ &amp; = \{ c \} \cup \{ \varepsilon \} <br>\\ &amp; = \{ c, \varepsilon \}<br>\end{align*}\]と計算できる。</p>



<div style="height:36px" class="wp-block-spacer"></div>



<p><strong>(iv) \( \mathrm{First} (C) \) の計算</strong></p>



<p>\( C \) が生成元の規則は \( C \to \textcolor{red}{Bc} \) だけなので、この規則のみに着目する。</p>



<p>よって、\[\begin{align*}<br>\mathrm{First} (C) &amp; \overset{ \mathrm{R2} }{=} \underbrace{ \mathrm{First} ( \textcolor{red}{Bc} ) }_{C \to \textcolor{red}{Bc}}<br>\\ &amp; \overset{ \mathrm{R3} }{=} \left( \mathrm{First} (B) - \{ \varepsilon \} \right) \cup \{ c \} \ \ \because \left( \varepsilon \in \mathrm{First} (B) \right)<br>\\ &amp; = \{ c \} \cup \{ c \}<br>\\ &amp; = \{ c \}<br>\end{align*}\]※ \( \mathrm{First} (B) \) に \( \varepsilon \) が含まれているため、公式が変化する点に注意！</p>



<div style="height:62px" class="wp-block-spacer"></div>



<h4 class="wp-block-heading">(2) Follow集合の算出</h4>



<p>[略解]\[\begin{align*}<br>\mathrm{Follow} (S) &amp; = \{ c , \$ \} \\ <br>\mathrm{Follow} (A) &amp; = \{ a, c, \$ \} \\ <br>\mathrm{Follow} (B) &amp; = \{ c, \$ \} \\<br>\mathrm{Follow} (C) &amp; = \{ c \}<br>\end{align*}\]</p>



<p><strong>(i) \( \mathrm{Follow} (S) \) の算出式</strong></p>



<p>[公式1] \( S \) は出発記号？ → Yes。なので、\( \mathrm{Follow} (S) \) に \( \$  \) を追加。\[<br>\mathrm{Follow} ( \textcolor{magenta}{S} )  += \{ \$ \}<br>\]</p>



<div style="height:23px" class="wp-block-spacer"></div>



<p>ここで、\( \textcolor{magenta}{S} \) が生成先に含まれる規則は、\( B \to \textcolor{magenta}{S} \) のみなので、\( B \to \textcolor{magenta}{S}  \) にのみ着目すればOK。</p>



<p>\( B \to  \textcolor{magenta}{ S } \) において、 \( \textcolor{magenta}{S} \) の後ろの文字が存在しない。そのため、\( \textcolor{blue}{\beta = \varepsilon} \) である。</p>



<p>[公式2] \( \beta \not =  \varepsilon \)？ → \( \textcolor{blue}{\beta = \varepsilon} \) なのでNo。</p>



<div style="height:23px" class="wp-block-spacer"></div>



<p>[公式3] \( \varepsilon \in \mathrm{First} ( \beta ) \)？ → \( \mathrm{First} ( \textcolor{blue}{\beta} )= \mathrm{First} ( \textcolor{blue}{\varepsilon} ) = \{ \varepsilon \} \) なのでYes。</p>



<p>なので、\( \textcolor{blue}{B} \to \textcolor{magenta}{S} \) に対し、以下の集合の要素を追加。\[\begin{align*}<br>\mathrm{Follow} ( \textcolor{magenta}{S} ) + &amp; = \mathrm{Follow} ( \textcolor{blue}{B} ) <br>\end{align*}\]</p>



<p>よって、\( \mathrm{Follow} (S) \) で追加する要素（計算過程）は以下の図の通りである。</p>



<figure class="wp-block-image aligncenter size-full"><img width="841" height="423" src="https://www.momoyama-usagi.com/wp-content/uploads/konpai3-26.gif" alt="" class="wp-image-16944"/><figcaption>\( \mathrm{Follow} (S) \) の計算過程の図示</figcaption></figure>



<div style="height:36px" class="wp-block-spacer"></div>



<p><strong>(ii) \( \mathrm{Follow} (A) \) の算出式</strong></p>



<p>[公式1] \( A \) は出発記号？ →No。なにもしない。</p>



<div style="height:23px" class="wp-block-spacer"></div>



<p>ここで、\( \textcolor{magenta}{A} \) が生成先に含まれる規則は、\( S \to  \textcolor{magenta}{A} a B \), \( A \to cC \textcolor{magenta}{A} \), \( B \to B \textcolor{magenta}{A} \) の3つがあるが、\( A \to cC \textcolor{magenta}{A} \) は右再帰な規則なので無視。よって、\( S \to  \textcolor{magenta}{A} a B \), \( B \to  B \textcolor{magenta}{A}  \) の2つに着目すればOK。</p>



<p><strong>[ii-a] \( S \to a \textcolor{magenta}{A} a B \) に着目したとき</strong></p>



<p>\( S \to a \textcolor{magenta}{ A } \textcolor{blue}{ \underbrace{aB}_{ \beta } } \) とおく。（つまり \( \textcolor{blue}{\beta = a} \)）</p>



<p>[公式2] \( \beta \not =  \varepsilon \)？ → \( \textcolor{blue}{\beta = aB} \not = \varepsilon \) なのでYes。</p>



<p>なので、\( S \to a \textcolor{magenta}{A} \textcolor{blue}{ aB } \) に対し、以下の集合の要素を追加。\[\begin{align*}<br>\mathrm{Follow} ( \textcolor{magenta}{A} ) + &amp; = \mathrm{First} ( \textcolor{blue}{aB} ) <br>\\ &amp;  \overset{ \mathrm{R3} }{=} \mathrm{First} ( \textcolor{blue}{a} ) <br>\\ &amp;  \overset{ \mathrm{R1} }{=} \{ a \}<br>\\ &amp; = \{ a \}<br>\end{align*}\]</p>



<div style="height:23px" class="wp-block-spacer"></div>



<p>[公式3] \( \varepsilon \in \mathrm{First} ( \beta ) \)？ → \( \mathrm{First} ( \textcolor{blue}{\beta} )= \mathrm{First} ( \textcolor{blue}{aB} ) = \{ \varepsilon \} \) = \{ a \} \) なのでNo。</p>



<div style="height:23px" class="wp-block-spacer"></div>



<p><strong>[ii-b] \( B \to B \textcolor{magenta}{A} \) に着目したとき</strong></p>



<p>この規則では、\( \textcolor{magenta}{S} \) の後ろの文字が存在しない。そのため、\( \textcolor{blue}{\beta = \varepsilon} \) である。</p>



<p>[公式2] \( \beta \not =  \varepsilon \)？ → \( \textcolor{blue}{\beta = \varepsilon} \) なのでNo。</p>



<div style="height:23px" class="wp-block-spacer"></div>



<p>[公式3] \( \varepsilon \in \mathrm{First} ( \beta ) \)？ → \( \mathrm{First} ( \beta ) = \{ \varepsilon \} \) なのでYes。</p>



<p>なので、\( \textcolor{blue}{B} \to  B \textcolor{magenta}{A} \) に対し、以下の集合の要素を追加。\[\begin{align*}<br>\mathrm{Follow} (\textcolor{magenta}{A} ) + &amp; = \mathrm{Follow} ( \textcolor{blue}{B} ) <br>\end{align*}\]</p>



<div style="height:23px" class="wp-block-spacer"></div>



<p>よって、\( \mathrm{Follow} (A) \) に追加される要素は以下の図で示す通り。</p>



<figure class="wp-block-image aligncenter size-full"><img width="1005" height="504" src="https://www.momoyama-usagi.com/wp-content/uploads/konpai3-27.gif" alt="" class="wp-image-16945"/><figcaption>\( \mathrm{Follow} (A) \) の計算過程の図示</figcaption></figure>



<div style="height:36px" class="wp-block-spacer"></div>



<p><strong>(iii) \( \mathrm{Follow} (B) \) の算出式</strong></p>



<p>[公式1] \( B \) は出発記号？ →No。なにもしない。</p>



<div style="height:23px" class="wp-block-spacer"></div>



<p>ここで、\( \textcolor{magenta}{B} \) が生成先に含まれる規則は、\( S \to Aa \textcolor{magenta}{B} \), \( B \to \textcolor{magenta}{B} A \), \( C \to B \textcolor{magenta}{c} \) の3つがあるため、この3つの規則に着目すればOK。</p>



<div style="height:23px" class="wp-block-spacer"></div>



<p><strong>[iii-a] \( S \to Aa \textcolor{magenta}{B} \) に着目したとき</strong></p>



<p>この規則では、\( \textcolor{magenta}{B} \) の後ろの文字が存在しない。そのため、\( \textcolor{blue}{\beta = \varepsilon} \) である。</p>



<p>[公式2] \( \beta \not =  \varepsilon \)？ → \( \textcolor{blue}{\beta = \varepsilon} \) なのでNo。</p>



<div style="height:23px" class="wp-block-spacer"></div>



<p>[公式3] \( \varepsilon \in \mathrm{First} ( \beta ) \)？ → \( \mathrm{First} ( \textcolor{blue}{\beta} )= \mathrm{First} ( \textcolor{blue}{\varepsilon} ) = \{ \varepsilon \} \) なのでYes。</p>



<p>なので、\( \textcolor{blue}{S} \to  A a\textcolor{magenta}{B} \) に対し、以下の集合の要素を追加。\[\begin{align*}<br>\mathrm{Follow} (\textcolor{magenta}{B} ) + &amp; = \mathrm{Follow} ( \textcolor{blue}{S} ) <br>\end{align*}\]</p>



<div style="height:23px" class="wp-block-spacer"></div>



<p><strong>[iii-b] \( B \to \textcolor{magenta}{B} A \) に着目したとき</strong></p>



<p>\(B \to  \textcolor{magenta}{ B } \textcolor{blue}{ \underbrace{A}_{ \beta } } \) とおく。（つまり \( \textcolor{blue}{\beta = A} \)）</p>



<p>[公式2] \( \beta \not =  \varepsilon \)？ → \( \textcolor{blue}{\beta = A} \not = \varepsilon \) なのでYes。</p>



<p>なので、\( B \to a \textcolor{magenta}{B} \textcolor{blue}{ A } \) に対し、以下の集合の要素を追加。\[\begin{align*}<br>\mathrm{Follow} ( \textcolor{magenta}{B} ) + &amp; = \mathrm{First} ( \textcolor{blue}{A} ) <br>\\ &amp; = \{ c \}<br>\end{align*}\]</p>



<div style="height:23px" class="wp-block-spacer"></div>



<p>[公式3] \( \varepsilon \in \mathrm{First} ( \beta ) \)？ → \( \mathrm{First} ( \textcolor{blue}{\beta} )= \mathrm{First} ( \textcolor{blue}{A} ) = \{ c \} \) なのでNo。</p>



<div style="height:23px" class="wp-block-spacer"></div>



<p><strong>[iii-c] \( C \to \textcolor{magenta}{B} c \) に着目したとき</strong></p>



<p>\(C \to  \textcolor{magenta}{ B } \textcolor{blue}{ \underbrace{c}_{ \beta } } \) とおく。（つまり \( \textcolor{blue}{\beta = c} \)）</p>



<p>[公式2] \( \beta \not =  \varepsilon \)？ → \( \textcolor{blue}{\beta = c} \not = \varepsilon \) なのでYes。</p>



<p>なので、\( C \to a \textcolor{magenta}{B} \textcolor{blue}{ c } \) に対し、以下の集合の要素を追加。\[\begin{align*}<br>\mathrm{Follow} ( \textcolor{magenta}{B} ) + &amp; = \mathrm{First} ( \textcolor{blue}{c} ) <br>\\ &amp; = \{ c \}<br>\end{align*}\]</p>



<div style="height:23px" class="wp-block-spacer"></div>



<p>[公式3] \( \varepsilon \in \mathrm{First} ( \beta ) \)？ → \( \mathrm{First} ( \textcolor{blue}{\beta} )= \mathrm{First} ( \textcolor{blue}{c} )  = \{ c \} \) なのでNo。</p>



<div style="height:23px" class="wp-block-spacer"></div>



<p>[iii-a]～[iii-c] より、\( \mathrm{Follow} (B) \) に追加される要素は以下の図で示す通り。</p>



<figure class="wp-block-image aligncenter size-large"><img width="1024" height="351" src="https://www.momoyama-usagi.com/wp-content/uploads/konpai3-28-1024x351.gif" alt="" class="wp-image-16946" srcset="https://www.momoyama-usagi.com/wp-content/uploads/konpai3-28-1024x351.gif 1024w, https://www.momoyama-usagi.com/wp-content/uploads/konpai3-28-300x103.gif 300w, https://www.momoyama-usagi.com/wp-content/uploads/konpai3-28-768x263.gif 768w" /><figcaption>\( \mathrm{Follow} (B) \) の計算過程の図示</figcaption></figure>



<div style="height:36px" class="wp-block-spacer"></div>



<p><strong>(iv) \( \mathrm{Follow} (C) \) の算出式</strong></p>



<p>[公式1] \( C \) は出発記号？ →No。なにもしない。</p>



<div style="height:23px" class="wp-block-spacer"></div>



<p>ここで、\( \textcolor{magenta}{C} \) が生成先に含まれる規則は、\( A \to c \textcolor{magenta}{C} A \) のみ。なのでこの規則に着目すればOK。</p>



<p>この規則について、\(A \to c  \textcolor{magenta}{ C } \textcolor{blue}{ \underbrace{A}_{ \beta } } \) とおく。（つまり \( \textcolor{blue}{\beta = A} \)）</p>



<p>[公式2] \( \beta \not =  \varepsilon \)？ → \( \textcolor{blue}{\beta = A} \not = \varepsilon \) なのでYes。</p>



<p>なので、\( C \to c \textcolor{magenta}{C} \textcolor{blue}{ A } \) に対し、以下の集合の要素を追加。\[\begin{align*}<br>\mathrm{Follow} ( \textcolor{magenta}{C} ) + &amp; = \mathrm{First} ( \textcolor{blue}{A} ) <br>\\ &amp; = \{ c \}<br>\end{align*}\]</p>



<div style="height:23px" class="wp-block-spacer"></div>



<p>[公式3] \( \varepsilon \in \mathrm{First} ( \beta ) \)？ → \( \mathrm{First} ( \textcolor{blue}{\beta} )= \mathrm{First} ( \textcolor{blue}{A} )  = \{ c \} \) なのでNo。</p>



<div style="height:23px" class="wp-block-spacer"></div>



<p>よって、\( \mathrm{Follow} (C) \) に追加される要素は以下の図で示す通り。</p>



<figure class="wp-block-image aligncenter size-full"><img width="879" height="230" src="https://www.momoyama-usagi.com/wp-content/uploads/konpai3-29.gif" alt="" class="wp-image-16947"/><figcaption>\( \mathrm{Follow} (B) \) の計算過程の図示</figcaption></figure>



<p><strong>それぞれの計算結果をまとめてFollow集合を算出</strong></p>



<p>先ほど出した \( \mathrm{Follow} (S) \), \( \mathrm{Follow} (A) \), \( \mathrm{Follow} (B) \), \( \mathrm{Follow} (C) \) の計算過程を1つの図に表すと、下のようになる。</p>



<figure class="wp-block-image aligncenter size-large"><img width="1024" height="721" src="https://www.momoyama-usagi.com/wp-content/uploads/bandicam-2022-09-19-09-38-10-080-1024x721.jpg" alt="" class="wp-image-17264" srcset="https://www.momoyama-usagi.com/wp-content/uploads/bandicam-2022-09-19-09-38-10-080-1024x721.jpg 1024w, https://www.momoyama-usagi.com/wp-content/uploads/bandicam-2022-09-19-09-38-10-080-300x211.jpg 300w, https://www.momoyama-usagi.com/wp-content/uploads/bandicam-2022-09-19-09-38-10-080-768x541.jpg 768w, https://www.momoyama-usagi.com/wp-content/uploads/bandicam-2022-09-19-09-38-10-080-1536x1081.jpg 1536w, https://www.momoyama-usagi.com/wp-content/uploads/bandicam-2022-09-19-09-38-10-080.jpg 1553w" /></figure>



<p>※ 点線部分は、間接的な右再帰により、2つのFollow集合が等しい（＝一心同体）になっていることを表す。つまり \( \mathrm{Follow} (S) = \mathrm{Follow} (B) \)。</p>



<p>あとは、求められるFollow集合から順にFollow集合を求めていけばOK。</p>



<p>※ 今回の場合は、\( \mathrm{Follow} (A) \) 集合は点線部分のFollow集合が求まらないと計算できません。それ以外の集合は自由な順番で計算できます。 </p>



<p>(iv) \( \mathrm{Follow} (C) \) の計算結果</p>



<figure class="wp-block-image aligncenter size-large"><img width="1024" height="721" src="https://www.momoyama-usagi.com/wp-content/uploads/bandicam-2022-09-19-09-38-12-596-1024x721.jpg" alt="" class="wp-image-17265" srcset="https://www.momoyama-usagi.com/wp-content/uploads/bandicam-2022-09-19-09-38-12-596-1024x721.jpg 1024w, https://www.momoyama-usagi.com/wp-content/uploads/bandicam-2022-09-19-09-38-12-596-300x211.jpg 300w, https://www.momoyama-usagi.com/wp-content/uploads/bandicam-2022-09-19-09-38-12-596-768x541.jpg 768w, https://www.momoyama-usagi.com/wp-content/uploads/bandicam-2022-09-19-09-38-12-596-1536x1081.jpg 1536w, https://www.momoyama-usagi.com/wp-content/uploads/bandicam-2022-09-19-09-38-12-596.jpg 1553w" /></figure>



<p>[計算式]\[\begin{align*}<br>\mathrm{Follow} (C) &amp; = \mathrm{First} (a) <br>\\ &amp; = \{ c \}<br>\end{align*}\]</p>



<div style="height:32px" class="wp-block-spacer"></div>



<p>(i), (iii) \( \mathrm{Follow} (S) \), \( \mathrm{Follow} (B) \) の計算結果（2つのFollow集合は等しい）</p>



<figure class="wp-block-image aligncenter size-large"><img width="1024" height="721" src="https://www.momoyama-usagi.com/wp-content/uploads/bandicam-2022-09-19-09-38-15-458-1024x721.jpg" alt="" class="wp-image-17266" srcset="https://www.momoyama-usagi.com/wp-content/uploads/bandicam-2022-09-19-09-38-15-458-1024x721.jpg 1024w, https://www.momoyama-usagi.com/wp-content/uploads/bandicam-2022-09-19-09-38-15-458-300x211.jpg 300w, https://www.momoyama-usagi.com/wp-content/uploads/bandicam-2022-09-19-09-38-15-458-768x541.jpg 768w, https://www.momoyama-usagi.com/wp-content/uploads/bandicam-2022-09-19-09-38-15-458-1536x1081.jpg 1536w, https://www.momoyama-usagi.com/wp-content/uploads/bandicam-2022-09-19-09-38-15-458.jpg 1553w" /></figure>



<p>[計算式]\[\begin{align*}<br>\mathrm{Follow} (S) &amp; = \{ \$ \} \cup \mathrm{First} (A) \cup \mathrm{First} (c) <br>\\ &amp; = \{ \$ \} \cup \{ c \} \cup \{ c \}<br>\\ &amp; = \{ c , \$ \}<br>\end{align*}\]※ \( \mathrm{Follow} (B) \) 加えられている要素もいったん \( \mathrm{Follow} (S) \) に足している。</p>



<p>\[\begin{align*}<br>\mathrm{Follow} (B) &amp; = \mathrm{Follow} (S)<br>\\ &amp; = \{ c , \$ \}<br>\end{align*}\]</p>







<div style="height:32px" class="wp-block-spacer"></div>



<p>(ii) \( \mathrm{Follow} (A) \)  の計算結果</p>



<figure class="wp-block-image aligncenter size-large"><img width="1024" height="721" src="https://www.momoyama-usagi.com/wp-content/uploads/bandicam-2022-09-19-09-38-18-414-1024x721.jpg" alt="" class="wp-image-17267" srcset="https://www.momoyama-usagi.com/wp-content/uploads/bandicam-2022-09-19-09-38-18-414-1024x721.jpg 1024w, https://www.momoyama-usagi.com/wp-content/uploads/bandicam-2022-09-19-09-38-18-414-300x211.jpg 300w, https://www.momoyama-usagi.com/wp-content/uploads/bandicam-2022-09-19-09-38-18-414-768x541.jpg 768w, https://www.momoyama-usagi.com/wp-content/uploads/bandicam-2022-09-19-09-38-18-414-1536x1081.jpg 1536w, https://www.momoyama-usagi.com/wp-content/uploads/bandicam-2022-09-19-09-38-18-414.jpg 1553w" /></figure>



<p>[計算式]\[\begin{align*}<br>\mathrm{Follow} (A) &amp; =\mathrm{Follow} (B) \cup \mathrm{First} (a) <br>\\ &amp; = \{ c, \$ \} \cup \{ a \} <br>\\ &amp; = \{ a, c , \$ \}<br>\end{align*}\]※ \( \mathrm{Follow} (B) \) を \( \mathrm{Follow} (S) \) としてもOK。</p>



<div style="height:62px" class="wp-block-spacer"></div>



<h4 class="wp-block-heading">(3) Director集合の計算・LL(1)文法の判定</h4>



<p>各非終端記号に対して、生成元から2つ以上の生成規則を持つものは、</p>



<ol class="wp-block-list"><li>\( A \) が生成元となる規則：\( A \to cCA \), \( A \to c \)</li><li>\( B \) が生成元となる規則：\( B \to S \), \( B \to BA \), \( B \to \varepsilon \)</li></ol>



<p>である。あとは、非終端記号ごとに「どの生成規則同士の積をとっても、Director集合が空集合になること」を確認すればOK。</p>



<p>1) \( A \) が生成元の生成規則 \( A \to cCA \), \( A \to c \) に対してDirector集合確認</p>



<p>\( \textcolor{magenta}{A} \to \textcolor{deepskyblue}{cCA}  \) のDirector集合\[\begin{align*}<br>\mathrm{Director} ( \textcolor{magenta}{A} , \textcolor{deepskyblue}{cCA}  ) &amp; = \mathrm{First} ( cCA )<br>\\ &amp;  \overset{ \mathrm{R3} }{=} \mathrm{First} ( c )<br>\\ &amp;  \overset{ \mathrm{R1} }{=} \{ c \}<br>\end{align*}\]</p>



<p>\( \textcolor{magenta}{A} \to \textcolor{deepskyblue}{c}  \) のDirector集合\[\begin{align*}<br>\mathrm{Director} ( \textcolor{magenta}{A} , \textcolor{deepskyblue}{c}  ) &amp; = \mathrm{First} ( c )<br>\\ &amp;  \overset{ \mathrm{R1} }{=} \{ c \}<br>\end{align*}\]</p>



<p>\( A \) に関する各Director集合同士の積を取ると、\[\begin{align*}<br>\mathrm{Director} ( A, cCA  ) \cap \mathrm{Director} ( A, c ) &amp; = \{ c \} \cap \{ c \}<br>\\ &amp; = \{ c \}<br>\end{align*}\]となるためNG。</p>



<p>よって、題意の文法はLL(1)文法ではない。</p>



<p>※ 1つでも \( \phi \) にならないものがあればその時点でLL(1)文法ではないことが確認できるため、他のDirector集合は求めなくてOKです。</p>



<div style="height:62px" class="wp-block-spacer"></div>



<h2 class="wp-block-heading">7. さいごに</h2>



<p>かなり長い記事となっていましたが、以上が</p>



<ul class="wp-block-list"><li>LL(1)文法</li><li>First集合</li><li>Follow集合</li><li>Director集合</li></ul>



<p>に関する説明でした。</p>



<p>この記事を見て、少しでもLL(1)文法やFirst, Follow, Director集合の計算の方法について理解いただけたのであれば非常にうれしいです。</p>



<p>次回は、左再帰な文法についての「問題点」と「左再帰を解消する方法」について説明する予定です。</p>



<p>[練習問題の中に入れられなかったおまけ問題] 生成規則 \( A \to B \) に対するDirector集合 \( \mathrm{Director} (A,B) \) を求めなさい。ただし、\[\begin{align*}<br> \mathrm{First} (A) &amp; = \{ a \}  \\ <br> \mathrm{First} (B) &amp; = \{ b, \varepsilon \}  \\ <br> \mathrm{Follow} (A) &amp; = \{ c \}  \\ <br> \mathrm{Follow} (B) &amp; = \{ d, \$ \}  <br>\end{align*}\]とする。解答はこの注釈に書いています<span class="footnote_referrer"><a tabindex="0" onclick="footnote_moveToReference_16248_11('footnote_plugin_reference_16248_11_12');" onkeypress="footnote_moveToReference_16248_11('footnote_plugin_reference_16248_11_12');" ><sup id="footnote_plugin_tooltip_16248_11_12" class="footnote_plugin_tooltip_text">[12]</sup></a><span id="footnote_plugin_tooltip_text_16248_11_12" class="footnote_tooltip">\( \varepsilon \in \mathrm{First} (B) \) なので、\( B \) が空文字になる可能性を考慮するのがミソです。\[\begin{align*}\mathrm{Director} (A,B) &amp; = \mathrm{First}(B) \cup&nbsp;&#x2026; <span class="footnote_tooltip_continue"  onclick="footnote_moveToReference_16248_11('footnote_plugin_reference_16248_11_12');">Continue reading</span></span></span>。</p>
<div class="speaker-mute footnotes_reference_container"> <div class="footnote_container_prepare"><p><span tabindex="0" class="footnote_reference_container_label pointer">注釈</span><span tabindex="0" class="footnote_reference_container_collapse_button" style="display: none;">[<a id="footnote_reference_container_collapse_button_16248_11">+</a>]</span></p></div> <div id="footnote_references_container_16248_11"><table class="footnotes_table footnote-reference-container"><caption class="accessibility">注釈</caption> <tbody> 

<tr class="footnotes_plugin_reference_row"> <th scope="row" class="footnote_plugin_index_combi pointer"  onclick="footnote_moveToAnchor_16248_11('footnote_plugin_tooltip_16248_11_1');"><a id="footnote_plugin_reference_16248_11_1" class="footnote_backlink"><span class="footnote_index_arrow">&#8593;</span>1</a></th> <td class="footnote_plugin_text">10文字弱、かつ生成規則が4つであればやみくもにやってもそこまで時間はかかりませんが、実際のプログラムに対して構文解析をする場合、膨大な文字数かつ膨大な生成規則があるため、やみくもにやっていると日が暮れてしまいます。</td></tr>

<tr class="footnotes_plugin_reference_row"> <th scope="row" class="footnote_plugin_index_combi pointer"  onclick="footnote_moveToAnchor_16248_11('footnote_plugin_tooltip_16248_11_2');"><a id="footnote_plugin_reference_16248_11_2" class="footnote_backlink"><span class="footnote_index_arrow">&#8593;</span>2</a></th> <td class="footnote_plugin_text">もう少し詳しく言うと、LL(1)文法はトップダウン構文解析（出発記号を起点として、どんどん生成規則を用いて分解していきながら解析する方法）において、1文字だけ先読みすることで文字列を後戻りすることなく構文解析ができる文法です。</td></tr>

<tr class="footnotes_plugin_reference_row"> <th scope="row" class="footnote_plugin_index_combi pointer"  onclick="footnote_moveToAnchor_16248_11('footnote_plugin_tooltip_16248_11_3');"><a id="footnote_plugin_reference_16248_11_3" class="footnote_backlink"><span class="footnote_index_arrow">&#8593;</span>3</a></th> <td class="footnote_plugin_text"> \( A \to Ab \) のように左再帰文法となる規則を適用しても、先頭文字列は \( A \) のまま変わらないため、無視しても問題ない。</td></tr>

<tr class="footnotes_plugin_reference_row"> <th scope="row" class="footnote_plugin_index_combi pointer"  onclick="footnote_moveToAnchor_16248_11('footnote_plugin_tooltip_16248_11_4');"><a id="footnote_plugin_reference_16248_11_4" class="footnote_backlink"><span class="footnote_index_arrow">&#8593;</span>4</a></th> <td class="footnote_plugin_text">いったん\[\begin{align*}<br>\mathrm{First} (A) &amp; = \mathrm{First} (B) \cup \mathrm{First} (c)<br>\\ &amp; = \underbrace{ \mathrm{First} (A) }_{ \mathrm{無視} } \cup \mathrm{First} (c)<br>\\ &amp; = \mathrm{First} (c)<br>\end{align*}\]のように、左辺に出てくるFirst集合（今回は \( \mathrm{First} (A) \) ）が右辺にも出てくる形にしてから、左辺にも右辺にも出てきたFirst集合を無視して計算してもOKです。</td></tr>

<tr class="footnotes_plugin_reference_row"> <th scope="row" class="footnote_plugin_index_combi pointer"  onclick="footnote_moveToAnchor_16248_11('footnote_plugin_tooltip_16248_11_5');"><a id="footnote_plugin_reference_16248_11_5" class="footnote_backlink"><span class="footnote_index_arrow">&#8593;</span>5</a></th> <td class="footnote_plugin_text">一般化すると、1文字目からn文字目までの文字すべてに空文字があれば、1文字目～n+1文字目の和を取ればOK。</td></tr>

<tr class="footnotes_plugin_reference_row"> <th scope="row" class="footnote_plugin_index_combi pointer"  onclick="footnote_moveToAnchor_16248_11('footnote_plugin_tooltip_16248_11_6');"><a id="footnote_plugin_reference_16248_11_6" class="footnote_backlink"><span class="footnote_index_arrow">&#8593;</span>6</a></th> <td class="footnote_plugin_text">\( \beta \) がそもそも存在しない、つまり \( \beta = \varepsilon \) のときは、\( \mathrm{First} ( \beta ) = \mathrm{First} ( \varepsilon ) &nbsp;\overset{ \mathrm{R1} }{=} \{ \varepsilon \} \) となるため、\( \varepsilon \) を無視すると追加できる集合がなくなる。</td></tr>

<tr class="footnotes_plugin_reference_row"> <th scope="row" class="footnote_plugin_index_combi pointer"  onclick="footnote_moveToAnchor_16248_11('footnote_plugin_tooltip_16248_11_7');"><a id="footnote_plugin_reference_16248_11_7" class="footnote_backlink"><span class="footnote_index_arrow">&#8593;</span>7</a></th> <td class="footnote_plugin_text">\( \textcolor{blue}{A} \to a \textcolor{magenta}{B} \) より、\[\begin{align*}<br>\mathrm{Follow} ( \textcolor{magenta}{B} ) + &amp; = \mathrm{Follow} ( \textcolor{magenta}{A} )<br>\\ &amp; = \mathrm{Follow} (B) \cup \mathrm{Follow} (A) <br>\end{align*}\]の式が導出でき、\( \textcolor{blue}{B} \to b \textcolor{magenta}{A} \) より、\[\begin{align*}<br>\mathrm{Follow} ( \textcolor{magenta}{A} ) + &amp; = \mathrm{Follow} ( \textcolor{magenta}{B} )<br>\\ &amp; = \mathrm{Follow} (A) \cup \mathrm{Follow} (B) <br>\end{align*}\]となるため、数式的にも \( \mathrm{Follow} (A) = \mathrm{Follow} (B)  \) が言える。\</td></tr>

<tr class="footnotes_plugin_reference_row"> <th scope="row" class="footnote_plugin_index_combi pointer"  onclick="footnote_moveToAnchor_16248_11('footnote_plugin_tooltip_16248_11_8');"><a id="footnote_plugin_reference_16248_11_8" class="footnote_backlink"><span class="footnote_index_arrow">&#8593;</span>8</a></th> <td class="footnote_plugin_text">実際に私もよく計算ミスします。</td></tr>

<tr class="footnotes_plugin_reference_row"> <th scope="row" class="footnote_plugin_index_combi pointer"  onclick="footnote_moveToAnchor_16248_11('footnote_plugin_tooltip_16248_11_9');"><a id="footnote_plugin_reference_16248_11_9" class="footnote_backlink"><span class="footnote_index_arrow">&#8593;</span>9</a></th> <td class="footnote_plugin_text">下の図の場合「\( \mathrm{Follow} (S) \) を求めるためには \( \mathrm{First} (c) \) と \( \{ \$ \} \) の要素を追加すればOK」ということを表しています。</td></tr>

<tr class="footnotes_plugin_reference_row"> <th scope="row" class="footnote_plugin_index_combi pointer"  onclick="footnote_moveToAnchor_16248_11('footnote_plugin_tooltip_16248_11_10');"><a id="footnote_plugin_reference_16248_11_10" class="footnote_backlink"><span class="footnote_index_arrow">&#8593;</span>10</a></th> <td class="footnote_plugin_text">集合 \( B \) に集合 \( A \) の要素を追加したのに、集合 \( B \) の要素の中に集合 \( A \) の一部の要素は実は入っていない、なんてことは起こりませんよね…？</td></tr>

<tr class="footnotes_plugin_reference_row"> <th scope="row" class="footnote_plugin_index_combi pointer"  onclick="footnote_moveToAnchor_16248_11('footnote_plugin_tooltip_16248_11_11');"><a id="footnote_plugin_reference_16248_11_11" class="footnote_backlink"><span class="footnote_index_arrow">&#8593;</span>11</a></th> <td class="footnote_plugin_text">具体的には、\( \{ $ \} \subseteq \mathrm{Follow} (S)  \), \( \mathrm{First} (c) \subseteq \mathrm{Follow} (S) \), \( \mathrm{Follow} (S) \subseteq \mathrm{Follow} (A) \), \( \mathrm{First} (A) \subseteq \mathrm{Follow} (B) \), \( \mathrm{Follow} (A) \subseteq \mathrm{Follow} (B) \) 5つが成立しているかすべて確かめればOKです。</td></tr>

<tr class="footnotes_plugin_reference_row"> <th scope="row" class="footnote_plugin_index_combi pointer"  onclick="footnote_moveToAnchor_16248_11('footnote_plugin_tooltip_16248_11_12');"><a id="footnote_plugin_reference_16248_11_12" class="footnote_backlink"><span class="footnote_index_arrow">&#8593;</span>12</a></th> <td class="footnote_plugin_text">\( \varepsilon \in \mathrm{First} (B) \) なので、\( B \) が空文字になる可能性を考慮するのがミソです。\[\begin{align*}<br>\mathrm{Director} (A,B) &amp; = \mathrm{First}(B) \cup \mathrm{Follow} (A) - \{ \varepsilon \}<br>\\ &amp; = \{ a,b \}<br>\end{align*}\]</td></tr>

 </tbody> </table> </div></div>]]></content:encoded>
					
					<wfw:commentRss>https://www.momoyama-usagi.com/entry/info-compiler3/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>うさぎでもわかるコンパイラ　第2羽　解析木・構文木の書き方</title>
		<link>https://www.momoyama-usagi.com/entry/info-compiler2</link>
					<comments>https://www.momoyama-usagi.com/entry/info-compiler2#respond</comments>
		
		<dc:creator><![CDATA[ももうさ]]></dc:creator>
		<pubDate>Sat, 10 Sep 2022 15:18:37 +0000</pubDate>
				<category><![CDATA[コンパイラ(言語処理系)]]></category>
		<category><![CDATA[情報]]></category>
		<category><![CDATA[コンパイラ]]></category>
		<category><![CDATA[構文解析]]></category>
		<category><![CDATA[言語処理系]]></category>
		<guid isPermaLink="false">https://www.momoyama-usagi.com/?p=16128</guid>

					<description><![CDATA[こんにちは、ももうさです。 第2羽となる今回から、コンパイラの処理の中の第2フェーズである「構文解析」で出てくる様々な仕組みについて数記事にわけて見ていきましょう。 皆さんは、高校で英語を習う際に「英文の構造を把握してか [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>こんにちは、ももうさです。</p>



<p>第2羽となる今回から、<a href="https://www.momoyama-usagi.com/entry/info-calc-sys11" data-type="URL" target="_blank" rel="noreferrer noopener">コンパイラの処理</a>の中の第2フェーズである「構文解析」で出てくる様々な仕組みについて数記事にわけて見ていきましょう。</p>



<figure class="wp-block-image aligncenter size-large"><img width="1024" height="826" src="https://www.momoyama-usagi.com/wp-content/uploads/ki2-24-1024x826.gif" alt="" class="wp-image-16156" srcset="https://www.momoyama-usagi.com/wp-content/uploads/ki2-24-1024x826.gif 1024w, https://www.momoyama-usagi.com/wp-content/uploads/ki2-24-300x242.gif 300w, https://www.momoyama-usagi.com/wp-content/uploads/ki2-24-768x619.gif 768w, https://www.momoyama-usagi.com/wp-content/uploads/ki2-24-1536x1238.gif 1536w, https://www.momoyama-usagi.com/wp-content/uploads/ki2-24-2048x1651.gif 2048w" /></figure>



<p>皆さんは、高校で英語を習う際に「英文の構造を把握してから」英文を理解したり、和訳したりした思い出があると思います<span class="footnote_referrer"><a tabindex="0" onclick="footnote_moveToReference_16128_13('footnote_plugin_reference_16128_13_1');" onkeypress="footnote_moveToReference_16128_13('footnote_plugin_reference_16128_13_1');" ><sup id="footnote_plugin_tooltip_16128_13_1" class="footnote_plugin_tooltip_text">[1]</sup></a><span id="footnote_plugin_tooltip_text_16128_13_1" class="footnote_tooltip">SV,  SVC, SVO, SVOO, SVOCの5種類。</span></span>。</p>



<figure class="wp-block-image aligncenter size-large"><img width="1024" height="212" src="https://www.momoyama-usagi.com/wp-content/uploads/ki2-23-1024x212.gif" alt="" class="wp-image-16151" srcset="https://www.momoyama-usagi.com/wp-content/uploads/ki2-23-1024x212.gif 1024w, https://www.momoyama-usagi.com/wp-content/uploads/ki2-23-300x62.gif 300w, https://www.momoyama-usagi.com/wp-content/uploads/ki2-23-768x159.gif 768w, https://www.momoyama-usagi.com/wp-content/uploads/ki2-23-1536x318.gif 1536w, https://www.momoyama-usagi.com/wp-content/uploads/ki2-23-2048x423.gif 2048w" /><figcaption>英文の構造の例（SVOC型）</figcaption></figure>



<p>コンパイラの世界でも同じように、「書かれたプログラムの構造を把握しながら」C言語などの高級言語をコンピュータ上で実行できる形（機械語）に翻訳するコンパイルが実行されるのですが、その際にコンピュータ上でプログラムの構造を</p>



<p>今回は、コンパイラで「書かれたプログラムの構造を（文法的に）把握する」する際に出てくる「解析木」や「構文木」について、例題や練習問題も踏まえながら学習していきましょう。</p>



<div style="height:100px" class="wp-block-spacer"></div>



<h2 class="wp-block-heading">[復習] 文脈自由文法とは</h2>



<p>まずは、コンピュータ上で文法を表現する方法の1つである文脈自由文法について復習しましょう。</p>



<p>文脈自由文法は、</p>



<ul class="wp-block-list"><li>非終端記号 \( N \)</li><li>終端記号 \( \Sigma \)</li><li>生成規則 \( P \)</li><li>出発記号 \( S \)</li></ul>



<p>の4つの要素で構成されており、この4種類で「文字列が文法のルールを満たしているか否か」を判定します。</p>



<figure class="wp-block-image aligncenter size-large"><img width="1024" height="181" src="https://www.momoyama-usagi.com/wp-content/uploads/ki2-22-1024x181.gif" alt="" class="wp-image-16150" srcset="https://www.momoyama-usagi.com/wp-content/uploads/ki2-22-1024x181.gif 1024w, https://www.momoyama-usagi.com/wp-content/uploads/ki2-22-300x53.gif 300w, https://www.momoyama-usagi.com/wp-content/uploads/ki2-22-768x136.gif 768w, https://www.momoyama-usagi.com/wp-content/uploads/ki2-22-1536x271.gif 1536w" /><figcaption>文脈自由文法の定義の書き方<br>（\( G = (P,S) \) のように \( N \), \( \Sigma \) を省略することもあり）</figcaption></figure>



<p>ここからは、具体的にそれぞれ4種類の記号がどのような働きをしているかを見ていきましょう。</p>



<h3 class="wp-block-heading">(1) 非終端記号</h3>



<p>文法を表現する際に使う「仮の変数」です。数学でいう「nとおく。」のnみたいなものだと思ってください。</p>



<p>非終端記号は、(4)で説明する生成規則に書き換えることが可能です。\( S \), \( E \), \( T \) などのアルファベット大文字で書かれることが多いです。</p>



<p>[余談] アルファベット大文字以外にも、<code>&lt;式&gt;</code>, <code>&lt;変数&gt;</code>. <code>&lt;数字&gt;</code> など、<code>&lt;名前&gt;</code> の形で非終端記号が表されることもあります。（基本情報や応用情報がまさにこの形で非終端記号を使っています）</p>



<h3 class="wp-block-heading">(2) 終端記号</h3>



<p>実際に文字列内に出てくる（仮の変数ではない）文字や記号が終端記号です。(4) で説明する生成規則によって書き換えることが出来ないのが特徴です。</p>



<p>終端記号には、\( a \), \( b \) などの小文字や数字、英単語、単語、記号（括弧・演算記号など）などの日常的に使われる文字（文字列）が指定されることが多いです。</p>



<h3 class="wp-block-heading">(3) 生成規則</h3>



<p>文法のルールを表す文脈自由文法の心臓部分です。</p>


<p><span>実際に「ある文字列」が文法のルールを満たしているか否かは、(4)で出てくる出発記号 \( S \) を生成規則 \( P \) で書き換えていった際に出てくる終端記号「ある文字列」を表現できるかどうかで判定します。</span></p>


<p><strong>[Point] 生成規則のまとめ書き</strong></p>



<p>\( S \to AB \), \( S \to C \) のように、同じ文字列から生成される規則は、\[<br>S \to AB | C<br>\]のように | を用いてまとめて書くのが一般的なので覚えておきましょう！</p>



<h3 class="wp-block-heading">(4) 出発記号</h3>



<p>名前の通り、生成規則を最初に加える非終端記号を指します。</p>



<div style="height:51px" class="wp-block-spacer"></div>



<p>ここで、実際に文脈自由文法についての復習問題を解いてみましょう。</p>


<div class='wp-block-dbp-frame l-frame-float is-design-onframe is-frame-style-default dbp-frame has-bgcolor'><div class="dbp-frame-title">復習問題</div><div class="dbp-frame-content has-content-gap">
<p>つぎの文脈自由文法\[<br>G = ( \{ S, A\} , \{ a \}, \{ S \to Aa , \ A \to a | Aaa \}, S )<br>\]の文法にあてはまる文字列は (ア)・(イ) のどちらか。</p>

<p>(ア) \( aaaa \)<br>(イ) \( aaaaa \)</p>
</div></div>


<p><strong>[解答]</strong> (ア)</p>



<p>実際に、出発記号 \( S \) から連鎖的に文法規則を適用していき、（ア）と（イ）のどちらが文法規則を適用した際に現れるかを確認すればOKです。</p>



<figure class="wp-block-image aligncenter size-large"><img width="1024" height="300" src="https://www.momoyama-usagi.com/wp-content/uploads/ki2-25-1024x300.gif" alt="" class="wp-image-16157" srcset="https://www.momoyama-usagi.com/wp-content/uploads/ki2-25-1024x300.gif 1024w, https://www.momoyama-usagi.com/wp-content/uploads/ki2-25-300x88.gif 300w, https://www.momoyama-usagi.com/wp-content/uploads/ki2-25-768x225.gif 768w, https://www.momoyama-usagi.com/wp-content/uploads/ki2-25-1536x451.gif 1536w, https://www.momoyama-usagi.com/wp-content/uploads/ki2-25-2048x601.gif 2048w" /><figcaption>樹形図を使って列挙していきましょう。<br>（出発記号 \( S \) に文法規則を適用していき、終端記号だけになるまで変換を続けていく）</figcaption></figure>



<p>すると、\( aaaa \) という文字列が出てきますね。よって答えは（ア）です。</p>



<div style="height:51px" class="wp-block-spacer"></div>



<p>文脈自由文法についてもう少し復習したいなという人は、下の記事をご覧ください！</p>



<figure class="wp-block-embed is-type-wp-embed is-provider-工業大学生ももやまのうさぎ塾 wp-block-embed-工業大学生ももやまのうさぎ塾"><div class="wp-block-embed__wrapper">
        <article class="pb p-id-166 is-position-relative pb-embed">
            <a class="pb-contents" href="https://www.momoyama-usagi.com/entry/info-automaton07">
                <div class="pb__thumb"><img width="300" height="98" src="https://www.momoyama-usagi.com/wp-content/uploads/2021/05/20190906161600-1-300x98.gif" class="is-position-overlay wp-post-image" alt="" lazysizes="1" srcset="https://www.momoyama-usagi.com/wp-content/uploads/2021/05/20190906161600-1-300x98.gif 300w, https://www.momoyama-usagi.com/wp-content/uploads/2021/05/20190906161600-1-768x251.gif 768w" /></div><div class="pb__body l-column is-flex-1"><div class="pb-title is-omit-line:2">うさぎでもわかるオートマトンと言語理論　第07羽　文脈自由文法</div><div class="pb-substr is-font-size:s is-omit-line:2">今回は、オートマトンと言語理論の中でも重要な文脈自由文法についてまとめました。文脈自由文法を読む方法、正規文法、チョムス</div></div>            </a>
        </article>
        
</div></figure>



<p><strong>[余談] 生成規則の書き方について</strong></p>



<p>生成規則は、基本的に\[<br>P = \{ S \to Aa , \ A \to a  \ | \ Aaa \}<br>\]のように「(生成元の非終端集合) → (生成される文字列)」の形で書くのが一般的ですが、\[<br>S \to Aa, \ \ A \to a  \ | \ Aaa<br>\]のように文字列を列挙して書く方法や、</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: plain; gutter: false; title: ; notranslate">
S ::= Aa
A ::= a
A ::= Aaa
</pre></div>


<p>のように \( \to \) を <code>::=</code> と書く手法もあります<span class="footnote_referrer"><a tabindex="0" onclick="footnote_moveToReference_16128_13('footnote_plugin_reference_16128_13_2');" onkeypress="footnote_moveToReference_16128_13('footnote_plugin_reference_16128_13_2');" ><sup id="footnote_plugin_tooltip_16128_13_2" class="footnote_plugin_tooltip_text">[2]</sup></a><span id="footnote_plugin_tooltip_text_16128_13_2" class="footnote_tooltip">基本情報や応用情報で出てくる文脈自由文法がまさに <code>(生成元)::=(生成先) </code>のような書き方をしています。（BNF記法などとも呼ばれます。）</span></span>。</p>



<p>文脈自由文法について復習できたところで、いよいよ「解析木」や「構文木」の書き方を見ていきましょう！</p>



<div style="height:100px" class="wp-block-spacer"></div>



<div style="height:0px" class="wp-block-spacer"></div>



<h2 class="wp-block-heading">1. 解析木の書き方</h2>


<p>解析木は、<span  style="background-image:linear-gradient(to bottom,transparent 0%,#FFF387 0%);" class="dbp-e-marker-animation y">出発記号 \( S \) からどのような文法規則を適用すると与えられた文字列になるのかを表した図</span>です。</p>


<p>と言われても少しわかりにくいと思うので、実際に例題を見ながら「解析木」の書き方、および解析木がどんなものなのかを見ていきましょう。</p>


<div class='wp-block-dbp-frame l-frame-float is-design-onframe is-frame-style-default dbp-frame has-bgcolor'><div class="dbp-frame-title">例題1</div><div class="dbp-frame-content has-content-gap">
<p>次の文脈自由文法で表される文法 \( G \) がある。\[<br>G = \left( \ \{ S, V \} \ , \  \{ a,b,c,d \} \ , \  P \ , \ S \ \right)<br>\]\[\begin{align*}<br>P = \{ \ \ S &amp; \to V  \ | \ (S+S) \ | \ S * S \\<br>V &amp; \to a \ | \ b \ | \ c \ | \ d \ \ \ \ \ \ \ \  \ \ \ \ \ \ \ \ \ \ \ \ \}<br>\end{align*}\]この文法 \( G \) に対し、以下の文字列 \( (a+b) * (c+d) \) の解析木を書きなさい。</p>

<p class="has-text-align-right">[基本情報技術者平成23年秋期 午前問4] (改題)</p>
</div></div>


<p><strong>[解説1]</strong></p>



<p>解析木は、「与えられた文字列が出発記号 \( S \) からどのような生成規則 \( P \) が適用して出てきたか」を表します。</p>


<p><span>つまり、解析木を書く問題は<span  style="background-image:linear-gradient(to bottom,transparent 0%,#FFF387 0%);" class="dbp-e-marker-animation y">与えられた文字列から生成規則を逆方向にたどっていき、出発記号 \( S \) に戻すパズル</span>だと思っていただけたらOKです<span class="footnote_referrer"><a tabindex="0" onclick="footnote_moveToReference_16128_13('footnote_plugin_reference_16128_13_3');" onkeypress="footnote_moveToReference_16128_13('footnote_plugin_reference_16128_13_3');" ><sup id="footnote_plugin_tooltip_16128_13_3" class="footnote_plugin_tooltip_text">[3]</sup></a><span id="footnote_plugin_tooltip_text_16128_13_3" class="footnote_tooltip">生成規則を逆方向にたどるとは、例えば \( A \to B + C \) の生成規則に対して、\( B+ C \) を \( A \) に変換することを表します。</span></span>。</span></p>


<div style="height:49px" class="wp-block-spacer"></div>



<p>ということで、早速例題の生成規則 \( P \) からなる文法 \( G \) に対する文字列 \( (a+b) * (c+d) \) の解析木を書いていきましょう。</p>



<figure class="wp-block-image aligncenter size-medium"><img width="300" height="256" src="https://www.momoyama-usagi.com/wp-content/uploads/ki-mac2-2-300x256.gif" alt="" class="wp-image-16171"/><figcaption>生成規則 \( P \)<br>（ \( V \) 以外 | を使わずに書いた場合）</figcaption></figure>



<p><strong>Step1. 方針を建てる</strong></p>



<p>やみくもに生成規則を逆にたどっていくのではなく、まず方針をたてましょう。</p>



<p>方針を建てる際には、生成規則内で1回しか出てこない非終端記号に着目できる場合は、その規則を使っていきます<span class="footnote_referrer"><a tabindex="0" onclick="footnote_moveToReference_16128_13('footnote_plugin_reference_16128_13_4');" onkeypress="footnote_moveToReference_16128_13('footnote_plugin_reference_16128_13_4');" ><sup id="footnote_plugin_tooltip_16128_13_4" class="footnote_plugin_tooltip_text">[4]</sup></a><span id="footnote_plugin_tooltip_text_16128_13_4" class="footnote_tooltip">この問題では、どの非終端記号 + , * , a, b, c, d も1回ずつを使っているので、</span></span>。</p>



<p><strong>[方針1] \( (S+S) \) の形を作り出す</strong></p>



<p>まず、括弧と＋が生成される規則は \( S \to (S+S) \) の1つにしか出てきません。なので、括弧 (   ) 部分は下のように \( (S+S) \) の形を作ってから \( S \to (S+S) \) を逆にたどるのかなという方針を立てます。</p>



<figure class="wp-block-image aligncenter size-large"><img width="1024" height="306" src="https://www.momoyama-usagi.com/wp-content/uploads/ki-mac2-4-1024x306.gif" alt="" class="wp-image-16173" srcset="https://www.momoyama-usagi.com/wp-content/uploads/ki-mac2-4-1024x306.gif 1024w, https://www.momoyama-usagi.com/wp-content/uploads/ki-mac2-4-300x90.gif 300w, https://www.momoyama-usagi.com/wp-content/uploads/ki-mac2-4-768x230.gif 768w" /><figcaption>\( (S+S) \) の形を作ると \( S \to (S+S) \) を逆に辿れる<br>[方針1]</figcaption></figure>



<p><strong>[方針2] \( S*S \) の形を作り出す</strong></p>



<p>また、\( * \) が生成される規則は \( S \to S * S \) の1つにしかないので、\( * \) は、下のように \( S*S \) を作ってから \( S \to S*S \) を逆にたどるのかなと方針を立てます。</p>



<figure class="wp-block-image aligncenter size-large"><img width="1024" height="413" src="https://www.momoyama-usagi.com/wp-content/uploads/ki-mac2-5-1024x413.gif" alt="" class="wp-image-16174" srcset="https://www.momoyama-usagi.com/wp-content/uploads/ki-mac2-5-1024x413.gif 1024w, https://www.momoyama-usagi.com/wp-content/uploads/ki-mac2-5-300x121.gif 300w, https://www.momoyama-usagi.com/wp-content/uploads/ki-mac2-5-768x309.gif 768w" /><figcaption>\( S*S \) の形を作ると \( S \to S*S \) を逆に辿れる</figcaption></figure>



<p><strong>[木構造]</strong></p>



<p>方針がたてれたところで、いよいよ解析木を作っていきましょう。</p>



<p>まず、\( V \to \ a \ | \ b \ | \ c \ | \ d \) を逆に適用することで、 \( a \), \( b \), \( c \), \( d \) を \( V \) に変換します。</p>



<figure class="wp-block-image aligncenter size-large"><img width="1024" height="306" src="https://www.momoyama-usagi.com/wp-content/uploads/ki2-7-1024x306.gif" alt="" class="wp-image-16135" srcset="https://www.momoyama-usagi.com/wp-content/uploads/ki2-7-1024x306.gif 1024w, https://www.momoyama-usagi.com/wp-content/uploads/ki2-7-300x90.gif 300w, https://www.momoyama-usagi.com/wp-content/uploads/ki2-7-768x229.gif 768w, https://www.momoyama-usagi.com/wp-content/uploads/ki2-7-1536x459.gif 1536w" /></figure>



<p>つぎに、\( V \) が生成される規則は \( S \to V \) の1つだけですね。</p>



<p>なので、先程出てきた \( V \) に対して生成規則を逆にたどることで \( S \) にします。</p>



<figure class="wp-block-image aligncenter size-large"><img width="1024" height="513" src="https://www.momoyama-usagi.com/wp-content/uploads/ki2-8-1024x513.gif" alt="" class="wp-image-16136" srcset="https://www.momoyama-usagi.com/wp-content/uploads/ki2-8-1024x513.gif 1024w, https://www.momoyama-usagi.com/wp-content/uploads/ki2-8-300x150.gif 300w, https://www.momoyama-usagi.com/wp-content/uploads/ki2-8-768x384.gif 768w, https://www.momoyama-usagi.com/wp-content/uploads/ki2-8-1536x769.gif 1536w" /></figure>



<p>すると、文字列は \( (S+S) * (S+S) \) となります。</p>



<p>ここで、[方針1]で登場した \( (S+S) \) の形が2つ出てきましたね。なので、\( S \to (S+S) \) の規則を逆に適用して、\( (S+S) \) を \( S \) にします。</p>



<figure class="wp-block-image aligncenter size-large"><img width="1024" height="542" src="https://www.momoyama-usagi.com/wp-content/uploads/ki2-9-1024x542.gif" alt="" class="wp-image-16137" srcset="https://www.momoyama-usagi.com/wp-content/uploads/ki2-9-1024x542.gif 1024w, https://www.momoyama-usagi.com/wp-content/uploads/ki2-9-300x159.gif 300w, https://www.momoyama-usagi.com/wp-content/uploads/ki2-9-768x406.gif 768w, https://www.momoyama-usagi.com/wp-content/uploads/ki2-9-1536x812.gif 1536w, https://www.momoyama-usagi.com/wp-content/uploads/ki2-9-2048x1083.gif 2048w" /></figure>



<p>すると、文字列が \( S*S \) の形となり、[方針2]で登場した \( S*S \) の形となりました。</p>



<p>なので、最後に \( S \to S * S \) を逆に適用すれば、めでたく文字列を出発記号 \( S \) にすることができます！</p>



<figure class="wp-block-image aligncenter size-large"><img width="1024" height="689" src="https://www.momoyama-usagi.com/wp-content/uploads/ki2-10-1024x689.gif" alt="" class="wp-image-16138" srcset="https://www.momoyama-usagi.com/wp-content/uploads/ki2-10-1024x689.gif 1024w, https://www.momoyama-usagi.com/wp-content/uploads/ki2-10-300x202.gif 300w, https://www.momoyama-usagi.com/wp-content/uploads/ki2-10-768x517.gif 768w, https://www.momoyama-usagi.com/wp-content/uploads/ki2-10-1536x1033.gif 1536w, https://www.momoyama-usagi.com/wp-content/uploads/ki2-10-2048x1378.gif 2048w" /></figure>



<p>よって、解析木は下のようになります。</p>



<figure class="wp-block-image aligncenter size-large"><img width="1024" height="718" src="https://www.momoyama-usagi.com/wp-content/uploads/ki2-2-1024x718.gif" alt="" class="wp-image-16130" srcset="https://www.momoyama-usagi.com/wp-content/uploads/ki2-2-1024x718.gif 1024w, https://www.momoyama-usagi.com/wp-content/uploads/ki2-2-300x210.gif 300w, https://www.momoyama-usagi.com/wp-content/uploads/ki2-2-768x539.gif 768w, https://www.momoyama-usagi.com/wp-content/uploads/ki2-2-1536x1077.gif 1536w, https://www.momoyama-usagi.com/wp-content/uploads/ki2-2-2048x1436.gif 2048w" /><figcaption>解析木<br>（例題1の答え）</figcaption></figure>



<p>[余談] 下のように、元の文字列を上に書き、出発記号 \( S \) が下になるような書き方をしてもOKです。</p>



<figure class="wp-block-image aligncenter size-large"><img width="1024" height="771" src="https://www.momoyama-usagi.com/wp-content/uploads/ki2-3-1024x771.gif" alt="" class="wp-image-16131" srcset="https://www.momoyama-usagi.com/wp-content/uploads/ki2-3-1024x771.gif 1024w, https://www.momoyama-usagi.com/wp-content/uploads/ki2-3-300x226.gif 300w, https://www.momoyama-usagi.com/wp-content/uploads/ki2-3-768x578.gif 768w, https://www.momoyama-usagi.com/wp-content/uploads/ki2-3-1536x1156.gif 1536w" /></figure>



<div style="height:100px" class="wp-block-spacer"></div>



<h2 class="wp-block-heading">2. 構文木の書き方</h2>



<p>解析木から「非終端記号」や「括弧などの関係ない記号」を取り除いたものが構文木となります。</p>



<p>先程の例題1を使って、解析木から構文木を作ってみましょう！</p>


<div class='wp-block-dbp-frame l-frame-float is-design-onframe is-frame-style-default dbp-frame has-bgcolor'><div class="dbp-frame-title">例題2</div><div class="dbp-frame-content has-content-gap">
<p>例題1と同じ、次の文脈自由文法で表される文法 \( G \) がある。\[<br>G = \left( \ \{ S, V \} \ , \  \{ a,b,c,d \} \ , \  P \ , \ S \ \right)<br>\]\[\begin{align*}<br>P = \{ \ \ S &amp; \to V  \ | \ (S+S) \ | \ S * S \\<br>V &amp; \to a \ | \ b \ | \ c \ | \ d \ \ \ \ \ \ \ \  \ \ \ \ \ \ \ \ \ \ \ \ \}<br>\end{align*}\]この文法 \( G \) に対し、以下の文字列 \( (a+b) * (c+d) \) の構文木を書きなさい。ただし、構文木を書く際には括弧を省くこと。</p>
</div></div>


<p><strong>[解説2]</strong></p>



<p>例題1で書いた解析木はこちらです。</p>



<figure class="wp-block-image aligncenter size-large is-resized"><img src="https://www.momoyama-usagi.com/wp-content/uploads/ki-mac2-9-1024x870.gif" alt="" class="wp-image-16190" width="596" height="506" srcset="https://www.momoyama-usagi.com/wp-content/uploads/ki-mac2-9-1024x870.gif 1024w, https://www.momoyama-usagi.com/wp-content/uploads/ki-mac2-9-300x255.gif 300w, https://www.momoyama-usagi.com/wp-content/uploads/ki-mac2-9-768x652.gif 768w" /></figure>



<p>まず、この解析木から下のの2つの操作をします。</p>



<ul class="wp-block-list"><li>非終端記号の削除</li><li>余計な括弧 (   ) の除去</li></ul>



<p>さらに、削除された（2つ以上の子をもつ）非終端記号の部分に対し、1つの子を削除された非終端記号の部分に移動させます<span class="footnote_referrer"><a tabindex="0" onclick="footnote_moveToReference_16128_13('footnote_plugin_reference_16128_13_5');" onkeypress="footnote_moveToReference_16128_13('footnote_plugin_reference_16128_13_5');" ><sup id="footnote_plugin_tooltip_16128_13_5" class="footnote_plugin_tooltip_text">[5]</sup></a><span id="footnote_plugin_tooltip_text_16128_13_5" class="footnote_tooltip">移動させる終端記号の選び方ですが、出発記号 \( S \)&nbsp;&#x2026; <span class="footnote_tooltip_continue"  onclick="footnote_moveToReference_16128_13('footnote_plugin_reference_16128_13_5');">Continue reading</span></span></span>。</p>



<figure class="wp-block-image aligncenter size-large is-resized"><img src="https://www.momoyama-usagi.com/wp-content/uploads/ki-mac2-10-1024x886.gif" alt="" class="wp-image-16195" width="523" height="452" srcset="https://www.momoyama-usagi.com/wp-content/uploads/ki-mac2-10-1024x886.gif 1024w, https://www.momoyama-usagi.com/wp-content/uploads/ki-mac2-10-300x260.gif 300w, https://www.momoyama-usagi.com/wp-content/uploads/ki-mac2-10-768x665.gif 768w" /></figure>



<p>すると、下のような構文木が出来上がります。</p>



<figure class="wp-block-image aligncenter size-large is-resized"><img src="https://www.momoyama-usagi.com/wp-content/uploads/ki2-18-1024x675.gif" alt="" class="wp-image-16146" width="625" height="412" srcset="https://www.momoyama-usagi.com/wp-content/uploads/ki2-18-1024x675.gif 1024w, https://www.momoyama-usagi.com/wp-content/uploads/ki2-18-300x198.gif 300w, https://www.momoyama-usagi.com/wp-content/uploads/ki2-18-768x506.gif 768w, https://www.momoyama-usagi.com/wp-content/uploads/ki2-18-1536x1012.gif 1536w" /><figcaption>構文木<br>（例題2の答え）</figcaption></figure>



<div style="height:100px" class="wp-block-spacer"></div>



<h2 class="wp-block-heading">3. 練習問題にチャレンジ！</h2>



<p>実際に解析木（や構文木）が書けるかどうか、2種類の練習問題にてチャレンジしてみましょう！</p>



<h3 class="wp-block-heading">練習1. 解析木・構文木を書いてみよう</h3>


<div class='wp-block-dbp-frame l-frame-float is-design-onframe is-frame-style-default dbp-frame has-bgcolor'><div class="dbp-frame-title">練習1</div><div class="dbp-frame-content has-content-gap">
<p>次の文脈自由文法で表される文法 \( G \) がある。\[<br>G = \left( \ \{ S, E, T \} \ , \  \{ i, =, + , ( , ) \} \ , \  P \ , \ S \ \right)<br>\]\[\begin{align*}<br>P = \{ \ \ S &amp; \to  E \ | \ i =S \\ E &amp; \to T \ | \ E + T \\  T &amp; \to i \ | \ ( S ) <br> \ \ \ \ \ \ \  \ \ \ \ \ \}<br>\end{align*}\]つぎの(1), (2)の問いに答えなさい。</p>

<p>(1) 文法 \( G \) に対し、文字列 \( i = (i+i) \) の解析木を書きなさい。<br>(2) 文法 \( G \) に対し、文字列 \( i = (i+i) \) の構文木を書きなさい。ただし、構文木を書く際には括弧を省くこと。</p>
</div></div>


<h3 class="wp-block-heading">練習2. 解析木が書ける文字列はどっち？</h3>


<div class='wp-block-dbp-frame l-frame-float is-design-onframe is-frame-style-default dbp-frame has-bgcolor'><div class="dbp-frame-title">練習2</div><div class="dbp-frame-content has-content-gap">
<p>次の文脈自由文法で表される文法 \( G \) がある。\[<br>G = \left( \ \{ S, E \} \ , \  \{ i, +, ( , ) \} \ , \  P \ , \ S \ \right)<br>\]\[\begin{align*}<br>P = \{ \ \ S &amp; \to  E \ | \ S + E \\ E &amp; \to i  \ | \  (S)<br> \ \ \ \ \ \ \  \ \ \ \ \ \}<br>\end{align*}\]つぎの(1), (2)の問いに答えなさい。</p>

<p>(1) 次の (ア), (イ) のうち、文法 \( G \) を満たす文字列はどちらか答えなさい。</p>

<p>(ア) \( ( ( i ) + i ) \) <br>(イ) \( i + ( + i )  \)</p>

<p>(2) (1)で答えた方の文字列に対して解析木を書きなさい。</p>
</div></div>


<div style="height:100px" class="wp-block-spacer"></div>



<h2 class="wp-block-heading">4. 練習問題の答え</h2>



<h3 class="wp-block-heading">解答1. </h3>



<h4 class="wp-block-heading">(1) 解析木</h4>



<p>最初に | でつながれている生成規則を1個ずつ省略せずに書き直してから、方針をたてましょう。</p>



<figure class="wp-block-image aligncenter size-large is-resized"><img src="https://www.momoyama-usagi.com/wp-content/uploads/ki-mac2-1-701x1024.gif" alt="" class="wp-image-16169" width="164" height="240" srcset="https://www.momoyama-usagi.com/wp-content/uploads/ki-mac2-1-701x1024.gif 701w, https://www.momoyama-usagi.com/wp-content/uploads/ki-mac2-1-205x300.gif 205w, https://www.momoyama-usagi.com/wp-content/uploads/ki-mac2-1-768x1123.gif 768w" /></figure>



<p><strong>★ 方針 </strong>★</p>



<p>[方針1]</p>



<p>まず、\( + \) が生成できる規則は、\( E \to E + T \) 1つのみですね。</p>



<p>なので、文字列の \( i + i \) の部分を生成規則を逆にたどっていくことで \( E+T \) にすることを考えます。</p>



<figure class="wp-block-image aligncenter size-full is-resized"><img src="https://www.momoyama-usagi.com/wp-content/uploads/ki-mac2-6.gif" alt="" class="wp-image-16175" width="633" height="197"/><figcaption>[方針1]</figcaption></figure>



<p>[方針2]</p>



<p>また、括弧が生成できる規則は、\( T  \to  (S) \) のみです。</p>



<p>そのため、文字列中に括弧が出てくる \( (i+i) \) 部分について、生成規則を逆にたどっていくことにより、\(  (S) \) にすることを考えます。</p>



<figure class="wp-block-image aligncenter size-full is-resized"><img src="https://www.momoyama-usagi.com/wp-content/uploads/ki-mac2-7.gif" alt="" class="wp-image-16176" width="689" height="336"/><figcaption>[方針2]</figcaption></figure>



<p>[方針3]</p>



<p>さらに、\( = \) が生成できる規則は \( S \to i = S \) のみです。</p>



<p>なので、\( i =  \textcolor{orange} {( i+ i)} \) 部分については、生成規則を逆にたどっていくことで \( i = \textcolo{orange}{ S } \) にすることを目指します<span class="footnote_referrer"><a tabindex="0" onclick="footnote_moveToReference_16128_13('footnote_plugin_reference_16128_13_6');" onkeypress="footnote_moveToReference_16128_13('footnote_plugin_reference_16128_13_6');" ><sup id="footnote_plugin_tooltip_16128_13_6" class="footnote_plugin_tooltip_text">[6]</sup></a><span id="footnote_plugin_tooltip_text_16128_13_6" class="footnote_tooltip">\( \textcolor{blue}{i =} (i+i)\) の \( \textcolor{blue}{ i = } \) の部分は終端記号なため、実質 \( \textcolor{orange}{ (i+i) } \) 部分を \( \textcolor{orange}{S} \)&nbsp;&#x2026; <span class="footnote_tooltip_continue"  onclick="footnote_moveToReference_16128_13('footnote_plugin_reference_16128_13_6');">Continue reading</span></span></span>。</p>



<figure class="wp-block-image aligncenter size-full is-resized"><img src="https://www.momoyama-usagi.com/wp-content/uploads/ki-mac2-8.gif" alt="" class="wp-image-16177" width="633" height="344"/><figcaption>[方針3]</figcaption></figure>



<p><strong>[解析木の作り方]</strong></p>



<p>方針をたてられたので、生成規則を逆にたどっていく（以下：逆にたどっていくことを逆変換と表記します）ことにより、解析木を創りましょう。</p>



<p>まずは、[方針1] の通り、\( i + i \) から生成規則を逆変換していくことにより、\( E \) にします。</p>



<figure class="wp-block-image aligncenter size-large is-resized"><img src="https://www.momoyama-usagi.com/wp-content/uploads/ki2-15-1024x742.gif" alt="" class="wp-image-16143" width="552" height="399" srcset="https://www.momoyama-usagi.com/wp-content/uploads/ki2-15-1024x742.gif 1024w, https://www.momoyama-usagi.com/wp-content/uploads/ki2-15-300x217.gif 300w, https://www.momoyama-usagi.com/wp-content/uploads/ki2-15-768x556.gif 768w" /></figure>



<p>つぎに、[方針2] の通り、括弧部分を逆変換によりひとまとめにします。</p>



<figure class="wp-block-image aligncenter size-large is-resized"><img src="https://www.momoyama-usagi.com/wp-content/uploads/ki2-16-944x1024.gif" alt="" class="wp-image-16144" width="505" height="547" srcset="https://www.momoyama-usagi.com/wp-content/uploads/ki2-16-944x1024.gif 944w, https://www.momoyama-usagi.com/wp-content/uploads/ki2-16-277x300.gif 277w, https://www.momoyama-usagi.com/wp-content/uploads/ki2-16-768x833.gif 768w" /></figure>



<p>最後に、[方針3] の通り、\( = \) を逆変換によりまとめれば、出発記号 \( S \) だけになるため、解析木の完成です！</p>



<figure class="wp-block-image aligncenter size-large is-resized"><img src="https://www.momoyama-usagi.com/wp-content/uploads/ki2-11-1024x1009.gif" alt="" class="wp-image-16139" width="552" height="544" srcset="https://www.momoyama-usagi.com/wp-content/uploads/ki2-11-1024x1009.gif 1024w, https://www.momoyama-usagi.com/wp-content/uploads/ki2-11-300x296.gif 300w, https://www.momoyama-usagi.com/wp-content/uploads/ki2-11-768x757.gif 768w, https://www.momoyama-usagi.com/wp-content/uploads/ki2-11-1536x1513.gif 1536w" /><figcaption>解析木<br>練習問題1(1)の答え</figcaption></figure>



<h4 class="wp-block-heading">(2) 構文木</h4>



<p>まず、(1)で求めた解析木から、</p>



<ul class="wp-block-list"><li>非終端記号の削除</li><li>括弧の除去</li></ul>



<p>をします。</p>



<figure class="wp-block-image aligncenter size-large is-resized"><img src="https://www.momoyama-usagi.com/wp-content/uploads/ki-mac2-12-804x1024.gif" alt="" class="wp-image-16217" width="400" height="509" srcset="https://www.momoyama-usagi.com/wp-content/uploads/ki-mac2-12-804x1024.gif 804w, https://www.momoyama-usagi.com/wp-content/uploads/ki-mac2-12-236x300.gif 236w, https://www.momoyama-usagi.com/wp-content/uploads/ki-mac2-12-768x978.gif 768w" /></figure>



<p>つぎに、削除された非終端記号のうち、○の部分（2つ以上の子をもつ部分）に対し、1つの子を削除された非終端記号の部分に移動させます。</p>



<figure class="wp-block-image aligncenter size-large is-resized"><img src="https://www.momoyama-usagi.com/wp-content/uploads/ki-mac2-11-773x1024.gif" alt="" class="wp-image-16196" width="464" height="615" srcset="https://www.momoyama-usagi.com/wp-content/uploads/ki-mac2-11-773x1024.gif 773w, https://www.momoyama-usagi.com/wp-content/uploads/ki-mac2-11-227x300.gif 227w, https://www.momoyama-usagi.com/wp-content/uploads/ki-mac2-11-768x1017.gif 768w" /></figure>



<p>すると、下のような構文木が完成します。</p>



<figure class="wp-block-image aligncenter size-full is-resized"><img src="https://www.momoyama-usagi.com/wp-content/uploads/ki-mac2-13.gif" alt="" class="wp-image-16218" width="589" height="479"/><figcaption>構文木<br>（練習問題1(2)の答え）</figcaption></figure>



<h3 class="wp-block-heading">解答2. </h3>



<h4 class="wp-block-heading">(1) 文字列が文法を満たしているかの判定</h4>


<p><span>文字列が文法 \( G \) を満たしているかを判定する際には、<span  style="background-image:linear-gradient(to bottom,transparent 0%,#FFF387 0%);" class="dbp-e-marker-animation y">文字列の一部分を切り出してその部分が文法的に満たせそうかを確認する方法</span>がおすすめです。</span></p>


<p>今回は、</p>



<p>(ア) \( ( ( i ) + i ) \) <br>(イ) \( i + ( + i )  \)</p>



<p>の2つの文字列のうち、どちらが文法を満たしているのかを判定するのでしたね。</p>



<p>なので、まずは文字列の一部分が文法を満たしているのかを確認していきましょう。</p>



<p>まず、(ア) の \( (i) \) と \( (i)+i \) に着目して構文木を書いてみましょう。</p>



<figure class="wp-block-image aligncenter size-large"><img width="1024" height="740" src="https://www.momoyama-usagi.com/wp-content/uploads/ki2-19-1024x740.gif" alt="" class="wp-image-16147" srcset="https://www.momoyama-usagi.com/wp-content/uploads/ki2-19-1024x740.gif 1024w, https://www.momoyama-usagi.com/wp-content/uploads/ki2-19-300x217.gif 300w, https://www.momoyama-usagi.com/wp-content/uploads/ki2-19-768x555.gif 768w, https://www.momoyama-usagi.com/wp-content/uploads/ki2-19-1536x1110.gif 1536w" /></figure>



<p>すると、どちらも \( S \) 1文字に書き換えることができました<span class="footnote_referrer"><a tabindex="0" onclick="footnote_moveToReference_16128_13('footnote_plugin_reference_16128_13_7');" onkeypress="footnote_moveToReference_16128_13('footnote_plugin_reference_16128_13_7');" ><sup id="footnote_plugin_tooltip_16128_13_7" class="footnote_plugin_tooltip_text">[7]</sup></a><span id="footnote_plugin_tooltip_text_16128_13_7" class="footnote_tooltip">一部分が \( S \) 1文字に書き換えられなからといって、与えられた文字列が文法を満たしていないとは限らない点に注意が必要です。</span></span>。</p>



<p>さらに、\(  \textcolor{red}{( i ) + i}  \) が \( \textcolor{red}{S} \) に書き換えられることが分かったので、(ア) の文字列 \( ( \textcolor{red}{( i ) + i} ) \) は \( ( \textcolor{red}{S} ) \) に書き換えられそうですね。</p>



<p>ここで、\( (S) \) は、\( S \to E \to (S) \) で導出できるため、(ア)の文字列は文法 \( G \) を満たすことがわかります。</p>



<div style="height:30px" class="wp-block-spacer"></div>



<p>一方 (イ) の規則はどうでしょうか。</p>



<p>文字列 \( (+i) \) 部分を変形しながら見ていきましょう。</p>



<p>すると、\( (+E) \) までは逆変換することができます。しかし、\( + \) を逆変換できる式は \( S \to S + E \) の1種類しか存在しない上、生成規則的に \( S \) に空文字 \( \varepsilon \) は入らなさそうなため、どう頑張っても \( (+E) \) から文字列を逆変換することができません。</p>



<figure class="wp-block-image aligncenter size-large is-resized"><img src="https://www.momoyama-usagi.com/wp-content/uploads/ki2-20-1024x684.gif" alt="" class="wp-image-16148" width="633" height="423" srcset="https://www.momoyama-usagi.com/wp-content/uploads/ki2-20-1024x684.gif 1024w, https://www.momoyama-usagi.com/wp-content/uploads/ki2-20-300x201.gif 300w, https://www.momoyama-usagi.com/wp-content/uploads/ki2-20-768x513.gif 768w, https://www.momoyama-usagi.com/wp-content/uploads/ki2-20-1536x1027.gif 1536w" /></figure>



<p>そのため、(イ) は文法 \( G \) を満たしませんね。</p>



<p>よって、文法 \( G \) を満たす文字列は (ア) となります。 ← (1) の答え</p>



<h4 class="wp-block-heading">(2) 解析木</h4>



<p>文法 \( G \) を満たす (ア) の文字列 \( ( ( i ) + i )  \) を書いていけばOKです。</p>



<p>ここで、(1)で書いた文字列の一部分 \( (i) \) と \( (i)+i \) の解析木を確認しましょう。</p>



<figure class="wp-block-image aligncenter size-large"><img width="1024" height="558" src="https://www.momoyama-usagi.com/wp-content/uploads/ki-mac2-14-1024x558.gif" alt="" class="wp-image-16231" srcset="https://www.momoyama-usagi.com/wp-content/uploads/ki-mac2-14-1024x558.gif 1024w, https://www.momoyama-usagi.com/wp-content/uploads/ki-mac2-14-300x163.gif 300w, https://www.momoyama-usagi.com/wp-content/uploads/ki-mac2-14-768x418.gif 768w" /></figure>



<p>あとは、この解析木を参考にしながら (ア) の文字列全体 \( ( ( i ) + i )  \) の解析木を書けばOKです！</p>



<figure class="wp-block-image aligncenter size-large is-resized"><img src="https://www.momoyama-usagi.com/wp-content/uploads/ki2-21-912x1024.gif" alt="" class="wp-image-16149" width="526" height="591" srcset="https://www.momoyama-usagi.com/wp-content/uploads/ki2-21-912x1024.gif 912w, https://www.momoyama-usagi.com/wp-content/uploads/ki2-21-267x300.gif 267w, https://www.momoyama-usagi.com/wp-content/uploads/ki2-21-768x862.gif 768w, https://www.momoyama-usagi.com/wp-content/uploads/ki2-21-1368x1536.gif 1368w" /><figcaption>練習問題2(2)の答え</figcaption></figure>
<div class="speaker-mute footnotes_reference_container"> <div class="footnote_container_prepare"><p><span tabindex="0" class="footnote_reference_container_label pointer">注釈</span><span tabindex="0" class="footnote_reference_container_collapse_button" style="display: none;">[<a id="footnote_reference_container_collapse_button_16128_13">+</a>]</span></p></div> <div id="footnote_references_container_16128_13"><table class="footnotes_table footnote-reference-container"><caption class="accessibility">注釈</caption> <tbody> 

<tr class="footnotes_plugin_reference_row"> <th scope="row" class="footnote_plugin_index_combi pointer"  onclick="footnote_moveToAnchor_16128_13('footnote_plugin_tooltip_16128_13_1');"><a id="footnote_plugin_reference_16128_13_1" class="footnote_backlink"><span class="footnote_index_arrow">&#8593;</span>1</a></th> <td class="footnote_plugin_text">SV,  SVC, SVO, SVOO, SVOCの5種類。</td></tr>

<tr class="footnotes_plugin_reference_row"> <th scope="row" class="footnote_plugin_index_combi pointer"  onclick="footnote_moveToAnchor_16128_13('footnote_plugin_tooltip_16128_13_2');"><a id="footnote_plugin_reference_16128_13_2" class="footnote_backlink"><span class="footnote_index_arrow">&#8593;</span>2</a></th> <td class="footnote_plugin_text">基本情報や応用情報で出てくる文脈自由文法がまさに <code>(生成元)::=(生成先) </code>のような書き方をしています。（BNF記法などとも呼ばれます。）</td></tr>

<tr class="footnotes_plugin_reference_row"> <th scope="row" class="footnote_plugin_index_combi pointer"  onclick="footnote_moveToAnchor_16128_13('footnote_plugin_tooltip_16128_13_3');"><a id="footnote_plugin_reference_16128_13_3" class="footnote_backlink"><span class="footnote_index_arrow">&#8593;</span>3</a></th> <td class="footnote_plugin_text">生成規則を逆方向にたどるとは、例えば \( A \to B + C \) の生成規則に対して、\( B+ C \) を \( A \) に変換することを表します。</td></tr>

<tr class="footnotes_plugin_reference_row"> <th scope="row" class="footnote_plugin_index_combi pointer"  onclick="footnote_moveToAnchor_16128_13('footnote_plugin_tooltip_16128_13_4');"><a id="footnote_plugin_reference_16128_13_4" class="footnote_backlink"><span class="footnote_index_arrow">&#8593;</span>4</a></th> <td class="footnote_plugin_text">この問題では、どの非終端記号 + , * , a, b, c, d も1回ずつを使っているので、</td></tr>

<tr class="footnotes_plugin_reference_row"> <th scope="row" class="footnote_plugin_index_combi pointer"  onclick="footnote_moveToAnchor_16128_13('footnote_plugin_tooltip_16128_13_5');"><a id="footnote_plugin_reference_16128_13_5" class="footnote_backlink"><span class="footnote_index_arrow">&#8593;</span>5</a></th> <td class="footnote_plugin_text">移動させる終端記号の選び方ですが、出発記号 \( S \) から生成された際に、一番最初に生成された終端記号が親になると思っていただけたらOKです。基本的に数式の構文解析の場合、* や + などの演算子が親に来ることがほとんどです。（例 1, 2, + の中からであれば + が親になる）</td></tr>

<tr class="footnotes_plugin_reference_row"> <th scope="row" class="footnote_plugin_index_combi pointer"  onclick="footnote_moveToAnchor_16128_13('footnote_plugin_tooltip_16128_13_6');"><a id="footnote_plugin_reference_16128_13_6" class="footnote_backlink"><span class="footnote_index_arrow">&#8593;</span>6</a></th> <td class="footnote_plugin_text"> \( \textcolor{blue}{i =} (i+i)\) の \( \textcolor{blue}{ i = } \) の部分は終端記号なため、実質 \( \textcolor{orange}{ (i+i) } \) 部分を \( \textcolor{orange}{S} \) にすることを目指せばOKです。</td></tr>

<tr class="footnotes_plugin_reference_row"> <th scope="row" class="footnote_plugin_index_combi pointer"  onclick="footnote_moveToAnchor_16128_13('footnote_plugin_tooltip_16128_13_7');"><a id="footnote_plugin_reference_16128_13_7" class="footnote_backlink"><span class="footnote_index_arrow">&#8593;</span>7</a></th> <td class="footnote_plugin_text">一部分が \( S \) 1文字に書き換えられなからといって、与えられた文字列が文法を満たしていないとは限らない点に注意が必要です。</td></tr>

 </tbody> </table> </div></div>]]></content:encoded>
					
					<wfw:commentRss>https://www.momoyama-usagi.com/entry/info-compiler2/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>うさぎでもわかるコンパイラ　第1羽　Lex(Flex)で字句解析をしてみよう！</title>
		<link>https://www.momoyama-usagi.com/entry/info-compiler1</link>
					<comments>https://www.momoyama-usagi.com/entry/info-compiler1#respond</comments>
		
		<dc:creator><![CDATA[ももうさ]]></dc:creator>
		<pubDate>Sat, 03 Sep 2022 05:51:55 +0000</pubDate>
				<category><![CDATA[コンパイラ(言語処理系)]]></category>
		<category><![CDATA[情報]]></category>
		<category><![CDATA[C言語]]></category>
		<category><![CDATA[Flex]]></category>
		<category><![CDATA[Lex]]></category>
		<category><![CDATA[コンパイラ]]></category>
		<guid isPermaLink="false">https://www.momoyama-usagi.com/?p=15935</guid>

					<description><![CDATA[※ この記事は、「正規表現」の知識と「コンパイラの処理の流れ」について軽く理解してから読むことをおすすめします。もし正規表現やコンパイラの処理の流れの知識について自信がない人は、下の記事にて復習をすることをおすすめします [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>※ この記事は、「正規表現」の知識と「コンパイラの処理の流れ」について軽く理解してから読むことをおすすめします。もし正規表現やコンパイラの処理の流れの知識について自信がない人は、下の記事にて復習をすることをおすすめします。</p>



<p><strong>[記事1] うさぎでもわかるオートマトンと言語理論　第09羽　正規表現と有限オートマトン</strong></p>



<figure class="wp-block-embed is-type-wp-embed is-provider-工業大学生ももやまのうさぎ塾 wp-block-embed-工業大学生ももやまのうさぎ塾"><div class="wp-block-embed__wrapper">
        <article class="pb p-id-144 is-position-relative pb-embed">
            <a class="pb-contents" href="https://www.momoyama-usagi.com/entry/info-automaton09">
                <div class="pb__thumb"><img width="300" height="277" src="https://www.momoyama-usagi.com/wp-content/uploads/2021/05/20191009084217-1-300x277.gif" class="is-position-overlay wp-post-image" alt="" lazysizes="1" srcset="https://www.momoyama-usagi.com/wp-content/uploads/2021/05/20191009084217-1-300x277.gif 300w, https://www.momoyama-usagi.com/wp-content/uploads/2021/05/20191009084217-1-768x710.gif 768w" /></div><div class="pb__body l-column is-flex-1"><div class="pb-title is-omit-line:2">うさぎでもわかるオートマトンと言語理論　第09羽　正規表現と有限オートマトン</div><div class="pb-substr is-font-size:s is-omit-line:2">今回は正規表現について簡単にですがまとめています。よく使われる正規表現の種類、正規表現を非決定性オートマトンで表す方法を</div></div>            </a>
        </article>
        
</div></figure>



<p><strong>[記事2] うさぎでもわかる計算機システム　Part11　コンパイラの処理の流れ（字句解析と意味解析のしくみ）</strong></p>



<figure class="wp-block-embed is-type-wp-embed is-provider-工業大学生ももやまのうさぎ塾 wp-block-embed-工業大学生ももやまのうさぎ塾"><div class="wp-block-embed__wrapper">
        <article class="pb p-id-120 is-position-relative pb-embed">
            <a class="pb-contents" href="https://www.momoyama-usagi.com/entry/info-calc-sys11">
                <div class="pb__thumb"><img width="300" height="260" src="https://www.momoyama-usagi.com/wp-content/uploads/konpai1-6-300x260.gif" class="is-position-overlay wp-post-image" alt="" lazysizes="1" srcset="https://www.momoyama-usagi.com/wp-content/uploads/konpai1-6-300x260.gif 300w, https://www.momoyama-usagi.com/wp-content/uploads/konpai1-6-1024x886.gif 1024w, https://www.momoyama-usagi.com/wp-content/uploads/konpai1-6-768x664.gif 768w, https://www.momoyama-usagi.com/wp-content/uploads/konpai1-6-1536x1329.gif 1536w" /></div><div class="pb__body l-column is-flex-1"><div class="pb-title is-omit-line:2">うさぎでもわかる計算機システム　Part11　コンパイラの処理の流れ（字句解析と意味解析のしくみ）</div><div class="pb-substr is-font-size:s is-omit-line:2">今回はコンパイラの処理の流れについて、特に字句解析・意味解析を中心に説明しています。</div></div>            </a>
        </article>
        
</div></figure>



<p>こんにちは、ももやまです。</p>



<p>皆さんが書いたプログラム（C言語など）が実際にコンピュータ上で実行できる形（機械語）にするためには、「コンパイル」をする必要があるのでしたね<span class="footnote_referrer"><a tabindex="0" onclick="footnote_moveToReference_15935_15('footnote_plugin_reference_15935_15_1');" onkeypress="footnote_moveToReference_15935_15('footnote_plugin_reference_15935_15_1');" ><sup id="footnote_plugin_tooltip_15935_15_1" class="footnote_plugin_tooltip_text">[1]</sup></a><span id="footnote_plugin_tooltip_text_15935_15_1" class="footnote_tooltip">&nbsp;&#x2026; <span class="footnote_tooltip_continue"  onclick="footnote_moveToReference_15935_15('footnote_plugin_reference_15935_15_1');">Continue reading</span></span></span>。</p>



<p>この「コンパイル」の流れ（C言語が機械語になるまでの過程）ですが、大まかに分けると下の4つに分けることができます。</p>



<figure class="wp-block-image aligncenter size-large"><img width="1024" height="884" src="https://www.momoyama-usagi.com/wp-content/uploads/konpai1-3-1024x884.gif" alt="" class="wp-image-15936" srcset="https://www.momoyama-usagi.com/wp-content/uploads/konpai1-3-1024x884.gif 1024w, https://www.momoyama-usagi.com/wp-content/uploads/konpai1-3-300x259.gif 300w, https://www.momoyama-usagi.com/wp-content/uploads/konpai1-3-768x663.gif 768w, https://www.momoyama-usagi.com/wp-content/uploads/konpai1-3-1536x1327.gif 1536w" /><figcaption>コンパイルの流れ</figcaption></figure>



<p>今回は、上の4つの過程の中でも最初の「字句解析」を実際に体験することができるLex(Flex)の読み方や書き方について見ていきます。</p>



<p>※ FlexはLexの上位互換みたいなもので、基本的な使い方などはLexと同じです。そのため、Flexについて知りたい人もこの記事をご覧いただいてOKです。<br>（具体的にFlexとLexがどう違うのかはこの記事では割愛します。）</p>



<h2 class="wp-block-heading">1. 字句解析ってなに？[復習]</h2>



<p>Lexについて勉強する前に、字句解析ではどんなことをするかを軽く復習しておきましょう。</p>



<p>皆さんは「英語で書かれた文章を日本語に直しなさい」という作業を英語の期末試験やら入試でやったことがあると思います。</p>



<figure class="wp-block-image aligncenter size-large"><img width="1024" height="140" src="https://www.momoyama-usagi.com/wp-content/uploads/konpai1-1-1024x140.gif" alt="" class="wp-image-15938" srcset="https://www.momoyama-usagi.com/wp-content/uploads/konpai1-1-1024x140.gif 1024w, https://www.momoyama-usagi.com/wp-content/uploads/konpai1-1-300x41.gif 300w, https://www.momoyama-usagi.com/wp-content/uploads/konpai1-1-768x105.gif 768w, https://www.momoyama-usagi.com/wp-content/uploads/konpai1-1-1536x210.gif 1536w" /><figcaption>英文の例（中学1年生レベル）</figcaption></figure>



<p>そのときに、英文に出てくる各英単語が「どんな品詞を持って、どんな意味を持つのか」を考えながら翻訳していたと思います。  </p>



<figure class="wp-block-image aligncenter size-large"><img width="1024" height="254" src="https://www.momoyama-usagi.com/wp-content/uploads/konpai1-5-1024x254.gif" alt="" class="wp-image-15944" srcset="https://www.momoyama-usagi.com/wp-content/uploads/konpai1-5-1024x254.gif 1024w, https://www.momoyama-usagi.com/wp-content/uploads/konpai1-5-300x74.gif 300w, https://www.momoyama-usagi.com/wp-content/uploads/konpai1-5-768x190.gif 768w, https://www.momoyama-usagi.com/wp-content/uploads/konpai1-5-1536x380.gif 1536w" /><figcaption>各単語の品詞・日本語訳をつけると…</figcaption></figure>


<p>コンパイラの世界でも、C言語（のような高級言語）をコンピュータが実行できる言語に翻訳する1つ目のステップとして、<strong><span style="text-decoration: underline;">C言語で書かれたファイルの文字列を、単語単位に分割していき、その単語の属性（英語でいう品詞）がどれにあたるの</span>か</strong>を機械的にチェックしていきます。</p>
<p>この<span  style="background-image:linear-gradient(to bottom,transparent 0%,#FFF387 0%);" class="dbp-e-marker-animation blue">ファイル内の文字列を単語単位に分割し、分割した単語（字句と呼びます）がどの属性（例: 識別子、キーワード、定数、文字列、etc...）にあたるのかをチェックしていく</span>過程が<span  style="background-image:linear-gradient(to bottom,transparent 0%,#FFF387 0%);" class="dbp-e-marker-animation blue">字句解析</span>なのです！</p>
<p>※ 属性というのはあまり一般的な言い方ではありませんが、わかりやすく表現するために本記事では属性という表現を使っています。</p>


<h2 class="wp-block-heading">2. 正規表現 [復習]</h2>



<p>字句解析では、ファイル内の文字列を字句ごとに分割したあとに、「それぞれの字句がどの属性（識別子、キーワード、定数、文字列、etc...）」に分類する際に、字句の属性ごとに「この文字列だったらこの属性になるよ～」というのを列挙します。</p>


<p>言い換えると、各属性ごとに「文字列を列挙した集合<span class="footnote_referrer"><a tabindex="0" onclick="footnote_moveToReference_15935_15('footnote_plugin_reference_15935_15_2');" onkeypress="footnote_moveToReference_15935_15('footnote_plugin_reference_15935_15_2');" ><sup id="footnote_plugin_tooltip_15935_15_2" class="footnote_plugin_tooltip_text">[2]</sup></a><span id="footnote_plugin_tooltip_text_15935_15_2" class="footnote_tooltip">文字列が集まった箱のようなものだと思ってください。</span></span>」を用意し、ファイル内の文字列を分割した書く字句ごとにどの集合に属するかを調べていくことをします<span class="footnote_referrer"><a tabindex="0" onclick="footnote_moveToReference_15935_15('footnote_plugin_reference_15935_15_3');" onkeypress="footnote_moveToReference_15935_15('footnote_plugin_reference_15935_15_3');" ><sup id="footnote_plugin_tooltip_15935_15_3" class="footnote_plugin_tooltip_text">[3]</sup></a><span id="footnote_plugin_tooltip_text_15935_15_3" class="footnote_tooltip">各字句がどの属性の文字列集合（文字列が集まった箱か）に属するかを調べていくかというのを考えます。</span></span>。</p>


<p>しかし、文字列を列挙した集合を作る際に、特定の文字列を指定するだけならともかく、「最初の1文字目はアルファベット、2文字目以降はアルファベット or 数字の文字列」のような指定の仕方をする場合、いちいち該当する文字を1文字1文字列挙していっては何日たっても列挙が終わりません。</p>


<p><span>ここで出てくる魔法のテクニックが正規表現です。正規表現では「最初の1文字目はアルファベット、2文字目以降はアルファベット or 数字の文字列」のように<span  style="background-image:linear-gradient(to bottom,transparent 0%,#FFF387 0%);" class="dbp-e-marker-animation y">一定のルールに従った文字列を（いちいち列挙することなく）1単語ですべて表現することができます</span>。</span></p>


<p>ここからは、Lexでよく使う正規表現をサクッと復習していきましょう。</p>



<h3 class="wp-block-heading">(1) 繰り返しを表す記号</h3>



<h4 class="wp-block-heading">(1-a) 0回以上の繰り返し * </h4>



<p><code>*</code> をつけた直前の文字を0回以上繰り返します。</p>



<p><strong>例: <code>sm<mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-red-color">o*</mark>ch</code> の場合に当てはまる文字列の例</strong></p>



<ul class="wp-block-list"><li>smch</li><li>sm<mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-red-color">o</mark>ch</li><li>sm<mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-red-color">oo</mark>ch</li><li>sm<mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-red-color">ooo</mark>ch</li><li>sm<mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-red-color">ooooooooooooooooooooooooooooooo</mark>ch</li></ul>



<h4 class="wp-block-heading">(1-b) 1回以上の繰り返し +</h4>



<p><code>+</code> をつけた直前の文字を1回以上繰り返します。</p>



<p><strong>例: <code>sm<mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-red-color">o</mark>+ch</code> の場合に当てはまる文字列の例</strong></p>



<ul class="wp-block-list"><li>sm<mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-red-color">o</mark>ch</li><li>sm<mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-red-color">oo</mark>ch</li><li>sm<mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-red-color">ooo</mark>ch</li><li>sm<mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-red-color">ooooooooooooooooooooooooooooooo</mark>ch</li></ul>



<p><code>smo+ch</code> と列挙した場合、<code>smch</code> は <code>+</code> の直前の文字列oを1回も繰り返していないため、当てはまらない。</p>



<h4 class="wp-block-heading">(1-c) 0回もしくは1回の繰り返し ?</h4>



<p><code>?</code> をつけた直前の文字を0回 or 1回繰り返します。</p>



<p><strong>例: <code>sm<mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-red-color">o</mark>?ch</code> の場合に当てはまる文字列</strong></p>



<ul class="wp-block-list"><li>smch</li><li>sm<mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-red-color">o</mark>ch</li></ul>



<p>※ この2種類以外の文字列は当てはまらない</p>



<h4 class="wp-block-heading">(1-d) 特定回数の繰り返し {min,max}</h4>



<p><code>{min,max}</code> をつけた直前の文字列を min 回 ～ max 回の間繰り返します。</p>



<p>※ min, max のどちらか片方は省略可能です。</p>



<p><strong>例1: <code>sm<mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-red-color">o{2,4}</mark>ch</code> の場合に当てはまる文字列 (min = 2, max = 4)</strong></p>



<ul class="wp-block-list"><li>sm<mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-red-color">oo</mark>ch</li><li>sm<mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-red-color">ooo</mark>ch</li><li>sm<mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-red-color">oooo</mark>ch</li></ul>



<p>※1 {2,4}をつけた直前の文字列 o を2～4回繰り返しているものだけが当てはまる<br>※2 この3種類以外の文字列は当てはまらない</p>



<p><strong>例2: <code>sm<mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-red-color">o{,3}</mark>ch</code> の場合に当てはまる文字列 (min = 指定なし, max = 3)</strong></p>



<ul class="wp-block-list"><li>smch</li><li>sm<mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-red-color">o</mark>ch</li><li>sm<mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-red-color">oo</mark>ch</li><li>sm<mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-red-color">ooo</mark>ch</li></ul>



<p>※1 {,3}をつけた直前の文字列 o を3回以下繰り返しているものだけが当てはまる<br>※2 この4種類以外の文字列は当てはまらない</p>



<p><strong>例3: <code>sm<mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-red-color">o{3,}</mark>ch</code> の場合に当てはまる文字列の例 (min = 3, max = 指定なし)</strong></p>



<ul class="wp-block-list"><li>sm<mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-red-color">ooo</mark>ch</li><li>sm<mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-red-color">oooo</mark>ch</li><li>sm<mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-red-color">ooooo</mark>ch</li><li>sm<mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-red-color">ooooooooooooooooo</mark>ch</li></ul>



<p>※ {3,}をつけた直前の文字列 o を3回以上繰り返しているものだけが当てはまる</p>



<h3 class="wp-block-heading">(2) 文字列を指定する表現</h3>



<h4 class="wp-block-heading">(2-a) グループ化のカッコ (  )</h4>



<p>文字列を (   ) すると、カッコ内の文字列をグループ化することができます。</p>



<p>(1)で説明した「繰り返しを表す記号」で使われます。</p>



<p><strong>例: <code><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-red-color">(usa)+</mark>dayo</code> の場合に当てはまる文字列の例</strong></p>



<ul class="wp-block-list"><li><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-red-color">usa</mark>dayo</li><li><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-red-color">usausa</mark>dayo</li><li><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-red-color">usausausa</mark>dayo</li></ul>



<p>※ <mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-red-color">usa</mark>で1グループなので、<mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-red-color">usa</mark><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-blue-color">u</mark>dayo のように、usa単位で繰り返しをしていない文字列は当てはまらない</p>



<h4 class="wp-block-heading">(2-b) いずれかを表す記号 |  ※ (   ) と同時に使用OK</h4>



<p>複数パターンの文字列を当てはめる場合に使います。</p>



<p><strong>例1: <mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-red-color">center</mark>|<mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-blue-color">centre </mark>の場合に当てはまる文字列</strong></p>



<ul class="wp-block-list"><li><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-red-color">center</mark></li><li><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-blue-color">centre</mark></li></ul>



<p><strong>例2: cent(<mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-red-color">er</mark>|<mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-blue-color">re</mark>) の場合に当てはまる文字列</strong></p>



<ul class="wp-block-list"><li>cent<mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-red-color">er</mark></li><li>cent<mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-blue-color">re</mark></li></ul>



<p>※ 基本的には、例2のように複数パターン当てはまる部分だけを (   ) と | を使って表すことが多い。</p>



<h4 class="wp-block-heading">(2-c) 1文字単位で当てはまる文字を指定する記号 [    ]</h4>



<p>カッコ [   ] を使うと、カッコ内で指定した文字が当てはまるようになります。</p>



<p>※ カッコ単体ではあまり使わず、他の文字列や記号、繰り返しを組み合わせて使うのが基本です。</p>



<p><strong>例1: [<mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-red-color">A</mark><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-blue-color">B</mark><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-light-green-color">C</mark>] の場合に当てはまる文字列(文字?)</strong></p>



<ul class="wp-block-list"><li><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-red-color">A</mark></li><li><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-blue-color">B</mark></li><li><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-light-green-color">C</mark></li></ul>



<p><strong>例2: [<mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-red-color">0</mark><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-blue-color">1</mark>]+ の場合に当てはまる文字列の例</strong></p>



<ul class="wp-block-list"><li><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-red-color">0</mark></li><li><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-blue-color">1</mark></li><li><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-red-color">00</mark></li><li><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-red-color">0</mark><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-blue-color">1</mark></li><li><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-blue-color">1</mark><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-red-color">0</mark></li><li><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-blue-color">11</mark></li></ul>



<p>※ <mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-light-green-color">[01]</mark><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-light-orange-color">+</mark> は、<mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-light-green-color">0, 1だけが出てくる</mark><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-light-orange-color">1文字以上</mark>の文字列がすべて当てはまる</p>



<p><strong>例3: 00<strong>[<mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-red-color">0</mark><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-blue-color">1</mark>]</strong>* の場合に当てはまる文字列の例</strong></p>



<ul class="wp-block-list"><li>00</li><li><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-black-color">00</mark><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-red-color">0</mark></li><li><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-black-color">00</mark><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-blue-color">1</mark></li><li><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-red-color"><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-black-color">00</mark>00</mark></li><li><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-red-color"><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-black-color">00</mark>0</mark><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-blue-color">1</mark></li><li><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-black-color">00</mark><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-blue-color">1</mark><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-red-color">0</mark></li><li><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-black-color">00</mark><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-blue-color">11</mark></li></ul>



<p>※ 「00」 or 「00が最初に来たあとに、0もしくは1だけが続く」文字列が当てはまります。</p>



<h4 class="wp-block-heading">(2-d) 1文字の指定 [   ] をする際の省略記法 - </h4>



<p>複数文字を指定する際に、ASCIIコード的に連続している文字を指定する場合は下のように省略記法 <code>-</code> を使うことができます。</p>



<p><strong>[表記例]</strong></p>



<ul class="wp-block-list"><li>[A-Z] → アルファベット大文字を指定</li><li>[a-z] → アルファベット小文字を指定</li><li>[A-Za-z] → アルファベットを指定</li><li>[0-9] → 数字を指定</li><li>[A-Za-z0-9] → アルファベット or 数字を指定</li></ul>



<p>実際の使用例も何個か見てみましょう。</p>



<p><strong>例1: [A-C] の場合に当てはまる文字列(文字?)</strong></p>



<ul class="wp-block-list"><li>A</li><li>B</li><li>C</li></ul>



<p>※ [A-C] は [ABC] と同じ</p>



<p><strong>例2: [0-9]+ の場合に当てはまる文字列の例</strong></p>



<ul class="wp-block-list"><li>3</li><li>0124151</li><li>534290</li><li>52309432865</li></ul>



<p>※ <mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-purple-color">[0-9]</mark><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-light-orange-color">+</mark> は、<mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-purple-color">数字</mark>が<mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-light-orange-color">1文字以上</mark>繰り返されるのを表す</p>



<h4 class="wp-block-heading">(2-e) 任意の1文字を表す記号 <mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-red-color">. </mark></h4>



<p><code>.</code> は1文字であればどんな文字でもOKです。<br>（ワイルドカード的な効果を持つと思っていただけたらOKです）</p>



<p><strong>例1: <mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-black-color">usa</mark><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-red-color">.</mark><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-black-color">iの場合に当てはまる</mark>文字列の例</strong></p>



<ul class="wp-block-list"><li>usa<mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-red-color">a</mark>i</li><li>usa<mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-red-color">g</mark>i</li><li>usa<mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-red-color">#</mark>i</li></ul>



<p><strong>例2: .+の場合に当てはまる文字列の例</strong></p>



<ul class="wp-block-list"><li>a</li><li>ohayo</li><li>hello</li><li>nihao</li><li>annyonghaseyo</li></ul>



<p>※ 1文字以上の文字列すべてがすべて当てはまります</p>



<p>これで、Lexで使う知識の復習は完了です。いよいよLexの中身に入っていきましょう。</p>



<h2 class="wp-block-heading">3. Lex(Flex)の書き方（構造）</h2>



<p>Lexプログラムの構造としては「定義部」、「規則部（ルール部）」、「ユーザー定義サブルーチン部」の3層構造となっており、拡張子は <code>.l</code> で表されます。</p>



<figure class="wp-block-image aligncenter size-large"><img width="1024" height="618" src="https://www.momoyama-usagi.com/wp-content/uploads/konpai1-1-1-1024x618.gif" alt="" class="wp-image-16033" srcset="https://www.momoyama-usagi.com/wp-content/uploads/konpai1-1-1-1024x618.gif 1024w, https://www.momoyama-usagi.com/wp-content/uploads/konpai1-1-1-300x181.gif 300w, https://www.momoyama-usagi.com/wp-content/uploads/konpai1-1-1-768x463.gif 768w" /><figcaption>Lexプログラムはこんな漢字 (sample.l)</figcaption></figure>



<p>それでは、「定義部」、「規則部（ルール部）」、「ユーザー定義サブルーチン部」で具体的にどのような内容が記述されるかを実際に見ていきましょう。</p>



<h3 class="wp-block-heading">(1) 定義部 [省略OK]</h3>



<p>「規則部」や「ユーザー定義サブルーチン部」で使う外部ヘッダファイルをインクルードしたり、外部変数を宣言する際に使います。</p>



<p>書き方としては、定義部の始点に <code>%{</code> 、終点に <code>%}</code> を書き、その間に必要な外部ヘッダファイルのインクルードや外部変数の宣言をC言語で行います。</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: cpp; title: ; notranslate">
%{ // 定義部スタートは必ず %{
#include &lt;stdio.h&gt; // 外部ヘッダファイル読み込み
int alphabet_capital = 0; // 外部変数
int alphabet_small   = 0; 
int number           = 0; 
int others           = 0; 
// 定義部の終わりは必ず %}
%} 
</pre></div>


<h3 class="wp-block-heading">(2) 規則部（ルール部）</h3>



<p>字句解析の規則を記述するLexの心臓部分で、Lexで最も重要な箇所です。</p>



<p>書き方としては、まず規則部の始点と終点に <code>%%</code> を書き、その間に「字句解析のルール」と、「ルールを満たしたときに処理される内容(C言語で記述)」を書きます。</p>



<figure class="wp-block-image aligncenter size-large"><img width="1024" height="486" src="https://www.momoyama-usagi.com/wp-content/uploads/konpai1-2-1-1024x486.gif" alt="" class="wp-image-16041" srcset="https://www.momoyama-usagi.com/wp-content/uploads/konpai1-2-1-1024x486.gif 1024w, https://www.momoyama-usagi.com/wp-content/uploads/konpai1-2-1-300x142.gif 300w, https://www.momoyama-usagi.com/wp-content/uploads/konpai1-2-1-768x365.gif 768w" /></figure>



<h4 class="wp-block-heading">lex限定の変数 - yytextとyyleng</h4>



<p>ルールを満たしたときに処理される内容を括弧内 {    } にC言語で記述する際に、Lex専用の変数 yytext, yychar を使うことができます。変数の特性は、下の通りです。</p>



<ul class="wp-block-list"><li><code>yytext</code> → ルールを満たしたとき、どの文字列でルールを満たしたかを文字列の形で表す</li><li><code>yyleng</code> → <code>yytext</code> の文字列の長さを表す</li></ul>



<p><strong>[例] 文字列 <code>ABABC</code> がルール <code>[A-Z]+</code> にマッチした場合</strong></p>



<ul class="wp-block-list"><li><code>yytext</code> → <code>ABABC</code></li><li><code>yyleng</code> → <code>5</code></li></ul>



<h3 class="wp-block-heading">(3) ユーザー定義サブルーチン部 [省略OK]</h3>



<p>(2)の字句解析をした結果を利用したC言語プログラムを書くことができます<span class="footnote_referrer"><a tabindex="0" onclick="footnote_moveToReference_15935_15('footnote_plugin_reference_15935_15_4');" onkeypress="footnote_moveToReference_15935_15('footnote_plugin_reference_15935_15_4');" ><sup id="footnote_plugin_tooltip_15935_15_4" class="footnote_plugin_tooltip_text">[4]</sup></a><span id="footnote_plugin_tooltip_text_15935_15_4" class="footnote_tooltip">下の例は、<code>main</code> 関数しかありませんが、新たに自分自信で関数を定義することもできます。</span></span>。</p>



<p>(1)の定義部と同じく省略することもできますが、省略しない場合はプログラム中の字句解析をする箇所に <code>yylex();</code> を必ず書く必要があります<span class="footnote_referrer"><a tabindex="0" onclick="footnote_moveToReference_15935_15('footnote_plugin_reference_15935_15_5');" onkeypress="footnote_moveToReference_15935_15('footnote_plugin_reference_15935_15_5');" ><sup id="footnote_plugin_tooltip_15935_15_5" class="footnote_plugin_tooltip_text">[5]</sup></a><span id="footnote_plugin_tooltip_text_15935_15_5" class="footnote_tooltip"> <code>yylex();</code> を書かない場合、字句解析が行われずにプログラムが終了します。</span></span>。</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: cpp; title: ; notranslate">
int main(void) {
    yylex(); // ここで (2)規則部に従って字句解析が行われる
    printf(&quot;英大文字:%3d文字\n&quot;,alphabet_capital);
    printf(&quot;英小文字:%3d文字\n&quot;,alphabet_small);
    printf(&quot;算用数字:%3d文字\n&quot;,number);
    printf(&quot;その他　:%3d文字\n&quot;,others);
}
</pre></div>


<p>第4章からは、Lexの心臓部分である「規則部(ルール部)」に着目して、Lexでの字句解析の動きを見ていきましょう。</p>



<h2 class="wp-block-heading">4. Lexの動きを見てみよう（基本編）</h2>



<p>規則部では、入力した文字列を「規則部内に正規表現で書いた各ルール」に従って先頭から1文字ずつ字句解析をしていきます。しかし、正規表現に慣れている人にとっても、Lexでの字句解析は少し複雑です。</p>



<p>そこで、ここからは実際にLexを用いて字句解析をする場合、どのような動作をするのかを全6パターンを用いて説明していきます。</p>



<h3 class="wp-block-heading">(1) レベル1　1文字を入力した場合</h3>



<p>まずは、1文字だけを入力する一番カンタンなパターンで字句解析の仕組みを把握しましょう。</p>



<p>3章で軽く説明した通り、規則部には「字句解析の各ルール」と「各ルールを満たした場合の各処理内容」が列挙されているのでしたね。</p>



<figure class="wp-block-image aligncenter size-large"><img width="1024" height="624" src="https://www.momoyama-usagi.com/wp-content/uploads/konpai1-6-1-1024x624.gif" alt="" class="wp-image-16055" srcset="https://www.momoyama-usagi.com/wp-content/uploads/konpai1-6-1-1024x624.gif 1024w, https://www.momoyama-usagi.com/wp-content/uploads/konpai1-6-1-300x183.gif 300w, https://www.momoyama-usagi.com/wp-content/uploads/konpai1-6-1-768x468.gif 768w" /></figure>



<p>例えば、入力として <code>A</code> という文字列が来た場合を考えましょう。</p>



<figure class="wp-block-image aligncenter size-large"><img width="1024" height="507" src="https://www.momoyama-usagi.com/wp-content/uploads/konpai1-8-1024x507.gif" alt="" class="wp-image-16057" srcset="https://www.momoyama-usagi.com/wp-content/uploads/konpai1-8-1024x507.gif 1024w, https://www.momoyama-usagi.com/wp-content/uploads/konpai1-8-300x149.gif 300w, https://www.momoyama-usagi.com/wp-content/uploads/konpai1-8-768x380.gif 768w" /><figcaption><code>A</code> が来たときに満たすルールと処理内容</figcaption></figure>



<p><code>A</code> という文字列は、各ルールの中の一番上のルール <code>[A-Z]</code> にマッチしますね。そのため、<code>[A-Z]</code> の右側にかかれている</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: cpp; gutter: false; title: ; notranslate">
printf(&quot;CAP&#x5B;%s]&quot;,yytext);
</pre></div>


<p>が実行され、<code>CAP[A]</code> というのが出力されます。</p>



<p>※ 規則部の出力で <code>yytext</code> と書くと、ルールにマッチした部分の文字列が出力されます。（今回の場合は <code>A</code> が出力される）</p>



<div style="height:77px" class="wp-block-spacer"></div>



<p>では、<code>9</code> という文字列が来た場合、上から何番目の規則にマッチして何が出力されるでしょう？ 少し考えてみましょう。</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: cpp; title: ; notranslate">
%%
&#x5B;A-Z] { printf(&quot;CAP&#x5B;%s]&quot;,yytext); }
&#x5B;a-z] { printf(&quot;SML&#x5B;%s]&quot;,yytext); }
&#x5B;0-9] { printf(&quot;NUM&#x5B;%s]&quot;,yytext); }
%%
</pre></div>


<div style="height:67px" class="wp-block-spacer"></div>



<p>正解は、上から3番目のルールです。ですので、3番目のルール <code>[0-9]</code> 右側にかかれているprintfの内容</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: cpp; gutter: false; title: ; notranslate">
printf(&quot;NUM&#x5B;%s]&quot;,yytext);
</pre></div>


<p>が実行され、<code>NUM[9]</code> が出力されますね。</p>



<figure class="wp-block-image aligncenter size-large"><img width="1024" height="507" src="https://www.momoyama-usagi.com/wp-content/uploads/konpai1-9-1024x507.gif" alt="" class="wp-image-16058" srcset="https://www.momoyama-usagi.com/wp-content/uploads/konpai1-9-1024x507.gif 1024w, https://www.momoyama-usagi.com/wp-content/uploads/konpai1-9-300x149.gif 300w, https://www.momoyama-usagi.com/wp-content/uploads/konpai1-9-768x380.gif 768w" /><figcaption>9 が来たときに満たすルールと処理内容</figcaption></figure>







<h3 class="wp-block-heading">(2) レベル2　複数文字入力した場合</h3>



<p>今度は、複数文字入力した場合を見ていきましょう。</p>



<p>複数文字を入力した場合、文字列の終点にたどり着くまで1文字目から順番にマッチする文字列を探していきます。</p>



<p>例えば、先程と同じ規則部を持つLexファイルに対して、<code>AbB3</code> を入力した場合、出力がどうなるかをアニメーションで追ってみましょう。</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: cpp; title: ; notranslate">
%%
&#x5B;A-Z] { printf(&quot;CAP&#x5B;%s]&quot;,yytext);}
&#x5B;a-z] { printf(&quot;SML&#x5B;%s]&quot;  ,yytext);}
&#x5B;0-9] { printf(&quot;NUM&#x5B;%s]&quot; ,yytext);}
%%
</pre></div>


<p><strong>[アニメーション]</strong></p>



<figure class="wp-block-image aligncenter size-full"><img width="1188" height="847" src="https://www.momoyama-usagi.com/wp-content/uploads/Q1NneVJxqTj9nmx4WXZ51662048112-1662048128-1.gif" alt="" class="wp-image-16062"/><figcaption>字句解析がされていく様子</figcaption></figure>



<p>よって、出力内容が </p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: plain; gutter: false; title: ; notranslate">
CAP&#x5B;A]SML&#x5B;b]CAP&#x5B;B]NUM&#x5B;3]
</pre></div>


<p>となることがわかります。</p>



<h3 class="wp-block-heading">(3) レベル3　どのルールにも当てはまらない場合</h3>



<p>Lexで字句解析を行う際に「どの規則にも当てはまらない文字列」が出てきた場合、どのような動きをするかも確認しておきましょう。</p>



<p>例えば、下の規則に文字列 <code>A3b</code> を入力することを考えます。</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: cpp; title: ; notranslate">
%%
&#x5B;A-Z] { printf(&quot;CAP&#x5B;%s]&quot;,yytext);}
&#x5B;a-z] { printf(&quot;SML&#x5B;%s]&quot;,yytext);}
%%
</pre></div>


<p>すると、最初の1文字 <code><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-red-color">A</mark></code> までは <code><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-red-color">CAP[A]</mark></code> と順調に規則にマッチするのですが、2文字目〜4文字目の 3, 3, 4 にマッチする規則はありません。</p>


<p>このように<span  style="background-image:linear-gradient(to bottom,transparent 0%,#FFF387 0%);" class="dbp-e-marker-animation y">マッチする規則がない場合は、入力した文字がそのまま出力されます</span>。そのため、<code>CAP[A]</code> に引き続き、入力した <code>334</code>&nbsp;が出力されます。</p>


<p>ただし最後の5文字目は、上から2番目の規則にマッチするため、<code>SML[b]</code> が <code>CAP[A]334</code> に引き続き出力されます。</p>



<p>よって、最終的な出力は <code>CAP[A]334SML[b]</code> となります。</p>



<figure class="wp-block-image aligncenter size-large"><img width="1024" height="678" src="https://www.momoyama-usagi.com/wp-content/uploads/lex1-1024x678.gif" alt="" class="wp-image-16075" srcset="https://www.momoyama-usagi.com/wp-content/uploads/lex1-1024x678.gif 1024w, https://www.momoyama-usagi.com/wp-content/uploads/lex1-300x199.gif 300w, https://www.momoyama-usagi.com/wp-content/uploads/lex1-768x508.gif 768w" /></figure>







<h2 class="wp-block-heading">5. Lexの動きを見てみよう（応用編）</h2>



<p>4章の基本編では、規則部の動きを確認するために、文字列を1文字ずつ字句解析させていき、その動きを確認しました。</p>



<p>この応用編では少しレベルを上げて、複数文字をマッチできるルールを入れたときの字句解析させたときのプログラムの動きを確認しましょう。</p>



<h3 class="wp-block-heading">(1) レベル4　複数文字のマッチが可能な場合の動き</h3>



<p>例えば、次の規則部を持つLexプログラムに対して、<code>1423DB</code> と入力することを考えましょう。</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: cpp; title: ; notranslate">
%%
&#x5B;A-D]   { printf(&quot;CAP&#x5B;%s]&quot; ,yytext);}
&quot;3D&quot;    { printf(&quot;3DD&#x5B;%s]&quot; ,yytext);}
1&#x5B;0-9]+ { printf(&quot;NUM&#x5B;%s]&quot; ,yytext);}
.       { printf(&quot;???&#x5B;%s]&quot; ,yytext);}
%%
</pre></div>


<p>まず、最初に上から3番目のルール <code>1[0-9]+</code> とマッチします。ここで、<code>1[0-9]+</code> というのは、「1で始まり、その後に0～9が1文字以上続く文字列」を表します。そのため、</p>



<ul class="wp-block-list"><li>1だけマッチさせる</li><li>14までマッチさせる</li><li>142までマッチさせる</li><li>1423までマッチさせる</li></ul>



<p>のどのパターンでも3番目のルールを適用させることが可能です。</p>


<p>このようなパターンの場合、<span  style="background-image:linear-gradient(to bottom,transparent 0%,#FFF387 0%);" class="dbp-e-marker-animation y">Lexは（ルールを満たす中で）マッチする文字数が最も多くなるパターンを選択します</span><span class="footnote_referrer"><a tabindex="0" onclick="footnote_moveToReference_15935_15('footnote_plugin_reference_15935_15_6');" onkeypress="footnote_moveToReference_15935_15('footnote_plugin_reference_15935_15_6');" ><sup id="footnote_plugin_tooltip_15935_15_6" class="footnote_plugin_tooltip_text">[6]</sup></a><span id="footnote_plugin_tooltip_text_15935_15_6" class="footnote_tooltip">難しい言い方をすると、<code>yytext</code> に入る文字数が最も多くなる（＝<code>yyleng</code> が最大になる）パターンを選択するとも言えます。</span></span>。そのため今回の場合は、1423まで <code>1[0-9]+</code> のルールでマッチします。</p>


<figure class="wp-block-image aligncenter size-large"><img width="1024" height="939" src="https://www.momoyama-usagi.com/wp-content/uploads/konpai1-10-1024x939.gif" alt="" class="wp-image-16059" srcset="https://www.momoyama-usagi.com/wp-content/uploads/konpai1-10-1024x939.gif 1024w, https://www.momoyama-usagi.com/wp-content/uploads/konpai1-10-300x275.gif 300w, https://www.momoyama-usagi.com/wp-content/uploads/konpai1-10-768x704.gif 768w" /></figure>



<p>※ 残りの2文字D, Bは、それぞれ <code>[A-D]</code> のルールに1文字ずつマッチさせられるので、 <code>NUM[1423</code>] に引き続いて <code>CAP[D]CAP[B]</code> と出力されます。</p>



<h3 class="wp-block-heading">(2) レベル5　適用できるルールが複数ある場合の動き</h3>



<p>例えば、下のLexプログラムに対して、<code>CCSakura</code> と入力することを考えましょう。</p>



<p>※ Lexでは上から3番目のルール <code>CC</code> のように、マッチさせる文字列を <code>"CC" </code>のようにダブルクオーテーション "" で囲んで示すことができます</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: cpp; title: ; notranslate">
%%
&#x5B;A-Z]   { printf(&quot;CAP&#x5B;%s]&quot; ,yytext);}
&#x5B;a-z]+  { printf(&quot;SML&#x5B;%s]&quot; ,yytext);}
&quot;CC&quot;    { printf(&quot;CCC&#x5B;%s]&quot; ,yytext);}
%%
</pre></div>


<p>まず、最初にどの規則をマッチするかを考えましょう。すると、</p>



<ul class="wp-block-list"><li>一番上の規則 <code>[A-D]</code> でCとマッチ（1文字分マッチ）</li><li>一番下の規則 <code>"CC"</code> でCCとマッチ（2文字分マッチ）</li></ul>



<p>のどちらかを適用できそうですね。</p>


<p>このように適用できるルールが複数ある場合は、<span  style="background-image:linear-gradient(to bottom,transparent 0%,#FFF387 0%);" class="dbp-e-marker-animation y">より長い文字数分マッチする規則が優先して適用されます</span>。言い換えると、<span  style="background-image:linear-gradient(to bottom,transparent 0%,#FFF387 0%);" class="dbp-e-marker-animation y">適用可能なルールの中で、マッチする文字列の文字数が最も長くなるようなルールが適用されます</span>。</p>
<p>そのため、最小に適用される規則は「一番下の規則 <code>"CC"</code> が優先され、<code>CCC[CC]</code> が出力」されます。</p>


<figure class="wp-block-image aligncenter size-large"><img width="1024" height="526" src="https://www.momoyama-usagi.com/wp-content/uploads/konpai1-11-1024x526.gif" alt="" class="wp-image-16060" srcset="https://www.momoyama-usagi.com/wp-content/uploads/konpai1-11-1024x526.gif 1024w, https://www.momoyama-usagi.com/wp-content/uploads/konpai1-11-300x154.gif 300w, https://www.momoyama-usagi.com/wp-content/uploads/konpai1-11-768x395.gif 768w, https://www.momoyama-usagi.com/wp-content/uploads/konpai1-11-1536x790.gif 1536w, https://www.momoyama-usagi.com/wp-content/uploads/konpai1-11-2048x1053.gif 2048w" /></figure>



<p>※ 残りの文字列Sakuraは、順番に</p>



<ul class="wp-block-list"><li>上から1番目の規則 <code>[A-Z]</code>  → <code>S</code> をマッチ</li><li>上から2番目の規則 <code>[a-z]</code>+ → <code>akura</code> をマッチ</li></ul>



<p>と適用できるため、<code>CCC[CC]</code> に引き続いて <code>CAP[S]SML[akura]</code>と出力されます。</p>



<h3 class="wp-block-heading">(3) レベル6　適用できるルールが複数 &amp; マッチする文字列が最長となる規則が複数ある場合</h3>



<p>適用できるルールが複数ある場合は、「マッチする文字列の文字数が最も長くなる規則」が優先して適用されるのでしたね。</p>



<p>しかし、「マッチする文字列の文字数が最も長くなる規則」が複数ある場合が出てくる場合があり、文字列の長さだけではマッチさせるルールが決まらないことがあります。</p>



<p>例えば、下のLexプログラムに対して、<code>C#</code> と入力することを考えましょう。</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: cpp; title: ; notranslate">
%%
&#x5B;A-Z] { printf(&quot;CAP&#x5B;%s]&quot;,yytext); }
&#x5B;a-z] { printf(&quot;SML&#x5B;%s]&quot;,yytext); }
&#x5B;0-9] { printf(&quot;NUM&#x5B;%s]&quot;,yytext); }
.     { printf(&quot;???&#x5B;%s]&quot;,yytext); }
%%
</pre></div>


<p>まず、最初にどの規則をマッチするかを考えましょう。すると、</p>



<ul class="wp-block-list"><li>一番上の規則 <code>[A-Z]</code> でCとマッチ → 1文字マッチ</li><li>一番下の規則 <code>.</code> でCとマッチ → 1文字マッチ</li></ul>



<p>のどちらかを適用できそうですが、どちらの規則も「1文字分」しかマッチしません。</p>


<p>このように適用できるルールが複数あり、なおかつ「マッチする文字列の文字数が最も長くなる規則」が複数ある場合は、<span  style="background-image:linear-gradient(to bottom,transparent 0%,#FFF387 0%);" class="dbp-e-marker-animation y">適用可能で最もマッチする文字列の文字数が長くなるルールのうち、最も上に書かれているルールが適用されます</span>。</p>
<p>今回の場合、より上にかかれている1番上の規則 <code>[A-Z]</code> が適用されるため、出力は <code>CAP[C]</code>&nbsp;となります。</p>



<figure class="wp-block-image aligncenter size-large"><img width="1024" height="857" src="https://www.momoyama-usagi.com/wp-content/uploads/konpai1-12-1024x857.gif" alt="" class="wp-image-16061" srcset="https://www.momoyama-usagi.com/wp-content/uploads/konpai1-12-1024x857.gif 1024w, https://www.momoyama-usagi.com/wp-content/uploads/konpai1-12-300x251.gif 300w, https://www.momoyama-usagi.com/wp-content/uploads/konpai1-12-768x643.gif 768w" /></figure>



<p>※ 残りの文字列 <code>#</code> は、一番下の規則以外満たさないため、<code>CAP[C]</code> に引き続いて <code>???[#]</code> が出力されます。</p>


<div class='wp-block-dbp-frame l-frame-inner is-design-inline is-frame-style-default dbp-frame has-bgcolor'><div class="dbp-frame-title">複数適用できるルールがある場合の優先</div><div class="dbp-frame-content has-content-gap">
<p>規則部内に複数適用できるルールがある場合、つぎの1, 2の優先順で適用するルールを決める。</p>

<ol class="wp-block-list"><li>より多くの文字列をマッチさせることができるルール</li><li>より上側に記載されているルール</li></ol>
</div></div>


<h2 class="wp-block-heading">6. 練習問題 (Lexの動きを確認しよう)</h2>



<p>それでは、規則部の動きについて理解できているかどうかを、練習問題を通じて確認しましょう。</p>



<h3 class="wp-block-heading">問題. </h3>



<p>以下のLexプログラム（規則部以外は省略されている）に、(1)〜(4)の文字列をそれぞれ入力したときの出力を答えなさい。</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: cpp; title: ; notranslate">
%%
&#x5B;0-1]&#x5B;0-9]+ { printf(&quot;OP1&#x5B;%s]&quot;,yytext); }
&#x5B;A-C]+0*    { printf(&quot;OP2&#x5B;%s]&quot;,yytext); }
&quot;3C&quot;        { printf(&quot;OP3&#x5B;%s]&quot;,yytext); }
&quot;B1&quot;        { printf(&quot;OP4&#x5B;%s]&quot;,yytext); }
&quot;#&quot;|&quot;@&quot;     { printf(&quot;OP5&#x5B;%s]&quot;,yytext); }
.           { printf(&quot;???&#x5B;%s]&quot;,yytext); }
%%
</pre></div>


<p>(1) 0120<br>(2) 3CA#@<br>(3) ABC02<br>(4) B197</p>



<div style="height:67px" class="wp-block-spacer"></div>



<h3 class="wp-block-heading">解答. </h3>



<p>それぞれのルールを日本語に直すと下のようになります。</p>



<ul class="wp-block-list"><li><code>[0-1][0-9]+</code> → 最初に0 or 1、その後に1文字以上数字が来ればマッチ</li><li><code>[A-C]+0*</code> → A, B, Cのいずれかが1文字以上来ればマッチ。A, B, Cが1文字以上続いたあとに0が続く文字列でもマッチ。</li><li><code>"3C"</code> → 3C だけマッチ。それ以外の文字列にはマッチしない。</li><li><code>"B1"</code> → B1 だけマッチ。それ以外の文字列にはマッチしない。</li><li><code>"#"|"@"</code> → # もしくは @ が来たときにマッチ。</li><li><code>.</code> → 任意の1文字にマッチ</li></ul>



<p>これを踏まえて、(1)〜(4)の出力を考えていきましょう。</p>



<h4 class="wp-block-heading">(1) 入力: 0120</h4>



<p>文字列0120は、一番上の規則</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: cpp; gutter: false; title: ; notranslate">
&#x5B;0-1]&#x5B;0-9]+ { printf(&quot;OP1&#x5B;%s]&quot;,yytext); }
</pre></div>


<p>に全てマッチできますね。（<mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-red-color">0</mark><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-blue-color">120</mark> → <mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-red-color">[0-1]</mark><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-blue-color">[0-9]+</mark>）</p>



<p>そのため、出力は <code>OP1[0120]</code> となります。</p>



<h4 class="wp-block-heading">(2) 入力: 3CA#@</h4>



<p>まず、最初の2文字 <code>3C</code> は上から3番目の規則</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: cpp; gutter: false; title: ; notranslate">
&quot;3C&quot;        { printf(&quot;OP3&#x5B;%s]&quot;,yytext); }
</pre></div>


<p>にマッチします。（出力: <code>OP3[3C]</code> ）</p>



<div style="height:20px" class="wp-block-spacer"></div>



<p>つぎに、3文字目 <code>A</code> が上から2番目の規則</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: cpp; gutter: false; title: ; notranslate">
&#x5B;A-C]+0*    { printf(&quot;OP2&#x5B;%s]&quot;,yytext); }
</pre></div>


<p>にマッチします。（出力: <code>OP2[A]</code> ）</p>



<p>※ 上から6番目の規則 <code>.</code> にもマッチしますが、より上にかかれている規則にもマッチするため、上から2番目の規則が優先的に選ばれます。</p>



<div style="height:20px" class="wp-block-spacer"></div>



<p>つぎに、4文字目 <code>#</code> が上から5番目の規則</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: cpp; gutter: false; title: ; notranslate">
&quot;#&quot;|&quot;@&quot;     { printf(&quot;OP5&#x5B;%s]&quot;,yytext); }
</pre></div>


<p>にマッチします。（出力: <code>OP5[#]</code> ）</p>



<p>※ 上から6番目の規則 <code>.</code> にもマッチしますが、より上にかかれている規則にもマッチするため、上から2番目の規則が優先的に選ばれます。</p>



<div style="height:20px" class="wp-block-spacer"></div>



<p>最後に5文字目 <code>@</code> も上から5番目の規則</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: cpp; gutter: false; title: ; notranslate">
&quot;#&quot;|&quot;@&quot;     { printf(&quot;OP5&#x5B;%s]&quot;,yytext); }
</pre></div>


<p>にマッチします。（出力: <code>OP5[@]</code> ）</p>



<p>※ 上から6番目の規則 <code>.</code> にもマッチしますが、より上にかかれている規則にもマッチするため、上から2番目の規則が優先的に選ばれます。</p>



<div style="height:20px" class="wp-block-spacer"></div>



<p>よって、<code>3CA#@</code> を入力したときの出力内容は <code>OP3[3C]OP2[A]OP5[#]OP5[@]</code> となります。</p>



<h4 class="wp-block-heading">(3) 入力: ABC02</h4>



<p>まず、最初の4文字 <code>ABC0</code> まで上から2番目の規則</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: cpp; gutter: false; title: ; notranslate">
&#x5B;A-C]+0*    { printf(&quot;OP2&#x5B;%s]&quot;,yytext); }
</pre></div>


<p>にマッチします。（出力: <code>OP2[ABC0]</code> ）</p>



<div style="height:20px" class="wp-block-spacer"></div>



<p>つぎに、最後の1文字 <code>2</code> が一番下（上から6番目）の規則</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: cpp; gutter: false; title: ; notranslate">
.           { printf(&quot;???&#x5B;%s]&quot;,yytext); }
</pre></div>


<p>にマッチします。（出力: <code>???[2]</code> ）</p>



<p>よって、<code>ABC02</code> を入力したときの出力内容は <code>OP2[ABC0]???[2]</code> となります。</p>



<h4 class="wp-block-heading">(4) 入力: B197</h4>



<p>まず、最初の2文字 <code>B1</code> までは上から4番目の規則</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: cpp; gutter: false; title: ; notranslate">
&quot;B1&quot;        { printf(&quot;OP4&#x5B;%s]&quot;,yytext); }
</pre></div>


<p>にマッチします。（出力: <code>OP4[B1]</code> ）</p>



<p>[補足] 上から2番目の規則</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: cpp; gutter: false; title: ; notranslate">
&#x5B;A-C]+0*    { printf(&quot;OP2&#x5B;%s]&quot;,yytext); }
</pre></div>

<p><span>にマッチするのでは？ と思った人もいるかもしれませんが、上から2番目の規則 <code>[A-C]+0*</code>の場合、最初の1文字 <code>B</code> にしかマッチしないため、<span  style="background-image:linear-gradient(to bottom,transparent 0%,#FFF387 0%);" class="dbp-e-marker y">より多くの文字列をマッチできる上から4番目の規則 <code>"B1"</code> が優先的に選ばれます</span>。</span></p>


<div style="height:20px" class="wp-block-spacer"></div>



<p>つぎに、3文字目の9、4文字目の7は上から6番目の規則</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: cpp; gutter: false; title: ; notranslate">
.           { printf(&quot;???&#x5B;%s]&quot;,yytext); }
</pre></div>


<p>に<strong><span style="text-decoration: underline;">1文字ずつ</span></strong>マッチします<span class="footnote_referrer"><a tabindex="0" onclick="footnote_moveToReference_15935_15('footnote_plugin_reference_15935_15_7');" onkeypress="footnote_moveToReference_15935_15('footnote_plugin_reference_15935_15_7');" ><sup id="footnote_plugin_tooltip_15935_15_7" class="footnote_plugin_tooltip_text">[7]</sup></a><span id="footnote_plugin_tooltip_text_15935_15_7" class="footnote_tooltip">上から1番目の規則 （0始まりの2桁以上の数字でないと受理しない）と間違えないように注意！</span></span>。そのため、<code>OP4[B1]</code> に引き続いて <code>???[9]???[7]</code> とマッチします。</p>



<p>よって、<code>B197</code> を入力したときの出力内容は <code><code>OP4[B1]???[9]???[7]</code></code> となります。</p>



<div style="height:97px" class="wp-block-spacer"></div>



<h2 class="wp-block-heading">[おまけ] 実際にLexを動かしてみよう！ (Mac・Linux)</h2>



<p>最後に、実際にコンピュータ上でLexプログラムを動かしてみましょう！</p>



<p>※ Mac・Linuxユーザーの人は何もインストールすることなく、Lexを使うことができます。<br>Windowsの人も「Flex for Windows」などをインストールをすればLexを動かすことは可能ですが、少し手順がめんどくさいです。）</p>



<h3 class="wp-block-heading">Step1. Lexプログラムを作成する</h3>



<p>まずは、テキトーなエディタを開き、下のプログラムを貼り付けて <code>debt.l</code> という名前で保存してください。（練習問題と同じプログラムです）</p>


<div class="wp-block-syntaxhighlighter-code aligncenter"><pre class="brush: cpp; title: ; notranslate">
%%
&#x5B;0-1]&#x5B;0-9]+ { printf(&quot;OP1&#x5B;%s]&quot;,yytext); }
&#x5B;A-C]+0*    { printf(&quot;OP2&#x5B;%s]&quot;,yytext); }
&quot;3C&quot;        { printf(&quot;OP3&#x5B;%s]&quot;,yytext); }
&quot;B1&quot;        { printf(&quot;OP4&#x5B;%s]&quot;,yytext); }
&quot;#&quot;|&quot;@&quot;     { printf(&quot;OP5&#x5B;%s]&quot;,yytext); }
.           { printf(&quot;???&#x5B;%s]&quot;,yytext); }
%%
</pre></div>


<p>保存し終わったら、ターミナルを開き、つぎの2つのコマンドを上から順番に1つずつ打ってください。</p>



<p>※ 何かしらのwarningが出た場合でも無視してOKです。エラーが出た場合は貼り付けが正しくできているかを確認してください。</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: plain; gutter: false; title: ; notranslate">
lex lex_pattern1.l
cc lex.yy.c -ll
</pre></div>


<p>すると、Lexファイルがコンパイルされ、実行ファイル<code> a.out</code> ができます。あとはこの <code>a.out</code> を実行すればOKです。</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: plain; gutter: false; title: ; notranslate">
./a.out
</pre></div>


<p>実行すると、「文字列の入力を待機している状態」になります。<br>（何もメッセージが出ていないからといって、応答なし状態になっているわけではないのでご安心ください。）</p>



<p>試しに、<code>3CA#@</code> と入れてEnterと押してみましょう。（練習問題(2)と同じ文字列です）</p>



<p>すると、練習問題(2)の解答と同じ文字列が出力されるはずです…！</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: cpp; gutter: false; title: ; notranslate">
OP3&#x5B;3C]OP2&#x5B;A]OP5&#x5B;#]OP5&#x5B;@]
</pre></div>


<p>※ 出力された場合はLexで実際に字句解析させることに成功しました！</p>



<div style="height:97px" class="wp-block-spacer"></div>



<h2 class="wp-block-heading">8. さいごに</h2>



<p>今回は、実際にLexプログラムを使って（ポインタや文字列操作のような複雑なC言語の知識を使うことなしに）字句解析を体験していきました。</p>



<p>次回からは、構文解析について数回に分けて学習していきましょう！</p>
<div class="speaker-mute footnotes_reference_container"> <div class="footnote_container_prepare"><p><span tabindex="0" class="footnote_reference_container_label pointer">注釈</span><span tabindex="0" class="footnote_reference_container_collapse_button" style="display: none;">[<a id="footnote_reference_container_collapse_button_15935_15">+</a>]</span></p></div> <div id="footnote_references_container_15935_15"><table class="footnotes_table footnote-reference-container"><caption class="accessibility">注釈</caption> <tbody> 

<tr class="footnotes_plugin_reference_row"> <th scope="row" class="footnote_plugin_index_combi pointer"  onclick="footnote_moveToAnchor_15935_15('footnote_plugin_tooltip_15935_15_1');"><a id="footnote_plugin_reference_15935_15_1" class="footnote_backlink"><span class="footnote_index_arrow">&#8593;</span>1</a></th> <td class="footnote_plugin_text">中には、PythonやRubyのように、コンパイラを用いて機械語に翻訳せず、書いたプログラムを解釈しながら（インタプリタを用いて）実行していく言語もあります。</td></tr>

<tr class="footnotes_plugin_reference_row"> <th scope="row" class="footnote_plugin_index_combi pointer"  onclick="footnote_moveToAnchor_15935_15('footnote_plugin_tooltip_15935_15_2');"><a id="footnote_plugin_reference_15935_15_2" class="footnote_backlink"><span class="footnote_index_arrow">&#8593;</span>2</a></th> <td class="footnote_plugin_text">文字列が集まった箱のようなものだと思ってください。</td></tr>

<tr class="footnotes_plugin_reference_row"> <th scope="row" class="footnote_plugin_index_combi pointer"  onclick="footnote_moveToAnchor_15935_15('footnote_plugin_tooltip_15935_15_3');"><a id="footnote_plugin_reference_15935_15_3" class="footnote_backlink"><span class="footnote_index_arrow">&#8593;</span>3</a></th> <td class="footnote_plugin_text">各字句がどの属性の文字列集合（文字列が集まった箱か）に属するかを調べていくかというのを考えます。</td></tr>

<tr class="footnotes_plugin_reference_row"> <th scope="row" class="footnote_plugin_index_combi pointer"  onclick="footnote_moveToAnchor_15935_15('footnote_plugin_tooltip_15935_15_4');"><a id="footnote_plugin_reference_15935_15_4" class="footnote_backlink"><span class="footnote_index_arrow">&#8593;</span>4</a></th> <td class="footnote_plugin_text">下の例は、<code>main</code> 関数しかありませんが、新たに自分自信で関数を定義することもできます。</td></tr>

<tr class="footnotes_plugin_reference_row"> <th scope="row" class="footnote_plugin_index_combi pointer"  onclick="footnote_moveToAnchor_15935_15('footnote_plugin_tooltip_15935_15_5');"><a id="footnote_plugin_reference_15935_15_5" class="footnote_backlink"><span class="footnote_index_arrow">&#8593;</span>5</a></th> <td class="footnote_plugin_text"> <code>yylex();</code> を書かない場合、字句解析が行われずにプログラムが終了します。</td></tr>

<tr class="footnotes_plugin_reference_row"> <th scope="row" class="footnote_plugin_index_combi pointer"  onclick="footnote_moveToAnchor_15935_15('footnote_plugin_tooltip_15935_15_6');"><a id="footnote_plugin_reference_15935_15_6" class="footnote_backlink"><span class="footnote_index_arrow">&#8593;</span>6</a></th> <td class="footnote_plugin_text">難しい言い方をすると、<code>yytext</code> に入る文字数が最も多くなる（＝<code>yyleng</code> が最大になる）パターンを選択するとも言えます。</td></tr>

<tr class="footnotes_plugin_reference_row"> <th scope="row" class="footnote_plugin_index_combi pointer"  onclick="footnote_moveToAnchor_15935_15('footnote_plugin_tooltip_15935_15_7');"><a id="footnote_plugin_reference_15935_15_7" class="footnote_backlink"><span class="footnote_index_arrow">&#8593;</span>7</a></th> <td class="footnote_plugin_text">上から1番目の規則 （0始まりの2桁以上の数字でないと受理しない）と間違えないように注意！</td></tr>

 </tbody> </table> </div></div>]]></content:encoded>
					
					<wfw:commentRss>https://www.momoyama-usagi.com/entry/info-compiler1/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>うさぎでもわかる画像処理　Part02　トーンカーブと画像処理 [Python・MATLABコード付き]</title>
		<link>https://www.momoyama-usagi.com/entry/info-img02</link>
					<comments>https://www.momoyama-usagi.com/entry/info-img02#respond</comments>
		
		<dc:creator><![CDATA[ももうさ]]></dc:creator>
		<pubDate>Mon, 22 Aug 2022 13:29:23 +0000</pubDate>
				<category><![CDATA[情報]]></category>
		<category><![CDATA[画像処理]]></category>
		<category><![CDATA[トーンカーブ]]></category>
		<guid isPermaLink="false">https://www.momoyama-usagi.com/?p=15617</guid>

					<description><![CDATA[こんにちは、ももやまです。 皆さんは、スマートフォンで撮影した画像を「他の人にLINEで送る」、「SNSに投稿をする」際にに画像を加工したことってありませんか？ この画像の加工、実は画像処理の技術がたっぷり詰まっているん [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>こんにちは、ももやまです。</p>



<p>皆さんは、スマートフォンで撮影した画像を「他の人にLINEで送る」、「SNSに投稿をする」際にに画像を加工したことってありませんか？</p>



<p>この画像の加工、実は画像処理の技術がたっぷり詰まっているんですよ…！</p>



<p>そこで今回は、</p>



<ul class="wp-block-list"><li>画像の加工の仕組みの中でも<strong><span style="text-decoration: underline;">最も基本的な画像処理</span></strong>とは何か？</li><li>最も基本的な画像処理で出てくる<strong><span style="text-decoration: underline;">トーンカーブ</span></strong>とは何か？</li><li>実際の画像処理の例を見てみよう！</li><li>カラー画像特有の画像処理テクニックを見てみよう！</li></ul>



<p>の4つについて勉強していきましょう。</p>



<p><strong>[注意] </strong>コンピュータ上でどのように画像が扱われているかを全く知らない人は、下の記事を読んで勉強することをおすすめします。</p>



<p>（※ 画素、画素値などの専門的な用語が何を表しているのか、およびカラー画像の扱い方を知っていれば読み飛ばしてOKです。)）</p>



<figure class="wp-block-embed is-type-wp-embed is-provider-工業大学生ももやまのうさぎ塾 wp-block-embed-工業大学生ももやまのうさぎ塾"><div class="wp-block-embed__wrapper">
        <article class="pb p-id-4148 is-position-relative pb-embed">
            <a class="pb-contents" href="https://www.momoyama-usagi.com/entry/info-img01">
                <div class="pb__thumb"><img width="300" height="121" src="https://www.momoyama-usagi.com/wp-content/uploads/image_pro1-1-300x121.gif" class="is-position-overlay wp-post-image" alt="" lazysizes="1" srcset="https://www.momoyama-usagi.com/wp-content/uploads/image_pro1-1-300x121.gif 300w, https://www.momoyama-usagi.com/wp-content/uploads/image_pro1-1-768x310.gif 768w" /></div><div class="pb__body l-column is-flex-1"><div class="pb-title is-omit-line:2">うさぎでもわかる画像処理　Part01　コンピュータとデジタル画像</div><div class="pb-substr is-font-size:s is-omit-line:2">こんにちは、ももやまです。 コンピュータの世界では、あらゆるもの（命令・データ）が2進数（0 or 1）で管理されているのでしたね</div></div>            </a>
        </article>
        
</div></figure>



<h2 class="wp-block-heading">1. 最も基本的な画像処理とは？</h2>



<h3 class="wp-block-heading">(1) グレースケール画像の場合</h3>


<p><span>画像処理には様々な方法がありますが、上で説明した通り最も単純で基本的な方法は、下のように<span  style="background-image:linear-gradient(to bottom,transparent 0%,#FFF387 0%);" class="dbp-e-marker-animation y">元の画像の画素値に対して、一定のルールに基づいて画素値を書き換えてあげる方法</span>です。</span></p>


<figure class="wp-block-image aligncenter size-large is-resized"><img src="https://www.momoyama-usagi.com/wp-content/uploads/ip1-42-1024x384.jpg" alt="" class="wp-image-15663" width="671" height="252" srcset="https://www.momoyama-usagi.com/wp-content/uploads/ip1-42-1024x384.jpg 1024w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-42-300x112.jpg 300w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-42-768x288.jpg 768w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-42.jpg 1387w" /><figcaption>一定のルールに基づき、画像処理を実施<br>(例: 各画素値を2倍)</figcaption></figure>



<p>例えば、上の例で紹介したルール<span class="footnote_referrer"><a tabindex="0" onclick="footnote_moveToReference_15617_17('footnote_plugin_reference_15617_17_1');" onkeypress="footnote_moveToReference_15617_17('footnote_plugin_reference_15617_17_1');" ><sup id="footnote_plugin_tooltip_15617_17_1" class="footnote_plugin_tooltip_text">[1]</sup></a><span id="footnote_plugin_tooltip_text_15617_17_1" class="footnote_tooltip">入力画像の画素値 \( x \) を2倍したものを出力画像の画素値 \( y \) とする、つまり \( y = 2x \) の変換を行うルール</span></span>を用いて実際に画像処理をすると、下のような出力画像を生成することができます。</p>



<figure class="wp-block-image aligncenter size-large is-resized"><img src="https://www.momoyama-usagi.com/wp-content/uploads/ip1-37-1024x381.jpg" alt="" class="wp-image-15658" width="657" height="244" srcset="https://www.momoyama-usagi.com/wp-content/uploads/ip1-37-1024x381.jpg 1024w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-37-300x112.jpg 300w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-37-768x286.jpg 768w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-37.jpg 1330w" /></figure>



<div style="height:51px" class="wp-block-spacer"></div>



<p>もちろん「単に画素値を2倍にする」のような単純な変換だけでなく、下のように複雑な式を使って画像処理をすることもできます。</p>



<figure class="wp-block-image aligncenter size-large is-resized"><img src="https://www.momoyama-usagi.com/wp-content/uploads/ip1-38-1024x381.jpg" alt="" class="wp-image-15659" width="763" height="283" srcset="https://www.momoyama-usagi.com/wp-content/uploads/ip1-38-1024x381.jpg 1024w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-38-300x112.jpg 300w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-38-768x286.jpg 768w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-38.jpg 1330w" /><figcaption>複雑な画像処理の例<br>(コントラストをアップさせる変換)</figcaption></figure>



<h3 class="wp-block-heading">(2) カラー画像の場合</h3>



<p>カラー画像の場合も、基本的には「最も基本的な画像処理」の仕方は同じです。</p>



<p>しかし、グレースケール画像と異なる点として、カラー画像はコンピュータ上では「R(赤)成分の画像」、「G(緑)成分の画像」、「B(青)成分の画像」の3種類を組み合わせて表現されます。</p>



<figure class="wp-block-image aligncenter size-large"><img width="1024" height="245" src="https://www.momoyama-usagi.com/wp-content/uploads/ip1-47-1024x245.jpg" alt="" class="wp-image-15671" srcset="https://www.momoyama-usagi.com/wp-content/uploads/ip1-47-1024x245.jpg 1024w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-47-300x72.jpg 300w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-47-768x184.jpg 768w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-47-1536x368.jpg 1536w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-47-2048x491.jpg 2048w" /></figure>



<p>言い換えると、グレースケール画像では1種類の画素値しかなかったのに対し、カラー画像の各画素には、</p>



<ul class="wp-block-list"><li><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-red-color">R成分の画素値</mark></li><li><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-light-green-color">G成分の画素値</mark></li><li><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-blue-color">B成分の画素値</mark></li></ul>



<p>の3種類の画素値が与えられております。</p>


<p>なので、カラー画像の画像処理は、<span  style="background-image:linear-gradient(to bottom,transparent 0%,#FFF387 0%);" class="dbp-e-marker-animation y">R, G, B各成分の画素値を一定のルールに基づいて書きかえる</span>ことで実現されます。</p>


<div style="height:51px" class="wp-block-spacer"></div>



<p>この3種類（R成分、G成分、B成分）の画素値の書き換えのルールとしては、大きく分けても</p>



<ol class="wp-block-list"><li>R, G, B各成分を同じルールに基づいて書き換える</li><li>R, G, B各成分の一部を書き換える</li></ol>



<p>の2種類あるため、グレースケール画像に比べて画像処理の幅は広がります。</p>



<h4 class="wp-block-heading">例1. R, G, B各成分を同じルールに基づいて書き換える場合</h4>



<p>まずはR, G, B各成分を同じルールで変換すると、どのような画像が生まれるかを見てみましょう。<br>（下で示した変換ルール1に従って変換をします）</p>



<figure class="wp-block-image aligncenter size-large is-resized"><img src="https://www.momoyama-usagi.com/wp-content/uploads/ip1-45-957x1024.jpg" alt="" class="wp-image-15669" width="753" height="806" srcset="https://www.momoyama-usagi.com/wp-content/uploads/ip1-45-957x1024.jpg 957w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-45-280x300.jpg 280w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-45-768x822.jpg 768w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-45.jpg 1282w" /><figcaption>変換ルール1<br>(R, G, B成分ともに画素値×2の変換)</figcaption></figure>



<p>実際に変換を行うと、明るさが変わった画像が出力されます。</p>



<figure class="wp-block-image aligncenter size-large"><img width="1024" height="375" src="https://www.momoyama-usagi.com/wp-content/uploads/ip1-43-1024x375.jpg" alt="" class="wp-image-15667" srcset="https://www.momoyama-usagi.com/wp-content/uploads/ip1-43-1024x375.jpg 1024w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-43-300x110.jpg 300w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-43-768x281.jpg 768w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-43.jpg 1400w" /></figure>


<p><span>このように、<span  style="background-image:linear-gradient(to bottom,transparent 0%,#FFF387 0%);" class="dbp-e-marker-animation y">R, G, B成分を同じルール変換することで、画像の明るさやコントラストを調整することができます</span>。</span></p>


<h4 class="wp-block-heading">例2. R, G, B各成分の一部をルールに従って書き換える場合</h4>



<p>今度は、R, G, B各成分うち、一部を書き換えた場合はどうなるかを見てみましょう。<br>（下で示した変換ルール2に従って変換をします）</p>



<figure class="wp-block-image aligncenter size-large is-resized"><img src="https://www.momoyama-usagi.com/wp-content/uploads/ip1-46-957x1024.jpg" alt="" class="wp-image-15670" width="731" height="782" srcset="https://www.momoyama-usagi.com/wp-content/uploads/ip1-46-957x1024.jpg 957w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-46-280x300.jpg 280w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-46-768x822.jpg 768w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-46.jpg 1282w" /><figcaption>変換ルール2<br>(B成分のみ画素値×2の変換、R, G成分はそのまま)</figcaption></figure>



<p>すると、下のように特定の色が強調された（弱めた）ような出力画像が出てきます。</p>



<figure class="wp-block-image aligncenter size-large"><img width="1024" height="375" src="https://www.momoyama-usagi.com/wp-content/uploads/ip1-44-1024x375.jpg" alt="" class="wp-image-15668" srcset="https://www.momoyama-usagi.com/wp-content/uploads/ip1-44-1024x375.jpg 1024w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-44-300x110.jpg 300w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-44-768x281.jpg 768w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-44.jpg 1400w" /></figure>


<p><span>このように、<span  style="background-image:linear-gradient(to bottom,transparent 0%,#FFF387 0%);" class="dbp-e-marker-animation y">R, G, B成分の一部を変換することで、画像内の色のバランスを調整することができます</span>。</span></p>


<div style="height:101px" class="wp-block-spacer"></div>



<h2 class="wp-block-heading">2. トーンカーブ</h2>



<h3 class="wp-block-heading">(1) なぜトーンカーブを使うのか</h3>



<p>画像処理で行う画素値の変換が「各画素値を2倍にする」のように単純なものであれば、数式だけでも画像処理の内容が直観的に理解できるかもしれません。</p>



<p>しかし、下のように複雑な数式になると、（数学が得意な一部分の人を除き）画像処理の内容は直観的には理解できませんよね。</p>



<figure class="wp-block-image aligncenter size-large is-resized"><img src="https://www.momoyama-usagi.com/wp-content/uploads/ip1-38-1024x381.jpg" alt="" class="wp-image-15659" width="763" height="283" srcset="https://www.momoyama-usagi.com/wp-content/uploads/ip1-38-1024x381.jpg 1024w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-38-300x112.jpg 300w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-38-768x286.jpg 768w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-38.jpg 1330w" /></figure>



<div style="height:42px" class="wp-block-spacer"></div>


<p><span>そこで画像処理の世界では、どのような変換を行ったかを下のような<span  style="background-image:linear-gradient(to bottom,transparent 0%,#FFF387 0%);" class="dbp-e-marker-animation y">入力画素値 \( x \) に対する出力画素値 \( y \) を表したグラフ</span>で表現します。</span><span>このグラフのことを<span  style="background-image:linear-gradient(to bottom,transparent 0%,#FFF387 0%);" class="dbp-e-marker-animation blue">トーンカーブ</span>と呼びます。</span></p>


<figure class="wp-block-image aligncenter size-large is-resized"><img src="https://www.momoyama-usagi.com/wp-content/uploads/ip1-54-1024x757.jpg" alt="" class="wp-image-15687" width="468" height="344"/></figure>


<p><span><span  style="background-image:linear-gradient(to bottom,transparent 0%,#FFF387 0%);" class="dbp-e-marker y">変換内容を数式ではなくグラフで示すことで、より画像処理の内容を直観的に確認することができます</span>ね！</span></p>


<h3 class="wp-block-heading">(2) トーンカーブの読み方</h3>



<p>ここで、入力画素値 \( x \) が127のときを例にして、トーンカーブから出力画素値 \( y \) を読み取る方法を確認しましょう。</p>



<p>入力画素値 \( x \) [横軸の値] が127のときの出力画素値 \( y \) [縦軸の値] を見てみると、127近くにあることがわかりますね。</p>



<figure class="wp-block-image aligncenter size-large is-resized"><img src="https://www.momoyama-usagi.com/wp-content/uploads/ip1-53-1024x779.jpg" alt="" class="wp-image-15686" width="545" height="414" srcset="https://www.momoyama-usagi.com/wp-content/uploads/ip1-53-1024x779.jpg 1024w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-53-300x228.jpg 300w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-53-768x584.jpg 768w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-53.jpg 1103w" /></figure>



<h3 class="wp-block-heading">(3) カラー画像の場合のトーンカーブ</h3>



<p>カラー画像の場合は、下のようにR成分、G成分、B成分それぞれのトーンカーブを示します。</p>



<figure class="wp-block-image aligncenter size-large is-resized"><img src="https://www.momoyama-usagi.com/wp-content/uploads/ip1-50-1024x310.jpg" alt="" class="wp-image-15683" width="800" height="242" srcset="https://www.momoyama-usagi.com/wp-content/uploads/ip1-50-1024x310.jpg 1024w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-50-300x91.jpg 300w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-50-768x232.jpg 768w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-50-1536x465.jpg 1536w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-50-2048x620.jpg 2048w" /><figcaption>カラー画像の場合のトーンカーブ1<br>（R, G, B成分を全て同じルールで変換する場合）</figcaption></figure>



<div style="height:42px" class="wp-block-spacer"></div>



<figure class="wp-block-image aligncenter size-large"><img width="1024" height="310" src="https://www.momoyama-usagi.com/wp-content/uploads/ip1-51-1024x310.jpg" alt="" class="wp-image-15684" srcset="https://www.momoyama-usagi.com/wp-content/uploads/ip1-51-1024x310.jpg 1024w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-51-300x91.jpg 300w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-51-768x232.jpg 768w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-51-1536x465.jpg 1536w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-51-2048x620.jpg 2048w" /><figcaption>カラー画像の場合のトーンカーブ2 [青強調]<br>（R, G, B成分を異なるルールで変換する場合）</figcaption></figure>



<div style="height:101px" class="wp-block-spacer"></div>



<h2 class="wp-block-heading">3. 基本的な4種のトーンカーブ [Python, MATLABコード付き]</h2>



<p>ここからは、画像処理の中でも最も基本的な4種類のトーンカーブについて</p>



<ul class="wp-block-list"><li>グレースケール画像のとき</li><li>カラー画像のとき（R, G, B成分全て同じトーンカーブを適用）</li></ul>



<p>それぞれでみていきましょう。</p>



<p>さらに、変換をするための Python, MATLABコードも紹介します！<br>(Pythonを使用する場合、numpy, cv2 をインストールする必要があるので注意！)</p>



<h3 class="wp-block-heading">(1) 折れ線型トーンカーブ</h3>



<p>単純に画素値を \( k \) 倍する処理をすることで、画像全体の明るさを変更するトーンカーブです</p>



<p>数式で書くと、\[ y = kx \]となります。<br>（入力画素値: \( x \), 出力画素値: \( y \)）</p>



<h4 class="wp-block-heading">(1-a) 画素値をk倍 (k &gt; 1)</h4>



<p>\( k \) に1より大きい値を入れると、元の画像よりも明るくなります。</p>



<h5 class="wp-block-heading"><strong>例) \( k = 2 \)、つまり画素値を2倍する変換 \( y = 2x \)</strong></h5>



<p><strong>[グレースケール画像]</strong></p>



<figure class="wp-block-image aligncenter size-large"><img width="1024" height="489" src="https://www.momoyama-usagi.com/wp-content/uploads/ip1-5-1024x489.jpg" alt="" class="wp-image-15626" srcset="https://www.momoyama-usagi.com/wp-content/uploads/ip1-5-1024x489.jpg 1024w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-5-300x143.jpg 300w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-5-768x367.jpg 768w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-5-1536x734.jpg 1536w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-5.jpg 1794w" /><figcaption>画素値を2倍にする変換：グレースケール<br>(画像の明るさ2倍)</figcaption></figure>



<p><strong>[カラー画像]</strong></p>



<figure class="wp-block-image aligncenter size-large"><img width="1024" height="555" src="https://www.momoyama-usagi.com/wp-content/uploads/ip1-12-1024x555.jpg" alt="" class="wp-image-15633" srcset="https://www.momoyama-usagi.com/wp-content/uploads/ip1-12-1024x555.jpg 1024w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-12-300x163.jpg 300w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-12-768x416.jpg 768w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-12-1536x832.jpg 1536w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-12.jpg 1801w" /></figure>


<p>ただし、<span  style="background-image:linear-gradient(to bottom,transparent 0%,#FFF387 0%);" class="dbp-e-marker-animation red">計算結果 \( kx \) が255を超える場合は出力画素値 \( y \) が255を超えず、255でとどまる</span>点に要注意です<span class="footnote_referrer"><a tabindex="0" onclick="footnote_moveToReference_15617_17('footnote_plugin_reference_15617_17_2');" onkeypress="footnote_moveToReference_15617_17('footnote_plugin_reference_15617_17_2');" ><sup id="footnote_plugin_tooltip_15617_17_2" class="footnote_plugin_tooltip_text">[2]</sup></a><span id="footnote_plugin_tooltip_text_15617_17_2" class="footnote_tooltip">余談ですが、画素値255オーバーしていて画像が白くなる現象のことを、「白飛びする」とか「サチる」などと呼ぶことがあります。</span></span>。</p>


<figure class="wp-block-image aligncenter size-full is-resized"><img src="https://www.momoyama-usagi.com/wp-content/uploads/ip1-4.jpg" alt="" class="wp-image-15625" width="575" height="414" srcset="https://www.momoyama-usagi.com/wp-content/uploads/ip1-4.jpg 1022w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-4-300x217.jpg 300w" /><figcaption>画素値を2倍しても、出力画素値は255で打ち止め</figcaption></figure>



<h4 class="wp-block-heading">(1-b) 画素値をk倍 (k &lt; 1)</h4>



<p>\( k \) に1より小さい値を入れると、元の画像よりも暗くなります。</p>



<h5 class="wp-block-heading"><strong>例) \( k = 1/2 \)、つまり画素値を1/2倍する変換 \( y = \frac{1}{2} x \)</strong></h5>



<p><strong>[グレースケール画像]</strong></p>



<figure class="wp-block-image aligncenter size-large"><img width="1024" height="485" src="https://www.momoyama-usagi.com/wp-content/uploads/ip1-6-1024x485.jpg" alt="" class="wp-image-15627" srcset="https://www.momoyama-usagi.com/wp-content/uploads/ip1-6-1024x485.jpg 1024w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-6-300x142.jpg 300w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-6-768x363.jpg 768w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-6-1536x727.jpg 1536w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-6.jpg 1811w" /></figure>



<p><strong>[カラー画像]</strong></p>



<figure class="wp-block-image aligncenter size-large"><img width="1024" height="555" src="https://www.momoyama-usagi.com/wp-content/uploads/ip1-13-1024x555.jpg" alt="" class="wp-image-15634" srcset="https://www.momoyama-usagi.com/wp-content/uploads/ip1-13-1024x555.jpg 1024w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-13-300x163.jpg 300w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-13-768x416.jpg 768w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-13-1536x832.jpg 1536w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-13.jpg 1801w" /></figure>



<h4 class="wp-block-heading">(1-c) ソースコード</h4>



<p>入力画像 <code>input_img</code>、倍率 <code>k</code> を引数とすることで、折れ線型トーンカーブを適用した画像を返す関数を紹介します。</p>



<p><strong>[Python]</strong></p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: python; title: ; notranslate">
import numpy as np

def polygonalTone(input_img,k):
    return np.dot(k,input_img) # np.dot は画素値が255を超える画素を自動的に255に置き換えてくれる
</pre></div>


<p><strong>[MATLAB]</strong></p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: matlabkey; title: ; notranslate">
function output_img = polygonalTone(input_img,k)
    % MATLABではオーバーフローはそのまま255となるので、特別な対策は不要
    output_img = k * input_img; 
end
</pre></div>


<h4 class="wp-block-heading">折れ線型トーンカーブまとめ</h4>



<figure class="wp-block-image aligncenter size-large"><img width="1024" height="722" src="https://www.momoyama-usagi.com/wp-content/uploads/ip1-55-1024x722.jpg" alt="" class="wp-image-15706" srcset="https://www.momoyama-usagi.com/wp-content/uploads/ip1-55-1024x722.jpg 1024w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-55-300x212.jpg 300w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-55-768x541.jpg 768w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-55-1536x1083.jpg 1536w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-55.jpg 1858w" /></figure>



<h3 class="wp-block-heading">(2) 初期値付き折れ線型トーンカーブ</h3>



<p>単純に入力画素値を \( k \) 倍する処理に加えて、一定値 \( a \) を出力画素値に加えます。</p>



<p>式で書くと、\[<br>y = kx + a<br>\]ですね。（入力画素値: \( x \), 出力画素値: \( y \)）</p>



<p><strong>例) 初期値 \( a = 127 \)、\( k = 1/2 \) のとき → コントラストを下げた画像が出力される</strong></p>



<p><strong>[グレースケール画像]</strong></p>



<figure class="wp-block-image aligncenter size-large"><img width="1024" height="488" src="https://www.momoyama-usagi.com/wp-content/uploads/ip1-7-1024x488.jpg" alt="" class="wp-image-15628" srcset="https://www.momoyama-usagi.com/wp-content/uploads/ip1-7-1024x488.jpg 1024w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-7-300x143.jpg 300w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-7-768x366.jpg 768w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-7-1536x732.jpg 1536w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-7.jpg 1799w" /></figure>



<p><strong>[カラー画像]</strong></p>



<figure class="wp-block-image aligncenter size-large"><img width="1024" height="555" src="https://www.momoyama-usagi.com/wp-content/uploads/ip1-14-1024x555.jpg" alt="" class="wp-image-15635" srcset="https://www.momoyama-usagi.com/wp-content/uploads/ip1-14-1024x555.jpg 1024w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-14-300x163.jpg 300w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-14-768x416.jpg 768w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-14-1536x832.jpg 1536w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-14.jpg 1801w" /></figure>



<h4 class="wp-block-heading">ソースコード</h4>



<p>入力画像 <code>input_img</code>、倍率 <code>k</code> 、初期値 <code>a</code> を引数とすることで、初期値付き折れ線型トーンカーブを適用した画像を返す関数を紹介します。</p>



<p><strong>[Python]</strong></p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: python; title: ; notranslate">
import numpy as np

def polygonalToneWithIni(input_img,k,a):
    return a + np.dot(k,input_img) # np.dot は画素値が255を超える画素を自動的に255に置き換えてくれる
</pre></div>


<p><strong>[MATLAB]</strong></p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: matlabkey; title: ; notranslate">
function output_img = polygonalToneWithIni(input_img,k,a)
    output_img = a + k * input_img; 
end
</pre></div>


<h4 class="wp-block-heading">初期値付き折れ線型トーンカーブまとめ</h4>



<figure class="wp-block-image aligncenter size-large"><img width="1024" height="520" src="https://www.momoyama-usagi.com/wp-content/uploads/ip1-56-1024x520.jpg" alt="" class="wp-image-15707" srcset="https://www.momoyama-usagi.com/wp-content/uploads/ip1-56-1024x520.jpg 1024w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-56-300x152.jpg 300w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-56-768x390.jpg 768w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-56-1536x780.jpg 1536w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-56.jpg 1858w" /></figure>



<h3 class="wp-block-heading">(3) 2値化</h3>


<p><span>画像内の明るい部分(画素)を真っ白(画素値255) に、暗い部分(画素)を真っ黒(画素値0) に変換する処理です。言い換えると、<span  style="background-image:linear-gradient(to bottom,transparent 0%,#FFF387 0%);" class="dbp-e-marker-animation y">画像内の各画素を「真っ白」or「真っ黒」の2色にする処理</span>と言えます。</span></p>


<p>数式で書くと、\[<br>y = \left\{ \begin{array}{cc} 255 &amp; ( x \geqq a ) \\ 0 &amp; ( x &lt; a )  \end{array} \right.<br>\]となります。（※ \( a \) はしきい値、入力画素値: \( x \)、出力画素値: \( y \)）</p>



<p><strong>例) 画素値128以上を白、128未満を黒とする場合 \( a = 128 \)</strong></p>



<p><strong>[グレースケール画像の場合]</strong></p>



<figure class="wp-block-image aligncenter size-large"><img width="1024" height="454" src="https://www.momoyama-usagi.com/wp-content/uploads/ip1-8-1024x454.jpg" alt="" class="wp-image-15629" srcset="https://www.momoyama-usagi.com/wp-content/uploads/ip1-8-1024x454.jpg 1024w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-8-300x133.jpg 300w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-8-768x340.jpg 768w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-8-1536x681.jpg 1536w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-8.jpg 1932w" /></figure>



<p><strong>[カラー画像の場合]</strong></p>



<p>R成分, G成分, B成分それぞれに2値化判定を行います<span class="footnote_referrer"><a tabindex="0" onclick="footnote_moveToReference_15617_17('footnote_plugin_reference_15617_17_3');" onkeypress="footnote_moveToReference_15617_17('footnote_plugin_reference_15617_17_3');" ><sup id="footnote_plugin_tooltip_15617_17_3" class="footnote_plugin_tooltip_text">[3]</sup></a><span id="footnote_plugin_tooltip_text_15617_17_3" class="footnote_tooltip">例えば、R成分の画素値が 200, G成分の画素値が150, B成分の画素値が100であれば、R,&nbsp;&#x2026; <span class="footnote_tooltip_continue"  onclick="footnote_moveToReference_15617_17('footnote_plugin_reference_15617_17_3');">Continue reading</span></span></span>。</p>



<figure class="wp-block-image aligncenter size-large"><img width="1024" height="546" src="https://www.momoyama-usagi.com/wp-content/uploads/ip1-15-1024x546.jpg" alt="" class="wp-image-15636" srcset="https://www.momoyama-usagi.com/wp-content/uploads/ip1-15-1024x546.jpg 1024w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-15-300x160.jpg 300w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-15-768x410.jpg 768w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-15-1536x820.jpg 1536w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-15.jpg 1831w" /></figure>



<h4 class="wp-block-heading">ソースコード</h4>



<p>入力画像 <code>input_img</code>、しきい値 <code>threshold</code> を引数とすることで、2値化を適用した画像を返す関数のソースコードです。</p>



<p><strong>[Python]</strong></p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: python; title: ; notranslate">
import numpy as np

def binTone(input_img,threshold):
    # しきい値 threshold 以上を真っ白(画素値255)、しきい値未満を真っ黒(画素値0)とする
    return np.where(input_img &gt;= threshold, 255, 0) 
</pre></div>


<p><strong>[MATLAB]</strong></p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: matlabkey; title: ; notranslate">
function output_img = binTone(input_img,threshold)
    output_img = (input_img &gt;= 128) * 255;
end
</pre></div>


<h4 class="wp-block-heading">2値化まとめ</h4>



<figure class="wp-block-image aligncenter size-large"><img width="1024" height="500" src="https://www.momoyama-usagi.com/wp-content/uploads/ip1-22-1024x500.jpg" alt="" class="wp-image-15643" srcset="https://www.momoyama-usagi.com/wp-content/uploads/ip1-22-1024x500.jpg 1024w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-22-300x146.jpg 300w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-22-768x375.jpg 768w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-22-1536x750.jpg 1536w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-22.jpg 1858w" /></figure>



<h3 class="wp-block-heading">(4) ネガポジ変換</h3>


<p><span>画像内の濃淡を入れ替える変換です。言い換えると、<span  style="background-image:linear-gradient(to bottom,transparent 0%,#FFF387 0%);" class="dbp-e-marker-animation y">画像内の明るい画素を暗い画素に、暗い画素を明るい画素に変換する処理</span>です。</span></p>
<p><span>数式で書くと、\[<br>y = 255 - x<br>\]です。（入力画素値: \( x \), 出力画素値: \( y \)）</span></p>


<p><strong>[グレースケール画像の場合]</strong></p>



<figure class="wp-block-image aligncenter size-large"><img width="1024" height="497" src="https://www.momoyama-usagi.com/wp-content/uploads/ip1-9-1024x497.jpg" alt="" class="wp-image-15630" srcset="https://www.momoyama-usagi.com/wp-content/uploads/ip1-9-1024x497.jpg 1024w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-9-300x146.jpg 300w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-9-768x373.jpg 768w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-9-1536x746.jpg 1536w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-9.jpg 1792w" /></figure>



<p>白うさぎは黒うさぎに、黒うさぎは白うさぎになりますね。</p>



<p><strong>[カラー画像の場合]</strong></p>



<figure class="wp-block-image aligncenter size-large"><img width="1024" height="546" src="https://www.momoyama-usagi.com/wp-content/uploads/ip1-16-1024x546.jpg" alt="" class="wp-image-15637" srcset="https://www.momoyama-usagi.com/wp-content/uploads/ip1-16-1024x546.jpg 1024w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-16-300x160.jpg 300w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-16-768x410.jpg 768w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-16-1536x820.jpg 1536w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-16.jpg 1831w" /></figure>



<h4 class="wp-block-heading">ソースコード</h4>



<p>入力画像 <code>input_img</code> を引数とすることで、ネガポジ変換を適用した画像を返す関数のソースコードです。</p>



<p><strong>[Python]</strong></p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: python; title: ; notranslate">
import numpy as np

def negaposiTone(input_img):
    return 255 - input_img
</pre></div>


<p><strong>[MATLAB]</strong></p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: matlabkey; title: ; notranslate">
function output_img = negaposiTone(input_img)
    output_img = 255 - input_img;
end
</pre></div>


<h4 class="wp-block-heading">ガンマ補正(変換)まとめ</h4>



<figure class="wp-block-image aligncenter size-large"><img width="1024" height="496" src="https://www.momoyama-usagi.com/wp-content/uploads/ip1-23-1024x496.jpg" alt="" class="wp-image-15644" srcset="https://www.momoyama-usagi.com/wp-content/uploads/ip1-23-1024x496.jpg 1024w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-23-300x145.jpg 300w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-23-768x372.jpg 768w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-23-1536x744.jpg 1536w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-23.jpg 1873w" /></figure>



<div style="height:101px" class="wp-block-spacer"></div>



<h2 class="wp-block-heading">4. 応用的なトーンカーブ [Python, MATLABコード付き]</h2>



<p>先ほど（3章）よりも少し複雑なトーンカーブも見ていきましょう。</p>



<h3 class="wp-block-heading">(1) ガンマ補正(変換)</h3>



<h4 class="wp-block-heading">(1-a) ガンマ変換とは</h4>



<p>理論的には「画素値を \( n \) 倍にすると、ディスプレイ（などの出力装置）の明るさも \( n \) 倍に変化」します。（この状態のことをリニアと呼びます。）</p>



<p>しかし、実際の出力装置（ディスプレイなど）は必ずしも理論的な変化をするとは限りません。</p>



<figure class="wp-block-image aligncenter size-large"><img width="1024" height="458" src="https://www.momoyama-usagi.com/wp-content/uploads/ip1-57-1024x458.jpg" alt="" class="wp-image-15742" srcset="https://www.momoyama-usagi.com/wp-content/uploads/ip1-57-1024x458.jpg 1024w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-57-300x134.jpg 300w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-57-768x343.jpg 768w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-57.jpg 1460w" /></figure>



<p>そこで、実際の出力装置をリニアに近づけるための処理を行います。この処理のことをガンマ補正と呼びます。</p>



<p>ガンマ補正では、入力画素値 \( x \)、出力画素値 \( y \) に対して\[<br>y = 255 \left( \frac{x}{255} \right)^{\gamma}<br>\]の処理を与えます<span class="footnote_referrer"><a tabindex="0" onclick="footnote_moveToReference_15617_17('footnote_plugin_reference_15617_17_4');" onkeypress="footnote_moveToReference_15617_17('footnote_plugin_reference_15617_17_4');" ><sup id="footnote_plugin_tooltip_15617_17_4" class="footnote_plugin_tooltip_text">[4]</sup></a><span id="footnote_plugin_tooltip_text_15617_17_4" class="footnote_tooltip">指数部分を \( \frac{1}{ \gamma } \) とし、\[y = 255 \left( \frac{x}{255} \right)^{ \frac{1}{\gamma} }\]と表記することも多いです。というのも、元画像 \( y \)&nbsp;&#x2026; <span class="footnote_tooltip_continue"  onclick="footnote_moveToReference_15617_17('footnote_plugin_reference_15617_17_4');">Continue reading</span></span></span><br>（※ \( \gamma \) は出力装置ごとに最も適した値を設定する）</p>



<h4 class="wp-block-heading">(1-b) ガンマ変換と明るさの関係</h4>



<p>実際にガンマ値 \( \gamma \) を変化させながらガンマ補正を行うと、どんな画像が生成できるかを見てみましょう。</p>



<figure class="wp-block-image aligncenter size-large"><img width="1024" height="655" src="https://www.momoyama-usagi.com/wp-content/uploads/ip1-19-1024x655.jpg" alt="" class="wp-image-15640" srcset="https://www.momoyama-usagi.com/wp-content/uploads/ip1-19-1024x655.jpg 1024w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-19-300x192.jpg 300w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-19-768x492.jpg 768w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-19-1536x983.jpg 1536w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-19-2048x1311.jpg 2048w" /></figure>



<p>具体的には、</p>



<ul class="wp-block-list"><li>ガンマ値 \( \gamma &gt; 1 \) → 元の画像より暗くなる変換</li><li>ガンマ値 \( \gamma = 1 \) → 元の画像と全く同じ変換（明るさ変化なし）</li><li>ガンマ値 \( \gamma &lt; 1 \) → 元の画像より明るくなる変換</li></ul>



<p>となります<span class="footnote_referrer"><a tabindex="0" onclick="footnote_moveToReference_15617_17('footnote_plugin_reference_15617_17_5');" onkeypress="footnote_moveToReference_15617_17('footnote_plugin_reference_15617_17_5');" ><sup id="footnote_plugin_tooltip_15617_17_5" class="footnote_plugin_tooltip_text">[5]</sup></a><span id="footnote_plugin_tooltip_text_15617_17_5" class="footnote_tooltip">ガンマ補正を逆数\[y = 255 \left( \frac{x}{255} \right)^{ \frac{1}{\gamma} }\] で定義した場合は、



ガンマ値 \( \gamma &gt; 1 \) →&nbsp;&#x2026; <span class="footnote_tooltip_continue"  onclick="footnote_moveToReference_15617_17('footnote_plugin_reference_15617_17_5');">Continue reading</span></span></span>。</p>



<h4 class="wp-block-heading">(1-c) 様々なガンマ値とトーンカーブ</h4>



<p>ガンマ値を 0.25 ～ 4 まで変化させるとトーンカーブはどのように変化するかを、実際にグラフを描画することで確認してみましょう。</p>



<center></center>



<p>各グラフのガンマ値は下の通りです。</p>



<ul class="wp-block-list"><li><mark style="background-color:rgba(0, 0, 0, 0);color:#6f2286" class="has-inline-color">紫 → \( \gamma = 0.25 \)</mark></li><li><mark style="background-color:rgba(0, 0, 0, 0);color:#0024c5" class="has-inline-color">青 → \( \gamma = 0.50 \)</mark></li><li><mark style="background-color:rgba(0, 0, 0, 0);color:#33b71f" class="has-inline-color">緑 → \( \gamma = 1.00 \)</mark></li><li><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-light-orange-color">黄 → \( \gamma = 2.00 \)</mark></li><li><mark style="background-color:rgba(0, 0, 0, 0);color:#ff0000" class="has-inline-color">赤 → \( \gamma = 4.00 \)</mark></li></ul>



<h4 class="wp-block-heading">(1-d) ソースコード紹介</h4>



<p>入力画像 <code>input_img</code>, およびガンマ値 <code>gamma</code> を引数とすることで、ガンマ変換を行う関数です。</p>



<p>※ 途中の計算で小数が出てくるため、いったん計算結果を小数で出してから整数型(uint8)に変換しています。</p>



<p><strong>[Python]</strong></p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: python; title: ; notranslate">
import numpy as np

def gammaTone(input_img,gamma):
    output_float = 255 * np.power(input_img / 255, gamma) # 計算結果をいったん実数型(float)で保持
    return output_float.astype(np.uint8)
</pre></div>


<p><strong>[MATLAB]</strong></p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: matlabkey; title: ; notranslate">
function output_img = gammaTone(input_img,gamma)
    output_double = 255 * power(double(input_img) / 255,gamma); % 計算結果をいったん実数型(double)で保持
    output_img = uint8(output_double);
end
</pre></div>


<h4 class="wp-block-heading">ガンマ補正まとめ</h4>



<figure class="wp-block-image aligncenter size-large"><img width="1024" height="619" src="https://www.momoyama-usagi.com/wp-content/uploads/ip1-27-1024x619.jpg" alt="" class="wp-image-15648" srcset="https://www.momoyama-usagi.com/wp-content/uploads/ip1-27-1024x619.jpg 1024w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-27-300x181.jpg 300w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-27-768x464.jpg 768w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-27-1536x928.jpg 1536w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-27-2048x1238.jpg 2048w" /></figure>



<h3 class="wp-block-heading">(2) S字トーンカーブ変換</h3>



<p>下のように、S字カーブを描くトーンカーブを用いて変換を行うと、コントラストが高くなった画像を出力することができます。</p>



<p>数式でS字カーブを描くためには\[<br>y = \frac{255}{2} \left\{ 1 - \cos \left( \frac{\pi}{255} x \right) \right\}<br>\]のように三角関数を使う方法や、ロジスティック方程式\[<br>y = \frac{255}{1 + ae^{ -b \left( x - \frac{255}{2} \right) } }<br>\]を使う方法があります<span class="footnote_referrer"><a tabindex="0" onclick="footnote_moveToReference_15617_17('footnote_plugin_reference_15617_17_6');" onkeypress="footnote_moveToReference_15617_17('footnote_plugin_reference_15617_17_6');" ><sup id="footnote_plugin_tooltip_15617_17_6" class="footnote_plugin_tooltip_text">[6]</sup></a><span id="footnote_plugin_tooltip_text_15617_17_6" class="footnote_tooltip">&nbsp;&#x2026; <span class="footnote_tooltip_continue"  onclick="footnote_moveToReference_15617_17('footnote_plugin_reference_15617_17_6');">Continue reading</span></span></span>。（ただし \( a &gt; 0 \), \( b &gt; 0 \)）</p>



<p><strong>[グレースケール画像]</strong></p>



<figure class="wp-block-image aligncenter size-large"><img width="1024" height="497" src="https://www.momoyama-usagi.com/wp-content/uploads/ip1-10-1024x497.jpg" alt="" class="wp-image-15631" srcset="https://www.momoyama-usagi.com/wp-content/uploads/ip1-10-1024x497.jpg 1024w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-10-300x146.jpg 300w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-10-768x373.jpg 768w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-10-1536x746.jpg 1536w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-10.jpg 1792w" /></figure>



<p><strong>[カラー画像]</strong></p>



<figure class="wp-block-image aligncenter size-large"><img width="1024" height="494" src="https://www.momoyama-usagi.com/wp-content/uploads/ip1-17-1024x494.jpg" alt="" class="wp-image-15638" srcset="https://www.momoyama-usagi.com/wp-content/uploads/ip1-17-1024x494.jpg 1024w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-17-300x145.jpg 300w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-17-768x370.jpg 768w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-17-1536x740.jpg 1536w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-17.jpg 1780w" /></figure>



<h4 class="wp-block-heading">ソースコード</h4>



<p>入力画像 <code>input_img</code> を引数とすることで、S字変換を適用した画像を返す関数のソースコードです。（ロジスティック方程式を利用しました）</p>



<p>※ 途中の計算で小数が出てくるため、いったん計算結果を小数で出してから整数型(uint8)に変換しています。</p>



<p><strong>[Python]</strong></p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: python; title: ; notranslate">
import numpy as np

def sigmoidTone(input_img):
    output_float = 255 / (1 + np.exp(-0.05 * (input_img - 127.5) ) ) # 計算結果をいったん実数型(float)で保持
    return output_float.astype(np.uint8)
</pre></div>


<p><strong>[MATLAB]</strong></p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: matlabkey; title: ; notranslate">
function output_img = sigmoidTone(input_img)
    output_double = 255 ./ (1 * exp(-0.05 * (double(input_img) - 127.5)));  % 計算結果をいったん実数型(double)で保持 
    output_img = uint8(output_double);
end
</pre></div>


<h4 class="wp-block-heading">S字カーブ変換まとめ</h4>



<figure class="wp-block-image aligncenter size-large"><img width="1024" height="496" src="https://www.momoyama-usagi.com/wp-content/uploads/ip1-24-1024x496.jpg" alt="" class="wp-image-15645" srcset="https://www.momoyama-usagi.com/wp-content/uploads/ip1-24-1024x496.jpg 1024w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-24-300x145.jpg 300w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-24-768x372.jpg 768w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-24-1536x744.jpg 1536w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-24.jpg 1873w" /></figure>



<h3 class="wp-block-heading">(3) ソラリゼーション変換</h3>



<p>濃淡の一部分を反転することで、ネガとポジが混ざり合った効果を持つ画像を生み出します。</p>



<p>数式では\[<br>y = \frac{255}{2} \left\{ 1 - \cos \left( \frac{3 \pi}{255} x \right) \right\}<br>\]のように三角関数を使うことで表現可能です<span class="footnote_referrer"><a tabindex="0" onclick="footnote_moveToReference_15617_17('footnote_plugin_reference_15617_17_7');" onkeypress="footnote_moveToReference_15617_17('footnote_plugin_reference_15617_17_7');" ><sup id="footnote_plugin_tooltip_15617_17_7" class="footnote_plugin_tooltip_text">[7]</sup></a><span id="footnote_plugin_tooltip_text_15617_17_7" class="footnote_tooltip">導出方法ですが、まず \( - \cos x \) の \( 0 \leqq x \leqq 3 \pi \) のグラフに着目します。あとは、このグラフの周期を \( 2 \pi \) から 170 に変換するように&nbsp;&#x2026; <span class="footnote_tooltip_continue"  onclick="footnote_moveToReference_15617_17('footnote_plugin_reference_15617_17_7');">Continue reading</span></span></span>。</p>



<p><strong>[グレースケール画像]</strong></p>



<figure class="wp-block-image aligncenter size-large"><img width="1024" height="491" src="https://www.momoyama-usagi.com/wp-content/uploads/ip1-11-1024x491.jpg" alt="" class="wp-image-15632" srcset="https://www.momoyama-usagi.com/wp-content/uploads/ip1-11-1024x491.jpg 1024w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-11-300x144.jpg 300w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-11-768x368.jpg 768w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-11-1536x737.jpg 1536w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-11.jpg 1814w" /></figure>



<p><strong>[カラー画像]</strong></p>



<p>あら不思議。虹色のうさぎさんが出てきましたね。</p>



<figure class="wp-block-image aligncenter size-large"><img width="1024" height="480" src="https://www.momoyama-usagi.com/wp-content/uploads/ip1-18-1024x480.jpg" alt="" class="wp-image-15639" srcset="https://www.momoyama-usagi.com/wp-content/uploads/ip1-18-1024x480.jpg 1024w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-18-300x141.jpg 300w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-18-768x360.jpg 768w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-18-1536x720.jpg 1536w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-18.jpg 1814w" /></figure>



<h4 class="wp-block-heading">ソースコード</h4>



<p>入力画像 <code>input_img</code> を引数とすることで、ソラリゼーション変換を適用した画像を返す関数のソースコードです。</p>



<p>※ 途中の計算で小数が出てくるため、いったん計算結果を小数で出してから整数型(uint8)に変換しています。</p>



<p><strong>[Python]</strong></p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: python; title: ; notranslate">
import numpy as np
import math

def solaTone(input_img):
    output_float = 127.5 - 255 / 2 * np.cos(3 * math.pi / 255 * input_img)
    return output_float.astype(np.uint8)
</pre></div>


<p><strong>[MATLAB]</strong></p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: matlabkey; title: ; notranslate">
function output_img = solaTone(input_img)
    output_double = 127.5 - 255 / 2 * cos(3 * pi / 255 * double(input_img));  % 計算結果をいったん実数型(double)で保持
    output_img = uint8(output_double);
end
</pre></div>


<h4 class="wp-block-heading">ソラリゼーション変換まとめ</h4>



<figure class="wp-block-image aligncenter size-large"><img width="1024" height="481" src="https://www.momoyama-usagi.com/wp-content/uploads/ip1-25-1024x481.jpg" alt="" class="wp-image-15646" srcset="https://www.momoyama-usagi.com/wp-content/uploads/ip1-25-1024x481.jpg 1024w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-25-300x141.jpg 300w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-25-768x361.jpg 768w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-25-1536x722.jpg 1536w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-25.jpg 1929w" /></figure>



<div style="height:101px" class="wp-block-spacer"></div>



<h2 class="wp-block-heading">5. カラー画像特有の画像処理 [Python, MATLABコード付き]</h2>



<p>カラー画像では、全体のコントラストを変える画像処理の他にも、<strong><span style="text-decoration: underline;">色を調整する</span></strong>という画像処理のテクニックがあります。</p>



<p>具体的には、R, G, Bのトーンカーブに対し、「カラー画像のR, G, Bのうちの一部にトーンカーブを適用し、色のバランスを変える」ということをします。</p>



<p>ただ文章で説明されるより、実際に例を見たほうが分かりやすいと思うので、実際に2パターンほど「カラー画像特有の画像処理テクニック」を見ていきましょう！</p>



<h3 class="wp-block-heading">(1) 特定の色を強調する変換</h3>



<p>特定の色を強調する場合は、強調したい色のトーンカーブに「折れ線型トーンカーブ \( k &gt; 1 \)」を適用し、残りの成分には何もしません。</p>



<p><strong>[適用するトーンカーブ]</strong></p>



<p>例えば、赤色(R成分)を強める変換をしてみましょう。ここで、R成分に \( k = 1.2 \) の折れ線型トーンカーブを適用します。</p>



<figure class="wp-block-image aligncenter size-large"><img width="1024" height="501" src="https://www.momoyama-usagi.com/wp-content/uploads/ip1-34-1024x501.jpg" alt="" class="wp-image-15655" srcset="https://www.momoyama-usagi.com/wp-content/uploads/ip1-34-1024x501.jpg 1024w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-34-300x147.jpg 300w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-34-768x376.jpg 768w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-34.jpg 1157w" /></figure>



<p><strong>[変換結果]</strong></p>



<p>赤色が強調された画像が得られましたね。</p>



<figure class="wp-block-image aligncenter size-large"><img width="1024" height="260" src="https://www.momoyama-usagi.com/wp-content/uploads/ip1-33-1024x260.jpg" alt="" class="wp-image-15654" srcset="https://www.momoyama-usagi.com/wp-content/uploads/ip1-33-1024x260.jpg 1024w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-33-300x76.jpg 300w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-33-768x195.jpg 768w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-33-1536x390.jpg 1536w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-33.jpg 1565w" /></figure>







<h3 class="wp-block-heading">(2) 特定の色を弱める変換</h3>



<p>今度は、特定の色を弱める変換を見てみましょう。</p>



<p>特定の色を弱める場合は、弱めたい色のトーンカーブに「折れ線型トーンカーブ \( k &lt; 1 \)」を適用し、残りの成分には何もしません。</p>



<p><strong>[適用するトーンカーブ]</strong></p>



<p>例えば、青色(B成分)を弱める変換をしてみましょう。ここで、B成分に \( k = 0.8 \) の折れ線型トーンカーブを適用します。</p>



<figure class="wp-block-image aligncenter size-large"><img width="1024" height="500" src="https://www.momoyama-usagi.com/wp-content/uploads/ip1-36-1024x500.jpg" alt="" class="wp-image-15657" srcset="https://www.momoyama-usagi.com/wp-content/uploads/ip1-36-1024x500.jpg 1024w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-36-300x146.jpg 300w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-36-768x375.jpg 768w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-36.jpg 1164w" /></figure>



<p><strong>[変換結果]</strong></p>



<p>青色が弱まった画像が得られましたね。言い換えると、赤色と緑色の度合いが高い画像が生成できましたね。</p>



<figure class="wp-block-image size-large"><img width="1024" height="258" src="https://www.momoyama-usagi.com/wp-content/uploads/ip1-35-1024x258.jpg" alt="" class="wp-image-15656" srcset="https://www.momoyama-usagi.com/wp-content/uploads/ip1-35-1024x258.jpg 1024w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-35-300x76.jpg 300w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-35-768x194.jpg 768w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-35-1536x387.jpg 1536w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-35.jpg 1563w" /></figure>



<h3 class="wp-block-heading">(3) ソースコード</h3>



<p>入力画像 <code>input_img</code>, 成分の倍率 <code>k</code> 、色 <code>color</code> を引数とすることで、特定の色を強めたり弱めたりすることができる関数を紹介します。</p>



<p>※ 少し関数が複雑なので、使用例を付けております。</p>



<p><strong>[Python]</strong></p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: python; title: ; notranslate">
import numpy as np
import cv2

# color -&gt; (0,1,2,3) が (青,緑,赤,全色&#x5B;明るさ調整]) に対応
def polygonalTone(input_img,k,color):
    output_img = 1.0 * input_img # 1.0を掛けることでoutput_imgが255越えしても255でストップする
    if color == 3:
        output_img = np.dot(k,input_img)
    else:
        output_img&#x5B;:,:,color] = np.dot(k,input_img&#x5B;:,:,color])
    return output_img

## 使用例
#画像読み込み
input_color = cv2.imread(INPUT_PATH)

# (1) 赤を強める &#x5B;R x 1.2]
output_color = polygonalTone(input_color,1.2,2)
cv2.imwrite(OUTPUT_PATH,output_color)

# (2) 青を弱める &#x5B;B x 0.8]
output_color = polygonalTone(input_color,0.8,0)
cv2.imwrite(OUTPUT_PATH + &quot;color_sky2.jpg&quot;,output_color)
</pre></div>


<p><strong>[MATLAB]</strong></p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: matlabkey; title: ; notranslate">
% color -&gt; (1,2,3,4) が (赤,緑,青,全色&#x5B;明るさ調整]) に対応
function output_img = polygonalToneColor(input_img,k,color)
    output_img = input_img;
    if color == 4 
        output_img = input_img * k;
    else
        output_img(:,:,color) = input_img(:,:,color) * k;
    end
end

%% 使用例
% カラー画像読み込み
input_color = imread(INPUT_PATH);

%% 画像処理ここから
% (1) 赤を強める&#x5B;R x 1.2]
output_color = polygonalToneColor(input_color,1.2,1);
imwrite(output_color,OUTPUT_PATH);

% (2) 青を弱める&#x5B;B x 0.8]
output_color = polygonalToneColor(input_color,0.8,3);
imwrite(output_color,OUTPUT_PATH);
</pre></div>


<div style="height:101px" class="wp-block-spacer"></div>



<h2 class="wp-block-heading">6. 実際にプログラムを動かして画像処理を体験しよう！</h2>



<p>3～5章で各画像処理を行うための関数を説明してきましたが、やはり実際にプログラムを動かして画像処理を体験したいですよね。</p>



<p>そこで、<strong><a rel="noreferrer noopener" href="https://github.com/momoyama1192/PracticeImageProcess1" data-type="URL" target="_blank">こちら</a></strong>に「すぐに実行できる」ソースコードと実行方法を書いた説明を用意しました！　実際にプログラムを動かしてみたい方は是非ご覧ください！</p>



<div style="height:101px" class="wp-block-spacer"></div>



<h2 class="wp-block-heading">7. 練習問題でおさらい！</h2>



<p>それでは、ここまでの内容を練習問題で復習しましょう！</p>



<h3 class="wp-block-heading">練習1. トーンカーブのおさらい [基本編]</h3>


<div class='wp-block-dbp-frame l-frame-float is-design-onframe is-frame-style-default dbp-frame has-bgcolor'><div class="dbp-frame-title">練習1</div><div class="dbp-frame-content has-content-gap">
<p>つぎの(1)～(5)の変換が表すトーンカーブを、図1内の [トーンカーブの選択肢] から選び、①～⑥の番号で答えなさい。また、図2の「元画像」に対して(1)～(5)の変換を適用するとどのような画像が生成されるか。最も適切なものを図2内の [変換画像 (猫)] から選び、ア～カの記号で答えなさい。</p>

<p>(1) 画素値を2倍にする変換<br>(2) 画素値を1/2倍にする変換<br>(3) ネガポジ変換<br>(4) 2値化変換<br>(5) ソラリゼーション</p>



<p><strong>[トーンカーブの選択肢]</strong></p>

<figure class="wp-block-image aligncenter size-large"><img width="1024" height="747" src="https://www.momoyama-usagi.com/wp-content/uploads/ip1-6-1024x747.gif" alt="" class="wp-image-15827" srcset="https://www.momoyama-usagi.com/wp-content/uploads/ip1-6-1024x747.gif 1024w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-6-300x219.gif 300w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-6-768x560.gif 768w" /><figcaption>図1. トーンカーブ</figcaption></figure>

<p><strong>[画像の選択肢]</strong></p>

<figure class="wp-block-image aligncenter size-large"><img width="1024" height="853" src="https://www.momoyama-usagi.com/wp-content/uploads/ip1-59-1024x853.jpg" alt="" class="wp-image-15813" srcset="https://www.momoyama-usagi.com/wp-content/uploads/ip1-59-1024x853.jpg 1024w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-59-300x250.jpg 300w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-59-768x640.jpg 768w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-59.jpg 1530w" /><figcaption>図2. 変換画像(猫)</figcaption></figure>
</div></div>


<div style="height:50px" class="wp-block-spacer"></div>



<h3 class="wp-block-heading">練習2. トーンカーブのおさらい [応用編]</h3>


<div class='wp-block-dbp-frame l-frame-float is-design-onframe is-frame-style-default dbp-frame has-bgcolor'><div class="dbp-frame-title">練習2</div><div class="dbp-frame-content has-content-gap">
<p>つぎの①, ②, ③ が示す変換を ①→②→③ の順に適用した。</p>

<p>① 画素値を2倍にする変換<br>② 画素値を1/2倍にする変換<br>③ ネガポジ変換</p>

<p>このとき、「入力画素値」と「③適用後の出力画素値」の関係を表すトーンカーブを図3を参考にしながら答えなさい。</p>

<figure class="wp-block-image aligncenter size-full is-resized"><img src="https://www.momoyama-usagi.com/wp-content/uploads/ip1-7.gif" alt="" class="wp-image-15872" width="443" height="337"/><figcaption>図3. トーンカーブ (サンプル)</figcaption></figure>
</div></div>


<div style="height:50px" class="wp-block-spacer"></div>



<h3 class="wp-block-heading">練習3. カラー画像とトーンカーブ</h3>


<div class='wp-block-dbp-frame l-frame-float is-design-onframe is-frame-style-default dbp-frame has-bgcolor'><div class="dbp-frame-title">練習3</div><div class="dbp-frame-content has-content-gap">
<p>つぎのカラー画像に対して、(1)変換1, (2)変換2, (3)変換3 を適用し、新たなカラー画像を作成した。このとき、(1)～(3)の変換で用いたR, G, Bトーンカーブの組み合わせとして正しいものを [R, G, Bトーンカーブの組み合わせ] 内の①～⑧から1つ選び、番号で答えなさい。</p>

<figure class="wp-block-image aligncenter size-large"><img width="1024" height="750" src="https://www.momoyama-usagi.com/wp-content/uploads/ip1-78-1024x750.jpg" alt="" class="wp-image-15859" srcset="https://www.momoyama-usagi.com/wp-content/uploads/ip1-78-1024x750.jpg 1024w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-78-300x220.jpg 300w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-78-768x562.jpg 768w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-78-1536x1125.jpg 1536w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-78-2048x1500.jpg 2048w" /></figure>

<p><strong>[R, G, Bトーンカーブの組み合わせ]</strong></p>

<figure class="wp-block-image aligncenter size-large"><img width="1024" height="1003" src="https://www.momoyama-usagi.com/wp-content/uploads/ip1-70-1024x1003.jpg" alt="" class="wp-image-15851" srcset="https://www.momoyama-usagi.com/wp-content/uploads/ip1-70-1024x1003.jpg 1024w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-70-300x294.jpg 300w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-70-768x752.jpg 768w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-70.jpg 1497w" /></figure>

<figure class="wp-block-image aligncenter size-large"><img width="1024" height="1003" src="https://www.momoyama-usagi.com/wp-content/uploads/ip1-71-1024x1003.jpg" alt="" class="wp-image-15852" srcset="https://www.momoyama-usagi.com/wp-content/uploads/ip1-71-1024x1003.jpg 1024w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-71-300x294.jpg 300w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-71-768x752.jpg 768w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-71.jpg 1497w" /></figure>

<figure class="wp-block-image aligncenter size-large"><img width="1024" height="657" src="https://www.momoyama-usagi.com/wp-content/uploads/ip1-72-1024x657.jpg" alt="" class="wp-image-15853" srcset="https://www.momoyama-usagi.com/wp-content/uploads/ip1-72-1024x657.jpg 1024w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-72-300x193.jpg 300w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-72-768x493.jpg 768w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-72.jpg 1497w" /></figure>
</div></div>


<div style="height:101px" class="wp-block-spacer"></div>



<h2 class="wp-block-heading">8. 練習問題の答え</h2>



<h3 class="wp-block-heading">解答1. トーンカーブのおさらい [基本編]</h3>



<p><strong>(1) 画素値を2倍にする変換</strong></p>



<p>全体的に明るくなっている写真を選べばOK。<br>画素値を明るくすると、真っ白な画素（画素値255）が出てくるのも (エ) を選ぶ決め手かも。</p>



<figure class="wp-block-image aligncenter size-large"><img width="1024" height="467" src="https://www.momoyama-usagi.com/wp-content/uploads/ip1-64-1024x467.jpg" alt="" class="wp-image-15836" srcset="https://www.momoyama-usagi.com/wp-content/uploads/ip1-64-1024x467.jpg 1024w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-64-300x137.jpg 300w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-64-768x350.jpg 768w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-64.jpg 1100w" /></figure>



<p><strong>(2) 画素値を1/2倍にする変換</strong></p>



<p>全体的に暗くなっている写真を選べばOK。</p>



<figure class="wp-block-image aligncenter size-large"><img width="1024" height="467" src="https://www.momoyama-usagi.com/wp-content/uploads/ip1-65-1024x467.jpg" alt="" class="wp-image-15837" srcset="https://www.momoyama-usagi.com/wp-content/uploads/ip1-65-1024x467.jpg 1024w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-65-300x137.jpg 300w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-65-768x350.jpg 768w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-65.jpg 1100w" /></figure>



<p><strong>(3) ネガポジ変換</strong></p>



<p>白黒が完全に入れ替わっている（黒猫が白猫になっている）画像は (ウ) 以外にない。</p>



<figure class="wp-block-image aligncenter size-large"><img width="1024" height="467" src="https://www.momoyama-usagi.com/wp-content/uploads/ip1-66-1024x467.jpg" alt="" class="wp-image-15838" srcset="https://www.momoyama-usagi.com/wp-content/uploads/ip1-66-1024x467.jpg 1024w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-66-300x137.jpg 300w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-66-768x350.jpg 768w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-66.jpg 1100w" /></figure>



<p><strong>(4) 2値化変換</strong></p>



<p>(オ) 以外の画像には、「真っ黒」or「真っ白」ではない部分があるので2値化変換ではない。</p>



<figure class="wp-block-image aligncenter size-large"><img width="1024" height="467" src="https://www.momoyama-usagi.com/wp-content/uploads/ip1-67-1024x467.jpg" alt="" class="wp-image-15839" srcset="https://www.momoyama-usagi.com/wp-content/uploads/ip1-67-1024x467.jpg 1024w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-67-300x137.jpg 300w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-67-768x350.jpg 768w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-67.jpg 1100w" /></figure>



<p><strong>(5) ソラリゼーション</strong></p>



<p>画像の一部分だけがネガポジ変換されているのがポイント</p>



<figure class="wp-block-image aligncenter size-large"><img width="1024" height="462" src="https://www.momoyama-usagi.com/wp-content/uploads/ip1-79-1024x462.jpg" alt="" class="wp-image-15865" srcset="https://www.momoyama-usagi.com/wp-content/uploads/ip1-79-1024x462.jpg 1024w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-79-300x135.jpg 300w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-79-768x346.jpg 768w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-79.jpg 1162w" /></figure>



<p><strong>[おまけ] 残りものの画像は…？</strong></p>



<p>(1)～(5)で選ばれなかった選択肢は、「S字カーブの変換」に対応しています。</p>



<p>変換の前後でコントラストが高くなっている（暗い部分と明るい部分がはっきりしている）のが特徴です。</p>



<figure class="wp-block-image aligncenter size-large"><img width="1024" height="470" src="https://www.momoyama-usagi.com/wp-content/uploads/ip1-80-1024x470.jpg" alt="" class="wp-image-15866" srcset="https://www.momoyama-usagi.com/wp-content/uploads/ip1-80-1024x470.jpg 1024w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-80-300x138.jpg 300w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-80-768x353.jpg 768w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-80.jpg 1171w" /></figure>



<div style="height:50px" class="wp-block-spacer"></div>



<h3 class="wp-block-heading">解答2. トーンカーブのおさらい [応用編]</h3>



<p><strong>[解答]</strong></p>



<figure class="wp-block-image aligncenter size-full is-resized"><img src="https://www.momoyama-usagi.com/wp-content/uploads/ip1-83.jpg" alt="" class="wp-image-15870" width="496" height="378" srcset="https://www.momoyama-usagi.com/wp-content/uploads/ip1-83.jpg 661w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-83-300x229.jpg 300w" /></figure>



<p><strong>[変換過程]</strong></p>



<p><strong>元画像 → ①適用後</strong></p>



<figure class="wp-block-image aligncenter size-large"><img width="1024" height="498" src="https://www.momoyama-usagi.com/wp-content/uploads/ip1-84-1024x498.jpg" alt="" class="wp-image-15871" srcset="https://www.momoyama-usagi.com/wp-content/uploads/ip1-84-1024x498.jpg 1024w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-84-300x146.jpg 300w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-84-768x373.jpg 768w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-84.jpg 1037w" /></figure>



<p><strong>①適用後 → ②適用後</strong></p>



<p>画素値を2倍にしてから1/2倍(0.5倍)に戻しても、画素値が255オーバーになった部分は元画像のようには戻らないのがポイント。</p>



<figure class="wp-block-image aligncenter size-large"><img width="1024" height="498" src="https://www.momoyama-usagi.com/wp-content/uploads/ip1-81-1024x498.jpg" alt="" class="wp-image-15868" srcset="https://www.momoyama-usagi.com/wp-content/uploads/ip1-81-1024x498.jpg 1024w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-81-300x146.jpg 300w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-81-768x373.jpg 768w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-81.jpg 1037w" /></figure>



<p><strong>②適用後 → ③適用後(答え)</strong></p>



<figure class="wp-block-image aligncenter size-large"><img width="1024" height="498" src="https://www.momoyama-usagi.com/wp-content/uploads/ip1-82-1024x498.jpg" alt="" class="wp-image-15869" srcset="https://www.momoyama-usagi.com/wp-content/uploads/ip1-82-1024x498.jpg 1024w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-82-300x146.jpg 300w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-82-768x373.jpg 768w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-82.jpg 1037w" /></figure>



<div style="height:50px" class="wp-block-spacer"></div>



<h3 class="wp-block-heading">解答3. カラー画像とトーンカーブ</h3>



<p><strong>(1) 正解: ④</strong></p>



<p>元画像に比べて、圧倒的に青色の成分が強くなっているのが決め手。</p>



<p>また、全体的に画像が明るくなったり暗くなったりしていないので、①や⑤のように全体の画素値を2倍(1/2倍)するトーンカーブではないのもポイント。</p>



<figure class="wp-block-image aligncenter size-large"><img width="1024" height="251" src="https://www.momoyama-usagi.com/wp-content/uploads/ip1-74-1024x251.jpg" alt="" class="wp-image-15855" srcset="https://www.momoyama-usagi.com/wp-content/uploads/ip1-74-1024x251.jpg 1024w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-74-300x73.jpg 300w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-74-768x188.jpg 768w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-74-1536x376.jpg 1536w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-74.jpg 1891w" /></figure>



<div style="height:50px" class="wp-block-spacer"></div>



<p><strong>(2) 正解: ⑥</strong></p>



<p>画像の赤部分がかなり消えていて、青と緑を中心とした画像になっているのが決め手。</p>



<p>また、(1)と同じく全体的に画像が明るくなったり暗くなったりしていないので、①や⑤のように全体の画素値を2倍(1/2倍)するトーンカーブではないのもポイント。</p>



<figure class="wp-block-image aligncenter size-large"><img width="1024" height="251" src="https://www.momoyama-usagi.com/wp-content/uploads/ip1-75-1024x251.jpg" alt="" class="wp-image-15856" srcset="https://www.momoyama-usagi.com/wp-content/uploads/ip1-75-1024x251.jpg 1024w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-75-300x73.jpg 300w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-75-768x188.jpg 768w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-75-1536x376.jpg 1536w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-75.jpg 1891w" /></figure>



<div style="height:50px" class="wp-block-spacer"></div>



<p><strong>(3) 正解: ⑤</strong></p>



<p>全体的に画像が暗くなっている点に着目。</p>



<p>また、(1)や(2)のように画像の色の度合いが変わっていないのもポイントの1つ。</p>



<figure class="wp-block-image aligncenter size-large"><img width="1024" height="251" src="https://www.momoyama-usagi.com/wp-content/uploads/ip1-76-1024x251.jpg" alt="" class="wp-image-15857" srcset="https://www.momoyama-usagi.com/wp-content/uploads/ip1-76-1024x251.jpg 1024w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-76-300x73.jpg 300w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-76-768x188.jpg 768w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-76-1536x376.jpg 1536w, https://www.momoyama-usagi.com/wp-content/uploads/ip1-76.jpg 1891w" /></figure>







<h2 class="wp-block-heading">9. さいごに</h2>



<p>今回は、</p>



<ul class="wp-block-list"><li>画像処理の最も基本的な部分である「画素値を一定のルールに従っていじる」点の説明</li><li>画素値の変換で使う一定のルールを図でわかりやすく示した「トーンカーブ」について</li><li>代表的なトーンカーブの例</li><li>カラー画像の画像処理の例</li></ul>



<p>という点について説明し、最後に練習問題をおさらいしていきました。</p>



<p>次回は、まわりの画素にも着目した画像処理についてみていきましょう！</p>
<div class="speaker-mute footnotes_reference_container"> <div class="footnote_container_prepare"><p><span tabindex="0" class="footnote_reference_container_label pointer">注釈</span><span tabindex="0" class="footnote_reference_container_collapse_button" style="display: none;">[<a id="footnote_reference_container_collapse_button_15617_17">+</a>]</span></p></div> <div id="footnote_references_container_15617_17"><table class="footnotes_table footnote-reference-container"><caption class="accessibility">注釈</caption> <tbody> 

<tr class="footnotes_plugin_reference_row"> <th scope="row" class="footnote_plugin_index_combi pointer"  onclick="footnote_moveToAnchor_15617_17('footnote_plugin_tooltip_15617_17_1');"><a id="footnote_plugin_reference_15617_17_1" class="footnote_backlink"><span class="footnote_index_arrow">&#8593;</span>1</a></th> <td class="footnote_plugin_text">入力画像の画素値 \( x \) を2倍したものを出力画像の画素値 \( y \) とする、つまり \( y = 2x \) の変換を行うルール</td></tr>

<tr class="footnotes_plugin_reference_row"> <th scope="row" class="footnote_plugin_index_combi pointer"  onclick="footnote_moveToAnchor_15617_17('footnote_plugin_tooltip_15617_17_2');"><a id="footnote_plugin_reference_15617_17_2" class="footnote_backlink"><span class="footnote_index_arrow">&#8593;</span>2</a></th> <td class="footnote_plugin_text">余談ですが、画素値255オーバーしていて画像が白くなる現象のことを、「白飛びする」とか「サチる」などと呼ぶことがあります。</td></tr>

<tr class="footnotes_plugin_reference_row"> <th scope="row" class="footnote_plugin_index_combi pointer"  onclick="footnote_moveToAnchor_15617_17('footnote_plugin_tooltip_15617_17_3');"><a id="footnote_plugin_reference_15617_17_3" class="footnote_backlink"><span class="footnote_index_arrow">&#8593;</span>3</a></th> <td class="footnote_plugin_text">例えば、R成分の画素値が 200, G成分の画素値が150, B成分の画素値が100であれば、R, G成分の画素値はしきい値の128以上なので、出力される画素値は255となる一方、B成分の画素値はしきい値の128未満なので、出力される画素値は0となります。（画素値はR: 255, G: 255, B: 0 となる）</td></tr>

<tr class="footnotes_plugin_reference_row"> <th scope="row" class="footnote_plugin_index_combi pointer"  onclick="footnote_moveToAnchor_15617_17('footnote_plugin_tooltip_15617_17_4');"><a id="footnote_plugin_reference_15617_17_4" class="footnote_backlink"><span class="footnote_index_arrow">&#8593;</span>4</a></th> <td class="footnote_plugin_text">指数部分を \( \frac{1}{ \gamma } \) とし、\[<br>y = 255 \left( \frac{x}{255} \right)^{ \frac{1}{\gamma} }<br>\]と表記することも多いです。というのも、元画像 \( y \) にガンマ値 \( \gamma \) がかかった状態\[<br>x =255 \left( \frac{y}{255} \right)^{ \gamma }<br>\]を補正するためには、元のガンマ値の逆数 \( \frac{1}{ \gamma } \) でガンマ補正\[<br>y = 255 \left( \frac{x}{255} \right)^{ \frac{1}{\gamma} }<br>\]をすればよいですね。なので、指数部分が \( \frac{1}{ \gamma } \) となっている上式を定義することで「ガンマ値 \( \gamma \) がかかった画像を補正する変換」と考えることができますね。</td></tr>

<tr class="footnotes_plugin_reference_row"> <th scope="row" class="footnote_plugin_index_combi pointer"  onclick="footnote_moveToAnchor_15617_17('footnote_plugin_tooltip_15617_17_5');"><a id="footnote_plugin_reference_15617_17_5" class="footnote_backlink"><span class="footnote_index_arrow">&#8593;</span>5</a></th> <td class="footnote_plugin_text">ガンマ補正を逆数\[y = 255 \left( \frac{x}{255} \right)^{ \frac{1}{\gamma} }\] で定義した場合は、</p>



<ul class="wp-block-list"><li>ガンマ値 \( \gamma &gt; 1 \) → 元の画像より明るくなる変換</li><li>ガンマ値 \( \gamma = 1 \) → 元の画像と全く同じ変換（明るさ変化なし）</li><li>ガンマ値 \( \gamma &lt; 1 \) → 元の画像より暗くなる変換</li></ul>



<p>と、明暗が反転するので注意が必要です。</td></tr>

<tr class="footnotes_plugin_reference_row"> <th scope="row" class="footnote_plugin_index_combi pointer"  onclick="footnote_moveToAnchor_15617_17('footnote_plugin_tooltip_15617_17_6');"><a id="footnote_plugin_reference_15617_17_6" class="footnote_backlink"><span class="footnote_index_arrow">&#8593;</span>6</a></th> <td class="footnote_plugin_text">微分方程式を習ったことがある人は、変数分離系について習うときに聞いたことがあるかもしれません。ロジスティック方程式についてより詳しく知りたい人は<a rel="noreferrer noopener" href="https://www.momoyama-usagi.com/entry/math-ode01#2-3" data-type="URL" target="_blank">こちら</a>の記事をご覧ください！</td></tr>

<tr class="footnotes_plugin_reference_row"> <th scope="row" class="footnote_plugin_index_combi pointer"  onclick="footnote_moveToAnchor_15617_17('footnote_plugin_tooltip_15617_17_7');"><a id="footnote_plugin_reference_15617_17_7" class="footnote_backlink"><span class="footnote_index_arrow">&#8593;</span>7</a></th> <td class="footnote_plugin_text">導出方法ですが、まず \( - \cos x \) の \( 0 \leqq x \leqq 3 \pi \) のグラフに着目します。あとは、このグラフの周期を \( 2 \pi \) から 170 に変換するように \( x \) 部分を変化させ、さらに値域が \( -1 \leqq y \leqq 1 \) から \( 0 \leqq y \leqq 255 \) になるように変換させることでこのグラフを作成できます。\</td></tr>

 </tbody> </table> </div></div>]]></content:encoded>
					
					<wfw:commentRss>https://www.momoyama-usagi.com/entry/info-img02/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>うさぎでもわかる論理回路　不完全指定順序回路（Don&#039;t Careが含まれる状態遷移図）の状態数最小化</title>
		<link>https://www.momoyama-usagi.com/entry/info-junjo6</link>
					<comments>https://www.momoyama-usagi.com/entry/info-junjo6#respond</comments>
		
		<dc:creator><![CDATA[ももうさ]]></dc:creator>
		<pubDate>Sun, 31 Jul 2022 13:01:17 +0000</pubDate>
				<category><![CDATA[情報]]></category>
		<category><![CDATA[論理回路]]></category>
		<category><![CDATA[順序回路]]></category>
		<guid isPermaLink="false">https://www.momoyama-usagi.com/?p=15291</guid>

					<description><![CDATA[こんにちは、ももやまです。 前回は「順序回路の設計で出てくる状態遷移図の状態数を最小化する」方法について説明しました。 しかし、この方法は各状態における各入力ごとの状態遷移先と出力が決まっている場合にのみ使える最小化方法 [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>こんにちは、ももやまです。</p>



<p>前回は「順序回路の設計で出てくる状態遷移図の状態数を最小化する」方法について説明しました。</p>



<figure class="wp-block-embed is-type-wp-embed is-provider-工業大学生ももやまのうさぎ塾 wp-block-embed-工業大学生ももやまのうさぎ塾"><div class="wp-block-embed__wrapper">
        <article class="pb p-id-15095 is-position-relative pb-embed">
            <a class="pb-contents" href="https://www.momoyama-usagi.com/entry/info-junjo5">
                <div class="pb__thumb"><img width="300" height="104" src="https://www.momoyama-usagi.com/wp-content/uploads/junjo5-20-300x104.jpg" class="is-position-overlay wp-post-image" alt="" lazysizes="1" srcset="https://www.momoyama-usagi.com/wp-content/uploads/junjo5-20-300x104.jpg 300w, https://www.momoyama-usagi.com/wp-content/uploads/junjo5-20-1024x356.jpg 1024w, https://www.momoyama-usagi.com/wp-content/uploads/junjo5-20-768x267.jpg 768w, https://www.momoyama-usagi.com/wp-content/uploads/junjo5-20-1536x533.jpg 1536w, https://www.momoyama-usagi.com/wp-content/uploads/junjo5-20.jpg 2004w" /></div><div class="pb__body l-column is-flex-1"><div class="pb-title is-omit-line:2">うさぎでもわかる論理回路　順序回路の状態数最小化</div><div class="pb-substr is-font-size:s is-omit-line:2">※ この記事は、すでに「順序回路の設計をする際の状態遷移図・状態遷移表の書き方」を学んだ人向けの記事です。そのため、まだ</div></div>            </a>
        </article>
        
</div></figure>


<p><span>しかし、この方法は<span  style="background-image:linear-gradient(to bottom,transparent 0%,#FFF387 0%);" class="dbp-e-marker-animation y">各状態における各入力ごとの状態遷移先と出力が決まっている場合にのみ使える</span>最小化方法です。言い換えると、状態遷移先や出力が決まっていない（Don't Careが含まれている）状態遷移表は最小化することができません。</span></p>


<p>そこで今回は、「状態遷移先が出力が決まっていない、つまり遷移先や出力に Don't Careが含まれている」場合（不完全指定順序回路）でも最小化をする方法を勉強していきましょう。</p>



<div style="height:59px" class="wp-block-spacer"></div>



<h2 class="wp-block-heading">1. 不完全指定順序回路とは</h2>


<p><span>状態遷移表の遷移先（次状態）や出力に Don't Careが含まれているような順序回路のことを不完全指定順序回路と呼びます。</span></p>
<p><span>不完全指定順序回路には2種類あり、</span></p>
<ul>
<li>そもそも遷移先が Don't Careになっている場合</li>
<li>遷移先は決まっているが、出力が Don't Careになっている場合</li>
</ul>
<p>があります。</p>


<h3 class="wp-block-heading">(1) そもそも遷移先がDon't Careになっている場合</h3>



<p>ある現状態から、ある入力を与えたときの次状態が定義されていない状態です。</p>


<p><span  style="background-image:linear-gradient(to bottom,transparent 0%,#FFF387 0%);" class="dbp-e-marker-animation y">次状態とそのときの出力の両方が同時に Don't Careになる</span>のが特徴です。</p>


<figure class="wp-block-image aligncenter size-large is-resized"><img src="https://www.momoyama-usagi.com/wp-content/uploads/junjo6-1-1024x594.jpg" alt="" class="wp-image-15295" width="669" height="388" srcset="https://www.momoyama-usagi.com/wp-content/uploads/junjo6-1-1024x594.jpg 1024w, https://www.momoyama-usagi.com/wp-content/uploads/junjo6-1-300x174.jpg 300w, https://www.momoyama-usagi.com/wp-content/uploads/junjo6-1-768x445.jpg 768w, https://www.momoyama-usagi.com/wp-content/uploads/junjo6-1.jpg 1314w" /></figure>



<p>上の例の場合、\( q_1 \) に対して \( x  = 1 \) を入力した際の次状態と出力が X (Don't Care) になっていますね。</p>



<h3 class="wp-block-heading">(2) 遷移先は決まっているが、出力が Don't Careになっている場合</h3>



<p>ある現状態から、ある入力を与えたときの次状態は定義されていますが、出力が定義されていない状態です。</p>


<p><span  style="background-image:linear-gradient(to bottom,transparent 0%,#FFF387 0%);" class="dbp-e-marker-animation y">出力部分だけが Don't Careになる</span>のが特徴です。</p>


<figure class="wp-block-image aligncenter size-large is-resized"><img src="https://www.momoyama-usagi.com/wp-content/uploads/junjo6-2-1024x607.jpg" alt="" class="wp-image-15296" width="667" height="395" srcset="https://www.momoyama-usagi.com/wp-content/uploads/junjo6-2-1024x607.jpg 1024w, https://www.momoyama-usagi.com/wp-content/uploads/junjo6-2-300x178.jpg 300w, https://www.momoyama-usagi.com/wp-content/uploads/junjo6-2-768x455.jpg 768w, https://www.momoyama-usagi.com/wp-content/uploads/junjo6-2.jpg 1314w" /></figure>



<p>上の例の場合、\( q_1 \) に対して \( x  = 1 \) を入力した際の次状態は \( q_0 \) と決まっていますが、出力が X (Don't Care) になっていますね。</p>







<h2 class="wp-block-heading">2. 例題で流れを確認しよう</h2>



<p>それでは、実際に不完全指定順序回路の状態最小化の流れを、例題で確認しましょう。</p>


<div class='wp-block-dbp-frame l-frame-float is-design-onframe is-frame-style-default dbp-frame has-bgcolor'><div class="dbp-frame-title">例題</div><div class="dbp-frame-content has-content-gap">
<p>次の状態遷移図で表されるを不完全指定順序回路の状態数が最小になるように（最小化）し、状態遷移図の形で答えなさい。</p>

<p>※ X は Don't Careを表す</p>

<figure class="wp-block-image aligncenter size-large"><img width="1024" height="565" src="https://www.momoyama-usagi.com/wp-content/uploads/junjo6-re-2-1024x565.jpg" alt="" class="wp-image-15344" srcset="https://www.momoyama-usagi.com/wp-content/uploads/junjo6-re-2-1024x565.jpg 1024w, https://www.momoyama-usagi.com/wp-content/uploads/junjo6-re-2-300x166.jpg 300w, https://www.momoyama-usagi.com/wp-content/uploads/junjo6-re-2-768x424.jpg 768w, https://www.momoyama-usagi.com/wp-content/uploads/junjo6-re-2-1536x848.jpg 1536w, https://www.momoyama-usagi.com/wp-content/uploads/junjo6-re-2.jpg 1603w" /><figcaption>状態遷移図</figcaption></figure>
</div></div>


<div style="height:59px" class="wp-block-spacer"></div>



<h3 class="wp-block-heading">Step1. 状態遷移表を作成する</h3>



<p>まずは、状態遷移図を状態遷移表に落としこみましょう。</p>



<p>ここで、ある入力に対しての遷移先（矢印）が書かれていない場合がDon't Careになる点に要注意です。今回の場合は、</p>



<ul class="wp-block-list"><li>\( q_2 \) のときに \( x = 0 \) を入力したとき</li><li>\( q_4 \) のときに \( x = 1 \) を入力したとき</li></ul>



<p>が存在しないので、この2つが「次状態・出力」ともにDon't Careとなります。</p>



<figure class="wp-block-image aligncenter size-full is-resized"><img src="https://www.momoyama-usagi.com/wp-content/uploads/junjo6-re-1.jpg" alt="" class="wp-image-15343" width="523" height="351" srcset="https://www.momoyama-usagi.com/wp-content/uploads/junjo6-re-1.jpg 983w, https://www.momoyama-usagi.com/wp-content/uploads/junjo6-re-1-300x201.jpg 300w, https://www.momoyama-usagi.com/wp-content/uploads/junjo6-re-1-768x516.jpg 768w" /></figure>



<h3 class="wp-block-heading">Step2. 両立性が成り立つ (ひとまとめに出来る可能性がある) 状態のペアを探す</h3>



<p>前回の（Don't Careが含まれない）順序回路では、等価となる状態（ひとまとめにできる状態）の組み合わせをグループ分けすることで求めていきましたね。</p>



<p>しかし、Don't Careが含まれる場合は「単にグループ分けするだけ」では等価となる状態を見つけることができません<span class="footnote_referrer"><a tabindex="0" onclick="footnote_moveToReference_15291_19('footnote_plugin_reference_15291_19_1');" onkeypress="footnote_moveToReference_15291_19('footnote_plugin_reference_15291_19_1');" ><sup id="footnote_plugin_tooltip_15291_19_1" class="footnote_plugin_tooltip_text">[1]</sup></a><span id="footnote_plugin_tooltip_text_15291_19_1" class="footnote_tooltip">イメージとしては、単独では Don't Careのおかげでひとまとめに出来ても、ひとまとめにしたペア同士を状態遷移表に適用する際に Don't&nbsp;&#x2026; <span class="footnote_tooltip_continue"  onclick="footnote_moveToReference_15291_19('footnote_plugin_reference_15291_19_1');">Continue reading</span></span></span>。</p>


<p><span>そこで、Don't Careが含まれるような順序回路を最小化する際には、<span  style="background-image:linear-gradient(to bottom,transparent 0%,#FFF387 0%);" class="dbp-e-marker-animation y">グループ化をする前に「ひとまとめにできる可能性がある状態のペア」を下の三角表に求めていきます</span>。</span></p>
<p>ここで、「ひとまとめにできる可能性」のことを「両立性」と呼びましょう。</p>
<p><img src="https://www.momoyama-usagi.com/wp-content/uploads/junjo-6g-4.gif" alt="" width="412" height="467" class="wp-image-15381 aligncenter"></p>
<p>言い換えると、Step2では<span  style="background-image:linear-gradient(to bottom,transparent 0%,#FFF387 0%);" class="dbp-e-marker-animation y">100%ひとまとめ出来ないペアを探していく</span>作業をします。</p>






<h4 class="wp-block-heading">Step2-1. 出力を確認し、ひとまとめ出来ないペアを探す</h4>



<p>まずは、下のように「出力が異なる状態」を探すことでひとまとめに出来ないペアを探していきます<span class="footnote_referrer"><a tabindex="0" onclick="footnote_moveToReference_15291_19('footnote_plugin_reference_15291_19_2');" onkeypress="footnote_moveToReference_15291_19('footnote_plugin_reference_15291_19_2');" ><sup id="footnote_plugin_tooltip_15291_19_2" class="footnote_plugin_tooltip_text">[2]</sup></a><span id="footnote_plugin_tooltip_text_15291_19_2" class="footnote_tooltip">出力が異なる状態は、100%ひとまとめにすることはできないため。</span></span>。</p>



<p>ここで、Don't Careはワイルドカード (0, 1どちらでもOK）的な役割をすると考えてください。</p>



<figure class="wp-block-image aligncenter size-full"><img width="1356" height="717" src="https://www.momoyama-usagi.com/wp-content/uploads/D2LYKiawMuHUTMCugHZp1659239094-1659239263.gif" alt="" class="wp-image-15376"/></figure>



<h4 class="wp-block-heading">Step2-2. 三角表からひとまとめに出来ないペアを探す</h4>



<p>つぎに、三角表の×が付いていない（ひとまとめができる可能性がある）ペアに対し、「同じ入力を与えたときにひとまとめにできない（三角表で×が付いている）ペアに遷移する」ペアに×を付けていきます。</p>



<p>基本的なルールとしては</p>



<ul class="wp-block-list"><li>×が付いていない各ペアに対し、次状態の各入力ごとのペアに着目</li><li>着目した次状態のどれか1つの入力のペアでも「三角表に×が付いていれば」、現状態のペアに×を付ける</li><li>×が付いた場合、スタート地点（振り出し）に戻る</li><li>三角表の右下に到達したら終了</li></ul>



<p>となります。</p>



<figure class="wp-block-image aligncenter size-large"><img width="1024" height="563" src="https://www.momoyama-usagi.com/wp-content/uploads/junjo-g6-2-3-1024x563.jpg" alt="" class="wp-image-15372" srcset="https://www.momoyama-usagi.com/wp-content/uploads/junjo-g6-2-3-1024x563.jpg 1024w, https://www.momoyama-usagi.com/wp-content/uploads/junjo-g6-2-3-300x165.jpg 300w, https://www.momoyama-usagi.com/wp-content/uploads/junjo-g6-2-3-768x422.jpg 768w, https://www.momoyama-usagi.com/wp-content/uploads/junjo-g6-2-3-1536x844.jpg 1536w, https://www.momoyama-usagi.com/wp-content/uploads/junjo-g6-2-3.jpg 1812w" /></figure>



<figure class="wp-block-image aligncenter size-full is-resized"><img src="https://www.momoyama-usagi.com/wp-content/uploads/bandicam-2022-07-31-14-00-52-955.jpg" alt="" class="wp-image-15393" width="357" height="442" srcset="https://www.momoyama-usagi.com/wp-content/uploads/bandicam-2022-07-31-14-00-52-955.jpg 636w, https://www.momoyama-usagi.com/wp-content/uploads/bandicam-2022-07-31-14-00-52-955-242x300.jpg 242w" /><figcaption>ペアを確認する順番<br>（全パターンが網羅できれば必ずしもこの順番でなくてもOK）</figcaption></figure>



<p>ただし、</p>



<ul class="wp-block-list"><li>ペアのどちらか片方にでも X (Don't Care) が付いている場合</li><li>ペアがともに同じ状態の場合</li></ul>



<p>場合は、その入力のペアには「×」が付いていないとみなします。</p>



<figure class="wp-block-image aligncenter size-large is-resized"><img src="https://www.momoyama-usagi.com/wp-content/uploads/bandicam-2022-07-31-14-01-38-681-1014x1024.jpg" alt="" class="wp-image-15394" width="634" height="640" srcset="https://www.momoyama-usagi.com/wp-content/uploads/bandicam-2022-07-31-14-01-38-681-1014x1024.jpg 1014w, https://www.momoyama-usagi.com/wp-content/uploads/bandicam-2022-07-31-14-01-38-681-297x300.jpg 297w, https://www.momoyama-usagi.com/wp-content/uploads/bandicam-2022-07-31-14-01-38-681-150x150.jpg 150w, https://www.momoyama-usagi.com/wp-content/uploads/bandicam-2022-07-31-14-01-38-681-768x775.jpg 768w, https://www.momoyama-usagi.com/wp-content/uploads/bandicam-2022-07-31-14-01-38-681.jpg 1237w" /></figure>



<div style="height:50px" class="wp-block-spacer"></div>



<p><strong>★ 今回の状態遷移表 &amp; 三角表に適用すると…？</strong></p>



<figure class="wp-block-image aligncenter size-full is-resized"><img src="https://www.momoyama-usagi.com/wp-content/uploads/DCYIhtd6Dhjl6JVuEOr21659241717-1659241937.gif" alt="" class="wp-image-15377" width="800" height="434"/><figcaption>三角表と次状態から、三角表の×が埋まっていく様子</figcaption></figure>



<p>適用の結果、下のように三角表が求まりました。</p>



<p>この「×」が付いていない部分が両立性が成り立つ（ひとまとめに出来る可能性がある）ペアです。</p>



<figure class="wp-block-image aligncenter size-full is-resized"><img src="https://www.momoyama-usagi.com/wp-content/uploads/junjo-6g-6.gif" alt="" class="wp-image-15383" width="460" height="374"/><figcaption>三角表の完成<br>(×がないペアが両立性成立)</figcaption></figure>



<p>よって、状態群\[<br>\{ q_1, q_2 \}, \{ q_1, q_3 \}, \{ q_2 , q_3 \}, \{ q_2, q_4 \}<br>\]に両立性が成り立つ（ひとまとめに出来る可能性がある）ことがわかりました。</p>



<p>※ 両立性が成り立つ状態を \( \{ \ \ \ \} \) で表すことにします。例えば、\( a \), \( b \) に両立性が成り立つ場合は、\( \{ a,b \} \) と表記します。</p>



<h3 class="wp-block-heading">Step3. 3状態以上の両立性が成立するか確認</h3>



<p>つぎに「3状態以上に両立性が成立するか」を確認します。</p>



<p>ここで、3状態以上に両立性が成立するかの確認は次の通りです。</p>


<div class='wp-block-dbp-frame l-frame-inner is-design-inline is-frame-style-default dbp-frame has-bgcolor'><div class="dbp-frame-title">3状態以上の両立性の確認</div><div class="dbp-frame-content has-content-gap">
<ul class="wp-block-list" id="block-c52dd522-4e34-4c62-b154-7747bd65450f"><li>3状態の両立性 \( \{ a,b,c \} \) の確認<br>→ \( \{ a,b \} \), \( \{ b,c \} \), \( \{ a,c \} \) がすべて成立すること<br>（どの2状態を取ってきても両立性が成り立つこと）</li><li>4状態の両立性 \( \{ a,b,c,d \} \) の確認<br>→ \( \{ a,b,c \} \), \( \{ a,b,d \} \), \( \{ a,c,d \} \), \( \{ b,c,d \} \) がすべて成立すること<br>（どの3状態を取ってきても両立性が成り立つこと）</li><li>5状態の両立性 \( \{ a,b,c,d,e \} \) の確認<br>→ \( \{ a,b,c,d \} \), \( \{ a,b,c,e \} \), \( \{ a,b,d,e \} \), \( \{ a,c,d,e \} \), \( \{ b,c,d,e \} \) がすべて成立すること<br>→（どの4状態を取ってきても両立性が成り立つこと）</li></ul>

<p>※ 一般化すると、\( n \) 状態の両立性を確認するためには、どの \( n - 1 \) 状態を取ったとしても両立性が成り立つことが条件となる。</p>
</div></div>


<p>両立性が成立するかどうかは、下のように樹形図を書いて表現していくとわかりやすいです。</p>



<figure class="wp-block-image aligncenter size-large"><img width="1024" height="321" src="https://www.momoyama-usagi.com/wp-content/uploads/junjo6-re-7-1024x321.jpg" alt="" class="wp-image-15349" srcset="https://www.momoyama-usagi.com/wp-content/uploads/junjo6-re-7-1024x321.jpg 1024w, https://www.momoyama-usagi.com/wp-content/uploads/junjo6-re-7-300x94.jpg 300w, https://www.momoyama-usagi.com/wp-content/uploads/junjo6-re-7-768x241.jpg 768w, https://www.momoyama-usagi.com/wp-content/uploads/junjo6-re-7.jpg 1103w" /></figure>



<p>今回の場合、状態群 \( \{ q_1, q_2 \} \), \( \{ q_1, q_3 \} \), \( \{ q_2 , q_3 \} \) の両立性が成立することから、\( \{ q_1, q_2, q_3 \} \) の両立性が成り立つことが分かりますね。</p>



<h3 class="wp-block-heading">Step4. 両立性から最小化できる状態群の組み合わせを決定する</h3>



<p>つぎに、両立性が成り立つ状態（と単独の状態）から、なるべく少ない状態数で問題文の状態をすべて満足できるような組み合わせを考えます。</p>



<p>※ 組み合わせを考える際には、「両立性が成り立つ状態群（と単独の状態）」に含まれる「与えられた状態（今回の場合は \( q_0 \) ～ \( q_4 \)）」を〇で表した表を書くことをおすすめします。</p>



<figure class="wp-block-image aligncenter size-large is-resized"><img src="https://www.momoyama-usagi.com/wp-content/uploads/junjo6-re-8-852x1024.jpg" alt="" class="wp-image-15350" width="515" height="619" srcset="https://www.momoyama-usagi.com/wp-content/uploads/junjo6-re-8-852x1024.jpg 852w, https://www.momoyama-usagi.com/wp-content/uploads/junjo6-re-8-249x300.jpg 249w, https://www.momoyama-usagi.com/wp-content/uploads/junjo6-re-8-768x923.jpg 768w, https://www.momoyama-usagi.com/wp-content/uploads/junjo6-re-8.jpg 909w" /></figure>



<h4 class="wp-block-heading">Step4-1. 単独でしか満足できない状態 (必須状態) を探す</h4>



<p>実際に表を見ると、\( q_0 \) はどの状態に対しても両立性が成り立たないので、\( q_0 \) 単品は確定で必要ですね。なので、これをグループ1としましょう。</p>



<h4 class="wp-block-heading">Step4-2. 最小のグループ数で全状態を満足させる</h4>



<p>なので、残りの \( q_1 \), \( q_2 \), \( q_3 \), \( q_4 \) をなるべく少ない状態数（グループ数）で満足できるようなペアを考えてみましょう。</p>



<p>ここでは、</p>



<ol class="wp-block-list"><li>両立性が成立する状態群から1つ選択し、グループに加える<br>（なるべく多くの状態がある状態群から選ぶ）</li><li>加えたときに追加で必要な状態を「同じ入力であれば同じグループに遷移する」点で考える<ul><li>最小状態で出来そうなら完成</li><li>最小状態で出来なさそうなら、1に戻り、他の状態群を選択する</li></ul></li></ol>



<div style="height:63px" class="wp-block-spacer"></div>



<p>まずは、3状態がまとまった状態群 \( \{ q_1, q_2, q_3 \} \) をグループ2に加えてみましょう。<br>※ なるべく多くの状態がまとまったものから順にグループだと仮定していきます。</p>



<p>ここで、X (Don't Care) はワイルドカード、つまりどのグループとして扱ってもよい状態だと思ってください。</p>



<figure class="wp-block-image aligncenter size-full is-resized"><img src="https://www.momoyama-usagi.com/wp-content/uploads/junjo6-re-9.jpg" alt="" class="wp-image-15351" width="673" height="462" srcset="https://www.momoyama-usagi.com/wp-content/uploads/junjo6-re-9.jpg 949w, https://www.momoyama-usagi.com/wp-content/uploads/junjo6-re-9-300x206.jpg 300w, https://www.momoyama-usagi.com/wp-content/uploads/junjo6-re-9-768x528.jpg 768w" /></figure>



<p>ここでGroup2の色のペアを確認すると、\( x = 0 \), \( x = 1 \) のとき共に同じGroup2に遷移していることがわかりますね。</p>



<figure class="wp-block-image aligncenter size-large"><img width="1024" height="649" src="https://www.momoyama-usagi.com/wp-content/uploads/junjo6-re-10-1024x649.jpg" alt="" class="wp-image-15352" srcset="https://www.momoyama-usagi.com/wp-content/uploads/junjo6-re-10-1024x649.jpg 1024w, https://www.momoyama-usagi.com/wp-content/uploads/junjo6-re-10-300x190.jpg 300w, https://www.momoyama-usagi.com/wp-content/uploads/junjo6-re-10-768x486.jpg 768w, https://www.momoyama-usagi.com/wp-content/uploads/junjo6-re-10.jpg 1124w" /></figure>



<p>あとは、まだ追加していない \( q_4 \) をGroup3とすれば、どの状態も「同じ入力を与えたときに同じグループに遷移する」状態が作れますね。</p>



<p>（ここで、\( q_4 \) に \( x = 1 \) を入力したときの X (Don't Care) は、どのグループにしても状態数が変わらないのでそのままDon't Careとして扱います<span class="footnote_referrer"><a tabindex="0" onclick="footnote_moveToReference_15291_19('footnote_plugin_reference_15291_19_3');" onkeypress="footnote_moveToReference_15291_19('footnote_plugin_reference_15291_19_3');" ><sup id="footnote_plugin_tooltip_15291_19_3" class="footnote_plugin_tooltip_text">[3]</sup></a><span id="footnote_plugin_tooltip_text_15291_19_3" class="footnote_tooltip">もちろん具体的にGroup1, 2, 3を設定してもOKです。ただし、順序実際に回路を設計する際に少し複雑になりますが…。</span></span>。）</p>



<figure class="wp-block-image aligncenter size-full is-resized"><img src="https://www.momoyama-usagi.com/wp-content/uploads/junjo6-re-11.jpg" alt="" class="wp-image-15353" width="706" height="524" srcset="https://www.momoyama-usagi.com/wp-content/uploads/junjo6-re-11.jpg 959w, https://www.momoyama-usagi.com/wp-content/uploads/junjo6-re-11-300x223.jpg 300w, https://www.momoyama-usagi.com/wp-content/uploads/junjo6-re-11-768x570.jpg 768w" /></figure>



<h4 class="wp-block-heading">Step4-3. 各グループ内で代表状態を1つ選択し、まとめる</h4>



<p>グループが確定したら、代表状態を1つ選択してまとめましょう。</p>



<p>ここで X (Don't Care) は、他のグループの出力に合うように設定してください<span class="footnote_referrer"><a tabindex="0" onclick="footnote_moveToReference_15291_19('footnote_plugin_reference_15291_19_4');" onkeypress="footnote_moveToReference_15291_19('footnote_plugin_reference_15291_19_4');" ><sup id="footnote_plugin_tooltip_15291_19_4" class="footnote_plugin_tooltip_text">[4]</sup></a><span id="footnote_plugin_tooltip_text_15291_19_4" class="footnote_tooltip">0, 1どちらを入れても成立する場合はXのままでOKです。</span></span>。</p>



<p>今回は、下のようにまとめてみましょう<span class="footnote_referrer"><a tabindex="0" onclick="footnote_moveToReference_15291_19('footnote_plugin_reference_15291_19_5');" onkeypress="footnote_moveToReference_15291_19('footnote_plugin_reference_15291_19_5');" ><sup id="footnote_plugin_tooltip_15291_19_5" class="footnote_plugin_tooltip_text">[5]</sup></a><span id="footnote_plugin_tooltip_text_15291_19_5" class="footnote_tooltip">各グループごとに全く新しい名前（例：Group1を"1"、Group2を"2"、Group3を"3"とする）としてもOKです。</span></span>。</p>



<ul class="wp-block-list"><li><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-red-color">Group1の状態 → \( q_0 \) にまとめる</mark></li><li><mark style="background-color:rgba(0, 0, 0, 0);color:#009fff" class="has-inline-color">Group2の状態 → \( q_1 \) にまとめる</mark></li><li><mark style="background-color:rgba(0, 0, 0, 0);color:#439c35" class="has-inline-color">Group3の状態 → \( q_4 \) にまとめる</mark></li></ul>



<figure class="wp-block-image aligncenter size-large"><img width="1024" height="507" src="https://www.momoyama-usagi.com/wp-content/uploads/junjo6-re-16-1024x507.jpg" alt="" class="wp-image-15358" srcset="https://www.momoyama-usagi.com/wp-content/uploads/junjo6-re-16-1024x507.jpg 1024w, https://www.momoyama-usagi.com/wp-content/uploads/junjo6-re-16-300x149.jpg 300w, https://www.momoyama-usagi.com/wp-content/uploads/junjo6-re-16-768x380.jpg 768w, https://www.momoyama-usagi.com/wp-content/uploads/junjo6-re-16-1536x760.jpg 1536w, https://www.momoyama-usagi.com/wp-content/uploads/junjo6-re-16-2048x1014.jpg 2048w" /></figure>



<h3 class="wp-block-heading">Step5. Step4で書いた状態遷移表を状態遷移図にする</h3>



<p>あとは、状態遷移表を状態遷移図に落とし込めば完成です！</p>



<p>（ここで Don't Careがある場合には表記に気を付けましょう。今回の例の場合、\( q_4 \) から \( x = 1 \) を入力としたときの遷移が存在しない点に注意が必要です。</p>



<figure class="wp-block-image aligncenter size-large is-resized"><img src="https://www.momoyama-usagi.com/wp-content/uploads/junjo6-re-13-1024x963.jpg" alt="" class="wp-image-15355" width="631" height="593" srcset="https://www.momoyama-usagi.com/wp-content/uploads/junjo6-re-13-1024x963.jpg 1024w, https://www.momoyama-usagi.com/wp-content/uploads/junjo6-re-13-300x282.jpg 300w, https://www.momoyama-usagi.com/wp-content/uploads/junjo6-re-13-768x722.jpg 768w, https://www.momoyama-usagi.com/wp-content/uploads/junjo6-re-13.jpg 1097w" /></figure>







<h2 class="wp-block-heading">3. グループ分けの際の補足 [Step4-2]</h2>



<p>例題のStep4-2で行った「状態郡を組み合わせたグループ分け」について、2点補足をしておきます。</p>



<h4 class="wp-block-heading">[補足1] 状態が複数グループに属してもOK</h4>



<p>与えられた状態をすべて満足するように状態群を選べていれば、状態が複数グループに属していてもOKです。</p>



<p>例えば、状態群から\[<br> \textcolor{red}{ \{ q_0 \} } ,  \textcolor{blue}{ \{ q_1, q_2, q_3 \} }, \textcolor{green}{ \{ q_2, q_4 \} }<br>\]と選択し、それぞれ</p>



<ul class="wp-block-list"><li><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-red-color">\( q_0 \) → Group1</mark></li><li><mark style="background-color:rgba(0, 0, 0, 0);color:#009fff" class="has-inline-color">\( q_1, q_2, q_3 \) → Group2</mark></li><li><mark style="background-color:rgba(0, 0, 0, 0);color:#439c35" class="has-inline-color">\( q_2, q_4 \) → Group3</mark></li></ul>



<p>とした場合、\( q_2 \) がGroup2, 3両方に属しますが、全状態が1回以上出てきているのでOKです。</p>



<p>ただしこの場合、</p>



<ul class="wp-block-list"><li>2つ以上のグループに属する状態は、グループごとに現状態を記述する</li><li>次状態に出てくる状態が2つ以上のグループに属する場合、<strong><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-light-red-color">各状態ごとに</mark></strong>都合のいい方を選択する</li></ul>



<p>ことに注意してください。</p>



<figure class="wp-block-image aligncenter size-large"><img width="1024" height="587" src="https://www.momoyama-usagi.com/wp-content/uploads/junjo6-re-15-1024x587.jpg" alt="" class="wp-image-15357" srcset="https://www.momoyama-usagi.com/wp-content/uploads/junjo6-re-15-1024x587.jpg 1024w, https://www.momoyama-usagi.com/wp-content/uploads/junjo6-re-15-300x172.jpg 300w, https://www.momoyama-usagi.com/wp-content/uploads/junjo6-re-15-768x440.jpg 768w, https://www.momoyama-usagi.com/wp-content/uploads/junjo6-re-15.jpg 1308w" /></figure>



<p>あとは、Group2, 3両方に属する \( q_2 \) に対して都合のいい方を選んでから、代表状態を選び、まとめればOKです。</p>



<figure class="wp-block-image aligncenter size-large"><img width="1024" height="507" src="https://www.momoyama-usagi.com/wp-content/uploads/junjo6-re-16-1024x507.jpg" alt="" class="wp-image-15358" srcset="https://www.momoyama-usagi.com/wp-content/uploads/junjo6-re-16-1024x507.jpg 1024w, https://www.momoyama-usagi.com/wp-content/uploads/junjo6-re-16-300x149.jpg 300w, https://www.momoyama-usagi.com/wp-content/uploads/junjo6-re-16-768x380.jpg 768w, https://www.momoyama-usagi.com/wp-content/uploads/junjo6-re-16-1536x760.jpg 1536w, https://www.momoyama-usagi.com/wp-content/uploads/junjo6-re-16-2048x1014.jpg 2048w" /></figure>



<h4 class="wp-block-heading">[補足2] グループ分けが1発でうまくいかない場合</h4>



<p>両立性はあくまでも「1つにまとめられる可能性」なので、選んだ状態群によっては、1発でグループ分けがうまくいかないことがあります。</p>



<p>例えば今回の例題の場合、\( \{ q_0 \} \) に加えて、状態群から \( \{ q_1, q_3 \} \), \( \{ q_2, q_4 \} \) の合計3状態で最小化できそうかと思うかもしれません。</p>



<p>しかし、実際に\( \{ q_1, q_3 \} \) をグループに加えてみると、最低でも \( \{ q_1, q_2 \} \) および \( \{ q_2, q_4 \} \) を加える必要があることがわかります<span class="footnote_referrer"><a tabindex="0" onclick="footnote_moveToReference_15291_19('footnote_plugin_reference_15291_19_6');" onkeypress="footnote_moveToReference_15291_19('footnote_plugin_reference_15291_19_6');" ><sup id="footnote_plugin_tooltip_15291_19_6" class="footnote_plugin_tooltip_text">[6]</sup></a><span id="footnote_plugin_tooltip_text_15291_19_6" class="footnote_tooltip">\( q_1, q_3 \) の入力 \( x = 1 \) に着目すると、\( (q_1, q_2) \) が出てくるため、最低でもこのペアは同じ状態に属せるように状態 \( \{ q_1, q_2 \} \)&nbsp;&#x2026; <span class="footnote_tooltip_continue"  onclick="footnote_moveToReference_15291_19('footnote_plugin_reference_15291_19_6');">Continue reading</span></span></span>。</p>



<p>そのため、\( \{ q_0 \} \), \( \{ q_1, q_3 \} \), \( \{ q_2, q_4 \} \) を使った最小化は出来ない（最低でもこれら3つの状態に加えて1つ別の状態が必要）なことがわかります。</p>



<figure class="wp-block-image aligncenter size-full"><img width="984" height="685" src="https://www.momoyama-usagi.com/wp-content/uploads/junjo6-re-14.jpg" alt="" class="wp-image-15356" srcset="https://www.momoyama-usagi.com/wp-content/uploads/junjo6-re-14.jpg 984w, https://www.momoyama-usagi.com/wp-content/uploads/junjo6-re-14-300x209.jpg 300w, https://www.momoyama-usagi.com/wp-content/uploads/junjo6-re-14-768x535.jpg 768w" /></figure>



<div style="height:100px" class="wp-block-spacer"></div>



<h2 class="wp-block-heading">4. 練習問題にチャレンジ</h2>



<p>それでは、不完全指定順序回路の最小化の練習を、例題より少し複雑な問題でしてみましょう。</p>


<div class='wp-block-dbp-frame l-frame-float is-design-onframe is-frame-style-default dbp-frame has-bgcolor'><div class="dbp-frame-title">練習問題</div><div class="dbp-frame-content has-content-gap">
<p>次の状態遷移表で表されるを不完全指定順序回路の状態数が最小になるように（最小化）し、状態遷移図の形で答えなさい。</p>

<figure class="wp-block-image aligncenter size-full"><img width="889" height="550" src="https://www.momoyama-usagi.com/wp-content/uploads/junjo6-19.jpg" alt="" class="wp-image-15313" srcset="https://www.momoyama-usagi.com/wp-content/uploads/junjo6-19.jpg 889w, https://www.momoyama-usagi.com/wp-content/uploads/junjo6-19-300x186.jpg 300w, https://www.momoyama-usagi.com/wp-content/uploads/junjo6-19-768x475.jpg 768w" /><figcaption>状態遷移表</figcaption></figure>

<p>※1 X は Don't Careを表す<br>※2 表の 00, 01, 10, 11は2変数の入力を表す</p>
</div></div>


<div style="height:53px" class="wp-block-spacer"></div>



<p><strong>[解説]</strong></p>



<p>今回は、最初から状態遷移表が与えられているので、Step1は不要です。</p>



<h3 class="wp-block-heading">Step2. 両立性が成り立つペアを探す</h3>



<h4 class="wp-block-heading">Step2-1. 出力の組み合わせから両立性が成り立たないペアを見つける</h4>



<p>まずは、出力に着目しながら両立性が成り立たないペアを見つけて行きましょう。</p>



<p>※ X (Don't Care) はワイルドカードなので、0, 1どちらか片方を入れて成り立てばOKです。</p>



<figure class="wp-block-image aligncenter size-full"><img width="1761" height="776" src="https://www.momoyama-usagi.com/wp-content/uploads/bSnpkWlk7ldrmXhkRl581659240151-1659240268.gif" alt="" class="wp-image-15375"/></figure>



<p>すると、三角表は下のようになります。</p>



<figure class="wp-block-image aligncenter size-full is-resized"><img src="https://www.momoyama-usagi.com/wp-content/uploads/junjo-6g-7.gif" alt="" class="wp-image-15384" width="342" height="278"/></figure>



<h4 class="wp-block-heading">Step2-2. 三角表からひとまとめに出来ないペアを探す</h4>



<p>つぎに、「次状態の入力と三角表」に着目しながら両立性が成り立たないペアを探しましょう。</p>



<p>具体的には、</p>



<ul class="wp-block-list"><li>×が付いていない各ペアに対し、次状態の各入力ごとのペアに着目</li><li>着目した次状態のどれか1つの入力のペアでも「三角表に×が付いていれば」、現状態のペアに×を付ける</li><li>×が付いた場合、スタート地点（振り出し）に戻る</li></ul>



<p>を「三角表の右下」に到達するまで続けます。</p>



<figure class="wp-block-image aligncenter size-full"><img width="1761" height="891" src="https://www.momoyama-usagi.com/wp-content/uploads/OV3uxGKHd0iXi67Du6OS1659241007-1659241474.gif" alt="" class="wp-image-15380"/><figcaption>三角表と各入力ごとの次状態から両立性が成り立たないペアを探す様子</figcaption></figure>



<p>※ スペースの関係上、X (Don't Care) とペアになっている部分には [Don't Care] の代わりに [wild] と表記しています。</p>



<div style="height:40px" class="wp-block-spacer"></div>



<p>すると、三角表は下のようになります。</p>



<figure class="wp-block-image aligncenter size-full is-resized"><img src="https://www.momoyama-usagi.com/wp-content/uploads/junjo-6g-8.gif" alt="" class="wp-image-15385" width="350" height="284"/></figure>



<p>つまり、×がついていない\[<br>\{ q_0 , q_1 \}, \{ q_0, q_3 \}, \{ q_1, q_4 \}, \{ q_2, q_3 \}, \{ q_2, q_4 \}, \{ q_3, q_4 \}<br>\]の状態郡が両立性を持つペアとなります。</p>



<h3 class="wp-block-heading">Step3. 3状態以上の両立性が成立するか確認</h3>



<p>つぎに、3状態以上の状態群でも両立性が成立するかどうかを樹形図を書くなどで確認しましょう。</p>



<figure class="wp-block-image aligncenter size-large"><img width="1024" height="290" src="https://www.momoyama-usagi.com/wp-content/uploads/junjo6-21-1024x290.jpg" alt="" class="wp-image-15315" srcset="https://www.momoyama-usagi.com/wp-content/uploads/junjo6-21-1024x290.jpg 1024w, https://www.momoyama-usagi.com/wp-content/uploads/junjo6-21-300x85.jpg 300w, https://www.momoyama-usagi.com/wp-content/uploads/junjo6-21-768x217.jpg 768w, https://www.momoyama-usagi.com/wp-content/uploads/junjo6-21.jpg 1303w" /></figure>



<p>今回は \( \{ q_2, q_3 \} \), \( \{ q_2, q_4 \} \), \( \{ q_3, q_4 \} \) に両立性が成立するので、\( \{ q_2, q_3, q_4 \} \) の3状態ある状態群に対して両立性が成立します。</p>



<h3 class="wp-block-heading">Step4. 両立性から最小化できる状態群の組み合わせを決定する</h3>



<h4 class="wp-block-heading">Step4-1. 単独でしか満足できない状態 (必須状態) を探す</h4>



<p>表を書くことでもわかるのですが、今回は \( q_0 \) ～ \( q_4 \) 単独でしか満足できない状態はありません。</p>



<figure class="wp-block-image aligncenter size-large is-resized"><img src="https://www.momoyama-usagi.com/wp-content/uploads/junjo6-22-800x1024.jpg" alt="" class="wp-image-15316" width="506" height="648" srcset="https://www.momoyama-usagi.com/wp-content/uploads/junjo6-22-800x1024.jpg 800w, https://www.momoyama-usagi.com/wp-content/uploads/junjo6-22-234x300.jpg 234w, https://www.momoyama-usagi.com/wp-content/uploads/junjo6-22-768x983.jpg 768w, https://www.momoyama-usagi.com/wp-content/uploads/junjo6-22.jpg 940w" /></figure>



<p>そのため、\( q_0 \) ～ \( q_4 \) を最小の状態数で満足させることを Step4-2 で考えます。</p>



<h4 class="wp-block-heading">Step4-2. 最小のグループ数で全状態を満足させる</h4>



<p>まず真っ先に</p>



<ul class="wp-block-list"><li>3状態ある状態群 \( \{ q_2, q_3, q_4 \} \) をGroup1とする</li><li>残りの \( \{ q_0, q_1 \} \) がGroup2になってくれればいいな</li></ul>



<p>が思いつくと思います。（この組み合わせなら2状態で表現できますし。）</p>



<div style="height:49px" class="wp-block-spacer"></div>



<p>なので、<mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-red-color">\( \{ q_2, q_3, q_4 \} \) </mark>をGroup1とし、各入力00, 01, 10, 11ごとの遷移先を確認しましょう。</p>



<p>すると、</p>



<ul class="wp-block-list"><li>00が入力のとき：Group1の状態から「\( q_4 \), \( q_1 \) に遷移する」<br>→<mark style="background-color:rgba(0, 0, 0, 0);color:#009fff" class="has-inline-color"> \( \{ q_0, q_1 \} \)</mark> を別グループ (Group2) として追加が必要</li><li>10が入力のとき：Group1の状態から「\( q_0 \), \( q_1 \) に遷移する」<br>→ <mark style="background-color:rgba(0, 0, 0, 0);color:#48aa39" class="has-inline-color">\( \{ q_1, q_4 \} \)</mark> を別グループ (Group3) として追加が必要</li></ul>



<p>となるため、最低でも3グループが必要となることがわかりますね。</p>



<figure class="wp-block-image aligncenter size-large"><img width="1024" height="634" src="https://www.momoyama-usagi.com/wp-content/uploads/junjo-6g-12-1024x634.gif" alt="" class="wp-image-15476" srcset="https://www.momoyama-usagi.com/wp-content/uploads/junjo-6g-12-1024x634.gif 1024w, https://www.momoyama-usagi.com/wp-content/uploads/junjo-6g-12-300x186.gif 300w, https://www.momoyama-usagi.com/wp-content/uploads/junjo-6g-12-768x476.gif 768w" /></figure>



<p>さらに、Group2 \( \{ q_0, q_1 \} \) から各入力00, 01, 10, 11ごとの遷移先を確認します。</p>



<p>すると、入力10, 11のときに \( q_0 \), \( q_3 \) に遷移するので、<mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-light-orange-color"> \( \{ q_0, q_3 \} \)</mark> も別グループ (Group4) として追加する必要があります。</p>



<figure class="wp-block-image aligncenter size-large"><img width="1024" height="600" src="https://www.momoyama-usagi.com/wp-content/uploads/junjo-6g-11-1024x600.gif" alt="" class="wp-image-15475" srcset="https://www.momoyama-usagi.com/wp-content/uploads/junjo-6g-11-1024x600.gif 1024w, https://www.momoyama-usagi.com/wp-content/uploads/junjo-6g-11-300x176.gif 300w, https://www.momoyama-usagi.com/wp-content/uploads/junjo-6g-11-768x450.gif 768w" /></figure>



<p>この時点で4グループ出てきてしまっているため、いったん \( \{ q_2, q_3, q_4 \} \) をグループに加えた場合は保留します。</p>



<div style="height:45px" class="wp-block-spacer"></div>



<p>代わりに、今度は \( \{ q_0, q_1 \} \) をGroup1としてみましょう。</p>



<p>すると、入力10, 11のときに \( q_0 \), \( q_3 \) に遷移するので、<mark style="background-color:rgba(0, 0, 0, 0);color:#009fff" class="has-inline-color"> \( \{ q_0, q_3 \} \)</mark> を同じ状態にするためにGroup2に加えましょう。</p>



<figure class="wp-block-image aligncenter size-large is-resized"><img src="https://www.momoyama-usagi.com/wp-content/uploads/junjo6-24-1024x603.jpg" alt="" class="wp-image-15318" width="697" height="410" srcset="https://www.momoyama-usagi.com/wp-content/uploads/junjo6-24-1024x603.jpg 1024w, https://www.momoyama-usagi.com/wp-content/uploads/junjo6-24-300x177.jpg 300w, https://www.momoyama-usagi.com/wp-content/uploads/junjo6-24-768x452.jpg 768w, https://www.momoyama-usagi.com/wp-content/uploads/junjo6-24.jpg 1215w" /></figure>



<p>今度は、<mark style="background-color:rgba(0, 0, 0, 0);color:#009fff" class="has-inline-color">\( \{ q_0, q_3 \} \)[Group2]</mark> の次状態に着目しましょう。</p>



<p>すると、入力00のときに \( q_2 \), \( q_4 \) に遷移するので、<mark style="background-color:rgba(0, 0, 0, 0);color:#48aa39" class="has-inline-color">\( \{ q_2, q_4 \} \)</mark> を同じ状態にするためにGroup3に加えます。</p>



<figure class="wp-block-image aligncenter size-large is-resized"><img src="https://www.momoyama-usagi.com/wp-content/uploads/junjo6-25-1024x649.jpg" alt="" class="wp-image-15319" width="673" height="427" srcset="https://www.momoyama-usagi.com/wp-content/uploads/junjo6-25-1024x649.jpg 1024w, https://www.momoyama-usagi.com/wp-content/uploads/junjo6-25-300x190.jpg 300w, https://www.momoyama-usagi.com/wp-content/uploads/junjo6-25-768x487.jpg 768w, https://www.momoyama-usagi.com/wp-content/uploads/junjo6-25.jpg 1215w" /></figure>



<p>さらに <mark style="background-color:rgba(0, 0, 0, 0);color:#48aa39" class="has-inline-color">\( \{ q_2, q_4 \} \) [Group3]</mark> の次状態に着目しましょう。</p>



<p>すると、00, 01, 10, 11どの入力をしたときも必ず Group1, Group2, Group3 の組み合わせ（もしくはDon't Careが片方にでもある）状態となっていますね。</p>



<figure class="wp-block-image aligncenter size-large"><img width="1024" height="739" src="https://www.momoyama-usagi.com/wp-content/uploads/junjo-6g-13-1024x739.gif" alt="" class="wp-image-15491" srcset="https://www.momoyama-usagi.com/wp-content/uploads/junjo-6g-13-1024x739.gif 1024w, https://www.momoyama-usagi.com/wp-content/uploads/junjo-6g-13-300x216.gif 300w, https://www.momoyama-usagi.com/wp-content/uploads/junjo-6g-13-768x554.gif 768w" /></figure>



<p>そのため、</p>



<ul class="wp-block-list"><li><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-red-color">Group1: \( \{ q_0, q_1 \} \)</mark></li><li><mark style="background-color:rgba(0, 0, 0, 0);color:#009fff" class="has-inline-color">Group2: \( \{ q_0, q_3 \} \)</mark></li><li><mark style="background-color:rgba(0, 0, 0, 0);color:#48aa39" class="has-inline-color">Group3: \( \{ q_2, q_4 \} \)</mark></li></ul>



<p>とした3状態に最小化が可能です。</p>



<h4 class="wp-block-heading">Step4-3. 各グループ内で代表状態を1つ選択し、まとめる</h4>



<p>あとは、下の表をグループごとにまとめればOKです。<br>（事前に同じグループの出力を一致させるために X に何を入れればよいかを小さく記入しています）</p>



<figure class="wp-block-image aligncenter size-large is-resized"><img src="https://www.momoyama-usagi.com/wp-content/uploads/junjo-6g-14-1024x892.gif" alt="" class="wp-image-15492" width="665" height="579" srcset="https://www.momoyama-usagi.com/wp-content/uploads/junjo-6g-14-1024x892.gif 1024w, https://www.momoyama-usagi.com/wp-content/uploads/junjo-6g-14-300x261.gif 300w, https://www.momoyama-usagi.com/wp-content/uploads/junjo-6g-14-768x669.gif 768w" /><figcaption>Before（圧縮前）</figcaption></figure>



<p>具体的には、</p>



<ul class="wp-block-list"><li><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-red-color">Group1: \( \{ q_0, q_1 \} \) → 代表 \( q_0 \)</mark> </li><li><mark style="background-color:rgba(0, 0, 0, 0);color:#009fff" class="has-inline-color">Group2: \( \{ q_0, q_3 \} \) → 代表 \( q_3 \)</mark></li><li><mark style="background-color:rgba(0, 0, 0, 0);color:#48aa39" class="has-inline-color">Group3: \( \{ q_2, q_4 \} \) → 代表 \( q_4 \)</mark></li></ul>



<p>と代表を決め、出力部分の X (Don’t Care) の値を決定してから状態遷移表を作成すればOKです。</p>



<figure class="wp-block-image aligncenter size-full"><img width="995" height="490" src="https://www.momoyama-usagi.com/wp-content/uploads/junjo-6g-15.gif" alt="" class="wp-image-15497"/><figcaption>After [圧縮後]</figcaption></figure>



<h3 class="wp-block-heading">Step5. 状態遷移図に変換する</h3>



<p>あとは、Step4-3で作った状態遷移表を状態遷移図に変換すればOKです。</p>



<figure class="wp-block-image aligncenter size-large"><img width="968" height="1024" src="https://www.momoyama-usagi.com/wp-content/uploads/junjo6-27-968x1024.jpg" alt="" class="wp-image-15321" srcset="https://www.momoyama-usagi.com/wp-content/uploads/junjo6-27-968x1024.jpg 968w, https://www.momoyama-usagi.com/wp-content/uploads/junjo6-27-284x300.jpg 284w, https://www.momoyama-usagi.com/wp-content/uploads/junjo6-27-768x813.jpg 768w, https://www.momoyama-usagi.com/wp-content/uploads/junjo6-27.jpg 1086w" /></figure>



<div style="height:100px" class="wp-block-spacer"></div>



<h2 class="wp-block-heading">5. さいごに</h2>



<p>今回は順序回路の状態遷移図に X [Don't Care] が含まれる不完全指定順序回路の状態最小化についてみていきました。</p>



<p>通常の順路回路の状態最小化より難易度が少し高く、理解が難しい部分ですがこの記事を見て理解の助けになれば幸いです。</p>



<div style="height:33px" class="wp-block-spacer"></div>



<p>これにて、順序回路に関する記事は全て終了です！　今まで見てくださり、ありがとうございましたm(__)m</p>



<p class="has-small-font-size">（工業大学生ももやまのうさぎ塾では、「うさぎでもわかる」をモットーに様々な大学数学系・情報系の科目を解説しています。なので、もし他の理系科目でわからないなと思うことがあれば、「(分野名) (単元名) うさぎ」などと是非調べてみてください。きっと、理解の助けになる私の記事が出てくるかなと思います。）</p>



<div style="height:100px" class="wp-block-spacer"></div>



<h2 class="wp-block-heading">6. 参考文献</h2>



<p>近畿大学 - 順序回路の状態数の最小化<br>[アクセス日: 2022/07/31]</p>



<p><a href="https://www.info.kindai.ac.jp/LC/lecture/LogicCircuits12note.pdf">https://www.info.kindai.ac.jp/LC/lecture/LogicCircuits12note.pdf</a></p>
<div class="speaker-mute footnotes_reference_container"> <div class="footnote_container_prepare"><p><span tabindex="0" class="footnote_reference_container_label pointer">注釈</span><span tabindex="0" class="footnote_reference_container_collapse_button" style="display: none;">[<a id="footnote_reference_container_collapse_button_15291_19">+</a>]</span></p></div> <div id="footnote_references_container_15291_19"><table class="footnotes_table footnote-reference-container"><caption class="accessibility">注釈</caption> <tbody> 

<tr class="footnotes_plugin_reference_row"> <th scope="row" class="footnote_plugin_index_combi pointer"  onclick="footnote_moveToAnchor_15291_19('footnote_plugin_tooltip_15291_19_1');"><a id="footnote_plugin_reference_15291_19_1" class="footnote_backlink"><span class="footnote_index_arrow">&#8593;</span>1</a></th> <td class="footnote_plugin_text">イメージとしては、単独では Don't Careのおかげでひとまとめに出来ても、ひとまとめにしたペア同士を状態遷移表に適用する際に Don't Careが干渉し、2種類のペアをひとまとめに出来ない可能性があるからです。</td></tr>

<tr class="footnotes_plugin_reference_row"> <th scope="row" class="footnote_plugin_index_combi pointer"  onclick="footnote_moveToAnchor_15291_19('footnote_plugin_tooltip_15291_19_2');"><a id="footnote_plugin_reference_15291_19_2" class="footnote_backlink"><span class="footnote_index_arrow">&#8593;</span>2</a></th> <td class="footnote_plugin_text">出力が異なる状態は、100%ひとまとめにすることはできないため。</td></tr>

<tr class="footnotes_plugin_reference_row"> <th scope="row" class="footnote_plugin_index_combi pointer"  onclick="footnote_moveToAnchor_15291_19('footnote_plugin_tooltip_15291_19_3');"><a id="footnote_plugin_reference_15291_19_3" class="footnote_backlink"><span class="footnote_index_arrow">&#8593;</span>3</a></th> <td class="footnote_plugin_text">もちろん具体的にGroup1, 2, 3を設定してもOKです。ただし、順序実際に回路を設計する際に少し複雑になりますが…。</td></tr>

<tr class="footnotes_plugin_reference_row"> <th scope="row" class="footnote_plugin_index_combi pointer"  onclick="footnote_moveToAnchor_15291_19('footnote_plugin_tooltip_15291_19_4');"><a id="footnote_plugin_reference_15291_19_4" class="footnote_backlink"><span class="footnote_index_arrow">&#8593;</span>4</a></th> <td class="footnote_plugin_text">0, 1どちらを入れても成立する場合はXのままでOKです。</td></tr>

<tr class="footnotes_plugin_reference_row"> <th scope="row" class="footnote_plugin_index_combi pointer"  onclick="footnote_moveToAnchor_15291_19('footnote_plugin_tooltip_15291_19_5');"><a id="footnote_plugin_reference_15291_19_5" class="footnote_backlink"><span class="footnote_index_arrow">&#8593;</span>5</a></th> <td class="footnote_plugin_text">各グループごとに全く新しい名前（例：Group1を"1"、Group2を"2"、Group3を"3"とする）としてもOKです。</td></tr>

<tr class="footnotes_plugin_reference_row"> <th scope="row" class="footnote_plugin_index_combi pointer"  onclick="footnote_moveToAnchor_15291_19('footnote_plugin_tooltip_15291_19_6');"><a id="footnote_plugin_reference_15291_19_6" class="footnote_backlink"><span class="footnote_index_arrow">&#8593;</span>6</a></th> <td class="footnote_plugin_text"> \( q_1, q_3 \) の入力 \( x = 1 \) に着目すると、\( (q_1, q_2) \) が出てくるため、最低でもこのペアは同じ状態に属せるように状態 \( \{ q_1, q_2 \} \) を新しいグループとして追加する必要がある。また、\( \{q_2, q_4 \} \) がまだ満足していないため、\{ q_2, q_4 \} \) も新しいグループとして追加する必要がある。</td></tr>

 </tbody> </table> </div></div>]]></content:encoded>
					
					<wfw:commentRss>https://www.momoyama-usagi.com/entry/info-junjo6/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
