改め Objective Technician

はぐれ技術者のやりたい放題

これぞ情報科学

2009-01-30 00:36:28 | プログラミング
接尾辞木(Suffix Tree)を作って高速に文字列照合する自作Javaプログラム。

再帰使いまくり。


import java.util.*;

public class SuffixTreeGenerator {

	//すべての接尾辞
	static Vector<String> all_suffixes = new Vector<String>();

	//接尾辞木オートマトンのルート
	static State root = new State(State.ROOT);


	public static void main(String[] args) {

		try {

			//全ての接尾辞を取得
			next_suffix(args[0]);

			//接尾辞木を構成
			prefix_grouping(all_suffixes, root, null, "");

			//接尾辞木を表示
			System.out.println("nSuffix Tree for string "" + args[0] + ""n");
			root.scan(0);
			System.out.println("nPattern Matching...");

			//文字列照合
			for(int i = 1; i <args.length; i++)<br>
				System.out.println(args[i] + " : " + (root.is_subsequence(args[i]) ? "yes" : "no"));

		}catch(ArrayIndexOutOfBoundsException e) {
			System.out.println("使い方:java SuffxTreeGenerator text pattern0 pattern1 pattern2 ... ");
			System.exit(1);
		}
	}


	//接尾辞を得る再帰関数
	static void next_suffix(String org) {
		if(org.equals(""))
			return;

		//頭文字を取り除いた文字列で再帰
		next_suffix(org.substring(1));
		all_suffixes.addElement(org);
	}


	//接尾辞木を構成する再帰関数
	static void prefix_grouping(Vector<String> suffixes, State current_state, State pre_state, String pre_key) {

		Hashtable<Character, Vector<String>> prefix_map = new Hashtable<Character, Vector<String>>();

		//頭文字が共通の文字列ごとに分ける
		initial_letter_grouping(suffixes, prefix_map);

		//木を構成(この中で再帰呼び出し)
		construct_tree(prefix_map, current_state);

		//枝分かれしていない枝をまとめる
		if(current_state.func.size() == 1)
			compress(current_state, pre_key, pre_state);
	}


	//枝分かれしていない枝をまとめる
	static void compress(State current_state, String pre_key, State pre_state) {

		String key = current_state.func.keys().nextElement();
		pre_state.add_func(pre_key + key, current_state.func.get(key));

		pre_state.func.remove(pre_key);
		current_state.func.clear();
	}


	//接尾辞木を構成
	static void construct_tree(Hashtable<Character, Vector<String>> prefix_map, State current_state) {

		Enumeration<Character> e = prefix_map.keys();
		while(e.hasMoreElements()) {
			Character common_char = e.nextElement();

			//共通の頭文字がなかった場合はそこから先を全部まとめる
			if(prefix_map.get(common_char).size() == 1)
				current_state.add_func(common_char.toString() + prefix_map.get(common_char).firstElement(), new State(State.LEAF));

			//あった場合は頭文字を束ねて先を再帰
			else {
				State next_state = new State(State.NODE);
				current_state.add_func(common_char.toString(), next_state);

				prefix_map.get(common_char).removeElement("");
				prefix_grouping(prefix_map.get(common_char), next_state, current_state, common_char.toString());
			}
		}
	}


	//頭文字が共通の文字列ごとに分ける
	static void initial_letter_grouping(Vector<String> suffixes, Hashtable<Character, Vector<String>> prefix_map) {

		Enumeration<String> e = suffixes.elements();
		while(e.hasMoreElements()) {
			String sequence = e.nextElement();

			//頭文字をキーとして文字列のマップを作成
			if(prefix_map.containsKey(sequence.charAt(0)))
				prefix_map.get(sequence.charAt(0)).addElement(sequence.substring(1));

			else {
				Vector<String> group = new Vector<String>();
				group.addElement(sequence.substring(1));
				prefix_map.put(sequence.charAt(0), group);
			}
		}
	}
}


