// currently only hacked for spheres, with radius and sd as two parameters bool HipGISAXS::fit_steepest_descent(real_t zcut, real_t radius_min, real_t radius_max, real_t radius_num, real_t sd_min, real_t sd_max, real_t sd_num, unsigned int dim, MPI::Intracomm& world_comm, int x_min, int x_max, int x_step) { int mpi_rank = world_comm.Get_rank(); if(!init_steepest_fit(world_comm, zcut)) return false; int num_alphai = 0, num_phi = 0, num_tilt = 0;; real_t alphai_min, alphai_max, alphai_step; HiGInput::instance().scattering_alphai(alphai_min, alphai_max, alphai_step); if(alphai_max < alphai_min) alphai_max = alphai_min; if(alphai_min == alphai_max || alphai_step == 0) num_alphai = 1; else num_alphai = (alphai_max - alphai_min) / alphai_step + 1; real_t phi_min, phi_max, phi_step; HiGInput::instance().scattering_inplanerot(phi_min, phi_max, phi_step); if(phi_step == 0) num_phi = 1; else num_phi = (phi_max - phi_min) / phi_step + 1; real_t tilt_min, tilt_max, tilt_step; HiGInput::instance().scattering_tilt(tilt_min, tilt_max, tilt_step); if(tilt_step == 0) num_tilt = 1; else num_tilt = (tilt_max - tilt_min) / tilt_step + 1; std::cout << "** Num alphai: " << num_alphai << std::endl << "** Num phi: " << num_phi << std::endl << "** Num tilt: " << num_tilt << std::endl; // prepare parameters std::vector<std::vector<real_t> > params; int num_params = 2; std::vector<real_t> temp; real_t deltap = 0.0; if(radius_num <= 1) temp.push_back(radius_min); else { deltap = fabs(radius_max - radius_min) / (radius_num - 1); for(int i = 0; i < radius_num; ++ i) { temp.push_back(radius_min + i * deltap); } // for } // if-else params.push_back(temp); temp.clear(); if(sd_num <= 1) temp.push_back(sd_min); else { deltap = fabs(sd_max - sd_min) / (sd_num - 1); for(int i = 0; i < sd_num; ++ i) { temp.push_back(sd_min + i * deltap); } // for } // if-else params.push_back(temp); temp.clear(); // this will work only on one shape and one structure const real_t err_threshold = 1e-8; const unsigned int max_iter = 200; std::vector<real_t> param_vals; //param_vals.push_back(16.0); //param_vals.push_back(6.0); param_vals.push_back(23.0); param_vals.push_back(2.0); std::vector<real_t> param_deltas; param_deltas.push_back(0.05); param_deltas.push_back(0.05); real_t gamma_const = 0.05; real_t qdeltay = QGrid::instance().delta_y(); real_t alpha_i = alphai_min; // high level of parallelism here (alphai, phi, tilt) for dynamicity ... for(int i = 0; i < num_alphai; i ++, alpha_i += alphai_step) { real_t alphai = alpha_i * PI_ / 180; real_t phi = phi_min; for(int j = 0; j < num_phi; j ++, phi += phi_step) { real_t tilt = tilt_min; for(int k = 0; k < num_tilt; k ++, tilt += tilt_step) { std::cout << "-- Computing reference GISAXS " << i * num_phi * num_tilt + j * num_tilt + k + 1 << " / " << num_alphai * num_phi * num_tilt << " [alphai = " << alpha_i << ", phi = " << phi << ", tilt = " << tilt << "] ..." << std::endl; /* run the reference gisaxs simulation using input params */ real_t* ref_data = NULL; if(!run_gisaxs(alpha_i, alphai, phi, tilt, ref_data, world_comm)) { if(mpi_rank == 0) std::cerr << "error: could not finish successfully" << std::endl; return false; } // if if(dim != 1) { std::cerr << "uh-oh: only 1D is supported for now" << std::endl; return false; } // if real_t* ref_z_cut = new (std::nothrow) real_t[nqy_]; for(unsigned int iy = 0; iy < nqy_; ++ iy) { // assuming nqz_ == 1 ... ref_z_cut[iy] = ref_data[nqx_ * iy + 0]; } // for delete[] ref_data; // this will store z cut values for each iteration for plotting later real_t* z_cuts = new (std::nothrow) real_t[nqy_ * max_iter]; real_t* temp_zcuts = new (std::nothrow) real_t[nqy_]; // do some preprocessing // start the main loop, bound by max_iter and err_threshold // compute gisaxs for current parameter values // compute the neighbors parameter values // for 12 combinations of current and neighbors, compute gisaxs and error // compute the derivatives (gradient) and error stuff // update parameter values // compute the error surface real_t err = 10.0; std::vector<real_t> param1_list; std::vector<real_t> param2_list; structure_iterator_t structure_iter = HiGInput::instance().structure_begin(); Structure* structure = &((*structure_iter).second); Shape* shape = HiGInput::instance().shape(*structure); shape_param_iterator_t shape_param = (*shape).param_begin(); real_t* data = NULL; std::vector<real_t> param_error_data; for(unsigned int iter = 0; iter < max_iter; ++ iter) { param1_list.clear(); param1_list.push_back(param_vals[0] - 2 * param_deltas[0]); // p1mm param1_list.push_back(param_vals[0] - param_deltas[0]); // p1m param1_list.push_back(param_vals[0]); // p1 param1_list.push_back(param_vals[0] + param_deltas[0]); // p1p param1_list.push_back(param_vals[0] + 2 * param_deltas[0]); // p1pp param2_list.clear(); param2_list.push_back(param_vals[1] - 2 * param_deltas[1]); // p2mm param2_list.push_back(param_vals[1] - param_deltas[1]); // p2m param2_list.push_back(param_vals[1]); // p2 param2_list.push_back(param_vals[1] + param_deltas[1]); // p2p param2_list.push_back(param_vals[1] + 2 * param_deltas[1]); // p2pp // current point (*shape_param).second.mean(param1_list[2]); (*shape_param).second.deviation(param2_list[2]); if(!run_gisaxs(alpha_i, alphai, phi, tilt, data, world_comm)) { if(mpi_rank == 0) std::cerr << "error: could not finish successfully" << std::endl; return false; } // if for(unsigned int iy = 0; iy < nqy_; ++ iy) { // assuming nqz_ == 1 ... z_cuts[iter * nqy_ + iy] = data[nqx_ * iy]; } // for delete[] data; data = NULL; real_t err22 = compute_cut_fit_error(z_cuts + iter * nqy_, ref_z_cut, qdeltay); // 12 neighbors (*shape_param).second.mean(param1_list[0]); (*shape_param).second.deviation(param2_list[2]); if(!run_gisaxs(alpha_i, alphai, phi, tilt, data, world_comm)) { if(mpi_rank == 0) std::cerr << "error: could not finish successfully" << std::endl; return false; } // if for(unsigned int iy = 0; iy < nqy_; ++ iy) { // assuming nqz_ == 1 ... temp_zcuts[iy] = data[nqx_ * iy]; } // for delete[] data; data = NULL; real_t err02 = compute_cut_fit_error(temp_zcuts, ref_z_cut, qdeltay); (*shape_param).second.mean(param1_list[1]); (*shape_param).second.deviation(param2_list[1]); if(!run_gisaxs(alpha_i, alphai, phi, tilt, data, world_comm)) { if(mpi_rank == 0) std::cerr << "error: could not finish successfully" << std::endl; return false; } // if for(unsigned int iy = 0; iy < nqy_; ++ iy) { // assuming nqz_ == 1 ... temp_zcuts[iy] = data[nqx_ * iy]; } // for delete[] data; data = NULL; real_t err11 = compute_cut_fit_error(temp_zcuts, ref_z_cut, qdeltay); (*shape_param).second.mean(param1_list[1]); (*shape_param).second.deviation(param2_list[2]); if(!run_gisaxs(alpha_i, alphai, phi, tilt, data, world_comm)) { if(mpi_rank == 0) std::cerr << "error: could not finish successfully" << std::endl; return false; } // if for(unsigned int iy = 0; iy < nqy_; ++ iy) { // assuming nqz_ == 1 ... temp_zcuts[iy] = data[nqx_ * iy]; } // for delete[] data; data = NULL; real_t err12 = compute_cut_fit_error(temp_zcuts, ref_z_cut, qdeltay); (*shape_param).second.mean(param1_list[1]); (*shape_param).second.deviation(param2_list[3]); if(!run_gisaxs(alpha_i, alphai, phi, tilt, data, world_comm)) { if(mpi_rank == 0) std::cerr << "error: could not finish successfully" << std::endl; return false; } // if for(unsigned int iy = 0; iy < nqy_; ++ iy) { // assuming nqz_ == 1 ... temp_zcuts[iy] = data[nqx_ * iy]; } // for delete[] data; data = NULL; real_t err13 = compute_cut_fit_error(temp_zcuts, ref_z_cut, qdeltay); (*shape_param).second.mean(param1_list[2]); (*shape_param).second.deviation(param2_list[0]); if(!run_gisaxs(alpha_i, alphai, phi, tilt, data, world_comm)) { if(mpi_rank == 0) std::cerr << "error: could not finish successfully" << std::endl; return false; } // if for(unsigned int iy = 0; iy < nqy_; ++ iy) { // assuming nqz_ == 1 ... temp_zcuts[iy] = data[nqx_ * iy]; } // for delete[] data; data = NULL; real_t err20 = compute_cut_fit_error(temp_zcuts, ref_z_cut, qdeltay); (*shape_param).second.mean(param1_list[2]); (*shape_param).second.deviation(param2_list[1]); if(!run_gisaxs(alpha_i, alphai, phi, tilt, data, world_comm)) { if(mpi_rank == 0) std::cerr << "error: could not finish successfully" << std::endl; return false; } // if for(unsigned int iy = 0; iy < nqy_; ++ iy) { // assuming nqz_ == 1 ... temp_zcuts[iy] = data[nqx_ * iy]; } // for delete[] data; data = NULL; real_t err21 = compute_cut_fit_error(temp_zcuts, ref_z_cut, qdeltay); (*shape_param).second.mean(param1_list[2]); (*shape_param).second.deviation(param2_list[3]); if(!run_gisaxs(alpha_i, alphai, phi, tilt, data, world_comm)) { if(mpi_rank == 0) std::cerr << "error: could not finish successfully" << std::endl; return false; } // if for(unsigned int iy = 0; iy < nqy_; ++ iy) { // assuming nqz_ == 1 ... temp_zcuts[iy] = data[nqx_ * iy]; } // for delete[] data; data = NULL; real_t err23 = compute_cut_fit_error(temp_zcuts, ref_z_cut, qdeltay); (*shape_param).second.mean(param1_list[2]); (*shape_param).second.deviation(param2_list[4]); if(!run_gisaxs(alpha_i, alphai, phi, tilt, data, world_comm)) { if(mpi_rank == 0) std::cerr << "error: could not finish successfully" << std::endl; return false; } // if for(unsigned int iy = 0; iy < nqy_; ++ iy) { // assuming nqz_ == 1 ... temp_zcuts[iy] = data[nqx_ * iy]; } // for delete[] data; data = NULL; real_t err24 = compute_cut_fit_error(temp_zcuts, ref_z_cut, qdeltay); (*shape_param).second.mean(param1_list[3]); (*shape_param).second.deviation(param2_list[1]); if(!run_gisaxs(alpha_i, alphai, phi, tilt, data, world_comm)) { if(mpi_rank == 0) std::cerr << "error: could not finish successfully" << std::endl; return false; } // if for(unsigned int iy = 0; iy < nqy_; ++ iy) { // assuming nqz_ == 1 ... temp_zcuts[iy] = data[nqx_ * iy]; } // for delete[] data; data = NULL; real_t err31 = compute_cut_fit_error(temp_zcuts, ref_z_cut, qdeltay); (*shape_param).second.mean(param1_list[3]); (*shape_param).second.deviation(param2_list[2]); if(!run_gisaxs(alpha_i, alphai, phi, tilt, data, world_comm)) { if(mpi_rank == 0) std::cerr << "error: could not finish successfully" << std::endl; return false; } // if for(unsigned int iy = 0; iy < nqy_; ++ iy) { // assuming nqz_ == 1 ... temp_zcuts[iy] = data[nqx_ * iy]; } // for delete[] data; data = NULL; real_t err32 = compute_cut_fit_error(temp_zcuts, ref_z_cut, qdeltay); (*shape_param).second.mean(param1_list[3]); (*shape_param).second.deviation(param2_list[3]); if(!run_gisaxs(alpha_i, alphai, phi, tilt, data, world_comm)) { if(mpi_rank == 0) std::cerr << "error: could not finish successfully" << std::endl; return false; } // if for(unsigned int iy = 0; iy < nqy_; ++ iy) { // assuming nqz_ == 1 ... temp_zcuts[iy] = data[nqx_ * iy]; } // for delete[] data; data = NULL; real_t err33 = compute_cut_fit_error(temp_zcuts, ref_z_cut, qdeltay); (*shape_param).second.mean(param1_list[4]); (*shape_param).second.deviation(param2_list[2]); if(!run_gisaxs(alpha_i, alphai, phi, tilt, data, world_comm)) { if(mpi_rank == 0) std::cerr << "error: could not finish successfully" << std::endl; return false; } // if for(unsigned int iy = 0; iy < nqy_; ++ iy) { // assuming nqz_ == 1 ... temp_zcuts[iy] = data[nqx_ * iy]; } // for delete[] data; data = NULL; real_t err42 = compute_cut_fit_error(temp_zcuts, ref_z_cut, qdeltay); // 22 0 // 02 1mm // 11 1m2m // 12 1m // 13 1m2p // 20 2mm // 21 2m // 23 2p // 24 2pp // 31 1p2m // 32 1p // 33 1p2p // 42 1pp real_t derr1 = (err32 - err12) / (2 * param_deltas[0]); real_t derr2 = (err23 - err21) / (2 * param_deltas[1]); err = sqrt(derr1 * derr1 + derr2 * derr2); std::cout << "++ Iteration: " << iter << ", Error: " << err << std::endl; std::cout << "++ Parameter 1: " << param_vals[0] << ", Parameter 2: " << param_vals[1] << std::endl; param_error_data.push_back(iter); param_error_data.push_back(param_vals[0]); param_error_data.push_back(param_vals[1]); param_error_data.push_back(err); if(err < err_threshold) break; real_t herr11 = (err42 + err02 - 2 * err22) / (4 * param_deltas[0] * param_deltas[0]); real_t herr12 = (err33 - err13 - (err31 - err11)) / (4 * param_deltas[0] * param_deltas[1]); real_t herr21 = (err33 - err13 - (err31 - err11)) / (4 * param_deltas[0] * param_deltas[1]); real_t herr22 = (err24 + err20 - 2 * err22) / (4 * param_deltas[1] * param_deltas[1]); real_t* herr = new (std::nothrow) real_t[2 * 2]; herr[0] = herr11; herr[1] = herr12; herr[2] = herr21; herr[3] = herr22; real_t* herrinv; mldivide(2, herr, herrinv); param_vals[0] -= gamma_const * (herrinv[0] * derr1 + herrinv[1] * derr2); param_vals[1] -= gamma_const * (herrinv[2] * derr1 + herrinv[3] * derr2); delete[] herrinv; delete[] herr; } // for // compute the error surface std::vector<std::vector<real_t> >::iterator mean_iter = params.begin(); std::vector<std::vector<real_t> >::iterator sd_iter = mean_iter + 1; std::vector<real_t> err_surface; for(std::vector<real_t>::iterator curr_mean = (*mean_iter).begin(); curr_mean != (*mean_iter).end(); ++ curr_mean) { for(std::vector<real_t>::iterator curr_sd = (*sd_iter).begin(); curr_sd != (*sd_iter).end(); ++ curr_sd) { (*shape_param).second.mean(*curr_mean); (*shape_param).second.deviation(*curr_sd); if(!run_gisaxs(alpha_i, alphai, phi, tilt, data, world_comm)) { if(mpi_rank == 0) std::cerr << "error: could not finish successfully" << std::endl; return false; } // if for(unsigned int iy = 0; iy < nqy_; ++ iy) { // assuming nqz_ == 1 ... temp_zcuts[iy] = data[nqx_ * iy]; } // for delete[] data; data = NULL; real_t curr_err = compute_cut_fit_error(temp_zcuts, ref_z_cut, qdeltay); err_surface.push_back(*curr_mean); err_surface.push_back(*curr_sd); err_surface.push_back(curr_err); } // for } // for // write data to files // define output filename std::stringstream alphai_b, phi_b, tilt_b; std::string alphai_s, phi_s, tilt_s; alphai_b << alpha_i; alphai_s = alphai_b.str(); phi_b << phi; phi_s = phi_b.str(); tilt_b << tilt; tilt_s = tilt_b.str(); std::string param_error_file(HiGInput::instance().param_pathprefix() + "/" + HiGInput::instance().runname() + "/param_error_ai=" + alphai_s + "_rot=" + phi_s + "_tilt=" + tilt_s + ".dat"); std::string z_cut_file(HiGInput::instance().param_pathprefix() + "/" + HiGInput::instance().runname() + "/z_cut_ai=" + alphai_s + "_rot=" + phi_s + "_tilt=" + tilt_s + ".dat"); std::string err_surf_file(HiGInput::instance().param_pathprefix() + "/" + HiGInput::instance().runname() + "/err_surf_ai=" + alphai_s + "_rot=" + phi_s + "_tilt=" + tilt_s + ".dat"); // write param_error_data std::ofstream param_error_f(param_error_file.c_str()); for(std::vector<real_t>::iterator pei = param_error_data.begin(); pei != param_error_data.end(); pei += 4) { param_error_f << *pei << "\t" << *(pei + 1) << "\t" << *(pei + 2) << "\t" << *(pei + 3) << std::endl; } // for param_error_f.close(); // write ref_z_cut and z_cuts std::ofstream zcut_f(z_cut_file.c_str()); for(unsigned int yy = 0; yy < nqy_; ++ yy) { zcut_f << ref_z_cut[yy] << "\t"; } // for zcut_f << std::endl; for(unsigned int i = 0; i < max_iter; ++ i) { for(unsigned int yy = 0; yy < nqy_; ++ yy) { zcut_f << z_cuts[i * nqy_ + yy] << "\t"; } // for zcut_f << std::endl; } // for zcut_f.close(); // write error surface std::ofstream err_surf_f(err_surf_file.c_str()); for(std::vector<real_t>::iterator surfi = err_surface.begin(); surfi != err_surface.end(); surfi += 3) { err_surf_f << *surfi << "\t" << *(surfi + 1) << "\t" << *(surfi + 2) << std::endl; } // for err_surf_f.close(); (*shape_param).second.mean(22.0); (*shape_param).second.deviation(7.0); param_error_data.clear(); delete[] temp_zcuts; delete[] z_cuts; delete[] ref_z_cut; std::cout << "parameter values: " << param_vals[0] << ", " << param_vals[1] << " [error: " << err << "]" << std::endl; // synchronize all procs after each run world_comm.Barrier(); } // for tilt } // for phi } // for alphai return true; } // HipGISAXS::fit_all_gisaxs()
// // % Erased all parts not wanted for codegeneration /Martin %% // Arguments : emxArray_real_T *s // emxArray_boolean_T *outliers // emxArray_boolean_T *outliers2 // Return Type : void // void locateOutliers(emxArray_real_T *s, emxArray_boolean_T *outliers, emxArray_boolean_T *outliers2) { int ia; int ic; emxArray_real_T *b_y1; int orderForDim; int iyLead; double work_data_idx_0; int m; double tmp1; double tmp2; emxArray_real_T *SigmaMat; emxArray_int32_T *r0; emxArray_int32_T *r1; emxArray_real_T *a; unsigned int s_idx_0; emxArray_real_T *C; int br; double mu; emxArray_real_T *b_s; /* locateOutliers: locates artifacts/outliers from data series */ /* */ /* Inputs: s = array containg data series */ /* method = artifact removal method to use. */ /* methods: 'percent' = percentage filter: locates data > x percent diff than previous data point. */ /* 'sd' = standard deviation filter: locates data > x stdev away from mean. */ /* 'above' = Threshold filter: locates data > threshold value */ /* 'below' = Threshold filter: locates data < threshold value */ /* 'median' = median filter. Outliers are located. */ /* Outputs: outliers = logical array of whether s is artifact/outlier or not */ /* eg. - [0 0 0 1 0], 1=artifact, 0=normal */ /* */ /* Examples: */ /* Locate outliers with 20% percentage filter: */ /* outliers = locateOutlers(s,'percent',0.2) */ /* Locate outliers that are above a threshold of 0.5: */ /* outliers = locateOutlers(s,'thresh','above',0.5) */ /* Locate outliers with median filter: */ /* outliers = locateOutlers(s,'median',4,5) */ /* */ /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */ /* Copyright (C) 2010, John T. Ramshur, [email protected] */ /* */ /* This file is part of HRVAS */ /* */ /* HRVAS is free software: you can redistribute it and/or modify */ /* it under the terms of the GNU General Public License as published by */ /* the Free Software Foundation, either version 3 of the License, or */ /* (at your option) any later version. */ /* */ /* HRVAS is distributed in the hope that it will be useful, */ /* but WITHOUT ANY WARRANTY; without even the implied warranty of */ /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ /* GNU General Public License for more details. */ /* */ /* You should have received a copy of the GNU General Public License */ /* along with Foobar. If not, see <http://www.gnu.org/licenses/>. */ /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */ ia = outliers->size[0]; outliers->size[0] = s->size[0]; emxEnsureCapacity((emxArray__common *)outliers, ia, (int)sizeof(boolean_T)); ic = s->size[0]; for (ia = 0; ia < ic; ia++) { outliers->data[ia] = false; } /* preallocate */ if (1 > s->size[0] - 1) { ic = 0; } else { ic = s->size[0] - 1; } emxInit_real_T(&b_y1, 1); if (s->size[0] == 0) { ia = b_y1->size[0]; b_y1->size[0] = 0; emxEnsureCapacity((emxArray__common *)b_y1, ia, (int)sizeof(double)); } else { if (s->size[0] - 1 <= 1) { orderForDim = s->size[0] - 1; } else { orderForDim = 1; } if (orderForDim < 1) { ia = b_y1->size[0]; b_y1->size[0] = 0; emxEnsureCapacity((emxArray__common *)b_y1, ia, (int)sizeof(double)); } else { orderForDim = s->size[0] - 1; ia = b_y1->size[0]; b_y1->size[0] = orderForDim; emxEnsureCapacity((emxArray__common *)b_y1, ia, (int)sizeof(double)); if (!(b_y1->size[0] == 0)) { orderForDim = 1; iyLead = 0; work_data_idx_0 = s->data[0]; for (m = 2; m <= s->size[0]; m++) { tmp1 = s->data[orderForDim]; tmp2 = work_data_idx_0; work_data_idx_0 = tmp1; tmp1 -= tmp2; orderForDim++; b_y1->data[iyLead] = tmp1; iyLead++; } } } } emxInit_real_T(&SigmaMat, 1); b_abs(b_y1, SigmaMat); /* percent chage from previous */ /* find index of values where pChange > perLimit */ orderForDim = s->size[0]; if (2 > orderForDim) { ia = 0; orderForDim = 0; } else { ia = 1; orderForDim = s->size[0]; } emxInit_int32_T(&r0, 2); iyLead = r0->size[0] * r0->size[1]; r0->size[0] = 1; r0->size[1] = orderForDim - ia; emxEnsureCapacity((emxArray__common *)r0, iyLead, (int)sizeof(int)); orderForDim -= ia; for (iyLead = 0; iyLead < orderForDim; iyLead++) { r0->data[r0->size[0] * iyLead] = ia + iyLead; } emxInit_int32_T1(&r1, 1); ia = r1->size[0]; r1->size[0] = ic; emxEnsureCapacity((emxArray__common *)r1, ia, (int)sizeof(int)); for (ia = 0; ia < ic; ia++) { r1->data[ia] = 1 + ia; } ic = r0->size[0] * r0->size[1]; for (ia = 0; ia < ic; ia++) { outliers->data[r0->data[ia]] = (SigmaMat->data[ia] / s->data[r1->data[ia] - 1] > 0.2); } emxFree_int32_T(&r1); emxFree_int32_T(&r0); emxInit_real_T1(&a, 2); /* Reference: */ /* Clifford, G. (2002). "Characterizing Artefact in the Normal */ /* Human 24-Hour RR Time Series to Aid Identification and Artificial */ /* Replication of Circadian Variations in Human Beat to Beat Heart Rate */ /* using a Simple Threshold." */ /* */ /* Aubert, A. E., D. Ramaekers, et al. (1999). "The analysis of heart */ /* rate variability in unrestrained rats. Validation of method and */ /* results." Comput Methods Programs Biomed 60(3): 197-213. */ /* convert to logical array */ /* preallocate */ iyLead = s->size[0]; s_idx_0 = (unsigned int)s->size[0]; ia = a->size[0] * a->size[1]; a->size[0] = (int)s_idx_0; a->size[1] = 2; emxEnsureCapacity((emxArray__common *)a, ia, (int)sizeof(double)); for (orderForDim = 1; orderForDim <= iyLead; orderForDim++) { a->data[orderForDim - 1] = (double)orderForDim / (double)iyLead; a->data[(orderForDim + a->size[0]) - 1] = 1.0; } mldivide(a, s, b_y1); emxInit_real_T(&C, 1); if (b_y1->size[0] == 1) { ia = C->size[0]; C->size[0] = a->size[0]; emxEnsureCapacity((emxArray__common *)C, ia, (int)sizeof(double)); ic = a->size[0]; for (ia = 0; ia < ic; ia++) { C->data[ia] = 0.0; for (iyLead = 0; iyLead < 2; iyLead++) { C->data[ia] += a->data[ia + a->size[0] * iyLead] * b_y1->data[iyLead]; } } } else { s_idx_0 = (unsigned int)a->size[0]; ia = C->size[0]; C->size[0] = (int)s_idx_0; emxEnsureCapacity((emxArray__common *)C, ia, (int)sizeof(double)); m = a->size[0]; orderForDim = C->size[0]; ia = C->size[0]; C->size[0] = orderForDim; emxEnsureCapacity((emxArray__common *)C, ia, (int)sizeof(double)); for (ia = 0; ia < orderForDim; ia++) { C->data[ia] = 0.0; } if (a->size[0] == 0) { } else { orderForDim = 0; while ((m > 0) && (orderForDim <= 0)) { for (ic = 1; ic <= m; ic++) { C->data[ic - 1] = 0.0; } orderForDim = m; } br = 0; orderForDim = 0; while ((m > 0) && (orderForDim <= 0)) { orderForDim = 0; for (iyLead = br; iyLead + 1 <= br + 2; iyLead++) { if (b_y1->data[iyLead] != 0.0) { ia = orderForDim; for (ic = 0; ic + 1 <= m; ic++) { ia++; C->data[ic] += b_y1->data[iyLead] * a->data[ia - 1]; } } orderForDim += m; } br += 2; orderForDim = m; } } } emxFree_real_T(&a); ia = s->size[0]; emxEnsureCapacity((emxArray__common *)s, ia, (int)sizeof(double)); ic = s->size[0]; for (ia = 0; ia < ic; ia++) { s->data[ia] -= C->data[ia]; } emxFree_real_T(&C); mu = mean(s); /* mean */ orderForDim = s->size[0]; if (s->size[0] > 1) { iyLead = s->size[0] - 1; } else { iyLead = s->size[0]; } if (s->size[0] == 0) { tmp2 = 0.0; } else { ia = 0; work_data_idx_0 = s->data[0]; for (ic = 2; ic <= orderForDim; ic++) { ia++; work_data_idx_0 += s->data[ia]; } work_data_idx_0 /= (double)s->size[0]; ia = 0; tmp1 = s->data[0] - work_data_idx_0; tmp2 = tmp1 * tmp1; for (ic = 2; ic <= orderForDim; ic++) { ia++; tmp1 = s->data[ia] - work_data_idx_0; tmp2 += tmp1 * tmp1; } tmp2 /= (double)iyLead; } emxInit_real_T(&b_s, 1); /* standard deviation */ /* Create a matrix of mean values by replicating the mu vector for n rows */ repmat(mu, (double)s->size[0], b_y1); /* Create a matrix of standard deviation values by replicating the sigma vector for n rows */ repmat(std::sqrt(tmp2), (double)s->size[0], SigmaMat); /* Create a matrix of zeros and ones, where ones indicate the location of outliers */ ia = b_s->size[0]; b_s->size[0] = s->size[0]; emxEnsureCapacity((emxArray__common *)b_s, ia, (int)sizeof(double)); ic = s->size[0]; for (ia = 0; ia < ic; ia++) { b_s->data[ia] = s->data[ia] - b_y1->data[ia]; } b_abs(b_s, b_y1); ia = outliers2->size[0]; outliers2->size[0] = b_y1->size[0]; emxEnsureCapacity((emxArray__common *)outliers2, ia, (int)sizeof(boolean_T)); ic = b_y1->size[0]; emxFree_real_T(&b_s); for (ia = 0; ia < ic; ia++) { outliers2->data[ia] = (b_y1->data[ia] > 3.0 * SigmaMat->data[ia]); } emxFree_real_T(&b_y1); emxFree_real_T(&SigmaMat); /* Reference: */ /* Aubert, A. E., D. Ramaekers, et al. (1999). "The analysis of heart */ /* rate variability in unrestrained rats. Validation of method and */ /* results." Comput Methods Programs Biomed 60(3): 197-213. */ /* convert to logical array */ }
Matrix& LASSO::train(Matrix& X, Matrix& Y, Options& options) { int p = size(X, 2); int ny = size(Y, 2); double epsilon = options.epsilon; int maxIter = options.maxIter; double lambda = options.lambda; bool calc_OV = options.calc_OV; bool verbose = options.verbose; /*XNX = [X, -X]; H_G = XNX' * XNX; D = repmat(diag(H_G), [1, n_y]); XNXTY = XNX' * Y; A = (X' * X + lambda * eye(p)) \ (X' * Y);*/ Matrix& XNX = horzcat(2, &X, &uminus(X)); Matrix& H_G = XNX.transpose().mtimes(XNX); double* Q = new double[size(H_G, 1)]; for (int i = 0; i < size(H_G, 1); i++) { Q[i] = H_G.getEntry(i, i); } Matrix& XNXTY = XNX.transpose().mtimes(Y); Matrix& A = mldivide( plus(X.transpose().mtimes(X), times(lambda, eye(p))), X.transpose().mtimes(Y) ); /*AA = [subplus(A); subplus(-A)]; C = -XNXTY + lambda; Grad = C + H_G * AA; tol = epsilon * norm(Grad); PGrad = zeros(size(Grad));*/ Matrix& AA = vertcat(2, &subplus(A), &subplus(uminus(A))); Matrix& C = plus(uminus(XNXTY), lambda); Matrix& Grad = plus(C, mtimes(H_G, AA)); double tol = epsilon * norm(Grad); Matrix& PGrad = zeros(size(Grad)); std::list<double> J; double fval = 0; // J(1) = sum(sum((Y - X * A).^2)) / 2 + lambda * sum(sum(abs(A))); if (calc_OV) { fval = sum(sum(pow(minus(Y, mtimes(X, A)), 2))) / 2 + lambda * sum(sum(abs(A))); J.push_back(fval); } Matrix& I_k = Grad.copy(); double d = 0; int k = 0; DenseVector& SFPlusCi = *new DenseVector(AA.getColumnDimension()); Matrix& S = H_G; Vector** SRows = null; if (typeid(H_G) == typeid(DenseMatrix)) SRows = denseMatrix2DenseRowVectors(S); else SRows = sparseMatrix2SparseRowVectors(S); Vector** CRows = null; if (typeid(C) == typeid(DenseMatrix)) CRows = denseMatrix2DenseRowVectors(C); else CRows = sparseMatrix2SparseRowVectors(C); double** FData = ((DenseMatrix&) AA).getData(); double* FRow = null; double* pr = null; int K = 2 * p; while (true) { /*I_k = Grad < 0 | AA > 0; I_k_com = not(I_k); PGrad(I_k) = Grad(I_k); PGrad(I_k_com) = 0;*/ _or(I_k, lt(Grad, 0), gt(AA, 0)); Matrix& I_k_com = _not(I_k); assign(PGrad, Grad); logicalIndexingAssignment(PGrad, I_k_com, 0); d = norm(PGrad, inf); if (d < tol) { if (verbose) println("Converge successfully!"); break; } /*for i = 1:2*p AA(i, :) = max(AA(i, :) - (C(i, :) + H_G(i, :) * AA) ./ (D(i, :)), 0); end A = AA(1:p,:) - AA(p+1:end,:);*/ for (int i = 0; i < K; i++) { // SFPlusCi = SRows[i].operate(AA); operate(SFPlusCi, *SRows[i], AA); plusAssign(SFPlusCi, *CRows[i]); timesAssign(SFPlusCi, 1 / Q[i]); pr = SFPlusCi.getPr(); // F(i, :) = max(F(i, :) - (S(i, :) * F + C(i, :)) / D[i]), 0); // F(i, :) = max(F(i, :) - SFPlusCi, 0) FRow = FData[i]; for (int j = 0; j < AA.getColumnDimension(); j++) { FRow[j] = max(FRow[j] - pr[j], 0); } } // Grad = plus(C, mtimes(H_G, AA)); plus(Grad, C, mtimes(H_G, AA)); k = k + 1; if (k > maxIter) { if (verbose) println("Maximal iterations"); break; } if (calc_OV) { fval = sum(sum(pow(minus(Y, mtimes(XNX, AA)), 2))) / 2 + lambda * sum(sum(abs(AA))); J.push_back(fval); } if (k % 10 == 0 && verbose) { if (calc_OV) fprintf("Iter %d - ||PGrad||: %f, ofv: %f\n", k, d, J.back()); else fprintf("Iter %d - ||PGrad||: %f\n", k, d); } } Matrix& res = minus( AA.getSubMatrix(0, p - 1, 0, ny - 1), AA.getSubMatrix(p, 2 * p - 1, 0, ny - 1) ); return res; }