返回所有行,或者只返回最后一行

Returning all rows, or just the last one

本文关键字:返回 一行 最后 或者      更新时间:2023-10-16

我正在写一堆(十几个)算法,它们以以下模式迭代处理向量:

ArrayXd prev;
ArrayXd curr;
prev = some_initial_vector();
for (i = 0; i < N; ++i) {
    // do lots of stuff, many lines to compute curr
    // use lots of algorithm specific variables initialised above
    ...
    prev = curr;
}
return curr;

我希望有一种方法可以返回curr的值的整个历史,以及ArrayXXd中的行。

我曾尝试通过编写两个显示curr句柄的类来解决这个问题,一个作为ArrayXd &,另一个作为Block<ArrayXXd, 1, -1>,但由于无法重新分配Block s,所以失败了。

解决这个问题的好方法是什么?也许我可以将BlockArrayXd本身存储在std::vector中,然后在最后将其转换为ArrayXXd

编辑:添加样本输入,输出

struct NotAccumulator {
    typedef ArrayXd return_type;
    ArrayXd curr;
    ArrayXd prev;
    void record () {}
    return_type result() {
        return prev;
    }
};
struct RowAccumulator {
    typedef ArrayXXd return_type;
    ArrayXd curr;
    ArrayXd prev;
    RowAccumulator(const uint N) {
        history.reserve(N);
    }
    void record () {
        history.push_back(curr);
    }
    return_type result () {
        uint rows = history.size();
        uint cols = history[0].size();
        ArrayXXd result_matrix (rows, cols);
        for(uint i = 0; i < rows; ++i) {
            result_matrix.row(i) = Map<ArrayXd> (history[i].data(), cols);
        }
        return result_matrix;
    }
private:
    std::vector<ArrayXd> history;
};
template <typename Accumulator>
typename Accumulator::return_type add_one(const ArrayXd & start, const uint how_many_times, Accumulator & u) {
    u.prev = start;
    for (uint i = 0; i < how_many_times; ++i) {
        u.curr = 1 + u.prev;
        u.record();
        u.prev = u.curr;
    }
    return u.result();
}
ArrayXd start (3);
start << 1, 0, -1;
NotAccumulator notAccumulator;
RowAccumulator rowAccumulator (5);
cout << add_one(start, 5, notAccumulator) << endl;
// outputs 6 5 4
cout << add_one(start, 5, rowAccumulator) << endl;
// outputs 2 1 0n 3 2 1n ... 6 5 4

如果您想尽可能避免数据复制,可以提前分配N-行ArrayXXd,避免使用return

prevcurr这样的缓冲器也是不必要的。以下代码还假设迭代次数N是预先已知的。

void GenerateHistory(int N, ArrayXXd* result) {
    result.row(0) = gen_row0_without_prev();
    for(int curr=1; curr<N; curr++) {
        result.row(curr) = gen_row_with_prev_row(result.row(curr-1));
    }
}

你可以用调用这个函数

int N = 100;
int m = 20;
ArrayXXd history(N, m);
GenerateHistory(N, &history);

编辑

让我们把复印的问题放在一边。这里有一个更新的代码,应该根据您的代码示例来满足要求。

ArrayXXd add_one(const ArrayXd& start, int num_iterations, bool acc) {
    if (acc) {
        ArrayXXd result = start;
        for(int i=0; i<num_iterations; i++) {
            result = result + 1;
        }
        return result;
    } else {
        ArrayXXd result(num_iterations, start.cols());
        result.row(0)=start+1;
        for(int i=1; i<num_iterations; i++) {
            result.row(i)=result.row(i-1);
        }
        return result;
    }
}
ArrayXd start (3);
start << 1, 0, -1;
bool acc = true;
cout << add_one(start, 5, !acc) << endl;
// outputs 6 5 4
cout << add_one(start, 5, acc) << endl;
// outputs 2 1 0n 3 2 1n ... 6 5 4