Exemplo n.º 1
0
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;
}
Exemplo n.º 2
0
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;
}