向量和索引的内积错误

Error in inner product of vectors and index

本文关键字:错误 索引 向量      更新时间:2023-10-16

我在代码中发现了一个错误,无法找出错误。我尝试通过逐步显示每个变量的输出进行调试,但找不到错误。以下是我所拥有的和我想做的:

我有一个矩阵a:

0000
0101
1010
1111

我有一个矩阵B:

10000
21000
30100
41100
20010
21010
40110
41110
30001
41001
30101
41101
40011
41011
40111
41111

矩阵B有16行和5列。矩阵A具有4行和4列。现在我声明一个矩阵C,它有4行和16列。

我想做的是计算B的每一行与a的对应行的内积。我的意思是,B的第一列应该定义我要相乘的a的行。因此,B矩阵实际上也有四维向量,第一个元素对应于A的行。可以说,B的第一列是选择A的行的索引。因为C++从零开始计数,所以我的索引减去1。这是我的代码:

std::vector< std::vector<int> > C(4, std::vector<int>(16));
std::vector<int> index(4);
std::vector<int> vectorA(4);
std::vector<int> vectorB(4);
for( int y = 0; y < 16; y++)
{
    for(int i=0; i<4; ++i){
    vectorA[i] = A[ B[y][0]-1 ][i];
    }
    for( int x = 1; x < 4; x++)
    {
        vectorB[x -1] = B[y][x];
    }

C[ B[y][0] -1][index[ B[y][0] -1] ] = inner_product(vectorA.begin(), vectorA.end(), vectorB.begin(), 0);
    index[B[y][0]-1] += 1;
}

这导致了我的矩阵C:

0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
1 1 2 0 0 0 0 0 0 0 0 0 0 0 0 0 
1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 
2 2 3 1 2 1 2 2 3 0 0 0 0 0 0 0 

前两行是正确的,但第三行和第四行是错误的。正确的解决方案必须是(可能除了第3行和第4行的订购):

0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
1 1 2 0 0 0 0 0 0 0 0 0 0 0 0 0 
1 1 2 0 0 0 0 0 0 0 0 0 0 0 0 0 
4 3 3 2 3 2 3 2 2 0 0 0 0 0 0 0 

我的问题在哪里?请帮忙,这让我疯了:(我试着一步一步地显示每个变量,但找不到为什么它是假的

谢谢和问候。

我不得不同意其他评论:您的代码有点令人困惑。您应该通过索引来简化对向量的访问。

您应该做的第一件简单的事情是将B的第一列更改为零。C++中的所有内容都是零基础的。采用它。不要在代码中通过减去一个来调整它。(这并没有获得太多的简单性,但对您的代码来说是症状。)

另一个混淆的来源是,你使用B的第一列作为A的索引。这可能是你想解决的问题的暗示,但它让事情变得不清楚:B的第一行有完全不同的含义,总是以对象按其含义分开的方式编码。

对我来说,最令人困惑的是,我真的不明白你在做什么。内积是指点积,对吧?您有两组向量要计算的点积。这应该会产生一组标量,一个1D向量,而不是2D矩阵。您可以用索引向量做一些特殊的事情,这使得结果成为2D矩阵。但你还没有解释它背后的目的/系统。为什么你需要一个向量作为索引,而不仅仅是一个标量??

Vectorindex是代码中最难看/最复杂的部分。在不知道你在做什么的情况下,我仍然猜测,当你开始在每次迭代中打印出完整的向量索引并检查它是否改变了你期望的方式时,你会发现哪里出了问题。

我不知道OP选择背后的理由是什么,所以我不能正确地评论所提供的代码的设计,但据我所知,示例输入也有一些错误。

给定如图所示的A和B矩阵,A的下一行与B中对应的矩阵的内积总是0:

                                     B[1]   { 2,     1, 0, 0, 0 },
row "2" or A[1] is { 0, 1, 0, 1 } <- B[4]   { 2,     0, 0, 1, 0 },
                                     B[5]   { 2,     1, 0, 1, 0 },

下一行也是如此。只有交换后,才能获得预期的输出,我在代码中就是这样做的。

vectorAvectorB以及相应的复制循环并不是真正必要的,并且可能是错误输出的原因:

for( int x = 1; x < 4; x++)
{ //            ^^^^^  this should be  <=  to reach the last element
    vectorB[x -1] = B[y][x];
}

我的代码,带有更新的输入和A和B的直接使用是:

#include <iostream>
#include <vector>
#include <numeric>
using vec_t = std::vector<int>;   // I assume a C++11 compliant compiler
using mat_t = std::vector<vec_t>;
using std::cout;
int main() {
    mat_t A{
        { 0, 0, 0, 0 },
        { 1, 0, 1, 0 }, // <-- those lines are swapped
        { 0, 1, 0, 1 }, // <--
        { 1, 1, 1, 1 }
    };
    mat_t B{
        { 1, 0, 0, 0, 0 },
        { 2, 1, 0, 0, 0 },
        { 3, 0, 1, 0, 0 },
        { 4, 1, 1, 0, 0 },
        { 2, 0, 0, 1, 0 },
        { 2, 1, 0, 1, 0 },
        { 4, 0, 1, 1, 0 },
        { 4, 1, 1, 1, 0 },
        { 3, 0, 0, 0, 1 },
        { 4, 1, 0, 0, 1 },
        { 3, 0, 1, 0, 1 },
        { 4, 1, 1, 0, 1 },
        { 4, 0, 0, 1, 1 },
        { 4, 1, 0, 1, 1 },
        { 4, 0, 1, 1, 1 },
        { 4, 1, 1, 1, 1 }
    };
    mat_t C(4, vec_t(16));
    vec_t pos(4);
    for ( int i = 0; i < 16; ++i )
    {
        int row = B[i][0] - 1;
        int col = pos[row];
        int prod = std::inner_product( A[row].begin(), A[row].end(),
                                      ++(B[i].begin()), 0 );
        //                            ^^^ skip the first element
        C[row][col] = prod;
        if ( prod )
            ++pos[row];
    }
    for ( auto & r : C )
    {
        for ( int x : r ) {
            cout << ' ' << x;
        }
        cout << 'n';
    }
    return 0;
}

输出为:

 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
 1 1 2 0 0 0 0 0 0 0 0 0 0 0 0 0
 1 1 2 0 0 0 0 0 0 0 0 0 0 0 0 0
 2 2 3 2 3 2 3 3 4 0 0 0 0 0 0 0

我不知道最后一行的排序是否如预期,但它模仿了OP代码的逻辑。