Learn to Live and Live to Learn

IT(たまにビジネス)に関する記事を読んで、考えて、使ってみたことをまとめる場。

SPARQLを使ってみる。

SPARQL(スパークル)はRDBで言うSQL言語=クエリ言語です。
それを利用して、RDF(Resource Description Framework。web上にあるリソースを記述するための枠組み)
から必要な情報を取り出したいと思います。

以下は
SPARQL で RDF データを検索する
に書かれていたことを自分のような残念なやつにわかるよう書き直したものです。

こんなデータがあるとして
f:id:A_01:20140122004939g:plainf:id:A_01:20140122004939g:plain

「Jon FoobarのブログURLを取り出す」クエリです。

prefix foaf: <http://xmlns.com/foaf/0.1/>
select ?url
from <bloggers.rdf>
where {
 ?contributor foaf:name "Jon Foobar" .
 ?contributor foaf:weblog ?url .
}

一つずつ見て行きましょう。

prefix foaf: <http://xmlns.com/foaf/0.1/>

FOAFはFriend of a Friendの略で、人に関する情報とその繋がりを公開・共有するプロジェクトを指します。
prefix(接頭辞)=foafを用いることでIRI(Internationalized Resource Idetifiers。URIの集合である識別子の仕様)=http://xmlns.com/foaf/0.1/を省略します。

select ?url

urlという変数(SQLで言うカラムやフィールド)を抜き出します。
変数の頭には?か$を付けます。

from <bloggers.rdf>

使用するデータセットURIを指定しています。

where {
 ?contributor foaf:name "Jon Foobar" .
 ?contributor foaf:weblog ?url .
}

条件文です。foafはprefixで定義したものだと思います。
foaf:nameプロパティが"Jon Foobar"なノードを?contributorにバインドし(関連付けし)
?contributorにバインドされたノードのfoaf:weblogプロパティを?url変数にバインドします。
この?urlが先ほどselectしていた?urlです。

参考
http://www.asahi-net.or.jp/~ax2s-kmtn/internet/rdf/rdf-sparql-query.html

Eclipseで実行時に引数を渡す方法

public static void main(String[] args) {←このargsを受け取りたいってときの方法です。

Eclipseでコマンドライン引数を与えて実行する方法 | 学習B5デスノート
にある通りなんですが、

mainメソッドのあるファイルを右クリック
→実行
→実行の構成
→(x)= 引数タブを選択
→プログラムの引数(A): 欄に引数を記入。スペース区切りで複数与えられます。
例)

プログラムの引数(A): hoge boo

だとargs[0] = hoge、args[1] = boo。
→適用
→実行!

TDDに挑戦【Java】

TDDとはTest Driven Development(テスト駆動開発)の略です。
テストコードを書いてから実装しましょう、という開発手法です。
今回は実際にどうやるのか

バグがないプログラムのつくり方 JavaとEclipseで学ぶTDDテスト駆動開発 (Be agile!)

バグがないプログラムのつくり方 JavaとEclipseで学ぶTDDテスト駆動開発 (Be agile!)

を読みながらJavaを使用してやってみました。

TDDの流れ

(1) テストコードを書く

assertEquals(期待値, 実行するもの);

(2) 仮実装
とりあえずコンパイルが通るものを作成。
(3) テスト
テストするファイルを右クリック→実行→JUnitテスト
(4) 失敗(JUnitモジュールが赤色に)※1
(5) テストを成功させるための最小限の実装
(6) テスト
(7) 成功(緑色)
(8) Triangulation(三角測量)=テストケースの追加
(9) 失敗(赤色)
(10) すべてのテストを通過できるようリファクタリング※2
(11) テスト成功!!

※1 失敗の理由はJUnitのモジュールにある
▷Goods.java
 ▷TestGetTaxIncludedPrice.java←該当ソースコードをクリック
すると、下にある障害トレースという項目に表示されます。

※2 リファクタリングとは
・コードの重複排除
・汎用化

試した環境とソースコード

環境

Eclipse Indigo
JUnit version3.8.2
JDK

ソースコード

GoodsTest.java

import junit.framework.TestCase;

public class GoodsTest extends TestCase {

	public GoodsTest(String name) {
		super(name);
	}
	
	public void testGetGoodsPrice() {
		Goods ice = new Goods(100);
		assertEquals(100, ice.getPrice());
	}
	
	public void testGetTaxIncludedPrice() {
		Goods ice = new Goods(100);
		assertEquals(105, ice.getTaxIncludedPrice());
		Goods handkerchief = new Goods(500);
		assertEquals(525, handkerchief.getTaxIncludedPrice());
	}

}

Goods.java

public class Goods {

	private int unitPrice = 0;
	
	public Goods(int unitPrice) {
		this.unitPrice = unitPrice;
	}

	public Object getPrice() {
		return this.unitPrice;
	}

	public Object getTaxIncludedPrice() {
		return (int) (this.unitPrice * 1.05);
	}

}

Perlでベンチマーク

Perlではその名もBenchmarkというモジュールを使うと
簡単にベンチマーク=性能比較を行えます。

まずはやってみました。

#!/usr/bin/perl -w
use strict;

use Benchmark qw/timethese cmpthese/;

my $result = timethese( 10000, {
	loop1 => sub{
		my $i = 0;
		while ( $i < 1500 ) {
			$i++;
		}
	},
	loop2 => sub{
		my $i = 0;
		while ( $i < 500 ) {
			$i++;
		}
	}
});

cmpthese $result;

実行結果はこちら。

Benchmark: timing 10000 iterations of loop1, loop2...
     loop1:  1 wallclock secs ( 0.76 usr +  0.00 sys =  0.76 CPU) @ 13157.89/s (n=10000)
     loop2:  0 wallclock secs ( 0.25 usr +  0.00 sys =  0.25 CPU) @ 40000.00/s (n=10000)
            (warning: too few iterations for a reliable count)
↓ここからがcmpthese↓
         Rate loop1 loop2
loop1 13158/s    --  -67%
loop2 40000/s  204%    --


説明させていただきます。
timethese関数

timethse( $count, {
    処理1 => sub {
    },
    処理2 => sub {
    }
});

で複数のコードを$countに指定した回数実行できます。
一つの場合はtimethisです。返り値は各関数=処理の性能情報です。
こんな感じです。

$VAR1 = {
          'loop1' => bless( [
                              1,
                              '0.74',
                              0,
                              0,
                              0,
                              10000
                            ], 'Benchmark' ),
          'loop2' => bless( [
                              0,
                              '0.25',
                              0,
                              0,
                              0,
                              10000
                            ], 'Benchmark' )
        };

timetheseで処理は指定回実行されるのですが
その結果を比較したいときはcmptheseを利用します。
cmptheseはtimetheseの結果を比較表で出力します。

comthese $timethese_result;

この書き方とこの書き方どっちが速いの?!というのを
知りたいとき手軽に使用できていいですね(^^)


参考URL
http://d.hatena.ne.jp/perlcodesample/20100509/1276960096
http://www2u.biglobe.ne.jp/MAS/perl/waza/bench.html
http://perldoc.jp/docs/modules/Benchmark-1.10/Benchmark.pod

mapを使って配列からハッシュを作成

「バタバタしていて…」と心の中でできない社会人の典型な言い訳している内に
ブログの最終更新日から10日も経っていました。反省します。

今日、知ったこと

map関数を使うと配列からハッシュを作れる。

例えば配列の要素をキーにして、バリューには1を入れたいときは

%hash = map{ $_, 1 } @array;

mapで配列の要素を一つずつ取り出して、キー, バリューの形で返します。

一応ハッシュができていることを確認しました。

$ perl -e 'my @array = qw/aaa bbb ccc/; my %hash = map{ $_, 1 } @array; foreach my $key ( keys( %hash ) ) { print $key . " => " . $hash{$key} . "\n"; }'
bbb => 1
aaa => 1
ccc => 1

こういう書き方もできるみたいです。

my %hash = map{ @_ => 1 } @array;

こちらのほうがハッシュっぽいですね(よくわかりませんが)。

参考:http://hirobanex.net/article/2011/04/1302036133

Hadoop StreamingでUNIXコマンドを実行

やってみました。

