bool distorted(const int v1,const int v2,const int v3,const std::vector<CVector<3,double> >& result) { if (result[v1][2]<0 || result[v2][2]<0 || result[v3][2]<0) return true; CVector<3,double> d12 = result[v2]-result[v1]; CVector<3,double> d23 = result[v3]-result[v2]; CVector<3,double> d31 = result[v1]-result[v3]; double n12 = GetNorm2(d12); double n23 = GetNorm2(d23); double n31 = GetNorm2(d31); if (n12>m_max_edge_length || n23>m_max_edge_length || n31>m_max_edge_length) return true; double cos1=dot(d12,-d31)/(n12*n31); double cos2=dot(-d12,d23)/(n12*n23); double cos3=dot(-d23,d31)/(n23*n31); double maxcos = std::max(std::max(cos1,cos2),cos3); double t = cos(m_distortion_angle*M_PI/180); return maxcos > t; }
double SubgradientDecomposition::Maximize(int iter_max, double gap_threshold, UpperBoundFn F_upper) { double theta, z, delta; double upper_bound_best = 1e100; Subproblem* s; int k; int gamma; // number of steps since the last improvement of the best objective value int gamma_bar = 20; int delta_min_num = 0; double norm2_max = 0; // init memset(buf, 0, n0*sizeof(double)); n = 0; for (s=subproblems->ScanFirst(); s; s=subproblems->ScanNext()) { if (s->weight < 0) { printf("Error: subproblem weight cannot be negative!\n"); exit(1); } if (s->weight == 0) continue; for (k=0; k<s->var_num; k++) buf[s->array[k]] += s->weight*s->weight; n += s->var_num; } for (k=0; k<n0; k++) { if (buf[k] <= 0) { printf("Incorrect decomposition: not all elements are covered!\n"); exit(1); } } double* vars = new double[2*n]; double* g = vars + n; ReadBest(vars); z = theta = ProjectAndComputeSubgradient(vars, g); WriteBest(vars); gamma = 0; for (k=0; k<iter_max; k++) { double upper_bound = F_upper(user_arg); if (k==0 || upper_bound_best>upper_bound) upper_bound_best = upper_bound; if (k==0) delta = (upper_bound_best - z)*options.C; if (z>=upper_bound_best-gap_threshold) break; double norm2 = GetNorm2(g, n); if (norm2 == 0) break; if (norm2_max < norm2) norm2_max = norm2; double upper_bound_estimate = z+delta; //if (upper_bound_estimate > upper_bound_best) upper_bound_estimate = upper_bound_best; double lambda = options.alpha*(upper_bound_estimate-theta)/norm2; if (options.verbose) printf("%d\t%f\t%f\tstep=%f", k, theta, upper_bound, lambda); Add(vars, g, lambda, n); theta = ProjectAndComputeSubgradient(vars, g); if (theta > z) { if (options.verbose) printf(" *"); delta *= options.A; z = theta; WriteBest(vars); gamma = 0; } else { delta *= options.B; if (gamma ++ >= gamma_bar) { if (options.verbose) printf(" restart"); gamma_bar += 10; if (gamma_bar > 50) gamma_bar = 50; ReadBest(vars); gamma = 0; theta = ProjectAndComputeSubgradient(vars, g); if (delta < (upper_bound_best - z)*0.01) { if (options.verbose) printf("\nconverged?\n"); break; } } } if (delta < (upper_bound_best - z)*options.C) { if (options.verbose) printf(" !"); if (delta_min_num ++ >= 30) { if (options.verbose) printf("\nconverged?\n"); break; } delta = (upper_bound_best - z)*options.C; } if (options.verbose) printf("\n"); } if (options.verbose) printf("lower_bound=%f\tupper_bound=%f\n", z, upper_bound_best); delete [] vars; return z; }