vector<sp_mat> build_E_blocks(const Simulator * sim, const Discretizer * disc, double gamma, bool include_oob){ Points points = disc->get_spatial_nodes(); uint N; if(include_oob) N = disc->number_of_all_nodes(); else N = disc->number_of_spatial_nodes(); uint A = sim->num_actions(); uint Ad = sim->dim_actions(); mat actions = sim->get_actions(); assert(size(A,Ad) == size(actions)); uint num_samples = 25; vector<sp_mat> E_blocks; sp_mat I = speye(N,N); vec u; ElementDist P,Q; for(uint i = 0; i < A; i++){ P = ElementDist(N,N); u = actions.row(i).t(); cout << "\tAction [" << i << "]: u = " << u.t(); for(uint j = 0; j < num_samples; j++){ P += sim->transition_matrix(disc,u,include_oob); } P /= (double) num_samples; E_blocks.push_back(I - gamma * P); } assert(A == E_blocks.size()); return E_blocks; }
vector<sp_mat> build_hallway_blocks(const uint N, const double p_stick, const double gamma){ // Build the transition matrices for -1,0,1 vector<sp_mat> blocks; // Left sp_mat P_left = build_hallway_P(N,p_stick,-1); blocks.push_back(speye(N,N) - gamma * P_left); // Stay blocks.push_back((1-gamma) * speye(N,N)); //Right sp_mat P_right = build_hallway_P(N,p_stick,1); blocks.push_back(speye(N,N) - gamma * P_right); return blocks; }
sp_mat build_hallway_P(const uint N, const double p_stick, const int action){ // Build the hallway transition matrix associated with // and action assert(action == -1 or action == 1); sp_mat P = p_stick * speye(N,N) + spdiag((1-p_stick) * ones<vec>(N-1),action); if(action < 0) P(0,N-1) = (1 - p_stick); else P(N-1,0) = (1 - p_stick); return P; }
void newton_matrix(ode_workspace *odews) { // Create a Newton matrix from the given step gamma and Jacobian in W cs *M, *eye; if (odews->mdeclared) { cs_nfree(odews->N); } else { odews->mdeclared = 1; } eye = speye(odews->W->J->m); M = cs_add(eye, odews->W->J, 1, -odews->dt); cs_spfree(eye); odews->N = cs_lu(M, odews->S, 1); cs_spfree(M); }
sp_mat Device1D::qCMatFunct(mat phin, mat phip, bool Equilibrum) { if ( phin.n_elem != sumPoint || ( phip.n_elem != sumPoint ) ) std::cerr << "Error: input wrong phin/phip size!" << std::endl; sp_mat cp=speye(sumPoint, sumPoint); if (Equilibrum == true ) { for ( int i = 0; i < bandGapArray.size(); i++) { phip(i) = bandGapArray[i] - phin(i); } } int k=0; for ( int i=0; i < materialList.size(); i++) { for ( int j=0; j < nyList[i]; j++) { if (typeList[i] == Semiconductor) { cp(k + 1, k + 1) = materialList[i].quantumCapa((double)phin(k), (double)phip(k)); //TODO: why here used to be k+1, then "cp(0, 0) = cp(1, 1);" } else if (typeList[i]==Dielectric) { }; k++; }; }; return ( cp ); }
SolverResult KojimaSolver::solve(const LCP & lcp, vec & x, vec & y) const{ superlu_opts opts; opts.equilibrate = true; opts.permutation = superlu_opts::COLAMD; opts.refine = superlu_opts::REF_SINGLE; vec q = lcp.q; sp_mat M = lcp.M + regularizer * speye(size(lcp.M)); uint N = q.n_elem; assert(N == x.n_elem); assert(N == y.n_elem); // Figure out what is free (-inf,inf) // and what is bound to be non-negative [0,inf) bvec free_vars = lcp.free_vars; uvec bound_idx = find(0 == free_vars); uvec free_idx = find(1 == free_vars); assert(N == bound_idx.n_elem + free_idx.n_elem); uint NB = bound_idx.n_elem; // number of bound vars uint NF = free_idx.n_elem; // number of free vars /* In what follows, the primal variables x are partitioned into free variables and bound variables x = [f;b]' Likewise, the dual variables are partitioned into y = [0,s]' */ /* The Newton system: [M_ff M_fb 0][df] [M_f x + q_f] [M_bf M_bb -I][db] + [M_b x + q_b - s] [0 S B][dv] [u1 + VBe] Where "M_ff" is the free-free block Overwrite the S,B diagonals every iteration*/ // Split M matrix into blocks based on free and bound indicies block_sp_mat M_part = sp_partition(M,free_idx,bound_idx); sp_mat M_recon = block_mat(M_part); assert(PRETTY_SMALL > norm(M_recon - M)); vec qf = q(free_idx); vec qb = q(bound_idx); vec b = x(bound_idx); vec f = x(free_idx); vec s = y(bound_idx); // Build the Newton matrix vector<vector<sp_mat>> block_G; block_G.push_back(block_sp_vec{sp_mat(),sp_mat(),sp_mat(NB,NB)}); block_G.push_back(block_sp_vec{-M_part[0][0],-M_part[0][1],sp_mat()}); block_G.push_back(block_sp_vec{-M_part[1][0],-M_part[1][1],speye(NB,NB)}); // Start iteration double mean_comp, steplen; double sigma = initial_sigma; uint iter; for(iter = 0; iter < max_iter; iter++){ if(verbose or iter_verbose) cout << "---Iteration " << iter << "---" << endl; assert(all(0 == y(free_idx))); // Mean complementarity mean_comp = dot(b,s) / (double) NB; if(mean_comp < comp_thresh) break; block_G[0][1] = spdiag(s); block_G[0][2] = spdiag(b); sp_mat G = block_mat(block_G); assert(size(N + NB,N + NB) == size(G)); // Form RHS from residual and complementarity vec h = vec(N + NB); vec res_f = M_part[0][0]*f + M_part[0][1]*b + qf; vec res_b = M_part[1][0]*f + M_part[1][1]*b + qb - s; h.head(NB) = sigma * mean_comp - b % s; h.subvec(NB,size(res_f)) = res_f; h.tail(NB) = res_b; //Archiver arch; //arch.add_sp_mat("G",G); //arch.add_vec("h",h); //arch.write("test.sys"); // Solve and extract directions vec dir = spsolve(G,h,"superlu",opts); assert((N+NB) == dir.n_elem); vec df = dir.head(NF); vec db = dir.subvec(NF,N-1); assert(NB == db.n_elem); vec ds = dir.tail(NB); vec dir_recon = join_vert(df,join_vert(db,ds)); assert(PRETTY_SMALL > norm(dir_recon-dir)); steplen = steplen_heuristic(b,s,db,ds,0.9); sigma = sigma_heuristic(sigma,steplen); f += steplen * df; b += steplen * db; s += steplen * ds; if(verbose){ double res = norm(join_vert(res_f,res_b)); cout <<"\t Mean complementarity: " << mean_comp <<"\n\t Residual norm: " << res <<"\n\t |df|: " << norm(df) <<"\n\t |db|: " << norm(db) <<"\n\t |ds|: " << norm(ds) <<"\n\t Step length: " << steplen <<"\n\t Centering sigma: " << sigma << endl; } } if(verbose){ cout << "Finished" <<"\n\t Final mean complementarity: " << mean_comp << endl; } x(free_idx) = f; x(bound_idx) = b; y(free_idx).fill(0); y(bound_idx) = s; return SolverResult(x,y,iter); }
SolverResult ProjectiveSolver::solve(const PLCP & plcp, vec & x, vec & y, vec & w) const{ sp_mat P = plcp.P; sp_mat U = plcp.U; vec q = plcp.q; uint N = P.n_rows; uint K = P.n_cols; assert(size(P.t()) == size(U)); bvec free_vars = plcp.free_vars; uvec bound_idx = find(0 == free_vars); uvec free_idx = find(1 == free_vars); assert(N == bound_idx.n_elem + free_idx.n_elem); uint NB = bound_idx.n_elem; // number of bound vars uint NF = free_idx.n_elem; // number of free vars assert(NF == accu(conv_to<uvec>::from(free_vars))); assert(N == x.n_elem); assert(N == y.n_elem); assert(K == w.n_elem); assert(ALMOST_ZERO > norm(y(free_idx))); if(verbose) cout << "Free variables: \t" << NF << endl << "Non-neg variables:\t" << NB << endl; sp_mat J = join_vert(sp_mat(NF,NB),speye(NB,NB)); assert(size(N,NB) == size(J)); assert(PRETTY_SMALL > norm(y(free_idx))); if(verbose) cout << "Forming pre-computed products..." << endl; mat PtP = mat(P.t() * P); assert(size(K,K) == size(PtP)); mat PtPU = PtP*U; assert(size(K,N) == size(PtPU)); mat Pt_PtPU = P.t() - PtPU; assert(size(K,N) == size(Pt_PtPU)); mat PtPUP = PtPU * P; assert(size(K,K) == size(PtPUP)); vec Ptq = P.t() * q; if(verbose) cout << "Done..." << endl; double sigma = initial_sigma; uint iter; double mean_comp; for(iter = 0; iter < max_iter; iter++){ if(verbose or iter_verbose) cout << "---Iteration " << iter << "---" << endl; // Mean complementarity vec s = y(bound_idx); vec b = x(bound_idx); mean_comp = dot(s,b) / (double) NB; if(mean_comp < comp_thresh) break; // Generate reduced Netwon system mat C = s+b; vec g = sigma * mean_comp - s % b; assert(NB == g.n_elem); // NB: A,G,and h have opposite sign from python version mat A = Pt_PtPU * J * spdiag(1.0 / C); assert(size(K,NB) == size(A)); mat G = PtPUP + (A * spdiag(s)) * J.t() * P; assert(size(K,K) == size(G)); vec Ptr = P.t() * (J * s) - PtPU*x - Ptq; vec h = Ptr + A*g; assert(K == h.n_elem); // Options don't make much difference vec dw = arma::solve(G+1e-15*eye(K,K),h, solve_opts::equilibrate); assert(K == dw.n_elem); // Recover dy vec Pdw = P * dw; vec JtPdw = J.t() * Pdw; assert(NB == JtPdw.n_elem); vec ds = (g - s % JtPdw) / C; assert(NB == ds.n_elem); // Recover dx vec dx = (J * ds) + (Pdw); assert(N == dx.n_elem); double steplen = steplen_heuristic(x(bound_idx),s,dx(bound_idx),ds,0.9); sigma = sigma_heuristic(sigma,steplen); x += steplen * dx; s += steplen * ds; y(bound_idx) = s; w += steplen * dw; if(verbose){ cout <<"\tMean complementarity: " << mean_comp <<"\n\tStep length: " << steplen <<"\n\tCentering sigma: " << sigma << endl; } } if(verbose){ cout << "Finished" <<"\n\t Final mean complementarity: " << mean_comp << endl; } return SolverResult(x,y,iter); }
PLCP augment_plcp(const PLCP & original, vec & x, vec & y, vec & w, double scale){ uint N = original.P.n_rows; uint K = original.P.n_cols; assert(size(K,N) == size(original.U)); sp_mat P = sp_mat(original.P); double I_norm = norm(speye(K,K) - P.t() * P); if(norm(I_norm) >= PRETTY_SMALL){ cerr << "Error: P does not look orthogonal (" << I_norm << ")..." << endl; } assert(I_norm < PRETTY_SMALL); sp_mat U = sp_mat(original.U); vec q = vec(original.q); assert(all(q(find(1 == original.free_vars)) <= 0)); vec q_neg = min(zeros<vec>(N),q); vec q_pos = max(zeros<vec>(N),q); x = ones<vec>(N) - q_neg; y = ones<vec>(N) + q_pos; y(find(1 == original.free_vars)).fill(0); assert(norm(q_pos(find(1 == original.free_vars))) < ALMOST_ZERO); assert(N == x.n_elem); assert(N == y.n_elem); assert(all(x >= 0)); assert(all(y >= 0)); vec res = x - y + q; w = spsolve(P.t()*P + 1e-15*speye(K,K),P.t()*(x - y + q)); vec w_res = P * w - res; if(norm(w_res) >= PRETTY_SMALL){ cerr << "Error: Reduced vector w residual large (" << w_res << ")..." << endl; } assert(norm(w_res) < PRETTY_SMALL); vec b = P.t()*x - U*x - w; assert(K == b.n_elem); P.resize(N+1,K+1); U.resize(K+1,N+1); q.resize(N+1); P(N,K) = 1.0; U(span(0,K-1),N) = b; U(K,N) = scale; q(N) = 0; x.resize(N+1); y.resize(N+1); w.resize(K+1); x(N) = 1; y(N) = scale; w(K) = 1.0 - scale; bvec free_vars = bvec(N+1); free_vars.head(N) = original.free_vars; free_vars(N) = 0; return PLCP(P,U,q,free_vars); }