int smo_c::minimize_ij(const SVMINT i, const SVMINT j){ // minimize xi, xi with simple_solve SVMFLOAT sum_i; // sum_k Hik x_k SVMFLOAT sum_j; // init sum_i,j sum_i=sum[i]; sum_j=sum[j]; sum_i -= qp->H[i*(n+1)]*x[i]; sum_i -= qp->H[i*n+j]*x[j]; sum_j -= qp->H[j*n+i]*x[i]; sum_j -= qp->H[j*(n+1)]*x[j]; SVMFLOAT old_xi = x[i]; SVMFLOAT old_xj = x[j]; simple_solve(&(x[i]), &(x[j]), qp->H[i*(n+1)]/2, qp->H[j*(n+1)]/2, qp->H[i*n+j], sum_i, sum_j, qp->A[i], qp->A[j], qp->l[i], qp->l[j], qp->u[i], qp->u[j]); SVMFLOAT target; target = (old_xi-x[i])*(qp->H[i*(n+1)]/2*(old_xi+x[i])+sum_i) +(old_xj-x[j])*(qp->H[j*(n+1)]/2*(old_xj+x[j])+sum_j) +qp->H[i*n+j]*(old_xi*old_xj-x[i]*x[j]); if(target < 0){ // cout<<"increase on SMO: "<<target<<endl; x[i] = old_xi; x[j] = old_xj; old_xi=0; old_xj=0; } else{ old_xi-=x[i]; old_xj-=x[j]; if((old_xi != 0) || (old_xj != 0)){ SVMINT k; SVMFLOAT* Hin = &(qp->H[i*n]); SVMFLOAT* Hjn = &(qp->H[j*n]); for(k=0;k<n;k++){ sum[k]-=Hin[k]*old_xi; sum[k]-=Hjn[k]*old_xj; }; }; }; return((abs(old_xi) > is_zero) || (abs(old_xj) > is_zero)); };
/** * 再帰的解法(実体) * 人間的な解法アルゴリズムは使わずに機械的解法で解く * 機械的解法で解けないときは、複数候補のあるマスの候補から一つ選んで解けるか試す * ということを再帰的に実行する。 * また、解が複数あるかどうかもチェックする。 * 解けたときは array に解をセットする。 * @param array ナンプレ盤面配列 * @param data 再帰用持ち回しデータ * @return -1 矛盾があって解けない * @return 1 解けた * @return 2 解が複数存在する。 */ static int recursion_solve_sub(numpl_array * array, recursion_solve_t *data) { numpl_array work; work = *array; int solved = simple_solve(&work); if (solved < 0) { return solved; } solved = is_solved(&work); if (solved == 1) { if (!data->saved) { data->save = work; data->saved = 1; } else if (!equal(&data->save, &work)) { solved = 2; } } if (solved != 0) { *array = work; return solved; } int result = -1; for (int i = 0; i < ARRAY_SIZE; i++) { if (is_single(work.ar[i])) { continue; } cell_t s = work.ar[i]; for (int j = 0; j < LINE_SIZE; j++) { work.ar[i] = s; unsigned int mask = s.symbol & (1 << j); if (!mask) { continue; } work.ar[i].symbol = mask; solved = recursion_solve_sub(&work, data); if (solved > 1) { *array = work; return solved; } else if (solved == 1) { *array = work; result = 1; } } break; } return result; }