简体   繁体   English

使用带有C#的Math.Net数值进行逐点乘法列数组和矩阵

[英]Point-wise Multiply Column Array and Matrix using Math.Net Numerics with C#

I want to perform a point-wise multiplication of a column array with each column array/vector in a given Matrix in C# using the Math.Net Numerics library. 我想使用Math.Net Numerics库对C#中给定矩阵中的每个列数组/向量执行列数组的逐点乘法。

There is little documentation on operations like this, so far I have the code below which doesn't work. 关于此类操作的文档很少,到目前为止,我下面的代码无法正常工作。 I am trying to use LINQ as I prefer that over for loops. 我正在尝试使用LINQ,因为我更喜欢for循环。 the problem I'm having with LINQ is I can't reassign my matrix when I try to enumerate each column of my matrix as a vector and do the PointwiseMultiply() method. LINQ遇到的问题是,当我尝试将矩阵的每一列枚举为向量并执行PointwiseMultiply()方法时,我无法重新分配矩阵。

Matrix fitKernel is my matrix, and I want to point-wise multiply each column by the wF column array and update my matrix fitKernel using LINQ. 矩阵fitKernel是我的矩阵,我想将每列乘以wF列数组,并使用LINQ更新我的矩阵fitKernel fitKernel is 9 x 5 Matrix, and wF is a 9 x 1 double[] array that I convert to a Vector in the LINQ below. fitKernel是9 x 5矩阵,wF是9 x 1 double []数组,我在下面的LINQ中将其转换为Vector。

Matrix<double> fitKernel = Matrix<double>.Build.DenseOfColumnArrays(c1, c2, c3, c4, ones); 

double[] wF = Enumerable.Repeat(1.0, 9).ToArray();

fitKernel = fitKernel.EnumerateColumns()
            .Select(v => v.PointwiseMultiply(Vector<double>.Build.DenseOfArray(wF)));

The above code using the EnumerateColumns() returns an IEnumerable of vectors, but when I try to assign the value to fitKernel it complains about assigning a type of Enumerable to a Matrix. 上面的代码使用EnumerateColumns()返回向量的IEnumerable,但是当我尝试将值分配给fitKernel时,它抱怨为矩阵分配Enumerable类型。

If you are going to write a for loop, you might as well write two. 如果要编写一个for循环,则最好编写两个。

    // a = double[9];
    // c = Matrix<double>

    for (int ic = 0; ic < c.ColumnCount; ic++)
    {
        for (int ir = 0; ir < c.RowCount; ir++) c[ir, ic] = a[ir] * c[ir, ic];
    }

It's probably the quickest and briefest solution, but I understand it doesn't tell the reader what you have in mind. 它可能是最快,最简短的解决方案,但据我了解,它并不能告诉读者您的想法。 OTOH, if you going to use an enumerator, it makes sense to let it control the loop. OTOH,如果要使用枚举器,则让它控制循环是有意义的。

        var va = Vector<double>.Build.DenseOfArray(a);

        var ColEnum = c.EnumerateColumnsIndexed() ;

        foreach (System.Tuple<int,Vector<double>> col in ColEnum)
        {
            Vector<double> v = (Vector<double>)col.Item2.PointwiseMultiply((Vector<double>)va);
            c.SetColumn(col.Item1, v);
        } 

The closest I could get to your first formulation is this: 我最接近您的第一个公式的是:

        var r = c.EnumerateColumns().Select(v => v.PointwiseMultiply(va));
        int i = 0;
        foreach (Vector ri in r) c.SetColumn(i++, ri);

The first line returns your new columns, but you still have to insert them into your Matrix. 第一行返回您的新列,但是您仍然必须将它们插入到Matrix中。 Note that we are trusting the enumerator to bring back the columns in their natural order. 请注意,我们信任枚举数以其自然顺序带回列。 It's possible to reduce this to two lines using EnumerateColumnsIndexed. 使用EnumerateColumnsIndexed可以将其减少到两行。 It requires more detail, but eliminates possible ambiguity about column order. 它需要更多细节,但是消除了有关列顺序的可能歧义。

By the way, it does not work to combine the PointwiseMultiply and the SetColumn in one statement like this: 顺便说一句,将PointwiseMultiply和SetColumn组合在一个这样的语句中是行不通的:

        var r = c.EnumerateColumnsIndexed().Select((v) => c.SetColumn(v.Item1, v.Item2.PointwiseMultiply(va)));

apparently because SetColumn is void. 显然是因为SetColumn为空。 If anyone has a workaround, please post it. 如果有人有解决方法,请发布它。

I think I figured it out but you have to use a for loop; 我想我已经解决了,但是您必须使用for循环; doesn't seem to be any easy way using LINQ: 使用LINQ似乎不是任何简单的方法:

for (int i = 0; i < fitKernel.ColumnCount; i++)
{
        var v = fitKernel.Column(i);
        v = v.PointwiseMultiply(Vector<double>.Build.DenseOfArray(wF));
        fitKernel.SetColumn(i, v);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM