void iter2_ist(void* _conf, const struct operator_s* normaleq_op, unsigned int D, const struct operator_p_s** prox_ops, const struct linop_s** ops, const struct operator_p_s* xupdate_op, long size, float* image, const float* image_adj, const float* image_truth, void* obj_eval_data, float (*obj_eval)(const void*, const float*)) { assert(D == 1); #if 0 assert(NULL == ops); #else UNUSED(ops); #endif UNUSED(xupdate_op); struct iter_ist_conf* conf = _conf; float eps = md_norm(1, MD_DIMS(size), image_adj); if (checkeps(eps)) goto cleanup; assert((conf->continuation >= 0.) && (conf->continuation <= 1.)); ist(conf->maxiter, eps * conf->tol, conf->step, conf->continuation, conf->hogwild, size, (void*)normaleq_op, select_vecops(image_adj), operator_iter, operator_p_iter, (void*)prox_ops[0], image, image_adj, image_truth, obj_eval_data, obj_eval); cleanup: ; }
void iter2_fista(iter_conf* _conf, const struct operator_s* normaleq_op, unsigned int D, const struct operator_p_s* prox_ops[D], const struct linop_s* ops[D], const float* biases[D], const struct operator_p_s* xupdate_op, long size, float* image, const float* image_adj, struct iter_monitor_s* monitor) { assert(D == 1); assert(NULL == biases); #if 0 assert(NULL == ops); #else UNUSED(ops); #endif UNUSED(xupdate_op); auto conf = CAST_DOWN(iter_fista_conf, _conf); float eps = md_norm(1, MD_DIMS(size), image_adj); if (checkeps(eps)) goto cleanup; assert((conf->continuation >= 0.) && (conf->continuation <= 1.)); fista(conf->maxiter, eps * conf->tol, conf->step, conf->continuation, conf->hogwild, size, select_vecops(image_adj), OPERATOR2ITOP(normaleq_op), OPERATOR_P2ITOP(prox_ops[0]), image, image_adj, monitor); cleanup: ; }
void iter2_conjgrad(void* _conf, const struct operator_s* normaleq_op, unsigned int D, const struct operator_p_s** prox_ops, const struct linop_s** ops, const struct operator_p_s* xupdate_op, long size, float* image, const float* image_adj, const float* image_truth, void* obj_eval_data, float (*obj_eval)(const void*, const float*)) { assert(0 == D); assert(NULL == prox_ops); assert(NULL == ops); UNUSED(xupdate_op); struct iter_conjgrad_conf* conf = _conf; float eps = md_norm(1, MD_DIMS(size), image_adj); if (checkeps(eps)) goto cleanup; conjgrad(conf->maxiter, conf->l2lambda, eps * conf->tol, size, (void*)normaleq_op, select_vecops(image_adj), operator_iter, image, image_adj, image_truth, obj_eval_data, obj_eval); cleanup: ; }
void iter2_conjgrad(iter_conf* _conf, const struct operator_s* normaleq_op, unsigned int D, const struct operator_p_s* prox_ops[D], const struct linop_s* ops[D], const float* biases[D], const struct operator_p_s* xupdate_op, long size, float* image, const float* image_adj, struct iter_monitor_s* monitor) { assert(0 == D); assert(NULL == prox_ops); assert(NULL == ops); assert(NULL == biases); UNUSED(xupdate_op); auto conf = CAST_DOWN(iter_conjgrad_conf, _conf); float eps = md_norm(1, MD_DIMS(size), image_adj); if (checkeps(eps)) goto cleanup; conjgrad(conf->maxiter, conf->l2lambda, eps * conf->tol, size, select_vecops(image_adj), OPERATOR2ITOP(normaleq_op), image, image_adj, monitor); cleanup: ; }
void iter_landweber(iter_conf* _conf, const struct operator_s* normaleq_op, const struct operator_p_s* thresh_prox, long size, float* image, const float* image_adj, const float* image_truth, void* objval_data, float (*obj_eval)(const void*, const float*)) { struct iter_landweber_conf* conf = CONTAINER_OF(_conf, struct iter_landweber_conf, base); float eps = md_norm(1, MD_DIMS(size), image_adj); if (checkeps(eps)) goto cleanup; assert(NULL == thresh_prox); UNUSED(obj_eval); UNUSED(objval_data); UNUSED(image_truth); landweber_sym(conf->maxiter, 1.E-3 * eps, conf->step, size, (void*)normaleq_op, select_vecops(image_adj), operator_iter, image, image_adj); cleanup: ; }
static void inverse(void* _data, float alpha, float* dst, const float* src) { struct irgnm_s* data = _data; md_clear(1, MD_DIMS(data->size), dst, FL_SIZE); float eps = md_norm(1, MD_DIMS(data->size), src); conjgrad(100, alpha, 0.1f * eps, data->size, (void*)data, select_vecops(src), normal, dst, src, NULL, NULL, NULL); }
/** * Proximal function for f(z) = lambda || z ||_2. * Solution is z = ( 1 - lambda * mu / norm(z) )_+ * z, * i.e. block soft thresholding * * @param prox_data should be of type prox_l2norm_data * @param mu proximal penalty * @param z output * @param x_plus_u input */ static void prox_l2norm_fun(const operator_data_t* prox_data, float mu, float* z, const float* x_plus_u) { struct prox_l2norm_data* pdata = CAST_DOWN(prox_l2norm_data, prox_data); md_clear(1, MD_DIMS(pdata->size), z, FL_SIZE); double q1 = md_norm(1, MD_DIMS(pdata->size), x_plus_u); if (q1 != 0) { double q2 = 1 - pdata->lambda * mu / q1; if (q2 > 0.) md_smul(1, MD_DIMS(pdata->size), z, x_plus_u, q2); } }
/** * Proximal function for f(z) = Ind{ || y - z ||_2 < eps } * * @param prox_data should be of type prox_l2ball_data * @param mu proximal penalty * @param z output * @param x_plus_u input */ static void prox_l2ball_fun(const operator_data_t* prox_data, float mu, float* z, const float* x_plus_u) { UNUSED(mu); struct prox_l2ball_data* pdata = CAST_DOWN(prox_l2ball_data, prox_data); if (NULL != pdata->center) md_sub(1, MD_DIMS(pdata->size), z, x_plus_u, pdata->center); else md_copy(1, MD_DIMS(pdata->size), z, x_plus_u, FL_SIZE); float q1 = md_norm(1, MD_DIMS(pdata->size), z); if (q1 > pdata->eps) md_smul(1, MD_DIMS(pdata->size), z, z, pdata->eps / q1); if (NULL != pdata->center) md_add(1, MD_DIMS(pdata->size), z, z, pdata->center); }
/* Chambolle Pock Primal Dual algorithm. Solves G(x) + F(Ax) * Assumes that G is in prox_ops[0], F is in prox_ops[1], A is in ops[1] */ void iter2_chambolle_pock(iter_conf* _conf, const struct operator_s* normaleq_op, unsigned int D, const struct operator_p_s* prox_ops[D], const struct linop_s* ops[D], const float* biases[D], const struct operator_p_s* xupdate_op, long size, float* image, const float* image_adj, struct iter_monitor_s* monitor) { assert(D == 2); assert(NULL == biases); assert(NULL == normaleq_op); UNUSED(xupdate_op); UNUSED(image_adj); auto conf = CAST_DOWN(iter_chambolle_pock_conf, _conf); const struct iovec_s* iv = linop_domain(ops[1]); const struct iovec_s* ov = linop_codomain(ops[1]); assert((long)md_calc_size(iv->N, iv->dims) * 2 == size); // FIXME: sensible way to check for corrupt data? #if 0 float eps = md_norm(1, MD_DIMS(size), image_adj); if (checkeps(eps)) goto cleanup; #else float eps = 1.; #endif chambolle_pock(conf->maxiter, eps * conf->tol, conf->tau, conf->sigma, conf->theta, conf->decay, 2 * md_calc_size(iv->N, iv->dims), 2 * md_calc_size(ov->N, ov->dims), select_vecops(image), OPERATOR2ITOP(ops[1]->forward), OPERATOR2ITOP(ops[1]->adjoint), OPERATOR_P2ITOP(prox_ops[1]), OPERATOR_P2ITOP(prox_ops[0]), image, monitor); //cleanup: //; }
void iter_landweber(iter_conf* _conf, const struct operator_s* normaleq_op, const struct operator_p_s* thresh_prox, long size, float* image, const float* image_adj, struct iter_monitor_s* monitor) { struct iter_landweber_conf* conf = CAST_DOWN(iter_landweber_conf, _conf); float eps = md_norm(1, MD_DIMS(size), image_adj); if (checkeps(eps)) goto cleanup; assert(NULL == thresh_prox); landweber_sym(conf->maxiter, 1.E-3 * eps, conf->step, size, select_vecops(image_adj), OPERATOR2ITOP(normaleq_op), image, image_adj, monitor); cleanup: ; }
void iter2_admm(void* _conf, const struct operator_s* normaleq_op, unsigned int D, const struct operator_p_s** prox_ops, const struct linop_s** ops, const struct operator_p_s* xupdate_op, long size, float* image, const float* image_adj, const float* image_truth, void* obj_eval_data, float (*obj_eval)(const void*, const float*)) { struct iter_admm_conf* conf = _conf; struct admm_plan_s admm_plan = { .maxiter = conf->maxiter, .maxitercg = conf->maxitercg, .rho = conf->rho, .image_truth = image_truth, .num_funs = D, .do_warmstart = conf->do_warmstart, .dynamic_rho = conf->dynamic_rho, .hogwild = conf->hogwild, .ABSTOL = conf->ABSTOL, .RELTOL = conf->RELTOL, .alpha = conf->alpha, .tau = conf->tau, .mu = conf->mu, .fast = conf->fast, }; struct admm_op a_ops[D]; struct admm_prox_op a_prox_ops[D]; for (unsigned int i = 0; i < D; i++) { a_ops[i].forward = linop_forward_iter; a_ops[i].normal = linop_normal_iter; a_ops[i].adjoint = linop_adjoint_iter; a_ops[i].data = (void*)ops[i]; a_prox_ops[i].prox_fun = operator_p_iter; a_prox_ops[i].data = (void*)prox_ops[i]; } admm_plan.ops = a_ops; admm_plan.prox_ops = a_prox_ops; admm_plan.xupdate_fun = operator_p_iter; admm_plan.xupdate_data = (void*)xupdate_op; struct admm_history_s admm_history; long z_dims[D]; for (unsigned int i = 0; i < D; i++) z_dims[i] = 2 * md_calc_size(linop_codomain(ops[i])->N, linop_codomain(ops[i])->dims); if (NULL != image_adj) { float eps = md_norm(1, MD_DIMS(size), image_adj); if (checkeps(eps)) goto cleanup; } admm(&admm_history, &admm_plan, admm_plan.num_funs, z_dims, size, (float*)image, image_adj, select_vecops(image), operator_iter, (void*)normaleq_op, obj_eval_data, obj_eval); cleanup: ; } void iter2_pocs(void* _conf, const struct operator_s* normaleq_op, unsigned int D, const struct operator_p_s** prox_ops, const struct linop_s** ops, const struct operator_p_s* xupdate_op, long size, float* image, const float* image_adj, const float* image_truth, void* obj_eval_data, float (*obj_eval)(const void*, const float*)) { const struct iter_pocs_conf* conf = _conf; assert(NULL == normaleq_op); assert(NULL == ops); assert(NULL == image_adj); UNUSED(xupdate_op); UNUSED(image_adj); struct pocs_proj_op proj_ops[D]; for (unsigned int i = 0; i < D; i++) { proj_ops[i].proj_fun = operator_p_iter; proj_ops[i].data = (void*)prox_ops[i]; } pocs(conf->maxiter, D, proj_ops, select_vecops(image), size, image, image_truth, obj_eval_data, obj_eval); } void iter2_call_iter(void* _conf, const struct operator_s* normaleq_op, unsigned int D, const struct operator_p_s** prox_ops, const struct linop_s** ops, const struct operator_p_s* xupdate_op, long size, float* image, const float* image_adj, const float* image_truth, void* obj_eval_data, float (*obj_eval)(const void*, const float*)) { assert(D <= 1); assert(NULL == ops); UNUSED(xupdate_op); struct iter_call_s* it = _conf; it->fun(it->_conf, normaleq_op, (1 == D) ? prox_ops[0] : NULL, size, image, image_adj, image_truth, obj_eval_data, obj_eval); }
void iter2_niht(iter_conf* _conf, const struct operator_s* normaleq_op, unsigned int D, const struct operator_p_s* prox_ops[D], const struct linop_s* ops[D], const float* biases[D], const struct operator_p_s* xupdate_op, long size, float* image, const float* image_adj, struct iter_monitor_s* monitor) { UNUSED(xupdate_op); UNUSED(biases); assert(D == 1); auto conf = CAST_DOWN(iter_niht_conf, _conf); struct niht_conf_s niht_conf = { .maxiter = conf->maxiter, .N = size, .trans = 0, .do_warmstart = conf->do_warmstart, }; struct niht_transop trans; if (NULL != ops) { trans.forward = OPERATOR2ITOP(ops[0]->forward); trans.adjoint = OPERATOR2ITOP(ops[0]->adjoint); trans.N = 2 * md_calc_size(linop_codomain(ops[0])->N, linop_codomain(ops[0])->dims); niht_conf.trans = 1; } float eps = md_norm(1, MD_DIMS(size), image_adj); if (checkeps(eps)) goto cleanup; niht_conf.epsilon = eps * conf->tol; niht(&niht_conf, &trans, select_vecops(image_adj), OPERATOR2ITOP(normaleq_op), OPERATOR_P2ITOP(prox_ops[0]), image, image_adj, monitor); cleanup: ; } void iter2_call_iter(iter_conf* _conf, const struct operator_s* normaleq_op, unsigned int D, const struct operator_p_s* prox_ops[D], const struct linop_s* ops[D], const float* biases[D], const struct operator_p_s* xupdate_op, long size, float* image, const float* image_adj, struct iter_monitor_s* monitor) { assert(D <= 1); assert(NULL == ops); assert(NULL == biases); UNUSED(xupdate_op); auto it = CAST_DOWN(iter_call_s, _conf); it->fun(it->_conf, normaleq_op, (1 == D) ? prox_ops[0] : NULL, size, image, image_adj, monitor); }
void iter2_admm(iter_conf* _conf, const struct operator_s* normaleq_op, unsigned int D, const struct operator_p_s* prox_ops[D], const struct linop_s* ops[D], const float* biases[D], const struct operator_p_s* xupdate_op, long size, float* image, const float* image_adj, struct iter_monitor_s* monitor) { auto conf = CAST_DOWN(iter_admm_conf, _conf); struct admm_plan_s admm_plan = { .maxiter = conf->maxiter, .maxitercg = conf->maxitercg, .cg_eps = conf->cg_eps, .rho = conf->rho, .num_funs = D, .do_warmstart = conf->do_warmstart, .dynamic_rho = conf->dynamic_rho, .dynamic_tau = conf->dynamic_tau, .relative_norm = conf->relative_norm, .hogwild = conf->hogwild, .ABSTOL = conf->ABSTOL, .RELTOL = conf->RELTOL, .alpha = conf->alpha, .tau = conf->tau, .tau_max = conf->tau_max, .mu = conf->mu, .fast = conf->fast, .biases = biases, }; struct admm_op a_ops[D ?:1]; struct iter_op_p_s a_prox_ops[D ?:1]; for (unsigned int i = 0; i < D; i++) { a_ops[i].forward = OPERATOR2ITOP(ops[i]->forward), a_ops[i].normal = OPERATOR2ITOP(ops[i]->normal); a_ops[i].adjoint = OPERATOR2ITOP(ops[i]->adjoint); a_prox_ops[i] = OPERATOR_P2ITOP(prox_ops[i]); } admm_plan.ops = a_ops; admm_plan.prox_ops = a_prox_ops; admm_plan.xupdate = OPERATOR_P2ITOP(xupdate_op); long z_dims[D ?: 1]; for (unsigned int i = 0; i < D; i++) z_dims[i] = 2 * md_calc_size(linop_codomain(ops[i])->N, linop_codomain(ops[i])->dims); if (NULL != image_adj) { float eps = md_norm(1, MD_DIMS(size), image_adj); if (checkeps(eps)) goto cleanup; } admm(&admm_plan, admm_plan.num_funs, z_dims, size, (float*)image, image_adj, select_vecops(image), OPERATOR2ITOP(normaleq_op), monitor); cleanup: ; } void iter2_pocs(iter_conf* _conf, const struct operator_s* normaleq_op, unsigned int D, const struct operator_p_s* prox_ops[D], const struct linop_s* ops[D], const float* biases[D], const struct operator_p_s* xupdate_op, long size, float* image, const float* image_adj, struct iter_monitor_s* monitor) { auto conf = CAST_DOWN(iter_pocs_conf, _conf); assert(NULL == normaleq_op); assert(NULL == ops); assert(NULL == biases); assert(NULL == image_adj); UNUSED(xupdate_op); UNUSED(image_adj); struct iter_op_p_s proj_ops[D]; for (unsigned int i = 0; i < D; i++) proj_ops[i] = OPERATOR_P2ITOP(prox_ops[i]); pocs(conf->maxiter, D, proj_ops, select_vecops(image), size, image, monitor); }
const struct linop_s* ops[static D], const struct operator_p_s* xupdate_op, long size, float* image, const float* image_adj, const float* image_truth, void* obj_eval_data, float (*obj_eval)(const void*, const float*)) { assert(0 == D); assert(NULL == prox_ops); assert(NULL == ops); UNUSED(xupdate_op); struct iter_conjgrad_conf* conf = CONTAINER_OF(_conf, struct iter_conjgrad_conf, base); float eps = md_norm(1, MD_DIMS(size), image_adj); if (checkeps(eps)) goto cleanup; conjgrad(conf->maxiter, conf->l2lambda, eps * conf->tol, size, (void*)normaleq_op, select_vecops(image_adj), operator_iter, image, image_adj, image_truth, obj_eval_data, obj_eval); cleanup: ; } void iter2_ist(iter_conf* _conf, const struct operator_s* normaleq_op, unsigned int D, const struct operator_p_s* prox_ops[static D],