2011-07-27 15 views
1

これは実際には2倍の質問です。最初に、オブジェクト指向のプログラミングの背景から来ている人物として、私はMathematicaのリストを、少し面倒なことの根拠としています。MathematicaのルールとGraphEditから返されるオブジェクトの違いは何ですか?

graph={{1, 2, 3, 4, 5}, {1->2, 2->4, 4->4, 4->5}}; 

、その後、プログラマはちょうど

graph[[1]] 

は頂点のリストを参照していることを覚えておく必要があります。だからここに(私の知る限り)Mathematicaのプログラマがグラフを定義する方法でありますそして

graph[[2]] 

は、エッジのリストを参照する(ルールのセットとして定義される。この場合には)

Mathematicaのルールについて学び、データ構造をオブジェクト指向の感じにする機会を見ました。他のいくつかのMathematicaのファイルが定義されている場合

Verts/.graph 
Edges/.graph 

によってこれは、しかし、奇妙な副作用を持つことができます(それぞれ)

graph={Verts->{1,2,3,4,5}, Edges->{1->2, 2->4, 4->4, 4->5}}; 

、その後、頂点と辺を参照してください。私のようなグラフに何かを定義することにしましたしかし、ルールの左辺は識別子ではなく、それ自体がオブジェクトであるため、どこかでグローバル変数としてVertsまたはEdgeを使用します。

質問1これは良い習慣ですか、Mathematicaのデータ構造を作成するのに悪いですか?私は、任意のプロパティを添付できるように、この方法はあるそれをやっている理由の一つ、色を言う:

AppendTo[graph, Colors->{Red, Red, Blue, Red, Red}]; (* Labels ea. vert with a color *) 

と私の機能は、特定のプロパティが追加された正確な順序を知っている必要はありません。

GetColor[graph_, vertIdx_]:=(Colors/.graph)[[vertIdx]]; 

と私はいつもの色情報を持つグラフデータ構造を持っているので、中にスポットを予約したくないたくない場合がありますので、これは、好ましい。たとえば、あなたはGETCOLORは以下のように定義された機能を持っているかもしれませんリスト(グラフ[[[3]]のような)を色情報として使用します。

2番目:GraphEditが上記のルールのようなものを返すことがわかりました。ルールのように見えます

Graph->{1->2,3->3,4->4,5->4} 

:たとえば、私が実行(およびグラフを描画する)場合

Needs["GraphUtilities`"]; 
g = GraphEdit[]; 
g[[2]] 

私のような出力が得られます!だから私はこれを試してみてください。

Graph/.g[[2]] 

{1->2,3->3,4->4,5->4} 

が戻ってきたことを期待します。しかし、その代わりに、出力はちょうど

Graph 

である。しかし、私が代わりに

g[[2]][[1]] /. g[[2]] 

を実行する場合、私は、予想される出力を得る、gは[[2]]本当にあることを意味し

{1->2,3->3,4->4,5->4} 

しかし、何らかの理由でg [2] [1](実行された場合Graphを印刷する)はGraphを入力するのと同じではありません。だから、一体何g [2] [[1]]ですか?

実際の識別子のように思えますが、上記の質問1の問題を解決するために使用したいと思います。誰かがその違いを知っていますか、またはMathematicaに1対1を入力する方法はありますか?

このドキュメント(またはオンライン)に関するドキュメントでは何も見つかりません。ありがとう。

答えて

4

GraphEditのルール

GraphEditその最初の要素と残りの要素グラフを記述ルールであるGraphicsオブジェクトであるリストを返します。各ルールの左側は記号ではなく文字列です。これはg // FullFormを使用して判断できます。グラフルールを抽出するには、リストの最初の要素を無視する必要があります。

"Graph" /. Drop[g, 1] 

のシミュレーションレコードタイプ

あなたが提案するように、レコードのようなデータ型を実装するための合理的なアプローチです:

graph={Verts->{1,2,3,4,5}, Edges->{1->2, 2->4, 4->4, 4->5}}; 

あればVertsEdgesが値を割り当てられていたことは事実であります「奇妙な副作用」が発生します。しかし、その問題を軽減するにはいくつかの方法があります。

まず、大文字の頭文字を持つシンボルに値(具体的にはOwnValues)を割り当てることを避けるため、Mathematicaでは非常に広範な慣習がある。 Wolframはすべての最上位変数の接頭辞として$を付けます。 $Context。あなたがこれらの規則に固執すれば、あなたはある程度の安全性を得るでしょう。

第2に、Packagesを使用して別々のネームスペースを用意することがあります。定義したパッケージの範囲内で、フィールド名として使用するシンボルのバインディングを完全に制御することができます。

第3に、Protectを使用して、フィールド名に値が割り当てられないようにすることができます。

これらのレコードタイプを実装する場合、LISPイデイオムに従い、コンストラクタとアクセッサ関数を定義できます。これらの機能は、このように使用される

ClearAll[makeGraph, graphVertices, graphEdges] 
makeGraph[vertices_, edges_] := {Verts -> vertices, Edges -> edges} 
graphVertices[graph_] := Verts /. graph 
graphEdges[graph_] := Edges /. graph 

:グラフたとえば、これらの機能は、このような何かを見ることができる

graph = makeGraph[{1,2,3,4,5}, {1->2,2->4,4->4,4->5}] 
(* {Verts -> {1, 2, 3, 4, 5}, Edges -> {1 -> 2, 2 -> 4, 4 -> 4, 4 -> 5}} *) 

graphVertices[graph] 
(* {1, 2, 3, 4, 5} *) 

graphEdges[graph] 
(* {1 -> 2, 2 -> 4, 4 -> 4, 4 -> 5} *) 

をこの方式を使用して、フィールドのキーVertsEdgesは、パッケージにプライベートにすることができ偶発的な価値の割り当てによって物事が損なわれる可能性を完全に回避することができます。

Mathematicaでは、式のHeadを使用して型を識別することが非常に一般的です。我々は、このイディオムに適合し、したがって、我々の記録機能を再定義することができる:

ClearAll[makeGraph, graphVertices, graphEdges] 
makeGraph[vertices_, edges_] := graphRecord[Verts -> vertices, Edges -> edges] 
graphVertices[graphRecord[rules___]] := Verts /. {rules} 
graphEdges[graphRecord[rules___]] := Edges /. {rules} 

これらと前の定義との間の唯一の材料差がグラフオブジェクトは、現在代わり{...}の形態graphRecord[...]の式で表されることである。

graph = makeGraph[{1,2,3,4,5}, {1->2,2->4,4->4,4->5}] 
(* graphRecord[Verts -> {1, 2, 3, 4, 5}, Edges -> {1->2, 2->4, 4->4, 4->5}] *) 

graphVertices[graph] 
(* {1, 2, 3, 4, 5} *) 

graphEdges[graph] 
(* {1 -> 2, 2 -> 4, 4 -> 4, 4 -> 5} *) 

なぜ変更されましたか?第1の理由は、頭部graphRecordがデータの種類を確実に識別するようになりました。第二に、graphRecordにのみ作用し、他には何も作用しないさらなる関数(準方法)を定義することができる。たとえば、次のように

graphEdgeCount[r_graphRecord] := graphEdges[r] // Length 
graphEdgeCount[x_] := (Message[graphEdgeCount::invArg, x]; Abort[]) 
graphEdgeCount::invArg = "Invalid argument to graphEdgeCount: ``"; 

用途:graphEdgeCountに無効な引数:graphEdgeCount :: invArgの評価の間

graphEdgeCount[graph] 
(* 4 *) 

graphEdgeCount["hi"] 
ハイテク
このすべてに最終推敲として

中止$、タイプとフィールド名が与えられたときに、すべてのレコード関数を自動的に定義するマクロ関数を定義することが可能です。しかし、このレスポンスはすでにTL; DRですので、おそらく他の質問のトピックとして残っているのが一番良いでしょう。

注:これらの機能がすべてパッケージのコンテキスト内で定義されている場合、その名前には初期大文字が使用されます(makeGraphではなくMakeGraph)。しかし、Mathematicaには、すでに単語が含まれている組み込みシンボルがたくさんあることに注意してください。Graph

+0

うわー、これは非常に便利で、Mathematicaを理解する上で多くの欠点があります。 Mathematicaドキュメンテーション用のドキュメントを書くべきだと思いますが、Mathematica Programming for C/Java/C++ Programmersの内容は次のようになります。ここではC/Java/C++で行うことができます。それをMathematicaでやってみましょう...あなたはそれを書くことを考えるかもしれません。 – jcb

+1

@quadelirus Mathematicaを理解する上での穴埋めについては、Leonid Shifrinの[Mathematicaプログラミング:高度な紹介](http://www.mathprogramming-intro.org/)を参考にしてください。 – WReach

0

私は答えはInputFormでは[]を使用して2に疑問を見出した(今日の前に、その機能については知られていなかった。)

InputForm[g[[2]][[1]]]; 

戻り

"Graph" 

だから、それは回避する方法を表示されます質問1の問題とGraphEditの定義方法に対する答えは、ルール内の文字列を「識別子」として使用することです。

質問1は、次のように改訂することができます。これは良い方法ですか?

+0

「FullForm」が面白いかもしれません。例えば、 'FullForm [g]'を試してみてください。 mathematicaのほとんどのオブジェクトは、 'Plot [Sin [x]、{x、-5、5}]'とそれに続く 'FullForm @%'を試してみると面白い。ですから、通常このようなことをすることができます:http://stackoverflow.com/questions/6477649/replacing-disks-by-crosses-using-graphics-in-mathematica/6478079#6478079(これはmathematicaではかなり一般的です。 "実際の"形は表現であり、他の表現のように操作することができます) – acl

4

使用しているMathematicaのバージョンは?

グラフ理論はV8のコアにもっと密接に統合されており、これは主に改善点です。オブジェクト指向のプログラマが好むような方法でグラフと対話することができます。

PropertyValue[{g, 3}, VertexStyle] 

残念ながら、古いグラフ理論の機能のほとんどはでうまく再生されない:そうのように、私は、プロパティを照会することができます

g = Graph[Range[5], {1 -> 2, 2 -> 4, 4 -> 4, 4 -> 5}]; 
g = SetProperty[{g, 3}, VertexStyle -> Red] 

:V8で、私はそうのようなあなたの例を実行したいですV8。ただし、コンテキスト指定に注意している場合は、これを使用できます。 GraphPlotのように、他の関数に渡す価値が何かを得るために

Needs["GraphUtilities`"]; 
g = GraphEdit[]; 

そして、

{vertices, edges} = {"VertexLabels", "Graph"} /. Rest[g] 

:V7では、私はそうのようなGraphEditの出力にアクセスすることができます。

これは、これが合理的な表現かどうかについて、あなたの質問に部分的に答えています。このタイプの表現は、置換規則を介して情報にアクセスすることを容易にする。これの良い例は、XMLのインポートの仕方によって与えられます。

関連する問題