リムナンテスは愉快な気分

徒然なるままに、言語、数学、音楽、プログラミング、時々人生についての記事を書きます

【Tone.js】絶対和音感を鍛えるアプリで四和音を出題する

前々回と前回はこちら。

limnanthaceae.hatenablog.com
limnanthaceae.hatenablog.com


今回の完成形はこんな感じ。

f:id:frecafloros:20210430231052p:plain

チェックリストの作成

出題する和音の種類を選択できるようにします。
の前に和音のピッチクラスを再整理します。

// chord の pitch class
const chordTypes = [
	// triad
	{'chordName': '', 'chordKeys': [0,4,7]},
	{'chordName': 'm', 'chordKeys': [0,3,7]},
	{'chordName': 'dim', 'chordKeys': [0,3,6]},
	{'chordName': 'aug', 'chordKeys': [0,4,8]},
	{'chordName': 'sus4', 'chordKeys': [0,5,7]},
	{'chordName': 'sus2', 'chordKeys': [0,2,7]},
	// tetrad
	{'chordName': '7', 'chordKeys': [0,4,7,10]},
	{'chordName': 'm7', 'chordKeys': [0,3,7,10]},
	{'chordName': 'M7', 'chordKeys': [0,4,7,11]},
	{'chordName': 'mM7', 'chordKeys': [0,3,7,11]},
	{'chordName': 'm7b5', 'chordKeys': [0,3,6,10]},
	{'chordName': 'dim7', 'chordKeys': [0,3,6,9]},
	{'chordName': 'aug7', 'chordKeys': [0,4,8,10]},
	{'chordName': 'augM7', 'chordKeys': [0,4,8,11]},
	{'chordName': '6', 'chordKeys': [0,4,7,9]},
	{'chordName': 'm6', 'chordKeys': [0,3,7,9]},
	{'chordName': 'add9', 'chordKeys': [0,2,4,7]},
	//pentad
	{'chordName': '9', 'chordKeys': [0,2,4,7,10]},
	{'chordName': 'm9', 'chordKeys': [0,2,3,7,10]},
	{'chordName': '7(b9)', 'chordKeys': [0,1,4,7,10]},
	{'chordName': 'm7(b9)', 'chordKeys': [0,1,3,7,10]},
	{'chordName': '7(#9)', 'chordKeys': [0,3,4,7,10]},
	{'chordName': 'm7(11)', 'chordKeys': [0,3,5,7,10]},
	{'chordName': '7(#11)', 'chordKeys': [0,4,6,7,10]},
	{'chordName': '7(13)', 'chordKeys': [0,4,7,9,10]},
	{'chordName': 'm7(13)', 'chordKeys': [0,3,7,9,10]},
]

思いつく限りを放り込みました。triad=三和音、tetrad=四和音、pentad=五和音です(古典音楽理論でtetradとかpentadとか言わないと思いますがtriadと揃えて造語しました)。本当は11とか13とか六和音とかありますが、ちょっと面倒なので今後機会があれば実装することにします。

htmlのチェックボックスの方では、上のリストに対応する値を設定します。

<div class="config">
	<dl>
		<dt><label><input type="checkbox" id="checkTriad">三和音:</label></dt>
		<dd>
			<label><input type="checkbox" name="chordval" value=0>(M)</label>
			<label><input type="checkbox" name="chordval" value=1>m</label>
			<label><input type="checkbox" name="chordval" value=2>dim</label>
			<label><input type="checkbox" name="chordval" value=3>aug</label>
			<label><input type="checkbox" name="chordval" value=4>sus4</label>
			<label><input type="checkbox" name="chordval" value=5>sus2</label>
		</dd>
	</dl>
	<dl>
		<dt><label><input type="checkbox" id="checkTetrad">四和音:</label></dt>
		<dd>
			<label><input type="checkbox" name="chordval" value=6>7</label>
			<label><input type="checkbox" name="chordval" value=7>m7</label>
			<label><input type="checkbox" name="chordval" value=8>M7</label>
			<label><input type="checkbox" name="chordval" value=9>mM7</label>
			<label><input type="checkbox" name="chordval" value=10>m7b5</label>
			<label><input type="checkbox" name="chordval" value=11>dim7</label>
			<label><input type="checkbox" name="chordval" value=12>aug7</label>
			<label><input type="checkbox" name="chordval" value=13>augM7</label>
			<label><input type="checkbox" name="chordval" value=14>6</label>
			<label><input type="checkbox" name="chordval" value=15>m6</label>
			<label><input type="checkbox" name="chordval" value=16>add9</label>
		</dd>
	</dl>
	<dl>
		<dt><label><input type="checkbox" id="checkPentad">五和音:</label></dt>
		<dd>
			<label><input type="checkbox" name="chordval" value=17>9</label>
			<label><input type="checkbox" name="chordval" value=18>m9</label>
			<label><input type="checkbox" name="chordval" value=19>7(b9)</label>
			<label><input type="checkbox" name="chordval" value=20>m7(b9)</label>
			<label><input type="checkbox" name="chordval" value=21>7(#9)</label>
			<label><input type="checkbox" name="chordval" value=22>m7(11)</label>
			<label><input type="checkbox" name="chordval" value=23>7(#11)</label>
			<label><input type="checkbox" name="chordval" value=24>7(13)</label>
			<label><input type="checkbox" name="chordval" value=25>m7(13)</label>
		</dd>
	</dl>
</div>

全選択できるように、「三和音」・「四和音」・「五和音」の横にもチェックボックスをつけておきます。例えば「三和音」をクリックすると三和音の全てにチェックが入るような仕様にする予定。

リスト型で作ってますが、cssの設定はdl、dt、ddに対して

dl{
	display: flex;
	margin: 0;
}

dt{
	font-weight: bold;
	width: 30%;
}

dd{
	margin: 0;
	display: inline-block;
	width: 70%;
}

です。dt(三和音・四和音・五和音)とdd(m、m7、etc.)の描画エリアの比が3:7になるようにしています。



See the Pen
chordtrainer-08
by frecafloros (@frecafloros)
on CodePen.


今はただの飾りですが。

単にチェックボックスをつけるだけなら<input type="checkbox"...>だけで十分なのですが、これだとチェックボックスからテキストが分離して改行されてしまう場合があります。これを回避するために<label>タグを使っています。<label>タグを使う利点は主に2つで、テキスト回り込みを回避することに加えて、テキストをクリックすることでもチェックが入れられることです。

<label>タグ自体のcss

label{
	white-space: nowrap;
}

で指定します。これでテキストが改行されなくなります。

選んだ種類の和音をランダムに選ぶ

どの和音がチェックされているかを取得→値をリストにスタック→乱数出す→スタックしたリストの値を使ってコード参照

の手順でやっていこうかなと思います。

その前に、三四五和音のチェックボックスの処理から行います。チェックされていたら該当の和音全部チェック入れる、チェックが外れたら全部消す、という処理をまず始めます。

三和音のところの要素はgetElementByIdで、(M)やmなどの具体的な和音はnameでグループ化しているのでgetElementsByNameで探すことができます。addEventListenerを使うとチェックボックスがon/offになるタイミングを感知することができるのでこいつを使います。チェックボックスはonがtrueでoffがfalseになっているので、下のようにfor文を回して処理していきます。

const checkTriad = document.getElementById("checkTriad");
const chordval = document.getElementsByName("chordval");

checkTriad.addEventListener("click", ()=>{
	if(checkTriad.checked){
		for(let i=0;i<=5;i++){
			chordval[i].checked = true;
		}
	}else{
		for(let i=0;i<=5;i++){
			chordval[i].checked = false;
		}
	}
});

四和音、五和音も同様に。(全選択した後にどこか一つの和音のチェックボックスを切っても、三・四・五和音のチェックボックスがonのままになってしまいますがいつか直します。)(よく考えたらonchangeでいいような…?)


続いて、「次の問題」ボタンが押されたら、onになっているチェックボックスを検知して値(value)をリストにぶっ込みます。値を取得してcheckChordTypes配列にひたすらプッシュ。

// checkbox 検知
checkChordTypes = [];
for(let i=0;i<chordval.length;i++){
	if(chordval[i].checked == true){
		checkChordTypes.push(chordval[i].value);
	}
}

そうするとチェックされたところの値だけをぶっこんだcheckChordTypes = [0,2,3,5,7]のような配列ができるので、この配列のindexを乱数回して指定します。例えば乱数で3が出たらcheckChordTypes[3]つまり5が選ばれた和音の種類、という算段。(一つも選択されてないときのエラー判定書いてないのでこの時多分バグる。あとで抽選しないように直す。)

chordNum = checkChordTypes[randomInt(0,checkChordTypes.length)];



See the Pen
chordtrainer-09
by frecafloros (@frecafloros)
on CodePen.


ひとまず実装したい機能は全部積めたので、ここらで終了にしたいと思います。
気が向いた時にバグ取り、ビジュアル面の強化、24平均律の和音などに手を出していこうかなと考えています。

【p5.js】絶対和音感アプリの見た目をどうにかする(左半分)

limnanthaceae.hatenablog.com


これの続きです。


どうにかします。
毎回CSSを勉強しては忘れるを繰り返しているのでちゃんと記録しようと思います。
(あと最初にCSS勉強した時のfloatとかtableとかで頑張ってた時代の先入観が抜けない)


この記事での完成形はこんな感じです。

f:id:frecafloros:20210429002941p:plain

右半分に設定(次回作る、と思う)と問題送りや答えの表示などの制御ボタン、左半分にコードと構成音の表示をするという形にします。

領域の整理

htmlを整形します。

<div class="container">
	<div class="obj-left">
		<div class="figure">figure</div>
		<div class="obj-chord">chord: <span id="chordname-txt"></span></div>
	</div>
	<div class="obj-right">
		<div class="config">config</div>
		<div class="c">
			<button class="btn-sound" onclick="buttonSound();">和音再生</button>
		</div>
		<div class="c">
			<button class="btn-answer" onclick="buttonAnswer();">答えの表示</button>
		</div>
		<div class="c">
			<button class="btn-next" onclick="buttonNext();">次の問題</button>
	</div>
</div>


中央寄せ、flexbox
flexbox使いながらmargin: auto;しても中央に行かないので注意

.container{
	display: flex;
	justify-content: center;
}

さて、ビジュアル面を作るためにp5.jsというライブラリを使っていきます。

function setup(){
  createCanvas(300,300).parent('chord-constellation');
  background('skyblue');
}

createCanvas()で描画領域を作成します。これだけでも動きますが、parent()でidを指定すると特定のdiv要素に作ったり複数作ったりすることができます。

下のデモでは分かりやすくするため背景色をbackground('skyblue')(水色)で塗ってあります。


See the Pen
chordtrainer-05
by frecafloros (@frecafloros)
on CodePen.


音の分布

chord constellation(日本語訳がわからない)を描画します。

f:id:frecafloros:20210429003813p:plain

これです。

前節で作ったsetup()にわちゃわちゃ追加していきましょう。
まず、音名を円状に等間隔で並べます。

translate(canvasWidth/2, canvasHeight/2);
const r = 80;
for(let i=0;i<12;i++){
  text(pitch2keyname[i], r*sin(i*TAU/12), -1*r*cos(i*TAU/12));

関数を扱いやすくするために、translate()で座標原点を移動させます。デフォルトは描画領域の左上角が座標原点になりますが、translate(canvasWidth/2, canvasHeight/2)とすると座標原点が描画領域の中央に移動します。

後ろのfor文で0番目のキー=Cから時計回りに音名を並べます。text()を使うと文字を突っ込むことができるのですが、第1引数がテキスト内容、第2引数が横の座標、第3引数が縦の座標だと思います。多分。

円状に並べるので三角関数を使います。sin()とかcos()にはデフォルトでrad(ラジアン)を突っ込むようになっているはずです。p5.jsでTAU=\tau=2\piが使えるので大変便利。


続いて、テキストの細かい設定をします。

textAlign(CENTER,CENTER);
textSize(16);
textFont('Optima');

textAlign()は基準点とテキスト配置の位置関係を表します。textAlign(CENTER,CENTER)なら、基準点はテキストボックスの中央になります。

textSize()で文字の大きさ(px)を指定します。px以外にも指定できるかもしれないけど調べてない。今回は16 pxで作成します。

textFont()で文字のフォントを指定します。デザイン性重視でOptimaを使用。多分webフォントというやつで、特にPCに入ってなくても表示される…と思う。


解答ボタンを押すと和音分布を表す棒が表示されるようにします。

// constellation の棒描画
const l = 50;
let tmpPitch = rootPc;

strokeWeight(2);
stroke(0);
line(0, 0, l*sin(tmpPitch*TAU/12), -1*l*cos(tmpPitch*TAU/12));

strokeWeight(1);
stroke(127);
for(let i=1;i<chord.length;i++){
  tmpPitch = rootPc + chordTypes[chordNum]['chordKeys'][i];
  line(0, 0, l*sin(tmpPitch*TAU/12), -1*l*cos(tmpPitch*TAU/12));
}

line()に直線の起終点の座標を与えると線が引けます。今回は根音だけ線を太く濃くしたいので、そこだけ他とは別に描画しました。


あと流石に300x300はでかすぎたので描画領域を200x200にリサイズ。


See the Pen
chordtrainer-06
by frecafloros (@frecafloros)
on CodePen.


コード名の表示

javascriptでhtmlを操作します。

<div class="obj-left">
	<div id="chord-constellation" class="figure"></div>
	<div class="obj-chord">
		<div id="chordname-txt">
			<span class="chord-name" id="chordname-1"></span><br>
			<span class="chord-element" id="chordname-2"></span>
		</div>
	</div>
</div>


解答ボタンを押したらコードネームを表示するようにします。
javascriptの側で、htmlの要素(ここではspan)にcssのclassを動的に追加します。このclassを予めcssの側で設定しておくことで、cssの適用をon / offで切り替えすることができます。

// chord name表示
targetName = document.getElementById("chordname-txt");
targetName.classList.add("chord-icon");
targetName.classList.add("orange");



See the Pen
chordtrainer-07
by frecafloros (@frecafloros)
on CodePen.


続き。

limnanthaceae.hatenablog.com

【Tone.js】絶対和音感を鍛えるアプリを作る

コード進行を耳コピしたいのに音がわからない…ということはありませんか?
というわけで和音を聞き取る特訓ができるアプリを作ります。tone.jsというライブラリを使うとブラウザ上で音を出すことができるようですので、これを使います。

基本設計

  1. スタートボタンを押すと和音が流れる
  2. 答え合わせボタンを押すと和音のコード名が表示される


というシンプルな構成にしようと思います。あんまり理想が高すぎると完成しないので。

1つ目の「スタートボタンを押すと和音が流れる」は、あらかじめ用意しておいた和音リストからランダムに選択し、和音を流す。2つ目の「答え合わせボタンを押すと和音のコード名が表示される」は、'Cm'や'Eaugadd9'といったようなコード名が最低限、将来的にはピッチクラス、構成音名、半音圏上の図示ができるようになればいいなぁ、くらいの気持ちです。

単音を鳴らす

Tone.jsはWeb Audio APIというやつを簡単に操作できるように作成されたJSのライブラリらしいです。

早速Tone.jsをインポートします。htmlのヘッダーに以下の記述を入れるとTone.jsが使えるようになります。

<script>https://cdnjs.cloudflare.com/ajax/libs/tone/14.8.15/Tone.js</script>

手始めに単音を鳴らします。練習として、ボタンを押すと「ラ」の音(220Hz)が八分音符の長さだけ流れるようにします。

let buttonStart = () => {
	const synth = new Tone.Synth().toDestination();
	synth.triggerAttackRelease("A3", "8n");	
};

デフォルトは多分120BPM(=1分間に四分音符が120拍の速さ)だと思います。

new Tone.Synth().toDestination()シンセサイザーを生成します。以降このシンセ(=オブジェクト)に対して操作をするような感じ。
triggerAttackRelease()は音を鳴らし(Attack)て止める(Release)までの一連の動作をやってくれます。第一引数はA3やC4などの音高を指定、第二引数は音の長さを指定します。音の長さは四分音符なら4n、八分音符なら8n、といった勝手です。

スタートボタンを押すとA3(220Hz)の音が流れるはずです。(スマホ等の場合はResultを押してから)


See the Pen
chordtrainer-01
by frecafloros (@frecafloros)
on CodePen.


和音を鳴らす

和音を鳴らします。ただのSynth()はmonosynthっぽいので代わりにPolySynth()を使います。PolySynth()以外で和音出せるのかは謎。

原理的には、前段の"A3"の代わりに["A3", "C4", "E4"]のようなコード構成音の配列を入れることで和音を鳴らします。

let buttonStart = () => {
	const synth = new Tone.PolySynth().toDestination();
	synth.triggerAttackRelease(["A3", "C4", "E4"], "8n");	
};

これでAmの和音が鳴る。

ついでに、今後の拡張性を考えて、根音(のピッチクラス)とコードの種類からコード構成音を自動生成できるようにします。

// scale
const scale = [
	'C3', 'C#3', 'D3', 'D#3', 'E3', 'F3', 'F#3', 'G3', 'G#3', 'A3', 'A#3', 'B3',
	'C4', 'C#4', 'D4', 'D#4', 'E4', 'F4', 'F#4', 'G4', 'G#4', 'A4', 'A#4', 'B4',
	'C5', 'C#5', 'D5', 'D#5', 'E5', 'F5', 'F#5', 'G5', 'G#5', 'A5', 'A#5', 'B5'
];

// chord の pitch class
const chordTypes = [
	{'chordName':'M', 'chordKeys': [0,4,7]},
	{'chordName':'m', 'chordKeys': [0,3,7]},
	{'chordName':'dim', 'chordKeys': [0,3,6]},
	{'chordName':'aug', 'chordKeys': [0,4,8]}
];

まずスケールですが、転回形を今後加えることを考えて一応3オクターブ分用意します。根音はC3からB3までのどれかを選択する感じで。コードのタイプはとりあえず三和音のメジャー、マイナー、dim、augを用意します。もろもろの都合により、辞書のリストになってます。そのうち増やす。

和音の配列を生成するために、ルート音とコード音からスケールの音を拾ってきてスタックしていきます。

// 和音生成
chord = [];
for (let j=0;j<chordTypes[2]['chordKeys'].length; j++){
	let pitch = scale[6+chordTypes[2]['chordKeys'][j]];
	chord.push(pitch);
}

上の例では、スケールの6番目(F#3)から+0番目、+4番目、+6番目(dimの配列)を拾ってきて音のリストを作っています。したがって完成したリストは["F#3", "A3", "C4"]となるはず。

下のデモでスタートボタンを押すとF#dimが鳴るはずです。


See the Pen
chordtrainer-02
by frecafloros (@frecafloros)
on CodePen.

ランダムに和音を鳴らす

絶対和音感を鍛えたいので、ランダムに和音が出題されてほしいです。なのでボタンをクリックしたときにどの和音を鳴らすかを乱数で決めます。

JavaScriptの乱数生成は[0, 1)を生成する関数しかない?ようなので、ランダムに整数値を吐き出す関数を作ります。

// 乱数生成器
let randomInt = (min, max) => {
	// 返値はmin以上max未満の整数
	min = Math.ceil(min);
	max = Math.floor(max);
	return Math.floor(Math.random() * (max - min) + min);
};

この関数はmin以上max未満の整数値をランダムで返します。
根音は12種類のうちから、コードは4種類のうちから1つずつ選びます。

スタートボタンを押すと和音がランダムに鳴るようになっていると思います。


See the Pen
chordtrainer-03
by frecafloros (@frecafloros)
on CodePen.


コードネームを表示する

「答えを表示」で今鳴っている和音のコードネームを表示させます。といっても前段で生成した乱数を元にテキスト化するだけです。

テキストをhtmlに流し込むにはgetElementById()を使って場所の指定をします。また、流し込むテキストの内容はinnerHTMLに代入する形で実現できます。

// chord name表示
targetName = document.getElementById("chordname-txt");
targetName.innerHTML = pitch2keyname[rootPc] + chordTypes[chordNum]['chordName'];

rootPcは根音のピッチクラス(0から11までの整数値)、chordNumは和音の構成を選択する値です。例えばchordNum=0はメジャーコードに対応しています。

下のデモでは、「次の問題」でまた別の和音をランダムに選択し鳴らします。「答えを表示」を押すと、CmF#dimといったような形で和音のコードネームが表示されるはずです。選ばれた和音は「和音再生」で何度も聞くことができます。


See the Pen
chordtrainer-04
by frecafloros (@frecafloros)
on CodePen.


とりあえず素体は出来たので、(細かいところが少し気にはなりますが)四和音などに拡張する前にUIをどうにかしたいですね。



続き

limnanthaceae.hatenablog.com

12平均律に飽きてしまった前衛的なみなさんに送るn平均律動画集(重いです)

12平均律はオワコン!時代はn平均律

1-11平均律

特に1-4平均律の曲はこの動画以外でみたことがない。
www.youtube.com

1平均律

と思っていたらあった。
Edolian - Cohesion (1EDO) - YouTube

結局のところプライベートを充足させれば社畜を回避できるのではないだろうか

表題の通り。つれづれなるままに書き散らします。



1日の定時労働時間は8時間…と見せかけて拘束時間が9時間。通勤時間が前後にあるので少なくとも1日あたり11時間を資本家に差し出すことでお賃金をもらうのが現代の奴隷労働者。残業がある場合は捧げる時間がさらに増えるわけですが。



もともと8時間労働というのは産業革命時代の産物である。当時の労働者は時間の限り働かされていたが、「8時間労働し、8時間睡眠、8時間プライベート」の元で労働時間のupperが8時間となった。

なんかそうやって聞くとプライベートが8時間もあるじゃんと思いつつも、でも実感として8時間もプライベートない。あるいは8時間も寝てる時間がないというのが率直な感想だと思う。通勤時間や昼休憩でプライベートまたは睡眠時間が削られていくのでそれはそうなのだけれども。



人間に与えられた1日は平等に24時間。平日とかに仕事だけをしているとどうなるかというと、人生が仕事一色になるという悲劇が発生します。ワーカーホリックになりたくない労働者階級が目指すべきは、「仕事」量と「遊び」量の体感時間を(自分が満足する状態に)調整することではないか。「仕事は適当に。遊びは真剣に。」ではないが、プライベートの可処分時間を増やして密度を上げるが、自分の思う今のところの最適解になりそうです。

そのためには、拘束時間外で極力仕事をしないようにうまくやりくりする必要がある。楽に早く60点くらいの利益を出す。多分そうすると結果的にメリハリがついて労働者としての能力も向上するのではないだろうか。これは「社会人たるもの〜」みたいな道徳ではなく、プライベートを人生の主体にするための方策である。つまり、物理的にも精神的にもプライベートを増やすのが目的であって、仕事で能力が身につくのは(我々からしたら)結果でしかない。(職務遂行能力を上げることが目的になっている言説は、労働者を使役する立場や資本家の都合がいいように言っているにすぎない。多分純粋に職務遂行能力を上げるだけだと、資本主義の奴隷になるだけ。まあ得られる結果は一緒なんですが。)

それから、「楽に働こうと思ってはいけない」みたいなことを言ってしまう奴隷の言葉には絶対に耳を貸してはいけない。むしろ楽に稼ぐための方法を常に考えるべきである。楽に働くなんて甘えだと言う人は、時間かけて苦労すれば金がもらえるという思想に甘えている。唯一楽してはいけないのは、「どうすれば楽に金を稼げるかを考える」こと。時間的にも労力的にも。あれもこれも全てはプライベートの時間を増やすためである。



仕事が楽しい人は仕事してください。自分のやりたいことが仕事になっている人も仕事してください。よく自分のやりたいことを仕事にするべき的な論調を見かけますが、やりたいことで、できることで、喜ばれることであるなんていう運のいいことはそうそうないですよ。そんな都合よく需要があるわけないじゃないですか。というわけで、自己実現はプライベートでやるという生き方に割り切ってしまってもいいんじゃあないでしょうか。仕事の成果とか成長とか富とか名誉とかが大事なのではなく、今日食べる飯とかコーヒー飲みながら本読む時間とか何となく数学する時間とか麻雀する時間を大事にする生き方、よいではないか。人類は全て墓場がゴールなんだよ。荼毘に付されたら無ですよ。この世なんて何の意味もないね。

あと個人的には、趣味を仕事にすると趣味が趣味でなくなるのが何となく嫌だなというのもある。極力趣味でやってることが仕事にも役立てるように近づけた方が効率良さそうだとは思いますけどね。



…といって開き直りすぎて仕事さぼりすぎると別の意味で奴隷になるので、

プライベートを本気で充実させる→そのために時間増やしたいから適当に仕事で成果を出すことに本気になる→そのためには拘束時間内で終わらせる精神力が必要→精神力を保つためには体力が必要→運動

という思考に持っていくのが社畜回避の方策になりうるのではないだろうか。
というわけで運動すれば万事解決。

直積と直和【環上の加群 4】

イスクイル飽きたので数学。

一次独立やらなんやらの前提。
加群加群を合成して大きい加群をつくったり、複雑な加群を小さい加群の直積や直和の形に分解する。

直積


def 4.1R可換環。2つのR-加群M_1,M_2に対して直積集合M_1\times M_2上に和とスカラー倍を(a\in Rとして)それぞれ

(x_1,x_2)+(y_1,y_2)=(x_1+y_1,x_2+y_2)
a(x_1,x_2)=(ax_1,ax_2)

と定義するとM_1\times M_2R-加群となる。これをM_1M_2の直積という。

ベクトルの和とスカラー倍と同じ。

例えば加法剰余群\mathbb{Z}/2\mathbb{Z}, \mathbb{Z}/3\mathbb{Z}\mathbb{Z}-加群ですが、これらの直積\mathbb{Z}/2\mathbb{Z}\times\mathbb{Z}/3\mathbb{Z}を考えます。例えば0,1\in\mathbb{Z}/2\mathbb{Z}, 1,2\in和は

(0,2)+(1,1)=(0+1,2+1)=(1,0)

スカラー倍は
4\cdot(1,2)=(4\cdot 1,4\cdot 2)=(0,2)

となります。\mathbb{Z}/2\mathbb{Z}\times\mathbb{Z}/3\mathbb{Z}\mathbb{Z}-加群です。

和:

f:id:frecafloros:20210306212409p:plain

スカラー倍:

f:id:frecafloros:20210306212424p:plain


実は有限個の加群の直積と直和は一致するのでM_1\times M_2=M_1\oplus M_2*1。ですが、無限個の加群の場合、直積と直和は等しくない別概念になります*2。無限個の場合を考慮した一般の場合はdef 4.2のようになります。


def 4.2R可換環R-加群の族\{M_\lambda\}_{\lambda\in\Lambda}に対して、直積集合\prod_{\lambda\in\Lambda}M_\lambdaを考える。和とスカラー倍を(a\in Rとして)それぞれ

(x_\lambda)+(y_\lambda)=(x_\lambda+y_\lambda)
a(x_\lambda)=(ax_\lambda)

と定義すると\prod_{\lambda\in\Lambda}M_\lambdaR-加群となる。これを\{M_\lambda\}_{\lambda\in\Lambda}の直積という。

(x_\lambda)」は「(x_1,x_2,\cdots)\in\prod_{\lambda\in\Lambda}M_\lambda, x_1\in M_1, x_2\in M_2,\cdots」くらいの感覚。

外部直和

直和の定義。
直和には2種類あり、めんどくさいことに外部直和内部直和がある。
「有限個の加群の直積と直和が一致する」というやつの直和は「外部直和」のこと。だと思う。というわけで外部直和の定義です。


def 4.3R-加群の族\{M_\lambda\}_{\lambda\in\Lambda}の直積\prod_{\lambda\in\Lambda}M_\lambdaの部分加法群として、
\begin{align}\bigoplus_{\lambda\in\Lambda}M_\lambda=\left\{(x_\lambda)\in\prod_{\lambda\in\Lambda}M_\lambda\middle| 有限個の\lambda を除いて x_\lambda=0\right\}\end{align}
R-加群となる。これを\{M_\lambda\}_{\lambda\in\Lambda}の(外部)直和という。

前述の通り|\Lambda|<\inftyのとき\bigoplus_{\lambda\in\Lambda}M_\lambda=\prod_{\lambda\in\Lambda}M_\lambda。「有限個の\lambdaを除いて」ということは選ぶ\lambdaは「0個」でもよいということで、有限個の加群の場合は直積と一致します。

なんでこんなめんどくさい定義の仕方をしているのかというと、普遍性がどうのこうのという話になってめんどくさいのでとりあえずスルーします。

また後述の内部直和と区別するために、こちらの外部直和を「\dot{\oplus}」(上ドット付き)などで表記する場合があります。

内部直和

内部直和の定義。
初歩的な環上の加群論では直和といえば殆ど内部直和のことらしい。

さて、なんか適当な加群Mの部分加群N_1,N_2\in Mに対して、これらの和は

N_1+N_2 = \{x_1+x_2\mid x_1\in N_1, x_2\in N_2\}

でした。このときy\in N_1+N_2y=y_1+y_2の形に一意に表される時、N_1+N_2は直和である、つまりN_1+N_2=N_1\oplus N_2と定義します。


def 4.4加群Mに対して、部分加群N_1,N_2\subset Mを考える。
y\in N_1+N_2y_1\in N_1, y_2\in N_2に対してy_1+y_2と一意に書けるとき、
N_1+N_2 = N_1 \oplus N_2


一般に、有限個の部分加群M_i\in M, (i=1,\cdots,n)の内部直和は次のように定義されます。


def 4.5MR-加群\{M_i\}_{i=1,\cdots,n}Mの部分加群の族とする。このとき、
\begin{align}\sum_{i=1}^n M_i:=\{x_1+\cdots+x_n \mid x_1\in M_1\cdots,x_n\in M_n\}\end{align}
Mの部分加群となる。もし、\sum_{i=1}^n M_iの任意の元x
x=x_1+\cdots+x_n
の形で表される時、\sum_{i=1}^n M_iは直和であるといい、
\begin{align}\sum_{i=1}^n M_i=\bigoplus_{i=1}^n M_i\end{align}
と表記する。

ある加群の部分加群で構成する(加群の「内部」で構成する)ので内部直和と呼ばれます。多分。
以降、外部直和を\dot{\oplus}、内部直和を\oplus、和を+で表記します。

このとき次の定理が成り立ちます。


prop 4.6加群Mの部分加群N_1,N_2\in Mに対して、N_1+N_2=N_1\oplus N_2のとき、
N_1\dot{\oplus} N_2\to N_1+N_2; (x_1,x_2)\mapsto x_1+x_2
全単射準同型。


prop 4.7加群Mに対して、部分加群N_1,N_2\subset Mを考える。このとき
N_1\oplus N_2 \Leftrightarrow N_1\cap N_2 = \{0\}


一般に、有限個の部分加群について次の4つは同値になります。


prop 4.8MR-加群\{M_i\}_{i=1,\cdots,n}Mの部分加群の族とする。

  1. 写像
    \begin{align}\dot{\bigoplus}_{i=1}^n M_i\to \sum_{i=1}^n M_i\end{align}
    (x_1,\cdots x_n)\mapsto x_1+\cdots+x_n
    全単射準同型。
  2. \sum_{i=1}^n M_iの任意の元xx_i\in M_iとしてx=x_1+\cdots+x_nの形に一意に表せる。
  3. x_1+\cdots+x_n=0\Rightarrow x_1=\cdots=x_n=0
  4. (M_1+\cdots+M_i)\cap M_{i+1} = \{0\}\,(i=1,\cdots,n-1)



↑初:加群の定義【環上の加群 1】 - リムナンテスは愉快な気分
←前:準同型定理(第一同型定理)【環上の加群 3】 - リムナンテスは愉快な気分
→次:自由加群【環上の加群 5】 - リムナンテスは愉快な気分

*1:むしろ上の定義を直和と呼んでしまう場合が多いようにも感じる

*2:圏論的には積と余積なので別概念かと言われると違うと思いますが

USB買って40分で「読み取り専用」になりやがったので対処

ブチギレそう
写真数十枚コピーしただけで壊れるのクソでは?殆ど使ってないんだが?

現状整理

終わったメモリ

GREEN HOUSE製64GB USBメモリ (FAT32で自動的にフォーマットされたもの)

状況

写真を何枚かMac HDD→USBメモリにコピー中に突然「読み取り専用」になった

症状

  • 読み取り専用に固定されてファイルの書き込み不可・削除も不可
  • 読み取り専用モード解除不可
  • フォーマット不可
  • 読み取り可能なのでUSB→HDDへのコピーは可能、移動は不可


64GBのメモリをFAT32でやったのがいけなかったんですかね?
返品しようにも微妙にコピー成功してる写真達が消せないので困る。データ見られたくないんですよねぇ…
とりあえずフォーマットさえ掛けられればOKなんだ…

結論

データ削除を諦めて現物交換しました。

対処

対策1 Macのディスクユーティリティで「復元」【失敗】

エラー吐いて失敗

対策2 Windows10のプロパティで読み取り専用のチェックを外す【失敗】

エラー吐いて失敗

対策3 Ubuntu 16.04のGpartedで強引にフォーマット掛ける【失敗】

既存のパーティションを削除して新しくパーティションを作るように命令。

カーネルに変更を伝えることができませんでした。おそらく、使用中だったのが原因だと思われます。そのため、古いパーティション情報がそのまま使われます。さらなる変更をする前に再起動してください。」と怒られて失敗。

対策4 Macのディスクユーティリティで「First Aid」を試す【失敗】

「終了コードは8」を吐く。いろいろ調べたら諸々の対策が出て来たので少しだけ光が見えるか?

対策5 fsck_〇〇コマンド【失敗】

ここからターミナルを叩き始める。

mice-cinemanami.hatenablog.com
komputilo.blogspot.com

上の資料によるとsudo fsck_〇〇 -fy /dev/disk〇s〇で修復できるらしい。

fsck_〇〇の〇〇の部分はsudo fstyp /dev/disk〇s〇で調べたやつを入れる。
手元のmacだと、fsck_csfsck_hfsfsck_udffsck_apfsfsck_exfatfsck_msdosが存在したので、この中のどれかだと思います。

disk〇s〇の〇s〇の部分はそのデバイス固有の数値?で、「デバイスユーティリティ」で見るかdiskutil listで確認。


…いや結局First Aidと一緒かい。同じエラーが出た。次。

何すればいいんだこれ

discussions.apple.com

ただこれによると、書き込みエラーになった時に書き込みロックされる機構が働いたらしいことはわかった。ディスクフォーマット受け付けないときはそうらしい。

本当は外部スイッチがあれば物理的にロック解除できるんだとは思うが、ないのでどうにかしてソフト的に読み取り専用を解除するしかない。

対策6 レジストリキーの修正【失敗】

(多分)Windows10のCPUのレジストリキーを直接操作して書き込みできるようにしようという作戦。

https://aprico-media.com/posts/4448

「コンピューター¥HKEY_LOCAL_MACHINE¥SYSTEM¥CurrentControlSet¥Control¥StorageDevicePolicies」にある「writeprotect」の値が「1」だと書き込み禁止になるので、「0」に修正することで書き込みできるようになる模様。

結果

「StorageDevicePolicies」がありませんでした。
というか原因はPCじゃなくてどう考えてもUSBなのでそれはそう。

「StorageDevicePolicies」がないということは、書き込み禁止の理由がレジストリのフラグではない、ということらしい。

対策7 diskpartでアクセス権限を操作【失敗】

再びhttps://aprico-media.com/posts/4448を参考に。

Windows10でなんとかしてdiskpartを実行。
コマンドプロンプトっぽいのが出てくるのでdisk listを叩いてUSBメモリのディスク番号を確認。
select disk 〇(〇はさっき確認したディスクの番号)でドライブの選択を変更。
attrib disk clear readonlyで書き込み禁止を解除できる。
無事に「ディスクの属性が正しく消去されました。」の表示。



…で書き込み禁止解除できたらとっくにできてるんですよね。意味なかった。失敗。

ただ、不可解なことが一つ。
attributes diskでディスク(USBメモリ)の状態を確認することができるのですが、なぜか「現在の読み取り専用状態」が「はい」で「読み取り専用」が「いいえ」になってた。どういうこと?

相変わらず書き込みと削除はできず。


detail.chiebukuro.yahoo.co.jp
これによると完全にUSBメモリの不具合で無理らしい。むむむ。

対策8 サードパーティのソフトを使う【失敗】

ubuntuのGpartedで受け付けないものが他のソフトで受け付けるわけがないと思うのですが。


無理でした。

結局

ヨ○バシに持って行きましたが、ヨ○バシ店員もお手上げ。
ここまでやって無理ならもう無理なので諦めましょう。

こんなハズレもう一生引かないでくれ…