PIONEチュートリアル-PNML
PIONEは、直接、pione定義書を記述する事もできますが、PNMLを用いて、ペトリネットの形式で記述することもできます. WoPeD(推奨)により、ペトリネットを記述し、PNML形式で保存します。それぞれのアクションは、マークダウン形式で記述する事ができます.
WoPeDを使ったpione定義書の作成
ここではWoPeDを使って、PNMLファイルを作成し、pione定義書を作成するチュートリアルを行います。
まず、WoPeDを起動し、新規作成するためにFileのNewを選択します。
新規作成したファイル内のProcess上で右クリックすると、アイテムを選択することができます。

pione定義書を作成する上では上部2つの"○"(Place)と"□"(Transition)を使用します。主に"○"(Place)はファイルなどの入出力データを指し、"□"(Transition)はRuleなどの処理を指します。そして、"○"(Place)と"□"(Transition)の間をドラッグ操作による矢印(Annotation)でつなぐと、入力ファイルからある処理を経て出力ファイルを作成するフローが完成します。

WoPeDでフローを作成したら、次は"□"(Transition)の中身を作成します。こちらは下記のようなマークダウン形式ファイルを作成します。##が意味持っていることに注意して下さい。
## Transition名 ここにコメントを記述することができます。 ``` Transition内のAction ``` ## 次のTransition名 . . .
PNMLファイルとマークダウンファイルを作成した後は下記のコマンドによって、pione定義書へコンパイルすることができます。
$ pione compile (pnmlファイル) --action (アクション定義ファイル) > (pione定義書ファイル名)
基本1(特定のファイルを出力する)
では、PIONEチュートリアル#基本1(特定のファイルを出力する)と同様にHelloプログラムを作ってみましょう。
まず、下記のようなHelloWorld.pnmlを作成します。このとき出力ファイルの">"はMain Ruleにおける出力を指しています。("<"はMain Ruleの入力)

次に下記のようなHelloWorld.mdを作成します。
# HelloWorld.pione
## Hello
Here, you can write Comment.
```
echo "Hello PIONE world !" > {$O[1]}
```
このファイルはこちらからダウンロードできます。
最後にコンパイルを行います。
pione compile HelloWorld.pnml --action HelloWorld.md > HelloWorld.pione
コンパイル後のpione定義書
Rule Main
output 'message.txt'
Flow
rule Hello
End
Rule Hello
output 'message.txt'
Action
echo "Hello PIONE world !" > {$O[1]}
End
PIONEチュートリアル#基本1(特定のファイルを出力する)と同様の機能を持つファイルHelloWorld.pioneが作成されました。
実行結果
/Basic1$ pione-client HelloWorld.pione -b HelloWorld
==> &Anonymous:Root([],{})
--> Rule Application: &Anonymous:Root([],{})
--> Distribution: &Anonymous:Root([],{})
>>> &Anonymous:Main([],{})
==> &Anonymous:Main([],{})
--> Rule Application: &Anonymous:Main([],{})
--> Distribution: &Anonymous:Main([],{})
>>> &Anonymous:Hello([],{})
==> &Anonymous:Hello([],{})
SH ------------------------------------------------------------
SH echo "Hello PIONE world !" > message.txt
SH ------------------------------------------------------------
<== &Anonymous:Hello([],{})
<-- Distribution: &Anonymous:Main([],{})
<-- Rule Application: &Anonymous:Main([],{})
<-- Distribution: &Anonymous:Root([],{})
<== &Anonymous:Main([],{})
<-- Rule Application: &Anonymous:Root([],{})
<== &Anonymous:Root([],{})
/Basic1$ cat HelloWorld/output/message.txt
Hello PIONE world !
同様にHelloWorld/output/message.txt へHello PIONE world !が出力されています。
基本2(複数ルールによる処理)
少しルールを増やした例を試してみましょう。
今回は各行に1つずつの数値が記述されている全ての.inファイルに対して、各数に2を掛ける処理(First)、さらに1を足す処理(Second)を施して、.outを出力するルールを作成します。
PNMLファイル

