2

私はこの秋、Pythonでプログラミングクラスのプロジェクトを行い、ユーザーの応答から学習する20の質問スタイルのゲームを作成しました。質問に対するyes/noの回答に基づいたツリーを使用し、「ブランチ」の終わりに到達したら、動物と一緒に各決定に固有の質問を選択して質問します。

クラスの終わりに向けて、C ++でいくつかの作業を行いました(ただし、私はまだ非常に新しいです)。休憩中にプロジェクトのC++バージョンを作成したいと思います。これにより実行がはるかに簡単になります。たとえば、実行可能ファイルとして。ただし、C ++にはピクルススタイルのデータストレージのオプションがあまりないことがわかりました。この状況では、Boost.serializationまたはBoost.Pythonが特にうまく機能するとは思いません。

他の選択肢はありますか、またはC ++で別の方法でデータを処理する方法についての提案がありますか?

元のPythonコードには次のものが含まれています。

    def check(self):
        correct, lastnode = self.ask(self.root) #lastnode is the closest guess to the new animal
        if correct =='n':
            print("Rats! I didn't get it. Please help me improve.")
            newanimal = AnTreeNode(input("What is your animal? "))
            oldanimal = lastnode
            newquestion = input("Please enter a yes/no question that would\n select between a(n) %s \
and a(n) %s: " %(newanimal,lastnode.data))+" "
            direction = input("What would be the correct answer for a(n) %s? " %newanimal)
            newnode = AnTreeNode(newquestion, parent = lastnode.parent)
            if lastnode.parent == None:
                self.root = newnode
            elif lastnode.parent.yes == lastnode:
                newnode.parent.yes = newnode
            else:
                newnode.parent.no = newnode
            if direction == 'y':
                newnode.yes, newnode.no = newanimal, oldanimal
            elif direction == 'n':
                newnode.yes, newnode.no = oldanimal, newanimal
            newanimal.parent = newnode
            oldanimal.parent = newnode
            self.dumpTree()
        elif correct == 'y':
            print("I am soooo smart!")

    def loadTree(self):
        try:
            f = open(self.treefile, "rb")
            self.root = pickle.load(f)
        except:
            self.root = AnTreeNode("frog")  

    def dumpTree(self):
        pickle.dump(self.root, open(self.treefile, 'wb'))

データをファイルまたは配列に保存した場合、ツリーを機能させる方法を考えることはできません(そして、配列に格納することで理解できますが、特に動的配列を作成したくありません)それらの問題は、特定のノードを参照する方法がわからないことです。他のオプション、またはそれらをどのように扱うかについての考えはありますか?ありがとう!(そしてメリークリスマス!)

4

2 に答える 2

3

実際、boost :: serializationは非常にうまく機能し、基本を学ぶことはそれほど難しくありません。

ただし、プロトコルバッファのような少し高いレベルのライブラリを検討することもできます。このようにして、PythonとC++の両方のバージョンで機能するデータベースを作成できます。

編集:boost :: pythonはバインディングを作成することしかできないため、適切なソリューションではありません。データを保存するためにそれを使用することは本当に苦痛でしょう。

Boost serializeを使用すると、C ++構造をシリアル化(およびディスクに簡単に保存)できます。ドキュメントの例を試してみてください。

プロトコルバッファは、バイナリ形式でデータを交換できるようにするシリアル化形式です。形式は明確に定義されているため、さまざまな言語から読み取り/書き込みを行ったり、データを交換したりできます。たとえばXMLのように、コード内で操作する方が簡単です:http ://code.google.com/p/protobuf/ ただし、boost::serializeよりも少し手間がかかると思います。いずれにせよ、どちらも学ぶ価値があり、さらなるプロジェクトに役立ちます。

于 2012-12-23T22:39:41.430 に答える
0

http://www.picklingtools.comにオープンソースのC++ライブラリがあり、 C ++でオブジェクトをピクルス化できます(Pythonプロジェクトからピクルス化したファイルを再利用できる可能性があります)。標準のPythonデータ構造(dict、list、tuples、ints、floatなど)をシリアル化するのに最適ですが、ある程度の作業でクラスを操作できます(結局、Pythonクラスは通常名前空間にdictを使用して実装されます)。

