1

Solver Foundationで2D配列をパラメータにバインドする方法は? 配列を double(,); として定義しようとしました。double()() およびタプル (double, i, j) のリストとして。

ここで提案されている拡張メソッドを SetBinding に実装することも試みました。http://blogs.msdn.com/b/solverfoundation/archive/2010/06/28/simpler-data-binding-using-linq-and-extension-methods.aspx

現在、下から 3 行目で失敗しています。m_cov.SetBinding(CovMatrix)、エラー「このメソッドは、インデックスが 0 のパラメーターで呼び出された場合にのみ有効です」

私は最新バージョンを使用しており、vb.net で作業しています。どんな助けでも感謝します。

ありがとう、ユグ

Public Sub ERC()

        Dim m_i = New [Set](Domain.Any, "I")
        Dim m_j = New [Set](Domain.Any, "J")
        'Dim m_allocation As Decision
        Dim CovMatrix As Double()() = {New Double() {0.1, 0.15, 0.4}, New Double() {0.3, 0.5, 0.8}, New Double() {0, 0.33, 0.05}}

        Dim m_context As SolverContext = SolverContext.GetContext()
        Dim m_model As Model = m_context.CreateModel()
        m_model.Name = "ERC"

        ' Create a Parameter for Cov
        Dim m_cov = New Parameter(Domain.Real, "Cov", m_i, m_j)
        m_model.AddParameter(m_cov)
            ' Create a Decision for Allocation
        Dim m_allocation As Decision = New Decision(Domain.RealRange(-1.0, 1.0), "Allocation", m_i)
        m_model.AddDecision(m_allocation)
        ' Add Constraint for SumWts
        m_model.AddConstraint("SumWts", (Model.Sum(Model.ForEach(m_i, Function(i_1) Model.Abs(Model.Sum(m_allocation(i_1)))))) = 1.0)
        ' Add Goal for Variance
        m_model.AddGoal("Variance", GoalKind.Minimize, Model.Sum(Model.ForEach(m_i, Function(i_2) Model.ForEach(m_j, Function(j_3) Model.Power((Model.Abs(Model.Sum(Model.ForEach(m_j, Function(j_4) Model.Product(m_cov(i_2, j_4), m_allocation(j_4), m_allocation(i_2))))) - Model.Abs(Model.Sum(Model.ForEach(m_j, Function(j_6) Model.Product(m_cov(j_3, j_6), m_allocation(j_6), m_allocation(j_3)))))), 2.0)))))

        m_cov.SetBinding(CovMatrix)
        m_context.Solve()
        Debug.Print(m_allocation.GetValuesByIndex().ToString)
End Sub
4

1 に答える 1

1

Nathan Brixius が提供するヘルパー クラスは、SetBindingをより簡単にします。彼のヘルパー クラスは C# で書かれているので、先に進んで、必要な特定のヘルパー関数を VB に変換しました (以下を参照)。

例外は、SetBinding関数が渡されたデータのインデックスを知る必要があることを示しています。MSF は汎用ドメインを処理するように構築されています。つまり、通常の配列インデックスには従いません。インデックス情報を明示的に指摘する必要があります。

あなたのコードの問題は、追加のインデックス データなしで生の配列を渡そうとしていることです。通常の 1D 配列でこれを修正するには、 を使用してインデックスを追加しますKeyValuePair(Of Integer, Double)。この場合、行列の場合、 のリストが必要ですTuple (index1, index2, Double)。基本的に、3x3 行列を 9 つのトリプルにフラット化し、インデックスのペアに従って各値を指定する必要があります。

マトリックスをリストに変換するVB関数は次のとおりです。

Private Function ToIEnumerable(Of T)(matrix As IEnumerable(Of IEnumerable(Of T))) As IEnumerable(Of Tuple(Of Integer, Integer, T))
    Dim m = matrix.[Select](Function(row, i) row.[Select](Function(cell, j) New Tuple(Of Integer, Integer, T)(i, j, cell)))
    Dim cells = From cell In m.SelectMany(Function(c) c)
    Return cells
End Function

この関数をクラスに含め、コードの SetBinding 行を次のように変更します。

m_cov.SetBinding(ToIEnumerable(CovMatrix), "Item3", "Item1", "Item2")

Tupleアイテムの順番に注目!MSF の規則により、値フィールドはインデックスの前に来ます。ソリューションの出力でも同じ順序が返されます (結果セットの決定を反復処理する場合は注意が必要です)。

Nathan のヘルパー クラスの残りの部分を変換すると、SetBinding 関数自体をオーバーロードしてToIEnumerable(data)呼び出しとキー/値識別子の順序を抽象化することで、さらに簡単になります。次に、単に呼び出すことができますmodel.SetBinding(rawMatrix)

かなり滑らかですね。;)

于 2013-06-08T12:32:54.223 に答える