//オートマトンの一状態
class State {

	static final int ROOT = 0;
	static final int NODE = 1;
	static final int LEAF = 2;

	//(入力系列、行き先)の組み合わせのテーブル
	Hashtable<String, State> func = null;

	//この状態の種類
	int status;

	State(int status) {
		this.status = status;

		if(status != State.LEAF)
			this.func = new Hashtable<String, State>();
	}

	//行き先を追加
	void add_func(String input, State destination) {
		this.func.put(input, destination);
	}


	//構造を深さ優先でスキャン、表示
	void scan(int depth) {

		if(this.status == State.LEAF) {
			return;
		}

		Enumeration<String> e = this.func.keys();
		while(e.hasMoreElements()) {
			String key = e.nextElement();

			System.out.print(" - " + key + "t");
			this.func.get(key).scan(depth + 1);
			System.out.println();
			for(int i = 0; i <depth; i++)<br>
				System.out.print("t");
		}
	}


	//索引構造をたどって文字列照合をする再帰関数
	boolean is_subsequence(String pattern) {

		boolean subseq = false;

		Enumeration<String> e = this.func.keys();
		while(e.hasMoreElements()) {
			String key = e.nextElement();

			int min_length = Math.min(key.length(), pattern.length());
			if(pattern.substring(0, min_length).equals(key.substring(0, min_length))) {

				if(key.length() >= pattern.length())
					return true;

				else if(this.func.get(key).status == State.LEAF)
					return false;

				else
					subseq = this.func.get(key).is_subsequence(pattern.substring(min_length));
			}
		}

		return subseq;
	}
}









再帰は情報科学の真髄だと思う。


情報科学ってナンデスカって聞かれたら、僕の場合「データ」と「情報」と「知識」の違いを説明して、それから再帰とか帰納とか分割統治とかの方法の威力を熱く語る。

再帰の記述能力は凄まじく、それでいてシンプルで美しい。




でも、ループで書けるところをわざわざ凝って何でも再帰で書くようになったらそれは病気だと思う。










また科目合格

2009-01-29 21:34:10 | 陸上競技
1月19日(Mon) 瑞鳳 星空 暖

jog
ストレッチ
坂ダッシュ
100m×3
80m×4
50m×5
jog
鉄棒振り上げ×5
c-donw


1月23日(Fri) 評定 曇

jog
ストレッチ
ドリル
鉄棒


1月24日(Sat) 評定 星空 涼

ハイスピードjog
ストレッチ
ドリル
100m流し×3
50mバウンディング×3
振り上げ逆上がり×5
c-down



1月27日(Tue) 評定 星空 涼

ハイスピードjog
ストレッチ
ドリル
ポール操作
踏み切り
ポール走100m×5
バウンディング50m×5
鉄棒振り上げ逆上がり×5
150m流し
c-down


1月29日(Thu) 評定 曇 涼

jog
ストレッチ
ドリル
ポール操作
ポール走
メディシン投げ
バウンディング
鉄棒振り上げ
流し
c-down



いろんなタスクが一気に押し寄せてきた1月が終わろうとしている…

まだ残ってるのがあるけどなんとか山は越えた…。




学会のあと日曜に受けた資格試験の自己採点。

今回受けた2科目のうち法規だけ合格して、4科目中残すはあと1科目になった。

前回受けたときに法規をなめてて確率レベルの点数を喰らったから、ムキになってがんばって勉強して今回は合格ライン余裕だったけど、その分専門がまだ準備不足だった…



今度こそ徹底的にやって合格してやる!



でもこの資格取っても自分の研究とは全然関係ない。

そもそも研究者になるんだったら国家資格とか全然意味ない。


でもせっかくここまでやったからあと少し頑張ろうと思う。
意味ないけど。




そういえば、試験前にケータイの電源切って机の上に置けって言われたとき、受験生の半数がケータイを2個以上持ってた。

