static gboolean rosenbrock_iter (GnmNlsolve *nl) { GnmSolver *sol = nl->sol; GnmIterSolver *isol = nl->isol; const int n = nl->n; int i, j; const gnm_float alpha = 3; const gnm_float beta = 0.5; gboolean any_at_all = FALSE; gnm_float *d, **A, *x, *dx, *t; char *state; int dones = 0; gnm_float ykm1 = isol->yk, *xkm1; gnm_float eps = gnm_pow2 (-16); int safety = 0; if (nl->tentative) { nl->tentative--; if (nl->tentative == 0) { if (nl->debug) g_printerr ("Tentative move rejected\n"); rosenbrock_tentative_end (nl, FALSE); } } if (isol->iterations % 20 == 0) { for (i = 0; i < n; i++) for (j = 0; j < n; j++) nl->xi[i][j] = (i == j); } A = g_new (gnm_float *, n); for (i = 0; i < n; i++) A[i] = g_new (gnm_float, n); dx = g_new (gnm_float, n); for (i = 0; i < n; i++) dx[i] = 0; x = g_new (gnm_float, n); t = g_new (gnm_float, n); d = g_new (gnm_float, n); for (i = 0; i < n; i++) { d[i] = (isol->xk[i] == 0) ? eps : gnm_abs (isol->xk[i]) * eps; } xkm1 = g_memdup (isol->xk, n * sizeof (gnm_float)); state = g_new0 (char, n); while (dones < n) { /* * A safety that shouldn't get hit, but might if the function * being optimized is non-deterministic. */ if (safety++ > n * GNM_MANT_DIG) break; for (i = 0; i < n; i++) { gnm_float y; if (state[i] == 2) continue; /* x = xk + (d[i] * xi[i]) */ for (j = 0; j < n; j++) x[j] = isol->xk[j] + d[i] * nl->xi[i][j]; set_vector (nl, x); y = get_value (nl); if (y <= isol->yk && gnm_solver_check_constraints (sol)) { if (y < isol->yk) { isol->yk = y; memcpy (isol->xk, x, n * sizeof (gnm_float)); dx[i] += d[i]; any_at_all = TRUE; } switch (state[i]) { case 0: state[i] = 1; /* Fall through */ case 1: d[i] *= alpha; break; default: case 2: break; } } else { switch (state[i]) { case 1: state[i] = 2; dones++; /* Fall through */ case 0: d[i] *= -beta; break; default: case 2: /* No sign change. */ d[i] *= 0.5; break; } } } } if (any_at_all) { gnm_float div, sum; for (j = n - 1; j >= 0; j--) for (i = 0; i < n; i++) A[j][i] = (j == n - 1 ? 0 : A[j + 1][i]) + dx[j] * nl->xi[j][i]; sum = 0; for (i = n - 1; i >= 0; i--) { sum += dx[i] * dx[i]; t[i] = sum; } for (i = n - 1; i > 0; i--) { div = gnm_sqrt (t[i - 1] * t[i]); if (div != 0) for (j = 0; j < n; j++) { nl->xi[i][j] = (dx[i - 1] * A[i][j] - nl->xi[i - 1][j] * t[i]) / div; g_assert (gnm_finite (nl->xi[i][j])); } } gnm_range_hypot (dx, n, &div); if (div != 0) { for (i = 0; i < n; i++) { nl->xi[0][i] = A[0][i] / div; if (!gnm_finite (nl->xi[0][i])) { g_printerr ("%g %g %g\n", div, A[0][i], nl->xi[0][i]); g_assert (gnm_finite (nl->xi[0][i])); } } } /* ---------------------------------------- */ if (!nl->tentative) { set_vector (nl, isol->xk); set_solution (nl); } if (nl->tentative) { if (isol->yk < nl->tentative_yk) { if (nl->debug) g_printerr ("Tentative move accepted!\n"); rosenbrock_tentative_end (nl, TRUE); } } else if (gnm_abs (isol->yk - ykm1) > gnm_abs (ykm1) * 0.01) { /* A big step. */ nl->smallsteps = 0; } else { nl->smallsteps++; } if (0 && !nl->tentative && nl->smallsteps > 50) { gnm_float yk = isol->yk; nl->tentative = 10; nl->tentative_xk = g_memdup (isol->xk, n * sizeof (gnm_float)); nl->tentative_yk = yk; for (i = 0; i < 4; i++) { gnm_float ymax = yk + gnm_abs (yk) * (0.10 / (i + 1)); if (i > 0) ymax = MIN (ymax, isol->yk); if (!newton_improve (nl, isol->xk, &isol->yk, ymax)) break; } if (nl->debug) print_vector ("Tentative move to", isol->xk, n); } } g_free (x); g_free (xkm1); g_free (dx); g_free (t); g_free (d); free_matrix (A, n); g_free (state); return any_at_all; }
int main() { int type; int i, j; int op3; double topd; double op2; char ic[MAXOP]; /* Input Char */ char tmp[MAXOP]; for (i = 0; i < VARMAX; i++) { var_array[i] = 0; } print_help(); while ((type = getop(ic)) != EOF) { op3 = elem(); if (op3 == 0) { /* Only one input completed. */ is_first_input = 1; } else if (op3 > 1) { is_first_input = 0; } i = j = 0; switch (type) { case NUMBER: push(atof(ic)); break; case VARIABLE: for (i = 2; ic[i] != '\0'; i++){ tmp[j++] = ic[i]; tmp[j] = '\0'; } var_array[ic[0] - 'A'] = atof(tmp); break; case '+': push(pop() + pop()); break; case '*': push(pop() * pop()); break; case '-': op2 = pop(); push(pop() - op2); break; case '/': op2 = pop(); if (op2 != 0.0){ push(pop() / op2); } else { printf("Error: Divide by zero.\n"); } break; case '%': op3 = (int) pop(); push((int) pop() % op3); break; case 'c': if (clear()) { printf("Stack Cleared.\n"); } break; case 'p': if ((topd = top()) != 0) { printf("Top stack element: %g", topd); printf(" of %d elements.\n", elem()); } break; case 's': if (swap()) { printf("Swap successful.\n"); } break; case 'd': if (dup()) { printf("Duplication is successful.\n"); } else { printf("Error: Stack empty.\n"); } break; case 'r': sprnt(); break; case 'o': if (elem() < 2) { printf("Error: pow requires at least two "); printf("items on the stack.\n"); break; } op2 = pop(); push(pow(op2, pop())); break; case 'i': set_solution(); push(sin(pop())); result(); break; case 'y': set_solution(); push(cos(pop())); break; case 't': set_solution(); push(tan(pop())); break; case 'x': set_solution(); push(exp(pop())); break; case 'q': set_solution(); push(sqrt(pop())); break; case 'f': set_solution(); push(floor(pop())); break; case 'l': set_solution(); push(ceil(pop())); break; case 'v': for (i = 0; i < VARMAX; i++) { if (i < VARMAX-1) { printf("%c: %10.10G\n", 'A' + i, var_array[i]); } else { printf("%c: %10.10G\n", '=', var_array[VARMAX]); } } break; case 'h': print_help(); break; case '\n': result(); break; default: if ((type >= 'A' && type <= 'Z') || type == '=') { if (type != '=') { push(var_array[type - 'A']); } else { push(var_array[VARMAX]); } } else { printf("Error: Unknown command \'%s\'\n", ic); } break; } } return 0; }