SmallOPS を発展させた Toy Open Production System を SourceForge.jp にて公開しています。
また、本コンテンツを書くに辺り、以下の参考書を参考にしています。
OAV形式のデータとは、オブジェクト・属性・属性値によって表現されるデータ構造のことである。 従って、以下のようなクラス図が得られる。
OPS5の文法では事実だけでなく、 プロダクションルールの条件部・行動部のそれぞれにも部分的にOAV形式のデータが存在する。 これらは文法的には同じものであるが、データ構造的には全くの別物である。 従って、SmallOPSでは上と同じような構造を持つデータ構造が3つ存在する。 それぞれのデータ構造の大きな違いは、主に属性値として取り得る値である。 SmallOPSでは、アトム・整数・変数の3つの属性値が存在するが各OAV形式データ構造が取り得る値を示す。
定数(アトム・整数) | 変数 | |
事実 | ○ | × |
条件 | ○ | ○ |
行動 | ○ | ○ |
本章では、それぞれのデータ構造の特性について説明する。
Factクラスは、事実を表すクラスである。 事実とは、システムが動いている世界においてわかっている具体的な事柄のことである。 具体的な事柄なので、事実は属性値として変数を含まない。 事実のクラス図を以下に示す。
Factクラスには、同じ名前・同じ属性列を持つクラスを同値であると判定するequalsメソッドが定義されている。 これは、WorkingMemoryクラスで必要になるもので同じ値を持った事実が挿入されることを防ぐ際に利用される。 事実の属性列をAttributesOfFactクラス、事実の属性値である定数をConstantクラスとすると Factクラスの定義に対応するC++のソースを以下に示す。
class Fact : public Object { private: /** * 属性列です。 */ AttributesOfFact attributes_; }; class AttributesOfFact : public Attributes { private: typedef std::map<std::string, ConstantPtr> AttributesMap; /** * 属性列です。 */ AttributesMap attributes_; };
属性値を蓄積するためのデータ構造がmapなのは、名前から属性値を高速で検索できるようにするためである。
Conditionクラスは、条件を表すクラスである。 条件には多くの事実を包含するような一般的な記述が行われるため、属性値として変数が許される。 条件のクラス図を以下に示す。
条件には正負の符号が付いているので、Conditionクラスはsign属性を持っている。 また、特徴的なのはunificateメソッドである。 unificateメソッドは事実の属性列を受け取り、 条件として挙げられている属性列が事実の属性列に存在するかどうかのマッチングを行うメソッドである。 全ての属性列に関してマッチングに成功した場合は条件が成立したことを表す。 条件の属性列をAttributesOfConditionクラス、 条件の属性値は定数と変数を許すのでその一般的な値をValueクラスとすると Conditionクラスの定義に対応するC++のソースを以下に示す。
class Condition : public Object { private: /** * 符号です。 */ bool sign_; /** * 属性列です。 */ AttributesOfCondition attributes_; }; class AttributesOfCondition : public Attributes { private: /** * 属性構造体です。 */ struct Attribute { std::string name_; ValuePtr value_; Attribute(const std::string& name, const ValuePtr& value) : name_(name), value_(value) { } }; typedef std::vector<Attribute> AttributeVector; /** * 属性列です。 */ AttributeVector attributes_; };
属性値を蓄積するためのデータ構造がvectorなのは、 事実とのマッチングのときにシーケンシャルにアクセスしたいからである。
ObjectInActionクラスは、 makeやmodify*1などの行動を表現するときに 行動の中に書かれるオブジェクトを表すクラスである。 条件でマッチングした値を行動部に反映するような場合があるので、 属性値として変数が許される。 以下に、行動のオブジェクトのクラス図を示す。
ObjectInActionクラスには、新しい事実を生成するinstantiateメソッドが定義されている。 これは、makeやmodifyなどの行動によって新しい事実が生成されるときに使われる。 行動のオブジェクトから事実を生成するということは、 行動のオブジェクトに含まれている変数を具体的な定数に変換することを指している。 行動のオブジェクトの属性列をAttributesOfObjectInActionクラス、 行動のオブジェクトの属性値を条件と同じValueクラスとすると ObjectInActionクラスの定義に対応するC++のソースを以下に示す。
class ObjectInAction : public Object { private: /** * 属性列です。 */ AttributesOfObjectInAction attributes_; }; class AttributesOfObjectInAction : public Attributes { private: /** * 属性構造体です。 */ struct AttributeOfObjectInAction { std::string name_; ValuePtr value_; AttributeOfObjectInAction(const std::string& name, const ValuePtr& value) : name_(name), value_(value) { } }; typedef std::vector<AttributeOfObjectInAction> AttributeVector; /** * 属性列です。 */ AttributeVector attributes_; };
本章では、 Factクラス・Conditionクラス・ObjectInActionクラスという OAV形式のデータについて説明を行った。 次章では、定数や変数についての説明を行う。