一瞬だけ、なんか自分が場違いなんじゃないかと思ってしまった。

実に面白い

2009-01-22 21:50:48 | 勉強
学会二日目

今回発表したのと別で平行して進めてるテーマで、僕の考えを暗に支持する発表を聞いた。


帰ったらすぐに確かめよう。



あとは、会場にプロジェクタが二台あって同じ画面が横に並んで二か所に映されてるから、それを交差法で両眼融合して「小さいディスプレイが顔の前に浮いて見えてるぜ」みたいなことをして話を聴きながら遊んでた。










そういえば、自転車に乗りながら大福を食べてる女性とすれ違った。


すげぇ…



思わず二度見してしまった。


学会発表

2009-01-21 22:18:47 | 勉強
面白がってくれる人が一人でもいればいいなぁ、ぐらいに思ってたけど、それなりに話に首を突っ込んでくれる人がいっぱいいて嬉しかった。

短い時間だったけど奥の深い質問(狙ってた質問)が結構な数来たおかげで、考えてたことをほぼ全部はき出せた。

と思う。



僕の発表で興味の対象にしてるキーワードが、今回の学会でやたらいろんな人の話に出てきてビクビクしてるけど、どうも自分の結果と矛盾する内容ではないようだ。

もしかして流行の最先端?



いや、それはカン違いだ。



半ズボンでいることの10のメリット

2009-01-19 00:36:40 | 自転車
雪が降っても半ズボンでいる人の主張。



1:自転車のチェーンでズボンの裾が汚れる心配をしなくていい
ズボン裾を括るツールがないことはないけど動きにくいしめんどい。半ズボンのほうがよっぽど楽。


2:冬でも太らない
薄着だから体重が増えないのか。身軽だから薄着するのか。卵かニワトリかの問題だと思うけど前者の効果は確実にある。


3:注目を浴びる
街を歩くと結構見られる。たぶん絶対に変な人だと思われてる。


4:エアコンがいらなくなる
体感温度が気温の変化にすごくロバストになる。仙台に来てから部屋に一人でいるときは一回も暖房冷房つけたことがない。


5:はみ出してるぜ!という気分になれる。

でも「生足」って言うなよコンチクショウ。


6:以下省略






でも、「変」と言うのは簡単だけど、変わってることをするのは結構エネルギーがいるんです。





午前0時の参道

2009-01-18 23:47:59 | 陸上競技
1月17日(Sat) 評定 晴 涼

jog
ストレッチ
ドリル
メディシン投げ
ポール操作
鉄棒ぶら下がり
振り上げ逆上がり×10
流し×6

c-down



1月18日(Sun) 瑞鳳 曇 涼

研究室帰り
jog
坂ダッシュ100m×3
c-down



明後日の学会発表のことで頭がいっぱい。

いっぱい予行練習したけど、あと50回ぐらい練習しておきたい。


今回見せる結果の生データを改めてあれこれいじってたら、この発表間際になって今まで気づかなかった事実を偶然発見してしまって、しかもかなりクリアに出てて話の大筋と矛盾しないからそれも発表に加えようか、でも論点がずれるから辞めとこうか…




先週、鬼玉に送ったメールが読まれた。
しかも念願の月曜日に!

自分のネタが公共の電波に乗って埼玉のラジオで流れてたと思うとドキドキする。


宮城に居ながらほぼリアルタイムでnack5を聴けるシステムを組んであるから、研究室で仕事しながらマル決参戦が可能。


実に快適だ。




明日も参戦してまた読んでもらえたら新事実も話そうか。読まれなくてもやっぱり発表に加えることにしようそうしよう。



∀x ∃y [p(x, y)] と ∃y ∀x [p(x, y)] の違い

2009-01-12 23:16:04 | 陸上競技
1月8日(Wed) 愛宕 曇 涼

行きjog
ストレッチ
モモ上げ
おんぶ
etc.
帰りjog
c-down


