当元素数 > 1000 时,如何制作向量的笛卡尔积?
How to make the cartesian products of vectors, when the number of elements > 1000?
我有 1,2,...,n 个向量。每个向量都有超过 10000 个元素,我必须得到这些向量的笛卡尔积。我有一个有效的代码,但只有不到 1000 个元素和 4 个向量。
我想将笛卡尔积写入文件,但如果输出文件大于 1GB,我会得到:"terminate called after throwing an instance of 'std::bad_alloc' what(): std::bad_alloc".
我的主要问题是,如何修复此内存分配错误?
这是我的一段可运行代码:
#include <iostream>
#include <vector>
#include <algorithm>
#include <time.h>
#include <fstream>
#include <math.h>
using namespace std;
vector<double> makeVectorByRange(double min, double max, double step){
vector<double> out = {};
for( ; min <= max; min+=step){
out.push_back(min);
}
return out;
}
void cart_product_solve_and_write_to_file (const vector<vector<double>>& inpV) {
vector<vector<double>> out = {{}};
std::ofstream outputFile;
std::fixed;
for (auto& u : inpV) {
vector<vector<double>> r;
r.clear();
for (auto& x : out) {
//make/open file, append
outputFile.open ("out.csv", std::ofstream::out | std::ofstream::app);
outputFile.precision(8);
for (auto y : u) {
r.push_back(x);
r.back().push_back(y);
if( r.back().size() == inpV.size() ){
// write the input parameters of griewank to file
for(double asd : r.back()){
outputFile << asd << ";";
}
outputFile << "; \n";
outputFile << std::flush;
r.back().clear();
}
}
//close file
outputFile.close();
}
out.swap(r);
}
}
// Pure cartesian product. This function returns the cartesian product as a vector, but if the input vectors are too big, it has an error
/*
vector < vector<double> > cartesian_product (const vector< vector<double> >& inpV) {
vector< vector<double> > out = {{}};
for (auto& u : inpV) {
vector< vector<double> > r;
for (auto& x : out) {
for (auto y : u) {
r.push_back(x);
r.back().push_back(y);
}
}
out.swap(r);
}
return out;
}
*/
int main(){
clock_t tStart = clock();
// it works
// const vector<vector<int> > test ={ {0,1,2,3,4}, {5,6,7}, {8,9,10,11,12,13} };
// vector<vector<int> > cart_prod = cartesian_product(test);
vector <vector<double> > test = {};
test.push_back( makeVectorByRange( 0, 0.5, 0.001) );
test.push_back( makeVectorByRange( 0, 0.5, 0.001) );
test.push_back( makeVectorByRange( 0, 0.5, 0.001) );
cart_product_solve_and_write_to_file(test);
printf("Time taken: %.6fs\n", (double)(clock() - tStart)/CLOCKS_PER_SEC);
return 0;
}
您需要迭代生成的笛卡尔积的所有组合。这通常通过递归来实现。然后在每个递归级别中迭代一个输入向量的元素。
这是将结果组合打印到 std::cout
的示例解决方案。您可以通过向递归函数提供一个打开的 std::ofstream
对象的附加参考参数来轻松修改它以打印到文件。
#include <iostream>
#include <vector>
template <typename T>
void vector_cartesian_product_helper(
const std::vector<std::vector<T>>& v, std::vector<T>& combination, size_t level)
{
if (level == v.size()) {
for (auto elem : combination)
std::cout << elem << ";";
std::cout << "\n";
}
else {
for (const auto& elem : v[level]) {
combination[level] = elem;
vector_cartesian_product_helper(v, combination, level + 1);
}
}
}
template <typename T>
void vector_cartesian_product(const std::vector<std::vector<T>>& v)
{
std::vector<T> combination(v.size());
vector_cartesian_product_helper(v, combination, 0);
}
int main(){
std::vector<std::vector<int>> test = {{0,1,2,3,4}, {5,6,7}, {8,9,10,11,12,13}};
vector_cartesian_product(test);
}
现场演示:https://wandbox.org/permlink/PoyEviWGDtEpvN1z
它适用于任何大小的向量,并且仅使用 O(N) 的额外内存,其中 N 是向量的数量.
我有 1,2,...,n 个向量。每个向量都有超过 10000 个元素,我必须得到这些向量的笛卡尔积。我有一个有效的代码,但只有不到 1000 个元素和 4 个向量。 我想将笛卡尔积写入文件,但如果输出文件大于 1GB,我会得到:"terminate called after throwing an instance of 'std::bad_alloc' what(): std::bad_alloc".
我的主要问题是,如何修复此内存分配错误?
这是我的一段可运行代码:
#include <iostream>
#include <vector>
#include <algorithm>
#include <time.h>
#include <fstream>
#include <math.h>
using namespace std;
vector<double> makeVectorByRange(double min, double max, double step){
vector<double> out = {};
for( ; min <= max; min+=step){
out.push_back(min);
}
return out;
}
void cart_product_solve_and_write_to_file (const vector<vector<double>>& inpV) {
vector<vector<double>> out = {{}};
std::ofstream outputFile;
std::fixed;
for (auto& u : inpV) {
vector<vector<double>> r;
r.clear();
for (auto& x : out) {
//make/open file, append
outputFile.open ("out.csv", std::ofstream::out | std::ofstream::app);
outputFile.precision(8);
for (auto y : u) {
r.push_back(x);
r.back().push_back(y);
if( r.back().size() == inpV.size() ){
// write the input parameters of griewank to file
for(double asd : r.back()){
outputFile << asd << ";";
}
outputFile << "; \n";
outputFile << std::flush;
r.back().clear();
}
}
//close file
outputFile.close();
}
out.swap(r);
}
}
// Pure cartesian product. This function returns the cartesian product as a vector, but if the input vectors are too big, it has an error
/*
vector < vector<double> > cartesian_product (const vector< vector<double> >& inpV) {
vector< vector<double> > out = {{}};
for (auto& u : inpV) {
vector< vector<double> > r;
for (auto& x : out) {
for (auto y : u) {
r.push_back(x);
r.back().push_back(y);
}
}
out.swap(r);
}
return out;
}
*/
int main(){
clock_t tStart = clock();
// it works
// const vector<vector<int> > test ={ {0,1,2,3,4}, {5,6,7}, {8,9,10,11,12,13} };
// vector<vector<int> > cart_prod = cartesian_product(test);
vector <vector<double> > test = {};
test.push_back( makeVectorByRange( 0, 0.5, 0.001) );
test.push_back( makeVectorByRange( 0, 0.5, 0.001) );
test.push_back( makeVectorByRange( 0, 0.5, 0.001) );
cart_product_solve_and_write_to_file(test);
printf("Time taken: %.6fs\n", (double)(clock() - tStart)/CLOCKS_PER_SEC);
return 0;
}
您需要迭代生成的笛卡尔积的所有组合。这通常通过递归来实现。然后在每个递归级别中迭代一个输入向量的元素。
这是将结果组合打印到 std::cout
的示例解决方案。您可以通过向递归函数提供一个打开的 std::ofstream
对象的附加参考参数来轻松修改它以打印到文件。
#include <iostream>
#include <vector>
template <typename T>
void vector_cartesian_product_helper(
const std::vector<std::vector<T>>& v, std::vector<T>& combination, size_t level)
{
if (level == v.size()) {
for (auto elem : combination)
std::cout << elem << ";";
std::cout << "\n";
}
else {
for (const auto& elem : v[level]) {
combination[level] = elem;
vector_cartesian_product_helper(v, combination, level + 1);
}
}
}
template <typename T>
void vector_cartesian_product(const std::vector<std::vector<T>>& v)
{
std::vector<T> combination(v.size());
vector_cartesian_product_helper(v, combination, 0);
}
int main(){
std::vector<std::vector<int>> test = {{0,1,2,3,4}, {5,6,7}, {8,9,10,11,12,13}};
vector_cartesian_product(test);
}
现场演示:https://wandbox.org/permlink/PoyEviWGDtEpvN1z
它适用于任何大小的向量,并且仅使用 O(N) 的额外内存,其中 N 是向量的数量.