Точечное умножение массива столбцов и матрицы с использованием Math.Net Numerics с С#

Я хочу выполнить точечное умножение массива столбцов с каждым массивом/вектором столбцов в заданной матрице на С#, используя библиотеку Math.Net Numerics.

Документации по подобным операциям мало, пока у меня есть приведенный ниже код, который не работает. Я пытаюсь использовать LINQ, так как предпочитаю циклы for. проблема, с которой я столкнулся с LINQ, заключается в том, что я не могу переназначить свою матрицу, когда пытаюсь перечислить каждый столбец моей матрицы как вектор и выполнить метод PointwiseMultiply().

Матрица fitKernel — это моя матрица, и я хочу поточечно умножить каждый столбец на массив столбцов wF и обновить мою матрицу fitKernel с помощью LINQ. fitKernel — это матрица 9 x 5, а wF — массив double[] 9 x 1, который я конвертирую в вектор в LINQ ниже.

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)));

Приведенный выше код, использующий EnumerateColumns(), возвращает IEnumerable векторов, но когда я пытаюсь присвоить значение fitKernel, он жалуется на присвоение типа Enumerable матрице.


person JMan    schedule 21.06.2018    source источник


Ответы (3)


Если вы собираетесь написать цикл 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];
    }

Вероятно, это самое быстрое и краткое решение, но я понимаю, что оно не сообщает читателю, что вы имеете в виду. 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);
        } 

Самое близкое, что я мог бы подобрать к вашей первой формулировке, таково:

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

Первая строка возвращает ваши новые столбцы, но вам все равно нужно вставить их в свою матрицу. Обратите внимание, что мы доверяем перечислителю вернуть столбцы в их естественном порядке. Это можно сократить до двух строк, используя EnumerateColumnsIndexed. Это требует большей детализации, но устраняет возможную двусмысленность в отношении порядка столбцов.

person phv3773    schedule 02.07.2018
comment
Спасибо за отзыв. Ваш последний фрагмент кода и мой ответ, который я опубликовал, служат решениями. Думаю, можно сделать вывод, что выполнить поточечное умножение и установку столбцов в матрице в одну строку через LINQ с помощью Math.Net Numerics не представляется возможным; вы должны использовать цикл foreach или for. - person JMan; 05.07.2018

Кстати, не получится объединить PointwiseMultiply и SetColumn в одном операторе вот так:

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

видимо, потому что SetColumn недействителен. Если у кого-то есть обходной путь, пожалуйста, напишите.

person phv3773    schedule 04.07.2018

Я думаю, что понял это, но вы должны использовать цикл for; не кажется простым способом использования 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);
}
person JMan    schedule 22.06.2018
comment
Существует форма Linq Select, которая принимает функцию с индексом и элементом, и вы можете использовать ее, но это зависит от того, делает ли установка столбца недействительной итератор. - person Pete Kirkham; 22.06.2018