上記の2つ目のplaceでの{S*}はPIONEの記述における{$I[1]}を表しています。
マークダウンファイル
# Serial2.pione
## First
Multiply 2 to all input data.
```
awk '{print $1*2}' {$I[1]} > {$O[1]}
```
## Second
Add 1 to all input data.
```
awk '{print $1+1}' {$I[1]} > {$O[1]}
```
このファイルはこちらからダウンロードできます。
コンパイル後のpione定義書
Rule Main
input '*.in'
output '*.out'
Flow
rule First
rule Second
End
Rule First
input '*.in'
output '{$*}.route'
Action
awk '{print $1*2}' {$I[1]} > {$O[1]}
End
Rule Second
input '*.route'
output '{$*}.out'
Action
awk '{print $1+1}' {$I[1]} > {$O[1]}
End
PIONEの実行結果
入力ファイル
| test1.in | test2.in | test3.in | test4.in | test5.in |
3 5 |
2 4 |
7 1 |
8 9 6 |
1 2 3 4 5 6 7 8 9 |
出力ファイル
| test1.out | test2.out | test3.out | test4.out | test5.out |
7 11 |
5 9 |
15 3 |
17 19 13 |
3 5 7 9 11 13 15 17 19 |
入力ファイルの各データが×2の後に+1の処理が施され、PIONEチュートリアル#基本5(直列:フロールールの設定 )と同様の処理を作成することができました。
基本3(複数種類の入出力がある処理)
複数種類の入出力がある少し複雑な処理を記述してみましょう。
今回は.txtファイルを元に.swapファイルで指定した行数を入れ替えたファイル.swtxtと.sedファイルで指定した文字列の置換を行ったファイル.sdtxtをそれぞれ出力します。
PNMLファイル

マークダウンファイル
# TextSwapSed.pione
## TextSwap
```
cp {$I[1]} intmp;
while read line ; \
do \
i1=$(echo $line | awk '{printf("%d", $1)}'); \
i2=$(echo $line | awk '{printf("%d", $2)}'); \
lnum=$(wc -l intmp | awk '{printf("%d", $1)}'); \
c1=$(expr $lnum - $i2); \
c2=$(expr $i2 - $i1); \
top=$( head -$i1 intmp ); \
middle=$( head -$i2 intmp | tail -$c2 ); \
bottom=$( tail -$c1 intmp ); \
t1=$(expr $i1 - 1); \
m1=$(expr $c2 - 1); \
top1=$( echo "$top" | head -$t1 ); \
str1=$( echo "$top" | tail -1 ); \
middle1=$( echo "$middle" | head -$m1 ); \
str2=$( echo "$middle" | tail -1 ); \
echo "$top1" > outtmp; \
echo "$str2" >> outtmp; \
echo "$middle1" >> outtmp; \
echo "$str1" >> outtmp; \
echo "$bottom" >> outtmp; \
cat outtmp | sed '/^$/d' > intmp; \
done < {$I[2]};
mv intmp {$O[1]};
```
## TextSed
```
cp {$I[1]} intmp;
while read line ; \
do \
str1=$(echo $line | awk '{printf("%s", $1)}'); \
str2=$(echo $line | awk '{printf("%s", $2)}'); \
sed -e "s/$str1/$str2/g" intmp > outtmp; \
cat outtmp | sed '/^$/d' > intmp; \
done < {$I[2]};
mv intmp {$O[1]};
```
このファイルはこちらからダウンロードできます。
コンパイル済みpione定義書の実行結果
入力ファイル
aaa aab aba abb baa bab bba bbb |
abc acb bac bca cab cba |
1 3 4 5 1 6 |
1 2 1 3 1 4 1 5 1 6 |
a c bc bd dc DC |
abc ddd aaa eee bc XX |
| Input1.txt | Input2.txt | line1.swap | line2.swap | ref1.sed | ref2.sed |
出力ファイル
bab aab aaa baa abb aba bba bbb |
bab aaa aab aba abb baa bba bbb |
ccc ccb cbd cbb bDC bdb bbd bbb |
eee aab aba abb baa bab bba bbb |
| Input1-line1.swtxt | Input1-line2.swtxt | Input1-ref1.sdtxt | Input1-ref2.sdtxt |
cba acb abc cab bca bac |
cba abc acb bac bca cab |
cbd ccb bDC bDC ccb cbd |
ddd acb bac XXa cab cba |
| Input2-line1.swtxt | Input2-line2.swtxt | Input2-ref1.sdtxt | Input2-ref2.sdtxt |
それぞれの.txtファイルに付いて.sed, .swapファイルによる変換が行われるので、計8つのファイルが出力されます。