「PIONE定義書のTIPS」の版間の差分

提供: Eospedia
移動: 案内検索
(出力ファイルのパターンが異なる場合)
 
(同じ利用者による、間の12版が非表示)
行59: 行59:
 
</pre>
 
</pre>
 
orを使用して、出力ファイルを結合するとnthを使って呼び出すことができます。これにより例えばファイル名を変更した場合でもoutputの部分だけ変更すれば良いことになります。(参照:[[PIONEチュートリアル#基本13(orの使用例)]]、[[PIONEの式#シーケンス]])<br>
 
orを使用して、出力ファイルを結合するとnthを使って呼び出すことができます。これにより例えばファイル名を変更した場合でもoutputの部分だけ変更すれば良いことになります。(参照:[[PIONEチュートリアル#基本13(orの使用例)]]、[[PIONEの式#シーケンス]])<br>
 +
<br>
 +
 +
=== 条件文を作りたい ===
 +
[[PIONEチュートリアル#基本7(条件文)]]をご覧下さい。この条件文はAction文以外で使用可能です。(Action文内はシェルスクリプト)<br>
 +
<br>
 +
 +
=== ループ文を作りたい ===
 +
ファイル毎によるループ文の例については[[PIONEチュートリアル#実行例15(ループ文3)]]をご覧下さい。変数毎のループ文の例については[[#eachとallについて]]をご覧下さい。<br>
 +
<br>
 +
 +
=== lengthの使用例 ===
 +
'*.txt'.allのようにallで宣言した入力ファイルはデータ型のシーケンスとして取り扱えるので、[[PIONEの式#シーケンス]]のlengthを使用すると、入力ファイル数を得ることができます。<br>
 +
<br>
 +
 +
例. allで読み込むファイル数が2以上のときのみ実行する場合
 +
<pre>
 +
Rule Main
 +
input '*.txt'.all
 +
output 'data.log'
 +
constraint $I[1].length() > 1
 +
Action
 +
touch {$O[1]}
 +
End
 +
</pre>
 +
<br>
 +
 +
=== eachとallについて ===
 +
eachとallはシーケンスのメソッドですので、入出力ファイルに限らずパラメータや演算などでも使用可能です。(参照:[[PIONEの式#シーケンス]])<br>
 +
<pre>
 +
Rule Main
 +
output 'data.txt'
 +
param $i := ((-60/10).upto(60/10)*10).all()
 +
Action
 +
for i in {$i}
 +
do
 +
echo "${i}" >> {$O[1]}
 +
done
 +
End
 +
</pre>
 +
上記の場合、パラメータをひとまとめにしたルールが1つ動作します。<br>
 +
<pre>
 +
  ==> &Anonymous:Root([],{})
 +
    --> Rule Application: &Anonymous:Root([],{})
 +
      --> Distribution: &Anonymous:Root([],{})
 +
            >>> &Anonymous:Main([],{i:(<i>-60|-50|-40|-30|-20|-10|0|10|20|30|40|50|60)})
 +
  ==> &Anonymous:Main([],{i:(<i>-60|-50|-40|-30|-20|-10|0|10|20|30|40|50|60)})
 +
  SH ------------------------------------------------------------
 +
  SH for i in -60 -50 -40 -30 -20 -10 0 10 20 30 40 50 60
 +
  SH do
 +
  SH echo "${i}" >> data.txt
 +
  SH done
 +
  SH ------------------------------------------------------------
 +
  <== &Anonymous:Main([],{i:(<i>-60|-50|-40|-30|-20|-10|0|10|20|30|40|50|60)})
 +
      <-- Distribution: &Anonymous:Root([],{})
 +
    <-- Rule Application: &Anonymous:Root([],{})
 +
  <== &Anonymous:Root([],{})
 +
</pre>
 +
allを除いた場合はeachとして各パラメータ毎にルールが動作します。<br>
 +
<pre>
 +
  ==> &Anonymous:Root([],{})
 +
    --> Rule Application: &Anonymous:Root([],{})
 +
      --> Distribution: &Anonymous:Root([],{})
 +
            >>> &Anonymous:Main([],{i:(<i>-60)})
 +
            >>> &Anonymous:Main([],{i:(<i>-50)})
 +
            >>> &Anonymous:Main([],{i:(<i>-40)})
 +
            >>> &Anonymous:Main([],{i:(<i>-30)})
 +
            >>> &Anonymous:Main([],{i:(<i>-20)})
 +
            >>> &Anonymous:Main([],{i:(<i>-10)})
 +
            >>> &Anonymous:Main([],{i:(<i>0)})
 +
            >>> &Anonymous:Main([],{i:(<i>10)})
 +
            >>> &Anonymous:Main([],{i:(<i>20)})
 +
            >>> &Anonymous:Main([],{i:(<i>30)})
 +
            >>> &Anonymous:Main([],{i:(<i>40)})
 +
            >>> &Anonymous:Main([],{i:(<i>50)})
 +
            >>> &Anonymous:Main([],{i:(<i>60)})
 +
  ==> &Anonymous:Main([],{i:(<i>-60)})
 +
  SH ------------------------------------------------------------
 +
  SH for i in -60
 +
  SH do
 +
  SH echo "${i}" >> data.txt
 +
  SH done
 +
  SH ------------------------------------------------------------
 +
  <== &Anonymous:Main([],{i:(<i>-60)})
 +
  ==> &Anonymous:Main([],{i:(<i>-50)})
 +
 +
-中略-
 +
 +
  <== &Anonymous:Main([],{i:(<i>50)})
 +
  ==> &Anonymous:Main([],{i:(<i>60)})
 +
  SH ------------------------------------------------------------
 +
  SH for i in 60
 +
  SH do
 +
  SH echo "${i}" >> data.txt
 +
  SH done
 +
  SH ------------------------------------------------------------
 +
  <== &Anonymous:Main([],{i:(<i>60)})
 +
      <-- Distribution: &Anonymous:Root([],{})
 +
    <-- Rule Application: &Anonymous:Root([],{})
 +
  <== &Anonymous:Root([],{})
 +
</pre>
 +
<br>
 +
 +
この記法を利用することで特に複数のfor文にてeachやallの処理を切り替えることが容易にできます。<br>
 +
<pre>
 +
Rule Main
 +
output '*.txt'.all
 +
Flow
 +
rule Sub {i:1.upto(3).each, j:1.upto(3).all, k:1.upto(3).all}
 +
End
 +
 +
Rule Sub
 +
output '*.txt'.all
 +
Action
 +
for i in {$i}
 +
do
 +
for j in {$j}
 +
do
 +
for k in {$k}
 +
do
 +
touch ${i}-${j}-${k}.txt
 +
done
 +
done
 +
done
 +
End
 +
</pre>
 +
<br>
 +
 +
=== シーケンスの要素が多くなったとき ===
 +
シーケンスの要素が多くなり、1行で記述すると可読性が落ちるときは下記のように改行を使用します。<br>
 +
<pre>
 +
$Config := ("CLUSTER":$CLUSTER) |
 +
("PADWIDTH":$PADWIDTH) |
 +
("PADHEIGHT":$PADHEIGHT) |
 +
("SHRINK":$SHRINK) |
 +
("PADMODE":$PADMODE)
 +
</pre>
 
<br>
 
<br>
  
行70: 行206:
 
下記に陥りやすい構文ミスやルールを記載します。<br>
 
下記に陥りやすい構文ミスやルールを記載します。<br>
 
 *rule名の先頭を数字で定義することはできない。(× 3Dto2D, ○ Ref3Dto2D)<br>
 
 *rule名の先頭を数字で定義することはできない。(× 3Dto2D, ○ Ref3Dto2D)<br>
 +
 *rule名にハイフンを含めることはできない。(× Ref3D-2D, ○ Ref3D_2D)<br>
 
 *ルールヘッダーは'''Rule'''、フロー定義では'''rule'''を書く。<br>
 
 *ルールヘッダーは'''Rule'''、フロー定義では'''rule'''を書く。<br>
 
 *Mainルールのinputファイルは[[pione-client]]の-iで指定しているディレクトリ内に全てあるか。<br>
 
 *Mainルールのinputファイルは[[pione-client]]の-iで指定しているディレクトリ内に全てあるか。<br>
 
 *Mainルールのoutputファイルは必ずいずれかのルールで全て作成されているか。<br>
 
 *Mainルールのoutputファイルは必ずいずれかのルールで全て作成されているか。<br>
 
 *パラメータのブロック定義はルール内では使用できない。<br>
 
 *パラメータのブロック定義はルール内では使用できない。<br>
 *input, outputで宣言するファイル名は必ず' '(シングルクォート)で囲むこと。<br>
+
 *input, outputで宣言するファイル名は基本的に' '(シングルクォート)で囲む。(参照:[[#入出力ファイルの宣言]])<br>
 
<br>
 
<br>
  

2015年3月15日 (日) 23:45時点における最新版

 ここではPIONE定義書に関するTIPSを示します。実装例はPIONEチュートリアルPIONEチュートリアル-PNML、実行例はPIONE Webclientチュートリアルをご覧下さい。

記述例

入出力ファイルの宣言

inputやoutputで宣言する入出力ファイル名は通常' '(シングルクォート)で囲みます。これは入出力ファイルをPIONEにおけるデータ表現型として宣言しなければならないためです。' '(シングルクォート)で囲まれた部分がデータ表現型になります。(参照:PIONEの式#データ表現型

Rule Main
	input '1.txt'
	output '2.txt'
Action
	cp {$I[1]} {$O[1]}
End


inputやoutput以降は最終的にデータ表現型であればよいので、' '(シングルクォート)で囲まなくても文字列型を経由してメソッドd()を使用すれば同様に入出力ファイルとして使用できます。(参照:PIONEの式#文字列型(string)

Rule Main
	input "1.txt".d()
	output (2.str()+".txt").d()
Action
	cp {$I[1]} {$O[1]}
End


出力ファイルのパターンが異なる場合

条件によって(入力ファイル名).outか(入力ファイル名)-Info.outのどちらかを出力するルールについて考えます。

param $Mode := 0

Rule Main
	input '*.txt'
	output '*.out'.all
Action
	if [ {$Mode} -eq 0 ] ; then
		cp {$I[1]} {$I[1][1]}.out
	else
		wc {$I[1]} > {$I[1][1]}-Info.out
	fi;
End

outputでの宣言を'*.out'.allで全ての.outファイルを対象としてAction内で実際に出力ファイル名を個別に指定しています。{$I[1][1]}.outや{$I[1][1]}-Info.outの処理が多い場合には可読性が落ちます。ファイル名を変更したい場合にも対応しきれない可能性があります。

param $Mode := 0

Rule Main
	input '*.txt'
	output '{$I[1][1]}.out' or '{$I[1][1]}-Info.out'
Action
	if [ {$Mode} -eq 0 ] ; then
		cp {$I[1]} {$O[1].nth(1)}
	else
		wc {$I[1]} > {$O[1].nth(2)}
	fi;
End

orを使用して、出力ファイルを結合するとnthを使って呼び出すことができます。これにより例えばファイル名を変更した場合でもoutputの部分だけ変更すれば良いことになります。(参照:PIONEチュートリアル#基本13(orの使用例)PIONEの式#シーケンス

条件文を作りたい

PIONEチュートリアル#基本7(条件文)をご覧下さい。この条件文はAction文以外で使用可能です。(Action文内はシェルスクリプト)

ループ文を作りたい

ファイル毎によるループ文の例についてはPIONEチュートリアル#実行例15(ループ文3)をご覧下さい。変数毎のループ文の例については#eachとallについてをご覧下さい。

lengthの使用例

'*.txt'.allのようにallで宣言した入力ファイルはデータ型のシーケンスとして取り扱えるので、PIONEの式#シーケンスのlengthを使用すると、入力ファイル数を得ることができます。

例. allで読み込むファイル数が2以上のときのみ実行する場合

Rule Main
	input '*.txt'.all
	output 'data.log'
	constraint $I[1].length() > 1
Action
	touch {$O[1]}
End


eachとallについて

eachとallはシーケンスのメソッドですので、入出力ファイルに限らずパラメータや演算などでも使用可能です。(参照:PIONEの式#シーケンス

Rule Main
	output 'data.txt'
	param $i := ((-60/10).upto(60/10)*10).all()
Action
	for i in {$i}
	do
		echo "${i}" >> {$O[1]}
	done
End

上記の場合、パラメータをひとまとめにしたルールが1つ動作します。

  ==> &Anonymous:Root([],{})
    --> Rule Application: &Anonymous:Root([],{})
      --> Distribution: &Anonymous:Root([],{})
            >>> &Anonymous:Main([],{i:(<i>-60|-50|-40|-30|-20|-10|0|10|20|30|40|50|60)})
  ==> &Anonymous:Main([],{i:(<i>-60|-50|-40|-30|-20|-10|0|10|20|30|40|50|60)})
   SH ------------------------------------------------------------
   SH 	for i in -60 -50 -40 -30 -20 -10 0 10 20 30 40 50 60
   SH 	do
   SH 		echo "${i}" >> data.txt
   SH 	done
   SH ------------------------------------------------------------
  <== &Anonymous:Main([],{i:(<i>-60|-50|-40|-30|-20|-10|0|10|20|30|40|50|60)})
      <-- Distribution: &Anonymous:Root([],{})
    <-- Rule Application: &Anonymous:Root([],{})
  <== &Anonymous:Root([],{})

allを除いた場合はeachとして各パラメータ毎にルールが動作します。

  ==> &Anonymous:Root([],{})
    --> Rule Application: &Anonymous:Root([],{})
      --> Distribution: &Anonymous:Root([],{})
            >>> &Anonymous:Main([],{i:(<i>-60)})
            >>> &Anonymous:Main([],{i:(<i>-50)})
            >>> &Anonymous:Main([],{i:(<i>-40)})
            >>> &Anonymous:Main([],{i:(<i>-30)})
            >>> &Anonymous:Main([],{i:(<i>-20)})
            >>> &Anonymous:Main([],{i:(<i>-10)})
            >>> &Anonymous:Main([],{i:(<i>0)})
            >>> &Anonymous:Main([],{i:(<i>10)})
            >>> &Anonymous:Main([],{i:(<i>20)})
            >>> &Anonymous:Main([],{i:(<i>30)})
            >>> &Anonymous:Main([],{i:(<i>40)})
            >>> &Anonymous:Main([],{i:(<i>50)})
            >>> &Anonymous:Main([],{i:(<i>60)})
  ==> &Anonymous:Main([],{i:(<i>-60)})
   SH ------------------------------------------------------------
   SH 	for i in -60
   SH 	do
   SH 		echo "${i}" >> data.txt
   SH 	done
   SH ------------------------------------------------------------
  <== &Anonymous:Main([],{i:(<i>-60)})
  ==> &Anonymous:Main([],{i:(<i>-50)})

-中略-

  <== &Anonymous:Main([],{i:(<i>50)})
  ==> &Anonymous:Main([],{i:(<i>60)})
   SH ------------------------------------------------------------
   SH 	for i in 60
   SH 	do
   SH 		echo "${i}" >> data.txt
   SH 	done
   SH ------------------------------------------------------------
  <== &Anonymous:Main([],{i:(<i>60)})
      <-- Distribution: &Anonymous:Root([],{})
    <-- Rule Application: &Anonymous:Root([],{})
  <== &Anonymous:Root([],{})


この記法を利用することで特に複数のfor文にてeachやallの処理を切り替えることが容易にできます。

Rule Main
	output '*.txt'.all
Flow
	rule Sub {i:1.upto(3).each, j:1.upto(3).all, k:1.upto(3).all}
End

Rule Sub
	output '*.txt'.all
Action
	for i in {$i}
	do
		for j in {$j}
		do
			for k in {$k}
			do
				touch ${i}-${j}-${k}.txt
			done
		done
	done
End


シーケンスの要素が多くなったとき

シーケンスの要素が多くなり、1行で記述すると可読性が落ちるときは下記のように改行を使用します。

$Config :=	("CLUSTER":$CLUSTER) |
			("PADWIDTH":$PADWIDTH) |
			("PADHEIGHT":$PADHEIGHT) |
			("SHRINK":$SHRINK) |
			("PADMODE":$PADMODE)


記法の注意点

パラメータと変数束縛の違い

PIONE定義書において、値を取り扱うときにパラメータもしくは変数束縛を使用することもしばしばあります。この2つは取り扱いが異なりますので、混同しないように気をつけましょう。また、これらを使う主な目的はFlow内の条件文などで使用することにあります。Action内に記述するときはシェル変数などとも区別しましょう。両者の違いについてはPIONE定義書を参照して下さい。

デバッグ

構文エラーに関する注意点

下記に陥りやすい構文ミスやルールを記載します。
 *rule名の先頭を数字で定義することはできない。(× 3Dto2D, ○ Ref3Dto2D)
 *rule名にハイフンを含めることはできない。(× Ref3D-2D, ○ Ref3D_2D)
 *ルールヘッダーはRule、フロー定義ではruleを書く。
 *Mainルールのinputファイルはpione-clientの-iで指定しているディレクトリ内に全てあるか。
 *Mainルールのoutputファイルは必ずいずれかのルールで全て作成されているか。
 *パラメータのブロック定義はルール内では使用できない。
 *input, outputで宣言するファイル名は基本的に' '(シングルクォート)で囲む。(参照:#入出力ファイルの宣言

pione action execPIONE定義書で使用したいとき

pione action execアクション文書(.mdファイル)のマークダウンで記述されたルールを単独で実行することができますので、デバッグの際に非常に有効なコマンドであるといえます。しかし、このpione action execは通常のPIONE定義書に対応していません。元のアクション文書が無い場合(コンパイルでなく直接の記述でPIONE定義書を作成した場合)、そのままのフォーマットではpione action execが使用できません。

例えば、PIONE定義書を下記のように記述すれば、pione action execに対応でき、かつpione-clientも実行できます。

Rule Main
    output 'out.txt'
Action

# この中はpione-clientのみの動作を記述可能
Out={$O[1]}

:<<:
※ ↓## (ルール名)の上は必ず1行空ける

## Main
```
# この中はpione action execのみの動作を記述可能(#:: 〜 :<<:までがどちらも実行される処理)
Out='out.txt'

#::
# この中はどちらも実行される
	echo "Message for Shell"
	echo "Message for File" > $Out
:<<:
```
::

# この中はpione-clientのみの動作を記述可能

End

このように記述すれば、PIONE定義書でもpione action execに対応できるようになります。

pione-clientで実行した場合

$ pione-client test.pione
  ==> &Anonymous:Root([],{})
    --> Rule Application: &Anonymous:Root([],{})
      --> Distribution: &Anonymous:Root([],{})
            >>> &Anonymous:Main([],{})
  ==> &Anonymous:Main([],{})

-中略-

  <== &Anonymous:Main([],{})
      <-- Distribution: &Anonymous:Root([],{})
    <-- Rule Application: &Anonymous:Root([],{})
  <== &Anonymous:Root([],{})
$ cat process/output/out.txt 
Message for File


pione action execで実行した場合

$ pione action exec test.pione Main
Message for Shell
$ cat out.txt 
Message for File