picklingtoolsライブラリの使用方法を示す簡単な例(そしてC ++とPythonで動作させる)

#include "chooseser.h"
#include <iostream>

int main (int argc, char **argv)
{
   // Create a Python style dictionary
   Val v = Tab("{'a':1, 'b':2.2, 'c':'three', 'nested':{ 'zz':1 }");
   v["d"] = "something";

   // print out a nested key
   cout << v["nested"]["zz"] << endl;  

   // Pickle the data structure to disk
   DumpValToFile(v, "state.p0", SERIALIZE_P2);

//  # Python side would read this same file with
// >>> import cPickle
// >>> result = cPickle.load( file('state.p0') ) # load fiigures out which prototcol

}

私はおそらく辞書かリストを使ってあなたのツリーを構築するでしょう:

questions_dict = { 'data': 'COW', 'left': None, 'right': { ''data':'CAT', left': None, 'right': None } }
print questions_dict['right']['data'] # Right child's data

LEFT = 1; RIGHT = 2; DATA = 0
questions_list = ["COW", None, ["CAT", None, None] ]
print questions_list[RIGHT][DATA]  # Right child's data

これにより、その辞書を作成したり、C ++とPythonの間でリストを作成したりして、必要なことを実行できます。すべてをそのまま使用できます。

Webサイトの[ドキュメント]タブに、C++でピクルスおよびピクルスを外す方法に関する重要なドキュメントがあります。始めるのに最適な場所は、おそらく http://www.picklingtools.com/documentation with theUser'sGuideです。

警告!先の危険! C ++からのシリアル化を使用してクラスを構築できます(したがって、Pythonの同じクラスはC ++に相当します)が、それは重要です。さらに難しいことです。標準のPythonデータ構造内にとどまることができれば、作業ははるかに楽になります。これを行うには、C++クラスをそのコンストラクターにシステムに登録する必要があります。ビルド関数が必要です(簡単な例については、以下を参照してください)。

// When registering things with the factory, they take in some tuple
// and return a Val: REDUCE tend to be more for built-in complicated
// types like Numeric, array and complex.  BUILD tends to more for
// user-defined types.
typedef void (*FactoryFunction)(const Val& name, 
                                const Val& input_tuple, 
                                Val& environment,  
                                Val& output_result);


// Example of how user-defined classes would probably serialize: the
// user-defined classes tend to be built with BUILD instead of REDUCE,
// which passes slightly different arguments to the tuple.  As an
// example, magine a simple Python class:
//
//   class Scott(object) :
//     def __init__(self, n) : self.data = int(n)
//
// A dumps(a,2) (where a= Scott(100)) looks like
// '\x80\x02c__main__\nScott\nq\x01)\x81q\x02}q\x03U\x04dataq\x04Kdsb.'/
//
// type_object: a tuple (string_name, args). i.e., ('__main__\nScott\n', ()) 
// input: a dictionary                       i.e., {'data', 100 }
inline void BuildScottFactoryFunction (const Val& type_object, 
                       const Val& input,
                       Val& /* environment */,
                       Val& output_result)
{
  cout << "SCOTT:type_object:" << type_object << endl;
  cout << "SCOTT:input:" << input << endl;

  string name = type_object(0);
  Tup&   args = type_object(1);
  cout << "name:" << name << " args:" << args << endl;

  if (name!="__main__\nScott\n") throw runtime_error("Not right name");
  Val& result = input("data");
  output_result = result;
}

次に、クラスを独自のPickleLoaderに登録する必要があります。

PickleLoader p(buffer, buffer_len);
p.registerFactory("__main__\nScott\n", BuildScottFactoryFunction);

これを機能させると、PythonクラスとC ++クラスの外観と感触を同じにし、pickleを使用して通信できますが、見た目よりも難しくなります(C ++には実行時イントロスペクションの実際の概念がないためです(RTTIに限定されています)。 ))、したがって、タプル、辞書、リストの観点からC++クラス全体を手動で記述しなければならない傾向があります。そして、これらの関数をピクルスローダーに登録します。それは可能ですが、問題の単純な性質を考えると、私はストックPythonデータ構造(リスト、dict、タプル、int、float、文字列、None)に固執し、それらを使用して20の質問ツリーを表します。

于 2014-07-16T15:32:12.153 に答える