2

ポリゴン内のポイントが占める領域を拡大するために、遺伝的プログラミングでフィットネス関数を記述しようとしています。ポリゴンの中心近くにいくつかのポイントがあります。これらのポイントを中心からポリゴンのすぐ内側まで拡張したいと考えています。

ポリゴンの内側のポイントが占める面積と外側のポリゴンの面積の差を使用して、フィットネス関数でそれを最小化しようとしていました。しかし、これを使用してポイントの座標を変更し、面積の差を再計算して繰り返し行う方法がわかりません。入力と出力がどのように見えるかを示しました。

前もって感謝します。

これは私がこれまでに書いたコードです。

require(rgp)
require(splancs)
require(grDevices)
functionSet1 <- functionSet("+", "*", "-", "/","^")
inputVariableSet1 <- inputVariableSet("x","y")
constantFactorySet1 <- constantFactorySet(function() rnorm(1))

outpolygon<-matrix(c(3.061188,2.517408,0.523754,-0.258800,0.981104,4.036885,
                     3.061188,4.069070,4.069070,2.695074,0.485581,-2.129055,
                     -2.653607,4.069070),nrow=7,byrow=F)
inpoints<-matrix(c(2.637644,-0.4456578,2.160003,0.8553066,1.501256,1.3137518,2.352020,-0.2643815,
                   1.254139,1.2241712,1.918191,0.6595725,1.453478,0.9153824,1.900110,1.0607272,
                   1.648038,0.6847361,2.194931,2.2842159),nrow=10,byrow=T)

plot(-10:10,xlim=c(-5,5),ylim=c(-5,5))
polygon(outpolygon[,1],outpolygon[,2])
points(inpoints[,1],inpoints[,2])

fitnessFunction1 <-  function(f){
  if(all(point.in.polygon(inpoints[,1],inpoints[,2],outpolygon[,1],outpolygon[,2])!=0)){
    rmse(areapl(inpoints[chull(inpoints[,1],inpoints[,2]),]),areapl(cbind(outpolygon[,1],outpolygon[,2])[chull(outpolygon[,1],outpolygon[,2]),]))
  }else{
    rmse(1000,0)
  }
}

gpResult1 <- geneticProgramming(functionSet=functionSet1,
                                inputVariables=inputVariableSet1,
                                constantSet=constantFactorySet1,
                                fitnessFunction=fitnessFunction1,    
                                stopCondition=makeTimeStopCondition(10))


best1 <- gpResult1$population[[which.min(sapply(gpResult1$population,
                                                fitnessFunction1))]]

ここに画像の説明を入力 ここに画像の説明を入力

4

1 に答える 1

2

これを行うにはいくつかの方法があります。最も簡単な方法は、実際には GP ではなく GA を使用することです。この場合、次のようなクワッドに分割された整数の配列があります。

[funcx1、valx1、funcy1、valy1、funcx2、valx2、funcy2、valy2、...、funcxn、valxn、funcyn、valyn]

フィット関数は funcxi のモジュラスを取り、対応する関数を取得します。次に、その関数の valxi の数値を対応する x 値に適用します。返されたポイントを考えると、あなたが言ったように面積を計算し、対応する面積を超えた場合は個人を罰します(負の定数または度数による係数)。

あるいは、何らかの理由で GP を使用する必要がある場合は、主に 2 つのルートがあります。コードを一般的なものにしたい場合 (つまり、進化したコードの同じチャンクを各ポイントに適用する; 注: これはかなり難しい)、より多くの非終端記号 (つまり関数) が必要になります。おそらく、少なくとも if ステートメントを追加します。自動的に定義された関数 (ADF) も適切で、Lisp の progn のようなある種のグループ化関数です。言うまでもなく、GA メソッドの方がはるかに簡単です。

もう 1 つのルートは、より構造化された GP を使用し、代わりに代入関数を追加することです。

GP 非終端記号: +、-、*、/、^、= (すべてのベクトル関数)

GP 端末: point1、point2、...、pointn、randompoint()

Lispy 構造を使用すると、コードは次のようになります。

(* (= (= point2 (* randompoint() (= point2 randompoint()))) point1) randompoint())

次に、それを評価するときに、下位のポイントを上位のポイントで上書きして、葉から根まですべての割り当てを行います。したがって、上記の例では、point2 がランダムなポイントとして割り当てられます (おそらく悪いことです)。結果はランダムな点で乗算され、その結果で point2 に行われた元の割り当てが上書きされます。同じ結果が point1 に割り当てられ、最後にランダムポイントが乗算されます。ただし、それ以上の代入がないため、最終的な値は単に破棄されます。

これが「より構造化された」理由は、ポイント以外で割り当てが発生しないようにする必要があるためです。文法ベースまたは文法ガイド付きの GP は、これが特に得意です。それらについて説明している Whigham (1995) の論文を参照してください。

http://sc.snu.ac.kr/courses/2007/fall/pg/aai/GP/whigham/whigham95grammaticallybased.pdf

GP を使用する場合は、いずれの場合も、上で説明した形式のリスト トラバーサル用にいくつかの関数を作成する必要があります。また、x と y ではなくポイントとベクトル関数を使用して、追跡する端末を少なくすることをお勧めします (また、プログラム ツリーが小さくなり、処理が速くなります)。ああ、randompoint() 関数が特定のポイントを返すことを確認してください (つまり、染色体に配置する前に評価することを確認してください。そうしないと、コードが一貫性​​のない結果を返すことになります。非常に悪いことです)。そして、これらの可能なポイントの範囲を妥当なものにしてください (つまり、10 平方のスペースにいる場合は 100 に行かないでください)。

まだ少し道のりはありますが、それが正しい方向に向かうことを願っています。

于 2013-03-19T20:51:36.780 に答える