$ hadoop/bin/hadoop jar hadoop/share/hadoop/tools/lib/hadoop-streaming-2.2.0.jar \
-input '/input/attempt.tsv' \
-output '/output' \
-mapper "awk '{ num = split( $1, aryData, "," ); for ( i=1; i<=num; i++ ) { print aryData[i]"\t"$3 } }'" \
-reducer '/usr/bin/uniq'

エラー出た(・∀・)

java.lang.Exception: java.lang.RuntimeException: PipeMapRed.waitOutputThreads(): subprocess failed with code 2
$ hadoop/bin/hadoop fs -rm -r /output

$ hadoop/bin/hadoop jar hadoop/share/hadoop/tools/lib/hadoop-streaming-2.2.0.jar \
-input '/input/attempt.tsv' \
-output '/output' \
-mapper /usr/bin/awk -F$'\t' '{ num = split( $1, aryData, "," ); for ( i=1; i<=num; i++ ) { print aryData[i]\"\t\"$3 } }' \ ←この行が駄目なようだが回避策がわからず断念。
-reducer '/usr/bin/uniq'

ローカルでやるといけるのに。。-mapper ""とダブルクオートで囲んどきながら中でもダブルクオート使っているからだと思います。

$ cat hadoop/input/attempt.tsv | awk '{ num = split( $1, aryData, "," ); for ( i=1; i<=num; i++ ) { print aryData[i]"\t"$3 } }' | LC_ALL=C sort | uniq
a	ccc
aaa	ccc
aaa	ddd
b	ddd

awkの部分をperlで代替して結果は出せました。

$ hadoop/bin/hadoop fs -rm -r /output

$ hadoop/bin/hadoop jar hadoop/share/hadoop/tools/lib/hadoop-streaming-2.2.0.jar \
-input '/input/attempt.tsv' \
-output '/output' \
-mapper '/usr/bin/perl awk.pl' \
-reducer '/usr/bin/uniq' \
-file 'hadoop/script/awk.pl'

$ hadoop/bin/hadoop fs -cat /output/part-00000
a	ccc
aaa	ccc
aaa	ddd
aaa	ccc
b	ddd

一応awk.pl。

#!/usr/bin/perl

use strict;
use warnings;

while ( <> ) {
	chomp;
	my @data = split/\t/, $_;
	my @key = split/,/, $data[0];
	for ( my $i = 0; $i < @key; $i++ ) {
		print $key[$i] . "\t" .  $data[2] . "\n";
	}
}

(Mapperの部分をawkで書く方法をご存知の方がいらっしゃいましたら教えていただけますと幸いですm(_ _)m)

JavaでマルチスレッドプログラムーRunnableインターフェイス実装編ー

昨日に引き続き今日は、Runnableインターフェイスを実装する場合のマルチスレッドプログラムです。

Q. Runnableインターファイスを実装するのはどんなとき?
A. 他に継承する必要のあるクラスがあり、Threadクラスを継承できないとき。

Q. どうやって実装するの?
A. ソースコードをご覧ください。

/*
 * Runnableインターフェイスの実装。
 * 
*/

public class ExThread2 {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		RunnableTestThread rtt = new RunnableTestThread();
		Thread t = new Thread(rtt);
		t.start();
		for (int i = 0; i < 10; i++) {
			System.out.println("hoge");
		}
	}

}

// 実際は何らかのクラスを既に継承していて、Threadクラスの継承ができない場合に使用。
// 例、class RunnableTestThread extends hoge implements Runnable {
class RunnableTestThread implements Runnable {
	public void run() {
		for (int i = 0; i < 10; i++) {
			System.out.println(this.getClass() + ":" + i);
		}
	}
}

実行結果

hoge
class RunnableTestThread:0
class RunnableTestThread:1
class RunnableTestThread:2
class RunnableTestThread:3
class RunnableTestThread:4
class RunnableTestThread:5
class RunnableTestThread:6
class RunnableTestThread:7
class RunnableTestThread:8
class RunnableTestThread:9
hoge
hoge
hoge
hoge
hoge
hoge
hoge
hoge
hoge

Q. 気を付けることは?
A. 上の実行結果を見ると

System.out.println("hoge");

が一度実行された後に

System.out.println(this.getClass() + ":" + i);

が走り、その後残りの

System.out.println("hoge");

が実行されています。
スレッド化された処理がいつ実行されるのかは注意がいると思います。