1月10日(Sat) 評定 晴 寒

jog
ストレッチ
ポール操作
鉄棒ぶら下がり右ひじ伸ばし
150mWS×5
振り上げ逆上がり
c-down


1月12日(Mon) 評定 星 暖

jog
ストレッチ
ドリル
150mWS×5
鉄棒ぶら下がり健康法
鉄棒振り上げ逆上がり
バウンディング50m×3
c-down

脱臼後初めて振り上げ逆上がりやった。






∀x ∃y [p(x, y)]:任意のxに対して、p(x, y) を満たすあるyが存在する。…①

∃y ∀x [p(x, y)]:あるyが存在して、このとき任意のxで p(x, y) が充足可能。…②


①と②の違い。

①:敵がどんな攻撃を仕掛けてきてもそれぞれに返し技がある。

②:必殺技を持っていて、これを出してしまえば敵は対処する術がない。




陸上競技で言えば、

①:個人それぞれにベストな練習方法や最適なフォームがある。

②:この練習さえやってれば誰でも速くなれるという万能な練習手段が存在する。




研究で言えば、

①:どんな結果が出ても何らかの説明が与えられる。

②:究極の理論があって、どんな現象もそれに従う。




なんか違う気がするけど…




どうやら世の中は①と②の比率が 99.9:0.1 ぐらいになってるみたいだと思う。


でも、②を目指しながらも①で地道に試行錯誤し続けるしかないのだと思う。



その境地がこれだと思う。







新年の目標

2009-01-06 00:01:09 | ムダ話
「目標」が「今年中に目標を達成しないこと」であるとき、目標の達成は可能か否か。























「目標」を x(t) とおく。ここで t は離散時間変数であり、単位は [日] とする。 x(t) は、元日の0:00時から起算してちょうど t [日] 経過した瞬間に目標が達成されていた場合に 1 を、そうでない場合に 0 を返すブール変数である。ここで、目標は時刻 t に非依存なタスクであるとする。


初期状態で目標は達成されておらず、将来に一度達成すれば再び未達成状態に遷移することがないという制限を与えた場合、 x(t) はある正の整数 T を用いて一般に以下の式で表現できる。


