double Lasso(size_t m, size_t n) { std::vector<T> A(m * n); std::vector<T> b(m); std::default_random_engine generator; std::uniform_real_distribution<T> u_dist(static_cast<T>(0), static_cast<T>(1)); std::normal_distribution<T> n_dist(static_cast<T>(0), static_cast<T>(1)); for (unsigned int i = 0; i < m * n; ++i) A[i] = n_dist(generator); std::vector<T> x_true(n); for (unsigned int i = 0; i < n; ++i) x_true[i] = u_dist(generator) < static_cast<T>(0.8) ? static_cast<T>(0) : n_dist(generator) / static_cast<T>(std::sqrt(n)); #ifdef _OPENMP #pragma omp parallel for #endif for (unsigned int i = 0; i < m; ++i) for (unsigned int j = 0; j < n; ++j) b[i] += A[i * n + j] * x_true[j]; // b[i] += A[i + j * m] * x_true[j]; for (unsigned int i = 0; i < m; ++i) b[i] += static_cast<T>(0.5) * n_dist(generator); T lambda_max = static_cast<T>(0); #ifdef _OPENMP #pragma omp parallel for reduction(max : lambda_max) #endif for (unsigned int j = 0; j < n; ++j) { T u = 0; for (unsigned int i = 0; i < m; ++i) //u += A[i * n + j] * b[i]; u += A[i + j * m] * b[i]; lambda_max = std::max(lambda_max, std::abs(u)); } pogs::MatrixDense<T> A_('r', m, n, A.data()); pogs::PogsDirect<T, pogs::MatrixDense<T> > pogs_data(A_); std::vector<FunctionObj<T> > f; std::vector<FunctionObj<T> > g; f.reserve(m); for (unsigned int i = 0; i < m; ++i) f.emplace_back(kSquare, static_cast<T>(1), b[i]); g.reserve(n); for (unsigned int i = 0; i < n; ++i) g.emplace_back(kAbs, static_cast<T>(0.2) * lambda_max); double t = timer<double>(); pogs_data.Solve(f, g); return timer<double>() - t; }
double LpEq(int m, int n, int nnz) { std::vector<T> val(nnz); std::vector<int> col_ind(nnz); std::vector<int> row_ptr(m + 2); std::vector<T> x(n); std::vector<T> y(m + 1); std::default_random_engine generator; std::uniform_real_distribution<T> u_dist(static_cast<T>(0), static_cast<T>(1)); // Enforce c == rand(n, 1) std::vector<std::tuple<int, int, T>> entries; entries.reserve(n); for (int i = 0; i < n; ++i) { entries.push_back(std::make_tuple(m, i, u_dist(generator))); } // Generate A and c according to: // A = 4 / n * rand(m, n) nnz = MatGenApprox(m + 1, n, nnz, val.data(), row_ptr.data(), col_ind.data(), static_cast<T>(0), static_cast<T>(4.0 / n), entries); pogs::MatrixSparse<T> A_('r', m + 1, n, nnz, val.data(), row_ptr.data(), col_ind.data()); pogs::PogsIndirect<T, pogs::MatrixSparse<T>> pogs_data(A_); std::vector<FunctionObj<T> > f; std::vector<FunctionObj<T> > g; // Generate b according to: // v = rand(n, 1) // b = A * v std::vector<T> v(n); for (unsigned int i = 0; i < n; ++i) v[i] = u_dist(generator); f.reserve(m + 1); for (unsigned int i = 0; i < m; ++i) { T b_i = static_cast<T>(0); for (unsigned int j = row_ptr[i]; j < row_ptr[i + 1]; ++j) b_i += val[j] * v[col_ind[j]]; f.emplace_back(kIndEq0, static_cast<T>(1), b_i); } f.emplace_back(kIdentity); g.reserve(n); for (unsigned int i = 0; i < n; ++i) g.emplace_back(kIndGe0); double t = timer<double>(); pogs_data.Solve(f, g); return timer<double>() - t; }
T LpIneq(size_t m, size_t n) { std::vector<T> A(m * n); std::vector<T> x(n); std::vector<T> y(m); std::default_random_engine generator; std::uniform_real_distribution<T> u_dist(static_cast<T>(0), static_cast<T>(1)); // Generate A according to: // A = [-1 / n *rand(m - n, n); -eye(n)] for (unsigned int i = 0; i < (m - n) * n; ++i) A[i] = -static_cast<T>(1) / static_cast<T>(n) * u_dist(generator); for (unsigned int i = static_cast<unsigned int>((m - n) * n); i < m * n; ++i) A[i] = (i - (m - n) * n) % (n + 1) == 0 ? -1 : 0; PogsData<T, T*> pogs_data(A.data(), m, n); pogs_data.x = x.data(); pogs_data.y = y.data(); // Generate b according to: // b = A * rand(n, 1) + 0.2 * rand(m, 1) pogs_data.f.reserve(m); for (unsigned int i = 0; i < m; ++i) { T b_i = static_cast<T>(0); for (unsigned int j = 0; j < n; ++j) b_i += A[i * n + j] * u_dist(generator); b_i += static_cast<T>(0.2) * u_dist(generator); pogs_data.f.emplace_back(kIndLe0, static_cast<T>(1), b_i); } // Generate c according to: // c = rand(n, 1) pogs_data.g.reserve(n); for (unsigned int i = 0; i < n; ++i) pogs_data.g.emplace_back(kIdentity, u_dist(generator)); T t = timer<T>(); Pogs(&pogs_data); return timer<T>() - t; }
void SolverWrap(SEXP A, SEXP fin, SEXP gin, SEXP params, SEXP x, SEXP y, SEXP u, SEXP v, SEXP opt, SEXP status) { SEXP Adim = GET_DIM(A); size_t m = INTEGER(Adim)[0]; size_t n = INTEGER(Adim)[1]; unsigned int num_obj = length(fin); pogs::MatrixDense<T> A_dense('c', m, n, REAL(A)); // Initialize Pogs data structure pogs::PogsDirect<T, pogs::MatrixDense<T> > pogs_data(A_dense); std::vector<FunctionObj<T> > f, g; f.reserve(m); g.reserve(n); // Populate parameters. PopulateParams(params, &pogs_data); // Allocate space for factors if more than one objective. int err = 0; for (unsigned int i = 0; i < num_obj && !err; ++i) { // Populate function objects. f.clear(); g.clear(); PopulateFunctionObj(VECTOR_ELT(fin, i), m, &f); PopulateFunctionObj(VECTOR_ELT(gin, i), n, &g); // Run solver. INTEGER(status)[i] = pogs_data.Solve(f, g); // Get Solution memcpy(REAL(x) + i * n, pogs_data.GetX(), n * sizeof(T)); memcpy(REAL(y) + i * m, pogs_data.GetY(), m * sizeof(T)); memcpy(REAL(u) + i * n, pogs_data.GetMu(), n * sizeof(T)); memcpy(REAL(v) + i * m, pogs_data.GetLambda(), m * sizeof(T)); REAL(opt)[i] = pogs_data.GetOptval(); } }
void SolverWrap(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { size_t m = mxGetM(prhs[0]); size_t n = mxGetN(prhs[0]); // Convert column major (matlab) to row major (c++). T* A = new T[m * n]; ColToRowMajor(reinterpret_cast<T*>(mxGetPr(prhs[0])), m, n, A); // Initialize Pogs data structure PogsData<T, T*> pogs_data(A, m, n); pogs_data.f.reserve(m); pogs_data.g.reserve(n); pogs_data.x = reinterpret_cast<T*>(mxGetPr(plhs[0])); if (nlhs >= 2) pogs_data.y = reinterpret_cast<T*>(mxGetPr(plhs[1])); // Populate parameters. int err = 0; if (nrhs == 4) err = PopulateParams(prhs[3], &pogs_data); // Populate function objects. if (err == 0) err = PopulateFunctionObj("f", prhs[1], m, &pogs_data.f); if (err == 0) err = PopulateFunctionObj("g", prhs[2], n, &pogs_data.g); // Run solver. if (err == 0) Pogs(&pogs_data); if (nlhs >= 3) reinterpret_cast<T*>(mxGetPr(plhs[2]))[0] = pogs_data.optval; delete [] A; }
double Logistic(size_t m, size_t n) { std::vector<T> A(m * (n + 1)); std::vector<T> d(m); std::vector<T> x(n + 1); std::vector<T> y(m); std::default_random_engine generator; std::uniform_real_distribution<T> u_dist(static_cast<T>(0), static_cast<T>(1)); std::normal_distribution<T> n_dist(static_cast<T>(0), static_cast<T>(1)); for (unsigned int i = 0; i < m; ++i) { for (unsigned int j = 0; j < n; ++j) A[i * (n + 1) + j] = n_dist(generator); A[i * (n + 1) + n] = 1; } std::vector<T> x_true(n + 1); for (unsigned int i = 0; i < n; ++i) x_true[i] = u_dist(generator) < 0.8 ? 0 : n_dist(generator) / n; x_true[n] = n_dist(generator) / n; #pragma omp parallel for for (unsigned int i = 0; i < m; ++i) { d[i] = 0; for (unsigned int j = 0; j < n + 1; ++j) // u += A[i + j * m] * x_true[j]; d[i] += A[i * n + j] * x_true[j]; } for (unsigned int i = 0; i < m; ++i) d[i] = 1 / (1 + std::exp(-d[i])) > u_dist(generator); T lambda_max = static_cast<T>(0); #pragma omp parallel for reduction(max : lambda_max) for (unsigned int j = 0; j < n; ++j) { T u = 0; for (unsigned int i = 0; i < m; ++i) // u += A[i * n + j] * (static_cast<T>(0.5) - d[i]); u += A[i + j * m] * (static_cast<T>(0.5) - d[i]); lambda_max = std::max(lambda_max, std::abs(u)); } Dense<T, ROW> A_(A.data()); PogsData<T, Dense<T, ROW>> pogs_data(A_, m, n + 1); pogs_data.x = x.data(); pogs_data.y = y.data(); pogs_data.f.reserve(m); for (unsigned int i = 0; i < m; ++i) pogs_data.f.emplace_back(kLogistic, 1, 0, 1, -d[i]); pogs_data.g.reserve(n + 1); for (unsigned int i = 0; i < n; ++i) pogs_data.g.emplace_back(kAbs, static_cast<T>(0.5) * lambda_max); pogs_data.g.emplace_back(kZero); double t = timer<double>(); Pogs(&pogs_data); return timer<double>() - t; }