FloatImage *VectorField::get_divergence(int xs, int ys) { int i,j; FloatImage *image = new FloatImage(xsize-2, ysize-2); float d = 0.1 / xsize; for (i = 1; i < xsize-1; i++) for (j = 1; j < ysize-1; j++) { float dx = xval(i+1, j) - xval(i-1, j); float dy = yval(i, j+1) - yval(i, j-1); float div = (dx + dy) / (2 * d); image->pixel(i-1, j-1) = div; } FloatImage *image2 = new FloatImage(xs, ys); for (i = 0; i < xs; i++) for (j = 0; j < ys; j++) { float x = (i + 0.5) / xs; float y = (j + 0.5) / ys; image2->pixel(i,j) = image->get_value(x,y); } delete image; return (image2); }
FloatImage *VectorField::get_vorticity(int xs, int ys) { int i,j; FloatImage *image = new FloatImage(xsize-2, ysize-2); float d = 0.1 / xsize; for (i = 1; i < xsize-1; i++) for (j = 1; j < ysize-1; j++) { float dx = yval(i+1, j) - yval(i-1, j); float dy = xval(i, j+1) - xval(i, j-1); float vort = (dx/d) - (dy/d); image->pixel(i-1, j-1) = vort; } FloatImage *image2 = new FloatImage(xs, ys); for (i = 0; i < xs; i++) for (j = 0; j < ys; j++) { float x = (i + 0.5) / xs; float y = (j + 0.5) / ys; image2->pixel(i,j) = image->get_value(x,y); } delete image; return (image2); }
// Interpolate table (linearly) to some specific k: double xTable::xval(double x, double y) const { x /= dx; y /= dx; int i = static_cast<int> (floor(y)); double fy = y-i; int j = static_cast<int> (floor(x)); double fx = x-j; return (1-fx)*( (1-fy)*xval(i,j) + fy*xval(i+1,j)) + fx*( (1-fy)*xval(i,j+1) + fy*xval(i+1,j+1)); }
void VJSArray::PushValues( const std::vector<const XBOX::VValueSingle*> inValues, JS4D::ExceptionRef *outException) const { for (std::vector<const XBOX::VValueSingle*>::const_iterator cur = inValues.begin(), end = inValues.end(); cur != end; cur++) { const VValueSingle* val = *cur; if (val == NULL) { VJSValue xval(fContext); xval.SetNull(); PushValue(xval, outException); } else PushValue(*val, outException); } }
//ALG 4/2/2012: added argument for penalty fcn //impscale goes in parms int rpart(int n, int nvarx, Sint *ncat, int method, int penalty, int maxpri, double *parms, double *ymat, FLOAT *xmat, Sint *missmat, struct cptable *cptable, struct node **tree, char **error, int *which, int xvals, Sint *x_grp, double *wt, double *opt, int ny, double *cost) { int i,k; int maxcat; double temp; /* ** initialize the splitting functions from the function table ** This is what we seek to minimize/maximize by virtue of splitting the node ** ALG 5/1/2012: added parent_objective, which returns scaling factor for the 'improve' ** number calculated by rp_choose. This is necessary in case in needs to be different from ** the 'risk' calculated by rp_eval. */ if (method <= NUM_METHODS) { //Rprintf("%d \n",method); looks good! i = method -1; rp_init = func_table_objective[i].init_split; rp_choose = func_table_objective[i].choose_split; rp_eval = func_table_objective[i].eval; rp_error = func_table_objective[i].error; rp_parent_objective = func_table_objective[i].parent_objective; rp.num_y = ny; rp.method_number = i; } else { *error = "Invalid value for 'method'"; return(1); } /* * ALG 4/4/2012. * Initialize the penalty on new variables. */ if(penalty <= NUM_PENALTY){ i = penalty - 1; rp.penalty_number = i; rp_penalty = func_table_penalty[i].penalty_fcn; } else{ *error = "Invalid value for 'penalty'"; return(1); } /* * ALG 4/11/2012 * Initialize the improve function- this is the function * that combines the penalty and splitting objective so that * penalty is always btwn 0-1. The main choice is to scale * the objective by the parent or the root value. * * In R code if no improve was chosen then a default is picked. * If not, R checks that combination of objective/penalty/improve * makes sense. */ int impscale; //scale by root or parent impscale = (int) opt[8]; if(impscale <= NUM_IMPROVE){ rp.impscale_number = impscale; rp_improve = func_table_improve[impscale-1].improve_fcn; } else{ *error = "Invalid value for improve scaling - should be either 1 (parent) or 2 (root)"; return(1); } /* ** set some other parameters */ rp.collapse_is_possible = 1; //most methods this is possible, where it's not this is fixed in the init fcn. rp.min_node = (int) opt[1]; rp.min_split = (int) opt[0]; rp.complexity= opt[2]; //cp parameter rp.maxsur = (int) opt[4]; rp.usesurrogate = (int) opt[5]; rp.sur_agree = (int) opt[6]; rp.maxnode = (int) pow((double)2.0, opt[7]) -1; rp.nvar = nvarx; rp.numcat = ncat; rp.maxpri = maxpri; if (maxpri <1) rp.maxpri =1; rp.n = n; rp.which = which; rp.wt = wt; rp.iscale = 0.0; rp.vcost = cost; rp.max_depth = 32; int temp2[rp.max_depth]; /* ALG 1/16/2012: initial vector for variables_used */ /* * ALG 2/11/2012: set rp.splitparams */ rp.splitparams = (double *)ALLOC(2, sizeof(double *)); rp.splitparams[0] = opt[9]; //alpha rp.splitparams[1] = opt[10]; //beta //Rprintf("%d",rp.splitparams[0]); //fine /* ** create the "ragged array" pointers to the matrix ** x and missmat are in column major order ** y is in row major order */ rp.xdata = (FLOAT **) ALLOC(nvarx, sizeof(FLOAT *)); for (i=0; i<nvarx; i++) { rp.xdata[i] = &(xmat[i*n]); } rp.ydata = (double **) ALLOC(n, sizeof(double *)); for (i=0; i<n; i++) rp.ydata[i] = &(ymat[i*rp.num_y]); /* ** allocate some scratch */ rp.tempvec = (int *)ALLOC(n, sizeof(int)); rp.xtemp = (FLOAT *)ALLOC(n, sizeof(FLOAT)); rp.ytemp = (double **)ALLOC(n, sizeof(double *)); rp.wtemp = (double *)ALLOC(n, sizeof(double)); /* ** create a matrix of sort indices, one for each continuous variable ** This sort is "once and for all". The result is stored on top ** of the 'missmat' array. ** I don't have to sort the categoricals. */ rp.sorts = (Sint**) ALLOC(nvarx, sizeof(Sint *)); maxcat=0; for (i=0; i<nvarx; i++) { rp.sorts[i] = &(missmat[i*n]); for (k=0; k<n; k++) { if (rp.sorts[i][k]==1) { rp.tempvec[k] = -(k+1); rp.xdata[i][k]=0; /*weird numerics might destroy 'sort'*/ } else rp.tempvec[k] = k; } if (ncat[i]==0) mysort(0, n-1, rp.xdata[i], rp.tempvec); else if (ncat[i] > maxcat) maxcat = ncat[i]; for (k=0; k<n; k++) rp.sorts[i][k] = rp.tempvec[k]; } /* ** And now the last of my scratch space */ if (maxcat >0) { rp.csplit = (int *) ALLOC(3*maxcat, sizeof(int)); rp.lwt = (double *) ALLOC(2*maxcat, sizeof(double)); rp.left = rp.csplit + maxcat; rp.right= rp.left + maxcat; rp.rwt = rp.lwt + maxcat; } else rp.csplit = (int *)ALLOC(1, sizeof(int)); /* ** initialize the top node of the tree */ temp =0; for (i=0; i<n; i++) { which[i] =1; temp += wt[i]; } /* ALG: haven't split on anything so far... */ for (i=0; i< rp.max_depth; i++){ temp2[i] = -1; } i = rp_init(n, rp.ydata, maxcat, error, parms, &rp.num_resp, 1, wt); nodesize = sizeof(struct node) + (rp.num_resp-2)*sizeof(double); *tree = (struct node *) CALLOC(1, nodesize); (*tree)->num_obs = n; (*tree)->sum_wt = temp; if (i>0) return(i); //ALG 5/1/2012. Calculate the root's objective for scaling improve, and set // rp.root_objective_scaling. rp.dummy = (double *) ALLOC(1,sizeof(double)); //7/18/2012: allocate (*rp_parent_objective)(n, rp.ydata, rp.dummy, &rp.root_objective_scaling, wt); (*rp_eval)(n, rp.ydata, (*tree)->response_est, &((*tree)->risk), wt); (*tree)->complexity = (*tree)->risk; rp.alpha = rp.complexity * (*tree)->risk; //Rprintf("Initialization complete. \n"); /* ** Do the basic tree */ partition(1, (*tree), &temp, temp2); //deal with the complexity table. cptable->cp = (*tree)->complexity; cptable->risk = (*tree)->risk; cptable->nsplit = 0; cptable->forward =0; cptable->xrisk =0; cptable->xstd =0; rp.num_unique_cp =1; if ((*tree)->rightson ==0) return(0); /* Nothing more needs to be done */ make_cp_list((*tree), (*tree)->complexity, cptable); make_cp_table((*tree), (*tree)->complexity, 0); if (xvals >1 && (*tree)->rightson !=0){ xval(xvals, cptable, x_grp, maxcat, error, parms); } /* ** all done */ return(0); }
TEST(MiniTensor_ROL, Paraboloid) { bool const print_output = ::testing::GTEST_FLAG(print_time); // outputs nothing Teuchos::oblackholestream bhs; std::ostream & os = (print_output == true) ? std::cout : bhs; constexpr Intrepid2::Index DIM{2}; using MSFN = Intrepid2::Paraboloid<Real, DIM>; Intrepid2::Vector<Real, DIM> min(0.0, 0.0); MSFN msfn(0.0, 0.0); ROL::MiniTensor_Objective<MSFN, Real, DIM> obj(msfn); // Set parameters. Teuchos::ParameterList params; params.sublist("Step").sublist("Line Search").sublist("Descent Method") .set("Type", "Newton-Krylov"); params.sublist("Status Test").set("Gradient Tolerance", 10.e-12); params.sublist("Status Test").set("Step Tolerance", 1.0e-14); params.sublist("Status Test").set("Iteration Limit", 128); // Define algorithm. ROL::Algorithm<Real> algo("Line Search", params); // Set Initial Guess Intrepid2::Vector<Real, DIM> xval(Intrepid2::RANDOM); ROL::MiniTensorVector<Real, DIM> x(xval); // Run Algorithm algo.run(x, obj, true, os); Intrepid2::Vector<Real, DIM> const sol = ROL::MTfromROL<Real, DIM>(x); os << "Solution : " << sol << '\n'; Real const epsilon{Intrepid2::machine_epsilon<Real>()}; Real const error = Intrepid2::norm(sol - min); ASSERT_LE(error, epsilon); }
TEST(MiniTensor_ROL, NLLS01) { bool const print_output = ::testing::GTEST_FLAG(print_time); // outputs nothing Teuchos::oblackholestream bhs; std::ostream & os = (print_output == true) ? std::cout : bhs; constexpr Intrepid2::Index NUM_CONSTR{3}; constexpr Intrepid2::Index NUM_VAR{5}; using MSEC = Intrepid2::Nonlinear01<Real, NUM_CONSTR>; MSEC msec; ROL::MiniTensor_EqualityConstraint<MSEC, Real, NUM_CONSTR, NUM_VAR> constr(msec); Intrepid2::Vector<Real, NUM_VAR> xval(Intrepid2::ZEROS); Intrepid2::Vector<Real, NUM_CONSTR> cval(Intrepid2::ZEROS); Intrepid2::Vector<Real, NUM_VAR> solval(Intrepid2::ZEROS); // Set initial guess. xval(0) = -1.8; xval(1) = 1.7; xval(2) = 1.9; xval(3) = -0.8; xval(4) = -0.8; // Set solution. solval(0) = -1.717143570394391e+00; solval(1) = 1.595709690183565e+00; solval(2) = 1.827245752927178e+00; solval(3) = -7.636430781841294e-01; solval(4) = -7.636430781841294e-01; Real const error_full_hess{2.3621708067012991e-02}; Real const error_gn_hess{2.3669791103726853e-02}; Real const tol{1.0e-08}; ROL::MiniTensorVector<Real, NUM_VAR> x(xval); ROL::MiniTensorVector<Real, NUM_CONSTR> c(cval); ROL::MiniTensorVector<Real, NUM_VAR> sol(solval); Teuchos::RCP<ROL::EqualityConstraint<Real>> pconstr = Teuchos::rcp(&constr, false); // Define algorithm. Teuchos::ParameterList params; std::string step{"Trust Region"}; params.sublist("Step").sublist(step).set("Subproblem Solver", "Truncated CG"); params.sublist("Status Test").set("Gradient Tolerance", 1.0e-10); params.sublist("Status Test").set("Constraint Tolerance", 1.0e-10); params.sublist("Status Test").set("Step Tolerance", 1.0e-18); params.sublist("Status Test").set("Iteration Limit", 128); ROL::Algorithm<Real> algo(step, params); ROL::NonlinearLeastSquaresObjective<Real> nlls(pconstr, x, c, false); os << "\nSOLVE USING FULL HESSIAN\n"; algo.run(x, nlls, true, os); Intrepid2::Vector<Real, NUM_VAR> xfinal = ROL::MTfromROL<Real, NUM_VAR>(x); os << "\nfinal x : " << xfinal << "\n"; Real error = std::abs(Intrepid2::norm(xfinal - solval) - error_full_hess); os << "\nerror : " << error << "\n"; ASSERT_LE(error, tol); algo.reset(); x.set(xval); ROL::NonlinearLeastSquaresObjective<Real> gnnlls(pconstr, x, c, true); os << "\nSOLVE USING GAUSS-NEWTON HESSIAN\n"; algo.run(x, gnnlls, true, os); xfinal = ROL::MTfromROL<Real, NUM_VAR>(x); os << "\nfinal x : " << xfinal << "\n"; error = std::abs(Intrepid2::norm(xfinal - solval) - error_gn_hess); os << "\nerror : " << error << "\n"; ASSERT_LE(error, tol); }
void CG_METHOD::CGMethod(const int& thread_id, const CSR_MATRIX<T>& A, VECTOR_ND<T>& x, const VECTOR_ND<T>& b) { LOG::Begin(thread_id, "CGMethod"); BEGIN_HEAD_THREAD_WORK { multithreading->SplitDomainIndex1D(0, A.N); } END_HEAD_THREAD_WORK const int N(x.num_dimension), start_ix(multithreading->start_ix_1D[thread_id]), end_ix(multithreading->end_ix_1D[thread_id]); BEGIN_HEAD_THREAD_WORK { res.Initialize(N); } END_HEAD_THREAD_WORK BEGIN_HEAD_THREAD_WORK { p.Initialize(N); } END_HEAD_THREAD_WORK BEGIN_HEAD_THREAD_WORK { Ap.Initialize(N); } END_HEAD_THREAD_WORK BEGIN_HEAD_THREAD_WORK { num_iteration = 0; } END_HEAD_THREAD_WORK T *rval(res.values), *pval(p.values), *Apval(Ap.values), *xval(x.values); T alpha, res_old, res_new; A.ComputeResidual(thread_id, x, b, res); for (int i = start_ix; i <= end_ix; i++) { p.values[i] = res.values[i]; } multithreading->Sync(thread_id); res_old = DotProduct(multithreading, thread_id, res, p); while(num_iteration < max_iteration) { A.Multiply(thread_id, p, Ap); alpha = res_old/ DotProduct(multithreading, thread_id, p, Ap); for (int i = start_ix; i <= end_ix; i++) { xval[i] += alpha*pval[i]; rval[i] -= alpha*Apval[i]; } multithreading->Sync(thread_id); res_new = DotProduct(multithreading, thread_id, res, res); if(res_new < sqr_tolerance) break; // In L2 Norm for (int i = start_ix; i <= end_ix; i++) { const T k = res_new/res_old; pval[i] = res.values[i] + k*p.values[i]; } multithreading->Sync(thread_id); res_old = res_new; BEGIN_HEAD_THREAD_WORK { num_iteration++; } END_HEAD_THREAD_WORK } multithreading->Sync(thread_id); BEGIN_HEAD_THREAD_WORK { residual = sqrt(res_new); if(use_detailed_log) { LOG::cout << "[CG] Iteration = " << num_iteration << ", Residual = " << residual << endl; } else { LOG::cout << "Iteration = " << num_iteration << ", Residual = " << residual << endl; } } END_HEAD_THREAD_WORK LOG::End(thread_id); }
void CG_METHOD::biCGSTABMethod(const int& thread_id, const CSR_MATRIX<T>& A, VECTOR_ND<T>& x, const VECTOR_ND<T>& b) { LOG::Begin(thread_id, "bi-CGMethod"); BEGIN_HEAD_THREAD_WORK { multithreading->SplitDomainIndex1D(0, A.N); } END_HEAD_THREAD_WORK const int N(x.num_dimension), start_ix(multithreading->start_ix_1D[thread_id]), end_ix(multithreading->end_ix_1D[thread_id]); BEGIN_HEAD_THREAD_WORK { res.Initialize(N); } END_HEAD_THREAD_WORK BEGIN_HEAD_THREAD_WORK { res_0.Initialize(N); } END_HEAD_THREAD_WORK BEGIN_HEAD_THREAD_WORK { s.Initialize(N); } END_HEAD_THREAD_WORK BEGIN_HEAD_THREAD_WORK { p.Initialize(N); } END_HEAD_THREAD_WORK BEGIN_HEAD_THREAD_WORK { Ap.Initialize(N); } END_HEAD_THREAD_WORK BEGIN_HEAD_THREAD_WORK { As.Initialize(N); } END_HEAD_THREAD_WORK BEGIN_HEAD_THREAD_WORK { num_iteration = 0; } END_HEAD_THREAD_WORK T *rval(res.values), *pval(p.values), *Apval(Ap.values), *xval(x.values), *sval(s.values), *Asval(As.values); T alpha, res_old, res_new, omega, beta, s_norm, residual_check; // Subvariables T deno_omega, nu_omega; A.ComputeResidual(thread_id, x, b, res); // The value of r_0^* for (int i = start_ix; i <= end_ix; i++) { res_0.values[i] = res.values[i]; } multithreading->Sync(thread_id); for (int i = start_ix; i <= end_ix; i++) { p.values[i] = res.values[i]; } multithreading->Sync(thread_id); res_old = DotProduct(multithreading, thread_id, res, res_0); while(num_iteration < max_iteration) { A.Multiply(thread_id, p, Ap); alpha = res_old/DotProduct(multithreading, thread_id, Ap, res_0); for (int i = start_ix; i <= end_ix; i++) { sval[i] = rval[i] - alpha*Apval[i]; } multithreading->Sync(thread_id); s_norm = sqrt(DotProduct(multithreading, thread_id, s, s)); if (s_norm < tolerance) { for (int i = start_ix; i <= end_ix; i++) { xval[i] = xval[i] + alpha*pval[i]; } multithreading->Sync(thread_id); break; } A.Multiply(thread_id, s, As); DotProduct(multithreading, thread_id, As, s, nu_omega); DotProduct(multithreading, thread_id, As, As, deno_omega); omega = nu_omega/deno_omega; for (int i = start_ix; i <= end_ix; i++) { xval[i] += alpha*pval[i] + omega*sval[i]; rval[i] = sval[i] - omega*Asval[i]; } multithreading->Sync(thread_id); res_new = DotProduct(multithreading, thread_id, res, res_0); residual_check = DotProduct(multithreading, thread_id, res, res); if(residual_check < sqr_tolerance) break; // In L2 Norm beta = (res_new/res_old)*(alpha/omega); for (int i = start_ix; i <= end_ix; i++) { pval[i] = rval[i] + beta*(pval[i] - omega*Apval[i]); } multithreading->Sync(thread_id); res_old = res_new; BEGIN_HEAD_THREAD_WORK { num_iteration++; } END_HEAD_THREAD_WORK } multithreading->Sync(thread_id); BEGIN_HEAD_THREAD_WORK { residual = sqrt(residual_check); if(use_detailed_log) { LOG::cout << "[bi-CG] Iteration = " << num_iteration << ", Residual = " << residual << endl; } else { LOG::cout << "Iteration = " << num_iteration << ", Residual = " << residual << endl; } } END_HEAD_THREAD_WORK LOG::End(thread_id); }
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Calibrator::calibrate // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ void Calibrator::calibrate(void) { // Bring globals into scope extern GladeXML *gui; // Locals unsigned int seq_index, count; char label_text[50]; bool skip, started, paused; Sequence *seq; GtkWidget *label, *notify, *window, *progress_bar; vector< vector<float> > temp; Template sequence_template(NUMBER_OF_CHANNELS,sequences->length()); gdk_threads_enter(); // Get GDK lock progress_bar = glade_xml_get_widget(gui, "cal_progress_bar"); window = glade_xml_get_widget(gui, "cal_progress"); label = glade_xml_get_widget(gui, "cal_label"); notify = glade_xml_get_widget(gui, "cal_notify"); username = (const char*)gtk_entry_get_text(GTK_ENTRY(glade_xml_get_widget(gui, "user_field"))); gdk_threads_leave(); // Release GDK lock for(seq_index = 0; seq_index < sequences->number(); ++seq_index) // calibrate for each sequence { // Reset calibration progress window sprintf(label_text, "Calibrate Sequence %d", seq_index+1); gdk_threads_enter(); // Get GDK lock gtk_widget_set_sensitive(glade_xml_get_widget(gui, "cal_skip"),TRUE); gtk_widget_set_sensitive(glade_xml_get_widget(gui, "cal_pause"),FALSE); gtk_label_set_text(GTK_LABEL(label),label_text); gdk_threads_leave(); // Release GDK lock update_cal_progress_window(-1); // wait for user to click start button do { gdk_threads_enter(); // Get GDK lock skip = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(glade_xml_get_widget(gui, "cal_skip"))); gdk_threads_leave(); // Release GDK lock if(skip) { gdk_threads_enter(); // Get GDK lock gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(glade_xml_get_widget(gui, "cal_skip")),FALSE); gdk_threads_leave(); ++seq_index; break; // return to beginning } gdk_threads_enter(); // Get GDK lock started = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(glade_xml_get_widget(gui, "cal_start"))); gdk_threads_leave(); // Release GDK lock }while(!started); if (seq_index < sequences->number()) { gdk_threads_enter(); // Get GDK lock gtk_widget_set_sensitive(glade_xml_get_widget(gui, "cal_start"), FALSE); gtk_widget_set_sensitive(glade_xml_get_widget(gui, "cal_skip"),FALSE); gtk_widget_set_sensitive(glade_xml_get_widget(gui, "cal_pause"),TRUE); gdk_threads_leave(); // Release GDK lock // Reset the template sequence_template.reset(); // average PERIODS_TO_AVERAGE periods of EEG signal for(count = 0; count < PERIODS_TO_AVERAGE; ++count) { // Check pause button do { gdk_threads_enter(); paused = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(glade_xml_get_widget(gui, "cal_pause"))); gdk_threads_leave(); for(unsigned i = 0; i < 10000; ++i); } while (paused); // Wait in loop temp = get_one_period(); if (!is_corrupt(temp) ) { sequence_template.add_data(temp); update_cal_progress_window(count); } else{ --count; } } sequence_template.generate_template(); seq = sequences->at(seq_index); seq->set_template(sequence_template); // Write cal file write_calibration_file(seq_index+1, sequence_template.get_template()); } // Reset toggle button gdk_threads_enter(); // Get GDK lock gtk_widget_set_sensitive(glade_xml_get_widget(gui, "cal_start"), TRUE); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(glade_xml_get_widget(gui, "cal_start")),FALSE); gdk_threads_leave(); // Release GDK lock } xval("xval.txt"); // Hide widget gdk_threads_enter(); // Get GDK lock gtk_widget_hide(window); gdk_threads_leave(); // Release GDK lock }
int main (int argc, char **argv) { int result = 0; IloEnv env; try { static int indices[] = { 0, 1, 2, 3, 4, 5, 6 }; IloModel model(env); /* ***************************************************************** * * * * S E T U P P R O B L E M * * * * The model we setup here is * * Minimize * * obj: 3x1 - x2 + 3x3 + 2x4 + x5 + 2x6 + 4x7 * * Subject To * * c1: x1 + x2 = 4 * * c2: x1 + x3 >= 3 * * c3: x6 + x7 <= 5 * * c4: -x1 + x7 >= -2 * * q1: [ -x1^2 + x2^2 ] <= 0 * * q2: [ 4.25x3^2 -2x3*x4 + 4.25x4^2 - 2x4*x5 + 4x5^2 ] + 2 x1 <= 9.0 * q3: [ x6^2 - x7^2 ] >= 4 * * Bounds * * 0 <= x1 <= 3 * * x2 Free * * 0 <= x3 <= 0.5 * * x4 Free * * x5 Free * * x7 Free * * End * * * * ***************************************************************** */ IloNumVarArray x(env); x.add(IloNumVar(env, 0, 3, "x1")); x.add(IloNumVar(env, -IloInfinity, IloInfinity, "x2")); x.add(IloNumVar(env, 0, 0.5, "x3")); x.add(IloNumVar(env, -IloInfinity, IloInfinity, "x4")); x.add(IloNumVar(env, -IloInfinity, IloInfinity, "x5")); x.add(IloNumVar(env, 0, IloInfinity, "x6")); x.add(IloNumVar(env, -IloInfinity, IloInfinity, "x7")); for (IloInt i = 0; i < x.getSize(); ++i) x[i].setObject(&indices[i]); IloObjective obj = IloMinimize(env, 3*x[0] - x[1] + 3*x[2] + 2*x[3] + x[4] + 2*x[5] + 4*x[6], "obj"); model.add(obj); IloRangeArray linear(env); linear.add(IloRange(env, 4.0, x[0] + x[1], 4.0, "c1")); linear.add(IloRange(env, 3.0, x[0] + x[2], IloInfinity, "c2")); linear.add(IloRange(env, -IloInfinity, x[5] + x[6], 5.0, "c3")); linear.add(IloRange(env, -2.0, -x[0] + x[6], IloInfinity, "c4")); for (IloInt i = 0; i < linear.getSize(); ++i) linear[i].setObject(&indices[i]); model.add(linear); IloRangeArray quad(env); quad.add(IloRange(env, -IloInfinity, -x[0]*x[0] + x[1] * x[1], 0, "q1")); quad.add(IloRange(env, -IloInfinity, 4.25*x[2]*x[2] - 2*x[2]*x[3] + 4.25*x[3]*x[3] + -2*x[3]*x[4] + 4*x[4]*x[4] + 2*x[0], 9.0, "q2")); quad.add(IloRange(env, 4.0, x[5]*x[5] - x[6]*x[6], IloInfinity, "q3")); for (IloInt i = 0; i < quad.getSize(); ++i) quad[i].setObject(&indices[i]); model.add(quad); /* ***************************************************************** * * * * O P T I M I Z E P R O B L E M * * * * ***************************************************************** */ IloCplex cplex(model); cplex.setParam(IloCplex::Param::Barrier::QCPConvergeTol, 1e-10); cplex.solve(); /* ***************************************************************** * * * * Q U E R Y S O L U T I O N * * * * ***************************************************************** */ IloNumArray xval(env); IloNumArray slack(env); IloNumArray qslack(env); IloNumArray cpi(env); IloNumArray rpi(env); IloNumArray qpi; cplex.getValues(x, xval); cplex.getSlacks(slack, linear); cplex.getSlacks(qslack, quad); cplex.getReducedCosts(cpi, x); cplex.getDuals(rpi, linear); qpi = getqconstrmultipliers(cplex, xval, quad); /* ***************************************************************** * * * * C H E C K K K T C O N D I T I O N S * * * * Here we verify that the optimal solution computed by CPLEX * * (and the qpi[] values computed above) satisfy the KKT * * conditions. * * * * ***************************************************************** */ // Primal feasibility: This example is about duals so we skip this test. // Dual feasibility: We must verify // - for <= constraints (linear or quadratic) the dual // multiplier is non-positive. // - for >= constraints (linear or quadratic) the dual // multiplier is non-negative. for (IloInt i = 0; i < linear.getSize(); ++i) { if ( linear[i].getLB() <= -IloInfinity ) { // <= constraint if ( rpi[i] > ZEROTOL ) { cerr << "Dual feasibility test failed for <= row " << i << ": " << rpi[i] << endl; result = -1; } } else if ( linear[i].getUB() >= IloInfinity ) { // >= constraint if ( rpi[i] < -ZEROTOL ) { cerr << "Dual feasibility test failed for >= row " << i << ":" << rpi[i] << endl; result = -1; } } else { // nothing to do for equality constraints } } for (IloInt q = 0; q < quad.getSize(); ++q) { if ( quad[q].getLB() <= -IloInfinity ) { // <= constraint if ( qpi[q] > ZEROTOL ) { cerr << "Dual feasibility test failed for <= quad " << q << ": " << qpi[q] << endl; result = -1; } } else if ( quad[q].getUB() >= IloInfinity ) { // >= constraint if ( qpi[q] < -ZEROTOL ) { cerr << "Dual feasibility test failed for >= quad " << q << ":" << qpi[q] << endl; result = -1; } } else { // nothing to do for equality constraints } } // Complementary slackness. // For any constraint the product of primal slack and dual multiplier // must be 0. for (IloInt i = 0; i < linear.getSize(); ++i) { if ( fabs (linear[i].getUB() - linear[i].getLB()) > ZEROTOL && fabs (slack[i] * rpi[i]) > ZEROTOL ) { cerr << "Complementary slackness test failed for row " << i << ": " << fabs (slack[i] * rpi[i]) << endl; result = -1; } } for (IloInt q = 0; q < quad.getSize(); ++q) { if ( fabs (quad[q].getUB() - quad[q].getLB()) > ZEROTOL && fabs (qslack[q] * qpi[q]) > ZEROTOL ) { cerr << "Complementary slackness test failed for quad " << q << ":" << fabs (qslack[q] * qpi[q]) << endl; result = -1; } } for (IloInt j = 0; j < x.getSize(); ++j) { if ( x[j].getUB() < IloInfinity ) { double const slk = x[j].getUB() - xval[j]; double const dual = cpi[j] < -ZEROTOL ? cpi[j] : 0.0; if ( fabs (slk * dual) > ZEROTOL ) { cerr << "Complementary slackness test failed for ub " << j << ": " << fabs (slk * dual) << endl; result = -1; } } if ( x[j].getLB() > -IloInfinity ) { double const slk = xval[j] - x[j].getLB(); double const dual = cpi[j] > ZEROTOL ? cpi[j] : 0.0; if ( fabs (slk * dual) > ZEROTOL ) { cerr << "Complementary slackness test failed for lb " << j << ": " << fabs (slk * dual) << endl; result = -1; } } } // Stationarity. // The difference between objective function and gradient at optimal // solution multiplied by dual multipliers must be 0, i.e., for the // optimal solution x // 0 == c // - sum(r in rows) r'(x)*rpi[r] // - sum(q in quads) q'(x)*qpi[q] // - sum(c in cols) b'(x)*cpi[c] // where r' and q' are the derivatives of a row or quadratic constraint, // x is the optimal solution and rpi[r] and qpi[q] are the dual // multipliers for row r and quadratic constraint q. // b' is the derivative of a bound constraint and cpi[c] the dual bound // multiplier for column c. IloNumArray kktsum(env, x.getSize()); // Objective function. for (IloExpr::LinearIterator it = obj.getLinearIterator(); it.ok(); ++it) kktsum[idx(it.getVar())] = it.getCoef(); // Linear constraints. // The derivative of a linear constraint ax - b (<)= 0 is just a. for (IloInt i = 0; i < linear.getSize(); ++i) { for (IloExpr::LinearIterator it = linear[i].getLinearIterator(); it.ok(); ++it) kktsum[idx(it.getVar())] -= rpi[i] * it.getCoef(); } // Quadratic constraints. // The derivative of a constraint xQx + ax - b <= 0 is // Qx + Q'x + a. for (IloInt q = 0; q < quad.getSize(); ++q) { for (IloExpr::LinearIterator it = quad[q].getLinearIterator(); it.ok(); ++it) kktsum[idx(it.getVar())] -= qpi[q] * it.getCoef(); for (IloExpr::QuadIterator it = quad[q].getQuadIterator(); it.ok(); ++it) { kktsum[idx(it.getVar1())] -= qpi[q] * xval[idx(it.getVar2())] * it.getCoef(); kktsum[idx(it.getVar2())] -= qpi[q] * xval[idx(it.getVar1())] * it.getCoef(); } } // Bounds. // The derivative for lower bounds is -1 and that for upper bounds // is 1. // CPLEX already returns dj with the appropriate sign so there is // no need to distinguish between different bound types here. for (IloInt j = 0; j < x.getSize(); ++j) kktsum[j] -= cpi[j]; for (IloInt j = 0; j < kktsum.getSize(); ++j) { if ( fabs (kktsum[j]) > ZEROTOL ) { cerr << "Stationarity test failed at index " << j << ": " << kktsum[j] << endl; result = -1; } } if ( result == 0) { // KKT conditions satisfied. Dump out the optimal solutions and // the dual values. streamsize oprec = cout.precision(3); ios_base::fmtflags oflags = cout.setf(ios::fixed | ios::showpos); cout << "Optimal solution satisfies KKT conditions." << endl; cout << " x[] = " << xval << endl; cout << " cpi[] = " << cpi << endl; cout << " rpi[] = " << rpi << endl; cout << " qpi[] = " << qpi << endl; cout.precision(oprec); cout.flags(oflags); } } catch (IloException& e) { cerr << "Concert exception caught: " << e << endl; result = -1; } catch (...) { cerr << "Unknown exception caught" << endl; result = -1; } env.end(); return result; } // END main