C ++迭代稀疏矩阵近似

时间:2015-12-26 09:41:51

标签: c++ sparse-matrix linear numerical

实现的算法比本书所说的要复杂得多,而且我不认为它正在进行正确的计算。该算法应该计算一个经济体中每种商品的成本(工作时间或“劳动力”)(数百万/十亿),因此复杂性非常重要。从书中引用:

  

一个经济体的投入产出表实际上可能主要是空白。实际上,每种产品平均只有几十或几百的投入,而不是一百万。这使得用列表矢量而不是矩阵表示系统更经济。因此,可以采取捷径来达成结果。我们可以使用另一种方法,即逐次逼近的方法。这里的想法是,作为第一近似,我们忽略了除直接消耗的劳动之外的生产过程的所有输入。这为我们提供了每种产品劳动价值的第一个近似估计值。这将被低估,因为它忽略了生产过程中的非劳动投入。为了得出我们的第二个近似值,我们在第一阶段计算的劳动力价值的基础上增加了非劳动投入。这将使我们更接近真正的劳动价值观。重复应用此过程将为我们提供所需精确度的答案。如果平均产品的价值的一半来自直接人工投入,那么围绕我们的近似过程的每次迭代将在我们的答案中添加一个重要的二进制数字。对于四个有效小数位数(这比市场可以实现的更好)的答案是正确的,我们的近似过程需要大约15次迭代。

     

此算法的时间顺序复杂度与产品数量乘以每个产品的平均输入数量,乘以数字所需的结果精度成正比。根据我们先前的假设,这可以在几分钟内在超级计算机上计算,而不是高斯消除所需的数千年(8)。

     

(8)Hodgson(1984,p.170)指出,求解输入 - 输出表的最佳方法涉及n ^ 2次计算。虽然他没有对这种说法做出任何解释,但我们认为他必须认识到使用迭代技术(否则复杂性将是n ^ 3),但他没有认识到技术系数矩阵将是稀疏的。如上所述,更好地利用数据结构可以大大降低复杂性。

我的实施:我不完全理解算法,你是否应该分别存储间接和直接和最终的劳动?有些东西让我的价值呈指数增长而不是收敛,变得更加精确,就像我认为的那样。

代码:(ioapprox.hpp)

#include <string>
#include <forward_list>
#include <algorithm>
#include <iostream>

struct com_node {
    double key;
    int active = 0;
    std::string name;
    std::forward_list<com_node*> input_list;
    float direct_labor = 0;
    float indirect_labor = 0;
    float fin_labor = 0;
};

struct com_matrix {
    double max_key = 0;
    std::forward_list<com_node*> com_list;
    void add(std::string, float);
    void add_input(double, double);
    void update_direct_labor();
    void update_fin_labor();
    void it_through_matrix(int xr);
    void prt_matrix();
};

// Complexity: O(1)
void com_matrix::add(std::string cname, float pdlc) {
    com_node * ind = new com_node;
    ind->key = max_key; max_key++;
    ind->direct_labor = pdlc;
    ind->name = cname;
    com_list.push_front(ind);
}//end add()

// Complexity: O(n)
void com_matrix::add_input(double ker1, double ker2) {
    int sent = 0;
    int sent2 = 0;
    com_node * save1 = 0;
    com_node * save2 = 0;
    for (std::forward_list<com_node*>::const_iterator iterator3 = com_list.begin(); iterator3 != com_list.end(); ++iterator3) {
        com_node * h = *iterator3;
        if (h->key == ker1) {
            sent = 1;
            save1 = h;
        }
    }
    for (std::forward_list<com_node*>::const_iterator iterator4 = com_list.begin(); iterator4 != com_list.end(); ++iterator4) {
        com_node * b = *iterator4;
        if (b->key == ker2) {
            sent2 = 1;
            save2 = b;
        }
    }
    if (sent == 0 && sent2 == 0) {
        save1->input_list.push_front(save2);
    }
}//end add_input()

// Complexity: O(n^2)
void com_matrix::update_direct_labor() {
    for (std::forward_list<com_node*>::const_iterator iterator = com_list.begin(); iterator != com_list.end(); ++iterator) {
        com_node * k = *iterator;
        float nidl = 0;
        for (std::forward_list<com_node*>::const_iterator iterator2 = (k->input_list).begin(); iterator2 != (k->input_list).end(); ++iterator2) {
            com_node * j = *iterator2;
            nidl += j->fin_labor;
        }//end for
        k->indirect_labor = nidl;
    }//end for
}//end update_direct_labor()

//Complexity O(n)
void com_matrix::update_fin_labor() {
    for (std::forward_list<com_node*>::const_iterator iterator = com_list.begin(); iterator != com_list.end(); ++iterator) {
        com_node * m = *iterator;
        m->fin_labor = (m->direct_labor + m->indirect_labor);
    }//end for
}//end update_fin_labor()

void com_matrix::prt_matrix() {
    for (std::forward_list<com_node*>::const_iterator iterator = com_list.begin(); iterator != com_list.end(); ++iterator) {
        com_node * v = *iterator;
        std::cout << std::to_string(v->key) << " | " << v->name << " | " << std::to_string(v->fin_labor) << std::endl;
    }//end for
    std::cout << std::endl;
}//end prt_matrix()

// Complexity: Cubic, unfortunately
void com_matrix::it_through_matrix(int r = 15) {
    for (int i = 0; i < r; i++) {
        update_direct_labor();
        update_fin_labor();
        prt_matrix();
    }//end for
}//end it_through_matrix()

更多代码(ioapprox.cpp)

#include "ioapprox.hpp"

int main() {

    com_matrix g;

    for (int i = 0; i < 1200; i++) {
        g.add(std::to_string(i), rand());
    }
    for (int n = 0; n < 1200; n++) {
        g.add_input(rand()%1200,rand()%1200);
    }
    g.it_through_matrix(3);
}

0 个答案:

没有答案