简体   繁体   中英

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.

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. 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.

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 is 9 x 5 Matrix, and wF is a 9 x 1 double[] array that I convert to a Vector in the LINQ below.

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.

If you are going to write a for loop, you might as well write two.

    // 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.

        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. 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. 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:

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

apparently because SetColumn is void. If anyone has a workaround, please post it.

I think I figured it out but you have to use a for loop; doesn't seem to be any easy way using 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);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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