x(t) = { 0 (0≦t<T); 1 (T≦t) …①



すると「今年中に目標を達成する」ことの必要十分条件は 0≦T<365 であるから、これを y(T) とおいて

y(T)= { 1 (0≦T<365); 0 (365≦T)

と書ける。

「今年中に目標を達成しない」は ¬y(T)である。

¬y(T) = { 0 (0≦T<365); 1 (365≦T) …②


仮定:「目標」が「今年中に目標を達成しないこと」である.より

x(t) = ¬y(T)

が成立する。このとき①と②が同値であることから

T = 365 …③

が導かれる。これは「今年中に目標を達成する」ことの必要十分条件(0≦T<365)を満たさないので許容解である。




以上の推論は離散時間の単位を半分ずつ細かくしていき、 [日] の間でも変数が値を持つように条件を設定しても成り立つ。

時間刻み幅を極限まで小さくしたとき、③の意味することは「目標達成の瞬間は新年のその年から次の年への年越しの一瞬(T=365)に行われなければならない」となる。

任意のε(>0)に対して時刻 365±ε で目標が達成されていることが観測されるような解は不可である。


したがって唯一の許容解(T=365)が存在し、この一瞬で目標を達成するという制約の下で「今年中に目標を達成しないという目標」は実行可能である。






以上の話を場合分けして時系列で追うと次のようになる。


0≦T<365 の場合:


初期状態は
x(0) = 0;
¬y(T) = (不定);
観測時が t ( <T) で、今年中に目標が達成されるという事象が不定の場合はy(T)はどちらの値をとってもよく、ただ条件(x(t) = ¬y(T))を満たす ¬y(T) (=0) が存在するのでこの段階では許容。 時刻 t = T で目標を達成すると x(t) = 1 となり、一方で ¬y(T) が 0 に定まり、ここでx(t) ≠ ¬y(T) であるので不可。



365<T の場合:


初期状態は
x(0) = 0;
¬y(T) = (不定);
で、先と同じ理由で許容。

時刻 t = 365 でまだ目標を達成していないので x(365) = 0 であるが、この時点で ¬y(T) = 1 に定まって x(t) ≠ ¬y(T) だから不可。



T=365 の場合:


初期状態は
x(0) = 0;
¬y(T) = (不定);
で許容。

初期状態は任意のε(0<ε≪1)に対して時刻 t = 365 - ε まで継続する。

時刻 t = 365 の瞬間で目標が達成されるので x(365) = 1 で、同時に年内には目標が達成されなかったので ¬y(T) = 1 に定まる。

区間 365 <t でも x(t) = ¬y(T) = 1 であり、したがってどの区間でも x(t) = ¬y(T) が成立している。



つまり t = 365 の瞬間に目標を達成することが「今年中に目標を達成しないという目標」を達成するための唯一の方法であるが、現実問題としてなにをどうすればそんなことができるのかは知らん。


例えば「目標」が「年が明けた瞬間に地球上にいないこと」だとしても、これは時刻に依存するタスクだからダメ。




論理的には可能でも現実的にたぶん無理。

「現実的に無理」の反例が思いつかない。



タスクが山のようだ

2009-01-05 21:58:14 | 陸上競技
年末年始の素行


12月25日(Thu) 評定 快晴 暖

jog
ストレッチ
ドリル
メディシン投げ
メディシンバウンディング
バウンディング
鉄棒ぶら下がり

c-down
 

12月27日(Sat) 曇 寒

自宅-研究室
往復jog

12月28日(Sun) 雪 寒

昨日と同じ


12月31日(Mon) U高校 曇 涼

晦日サッカー
今年もO橋先輩と競った


1月1日(Tue) 中学校周辺 星空 涼

30'jog

1月2日(Fri) 中学校周辺 夕焼 暖

40'jog


1月4日(Sun) 評定 曇 涼

jog
ストレッチ
ドリル
150mWS×5
鉄棒ぶら下がり

c-down


1月5日(Mon) 評定 曇 涼

jog
ストレッチ
ドリル
メディシン投げ
ポール操作
鉄棒ぶら下がり右ひじストレッチ

c-down


 
long jogやると腰が痛痒くなるようになった。






1月は…

学会のポスター完成させて発表練習やって

別の研究会の原稿書きと追加実験やって

共同研究の実験計画を考えつつ同時に探索的にデータ取りを進めて

国家試験の準備もして

授業の最終レポートがたぶん複数個あって

ゼミの資料も作って





とりあえず、帰省中に論文2本読んで資格勉強を進めた。



Yes, we can!






話がつながらないけど、帰省の最後の日にお台場の科学未来館に行った。

テレポート駅の発車音が大捜査線のテーマだった。


真下警部が撃たれた現場付近。



エンディングでみんなが走ってることろ(?)



テレビ局


未来館




ものすごく俊敏に動いてボールをキャッチするロボットアームに感動した。

画像処理と軌道計算とアーム動作の完了まで、人間業をはるかに超えている。


いつかヨーヨーを操るロボットアームが開発されて、ループとか出来るようになったらすごいと思う。

たぶん、ロボットにヨーヨーのルーピングをやらせるのはボールジャグリングをやらせるよりも格段に難しい。

例えば、ビラりそうになったときに軌道を修正するのはどうやって実装するのか。

糸の張力と視覚のフィードバックをどうやって使うのか。

学習でできるようになるとすれば、機械でもリバースループとか出来てしまうのか。



まだあるけどまぁいいや。




ミュージアムショップでこんなの買った。





これでライバルに差をつけろ!