예제 #1
0
        private double GetdF(Double[] V, Int32 Index, double accuracy)
        {
            double[] temp = new double[V.Length];

            for (Int32 i = 0; i < V.Length; i++)
            {
                if (i == Index)
                {
                    temp.SetValue(V[i] + accuracy, i);
                }
                else
                {
                    temp.SetValue(V[i], i);
                }
            }

            return((FunctionClass.Function3(temp) - FunctionClass.Function3(V)) / accuracy);
        }
예제 #2
0
        private void HookJeevesButton_Click(object sender, EventArgs e)
        {
            OutBox.Text = string.Empty;

            double eps  = Convert.ToDouble(EpsilonBox.Text); // Точность вычислений
            double step = Convert.ToDouble(StepBox.Text);    // Начальный шаг
            // Начальное приближение
            double x  = Convert.ToDouble(x0Box.Text);
            double y  = Convert.ToDouble(y0Box.Text);
            double y0 = FunctionClass.Function2(x, y);

            int    IterCount = 0;
            double fx;

            double lenght, y1, y2, y3, x1n, x2n, x1nn, x2nn;
            int    fl = 0;

            lenght = 1;

            do
            {
                fx           = FunctionClass.Function2(x, y);
                OutBox.Text += "x = " + Math.Round(x, 6).ToString() + "   y = " + Math.Round(y, 6).ToString() + "   f(x, y) = " + Math.Round(fx, 6).ToString() + "\r\n";

                fl = 0;
                y1 = FunctionClass.Function2(x + step, y);
                if (y1 < y0)
                {
                    x1n = x + step;
                }
                else
                {
                    y1 = FunctionClass.Function2(x - step, y);
                    if (y1 < y0)
                    {
                        x1n = x - step;
                    }
                    else
                    {
                        x1n = x;
                        y1  = y0;
                    }
                }
                y2 = FunctionClass.Function2(x1n, y + step);
                if (y2 < y1)
                {
                    x2n = y + step;
                }
                else
                {
                    y2 = FunctionClass.Function2(x1n, y - step);
                    if (y2 < y1)
                    {
                        x2n = y - step;
                    }
                    else
                    {
                        x2n = y;
                        y2  = y1;
                    }
                }
                if ((x1n == x) && (x2n == y))
                {
                    if (step > eps)
                    {
                        fl   = 1;
                        step = step / 2;
                    }
                }
                else
                {
                    fl = 1;
                    do
                    {
                        x1nn   = x1n + lenght * (x1n - x);
                        x2nn   = x2n + lenght * (x2n - y);
                        y3     = FunctionClass.Function2(x1nn, x2nn);
                        x      = x1nn;
                        y      = x2nn;
                        lenght = lenght * 0.5;
                    } while (y2 < y3);

                    IterCount++;
                    y0 = y3;
                }
            } while (fl == 1);

            fx                = FunctionClass.Function2(x, y);
            MinXBox.Text      = x.ToString();
            MinYBox.Text      = y.ToString();
            MinFBox.Text      = fx.ToString();
            IterCountBox.Text = IterCount.ToString();
        }
예제 #3
0
        private void BuildButton_Click(object sender, EventArgs e)
        {
            // Границы вычисления функции по осям X и Y
            double minX = Convert.ToDouble(MinXBox.Text);
            double maxX = Convert.ToDouble(MaxXBox.Text);
            double minY = Convert.ToDouble(MinYBox.Text);
            double maxY = Convert.ToDouble(MaxYBox.Text);
            // Масштаб
            double intervalX  = maxX - minX;
            double intervalY  = maxY - minY;
            double zoomX      = intervalX / bitmap.Width;          // 1 пиксель : 1 ед.измерения оси X
            double zoomY      = intervalY / bitmap.Height;         // 1 пиксель : 1 ед.измерения оси Y
            double eps        = Convert.ToDouble(EpsilonBox.Text); // Точность
            int    levelCount = Convert.ToInt32(LevelBox.Text);    // Количество линий уровня
            // Уровни
            int countX = Convert.ToInt32(bitmap.Width);
            int countY = Convert.ToInt32(bitmap.Height);

            double[,] values = new double[countX, countY]; // Сетка функции
            double[] levels = new double[levelCount];      // Уровни функции
            for (int i = 0; i < bitmap.Width; i++)
            {
                for (int j = 0; j < bitmap.Height; j++)
                {
                    double x = minX + i * zoomX;
                    double y = minY + j * zoomY;
                    double z = FunctionClass.Function2(x, y);

                    values[i, j] = z;
                }
            }
            double minValue = values[0, 0];  // Локальный минимум функции
            double maxValue = values[0, 0];  // Локальный максимум функции

            for (int i = 0; i < values.GetLength(0); i++)
            {
                for (int j = 0; j < values.GetLength(1); j++)
                {
                    if (values[i, j] < minValue)
                    {
                        minValue = values[i, j];
                    }

                    if (values[i, j] > maxValue)
                    {
                        maxValue = values[i, j];
                    }
                }
            }
            int levelStepX = bitmap.Width / levelCount / 2;
            int levelStepY = bitmap.Height / levelCount / 2;

            for (int i = 0; i < levelCount; i++)
            {
                levels[i] = values[i * levelStepX, i *levelStepY];
            }
            // Рисуем линии уровней
            ProgressBar.Value   = 0;
            ProgressBar.Maximum = bitmap.Width * bitmap.Height * levels.Length;

            for (int i = 0; i < bitmap.Width; i++)
            {
                for (int j = 0; j < bitmap.Height; j++)
                {
                    for (int k = 0; k < levels.Length; k++)
                    {
                        double x = minX + i * zoomX;
                        double y = minY + j * zoomY;
                        double z = FunctionClass.Function2(x, y);

                        if (z >= levels[k] - eps && z <= levels[k] + eps)
                        {
                            int c = (int)(255 * Math.Abs(z - levels[k]) / eps);
                            DrawPoint(i, bitmap.Height - j - 1, Color.FromArgb(c, c, c));
                        }

                        ProgressBar.Value++;
                    }
                }
            }
        }
예제 #4
0
        private void GaussButton_Click(object sender, EventArgs e)
        {
            OutBox.Text = string.Empty;

            double eps  = Convert.ToDouble(EpsilonBox.Text); // Точность вычислений
            double step = Convert.ToDouble(StepBox.Text);    // Начальный шаг
            // Начальное приближение
            double x = Convert.ToDouble(x0Box.Text);
            double y = Convert.ToDouble(y0Box.Text);

            int    IterCount = 0;
            double fx, prevX, prevY, curX = x, curY = y;
            double leftBorder, rightBorder;
            double x1, xm, x2;
            double y1, ym, y2;
            double z1, zm, z2;

            do
            {
                IterCount++;

                prevX = curX;
                prevY = curY;

                // По 1 координате
                leftBorder  = prevX - step;
                rightBorder = prevX + step;

                x1 = leftBorder + (rightBorder - leftBorder) / 4;
                xm = (leftBorder + rightBorder) / 2;
                x2 = rightBorder - (rightBorder - leftBorder) / 4;

                z1 = FunctionClass.Function2(x1, prevY);
                zm = FunctionClass.Function2(xm, prevY);
                z2 = FunctionClass.Function2(x2, prevY);

                while (Math.Abs(rightBorder - leftBorder) > eps)
                {
                    if ((z1 > zm) && (zm < z2))
                    {
                        leftBorder  = x1;
                        rightBorder = x2;

                        x1 = leftBorder + (rightBorder - leftBorder) / 4;
                        x2 = rightBorder - (rightBorder - leftBorder) / 4;
                    }
                    else if ((z1 > zm) && (zm > z2))
                    {
                        leftBorder = xm;

                        x1 = leftBorder + (rightBorder - leftBorder) / 4;
                        x2 = rightBorder - (rightBorder - leftBorder) / 4;
                        xm = (leftBorder + rightBorder) / 2;

                        zm = FunctionClass.Function2(xm, prevY);
                    }
                    else if ((z1 < zm) && (zm < z2))
                    {
                        rightBorder = xm;

                        x1 = leftBorder + (rightBorder - leftBorder) / 4;
                        x2 = rightBorder - (rightBorder - leftBorder) / 4;
                        xm = (leftBorder + rightBorder) / 2;

                        zm = FunctionClass.Function2(xm, prevY);
                    }

                    z1 = FunctionClass.Function2(x1, prevY);
                    z2 = FunctionClass.Function2(x2, prevY);
                }

                curX = (leftBorder + rightBorder) / 2;

                // По 2 координате
                leftBorder  = prevY - step;
                rightBorder = prevY + step;

                y1 = leftBorder + (rightBorder - leftBorder) / 4;
                ym = (leftBorder + rightBorder) / 2;
                y2 = rightBorder - (rightBorder - leftBorder) / 4;

                z1 = FunctionClass.Function2(curX, y1);
                zm = FunctionClass.Function2(curX, ym);
                z2 = FunctionClass.Function2(curX, y2);

                while (Math.Abs(rightBorder - leftBorder) > eps)
                {
                    if ((z1 > zm) && (zm < z2))
                    {
                        leftBorder  = y1;
                        rightBorder = y2;

                        y1 = leftBorder + (rightBorder - leftBorder) / 4;
                        y2 = rightBorder - (rightBorder - leftBorder) / 4;
                    }
                    else if ((z1 > zm) && (zm > z2))
                    {
                        leftBorder = ym;

                        y1 = leftBorder + (rightBorder - leftBorder) / 4;
                        y2 = rightBorder - (rightBorder - leftBorder) / 4;
                        ym = (leftBorder + rightBorder) / 2;

                        zm = FunctionClass.Function2(curX, ym);
                    }
                    else if ((z1 < zm) && (zm < z2))
                    {
                        rightBorder = ym;

                        y1 = leftBorder + (rightBorder - leftBorder) / 4;
                        y2 = rightBorder - (rightBorder - leftBorder) / 4;
                        ym = (leftBorder + rightBorder) / 2;

                        zm = FunctionClass.Function2(curX, ym);
                    }

                    z1 = FunctionClass.Function2(curX, y1);
                    z2 = FunctionClass.Function2(curX, y2);
                }

                curY = (leftBorder + rightBorder) / 2;
            }while (Math.Abs(FunctionClass.Function2(curX, curY) - FunctionClass.Function2(prevX, prevY)) > eps);

            fx                = FunctionClass.Function2(curX, curY);
            MinXBox.Text      = curX.ToString();
            MinYBox.Text      = curY.ToString();
            MinFBox.Text      = fx.ToString();
            IterCountBox.Text = IterCount.ToString();
        }
예제 #5
0
        private void NewtonButton_Click(object sender, EventArgs e)
        {
            OutBox.Text = string.Empty;

            // Шаг 1
            int    k = 0;  // Счетчик итераций
            double x0, y0; // Начальное приближение
            double a = 1;  // Шаг для модифицированного метода

            x0  = Convert.ToDouble(x0Box.Text);
            y0  = Convert.ToDouble(y0Box.Text);
            eps = Convert.ToDouble(EpsilonBox.Text);
            //a = Convert.ToDouble(StepBox.Text);

            double x = x0, y = y0;                     // Текущая точка

            double[] grad = new double[2];             // Градиент
            double [,] matrix      = new double[2, 2]; // Матрица Гессе
            double[,] invertMatrix = new double[2, 2]; // Обратная матрица Гессе
            double[] p         = new double[2];        // Направление спуска
            double[] curPoint  = new double[2];        // Текущая точка
            double[] nextPoint = new double[2];        // Следущая точка

calculate:

            OutBox.Text += "Итерация № " + k.ToString() + "\r\n" +
                           "Текущая точка (" + x + ", " + y + ")\r\n" +
                           "Значение функции в точке " + FunctionClass.Function2(x, y) + "\r\n";

            // Вычисляем градиент
            grad         = GetGrad(x, y);
            OutBox.Text += "Градиент\r\n (" + grad[0] + ", " + grad[1] + ")\r\n";

            // Вычисляем матрицу Гессе
            matrix       = GetHesse(x, y);
            OutBox.Text += "Матрица Гессе\r\n" +
                           "| " + matrix[0, 0] + " | " + matrix[0, 1] + " |\r\n" +
                           "| " + matrix[1, 0] + " | " + matrix[1, 1] + " |\r\n";
            // Шаг 2
            // Определяем обратную матрицу
            invertMatrix = InvertMatrix(matrix);
            if (invertMatrix == null)
            {
                return;
            }
            OutBox.Text += "Обратная матрица Гессе\r\n" +
                           "| " + invertMatrix[0, 0] + " | " + invertMatrix[0, 1] + " |\r\n" +
                           "| " + invertMatrix[1, 0] + " | " + invertMatrix[1, 1] + " |\r\n";

            // Шаг 3
            // Определяем направление спуска
            p            = GetDirect(grad, invertMatrix);
            OutBox.Text += "Направление спуска\r\n (" + p[0] + ", " + p[1] + ")\r\n";

            // Шаг 4
            // Определяем следующую точку
            curPoint[0] = x;
            curPoint[1] = y;
            //a = GoldenSection(curPoint, eps, -10, 10, p);
            nextPoint    = GetNextPoint(curPoint, a, p);
            OutBox.Text += "Новая точка (" + nextPoint[0] + ", " + nextPoint[1] + ")\r\n";

            // Шаг 5
            // Вычисление в новой точке градиента
            grad = GetGrad(nextPoint[0], nextPoint[1]);

            // Шаг 6
            // Если точность не достигнута, то продолжаем итерации
            x = nextPoint[0];
            y = nextPoint[1];

            if ((Math.Sqrt(grad[0] * grad[0] + grad[1] * grad[1]) > eps && Math.Abs(FunctionClass.Function2(curPoint[0], curPoint[1]) - FunctionClass.Function2(nextPoint[0], nextPoint[1])) > eps))
            {
                k++;
                OutBox.Text += "________________________________\r\n";
                goto calculate;
            }

            double f = FunctionClass.Function2(x, y);

            OutBox.Text += "*************************************\r\n" +
                           "Минимум функции равен " + f + "\r\n" +
                           "в точке (" + x + ", " + y + ")\r\n";

            MinXBox.Text      = x.ToString();
            MinYBox.Text      = y.ToString();
            MinFBox.Text      = f.ToString();
            IterCountBox.Text = (k + 1).ToString();
        }
예제 #6
0
 public double GetDfDy(double _x, double _y)
 {
     return((FunctionClass.Function2(_x, _y + Math.Pow(eps, 2)) - FunctionClass.Function2(_x, _y)) / Math.Pow(eps, 2));
 }
예제 #7
0
        // Метод Коши (Наискорейший градиентный спуск)
        private string Grad(double[] x0, double eps, double h)
        {
            // 1 шаг
            string result = "";

            double[] x      = new double[x0.Length], grad = new double[x0.Length];
            double   deltaX = 0;
            Int32    index  = 0;

            x0.CopyTo(x, 0);

            result += "Начальная точка:\r\n";
            for (Int32 i = 0; i < x0.Length; i++)
            {
                result += "x[" + i + "]=" + x0[i] + "\r\n";
            }
            result += "F(x[0], x[1]) = " + FunctionClass.Function3(x0) + "\r\n\r\n";

            do
            {
                index++;

                // 2 шаг
                result += "Вычисление градиенты: \r\n";
                for (Int32 i = 0; i < x.Length; i++)
                {
                    grad[i] = GetdF(x0, i, eps);
                    result += grad[i] + "\r\n";
                }

                // 3 шаг отпадает, т.к. нет ограничений на кол-во итераций

                // 4 шаг
                h       = GoldenSection(x, eps, leftBorder, rightBorder);
                result += "Шаг: " + h + "\r\n";

                // 5 шаг
                for (Int32 i = 0; i < x.Length; i++)
                {
                    x[i] = x0[i] - h * GetdF(x0, i, eps);
                }

                result += "\r\nНовая точка: \r\n";
                for (Int32 i = 0; i < x.Length; i++)
                {
                    result += "x[" + i + "] = " + x[i] + "\r\n";
                    deltaX  = Math.Pow(x[i] - x0[i], 2);
                }

                result += "F(x[0], x[1]) = " + FunctionClass.Function3(x) + "\r\n\r\n";
                x.CopyTo(x0, 0);
            }
            // 6 шаг
            while (Math.Sqrt(Math.Abs(deltaX)) > eps);


            result += "Минимум:\r\n";
            for (Int32 i = 0; i < x.Length; i++)
            {
                result += "x[" + i + "] = " + x[i] + "\r\n";
            }
            result += "Значение: " + FunctionClass.Function3(x);

            MinXBox.Text      = x[0].ToString();
            MinYBox.Text      = x[1].ToString();
            MinFBox.Text      = FunctionClass.Function3(x).ToString();
            IterCountBox.Text = index.ToString();

            return(result);
        }
예제 #8
0
        private double GoldenSection(out string log, double leftBorder, double rightBorder, double accuracy)
        {
            log = "Метод золотого сечения:\r\n\r\n" +
                  "Входные данные:\r\n" +
                  "     Левая граница a = " + leftBorder + "\r\n" +
                  "     Правая граница b = " + rightBorder + "\r\n" +
                  "     Точность eps = " + accuracy + "\r\n\r\n" +
                  "Итерации:\r\n\r\n";

            double tau = (-1 + Math.Sqrt(5)) / 2.0;

            double x1 = leftBorder + (rightBorder - leftBorder) * tau;
            double x2 = rightBorder - (rightBorder - leftBorder) * tau;
            double xm = (leftBorder + rightBorder) / 2;

            double y1 = FunctionClass.Function1(x1);
            double y2 = FunctionClass.Function1(x2);
            double ym = FunctionClass.Function1(xm);

            log += "a = " + leftBorder + " " + "b = " + rightBorder + " " + "xm = " + xm + " " + "x1 = " + x1 + " " + "x2 = " + x2 + "\r\n";
            log += "F(a) = " + FunctionClass.Function1(leftBorder) + " " + "F(b) = " + FunctionClass.Function1(rightBorder) + " " + "F(xm) = " + ym + " " + "F(x1) = " + y1 + " " + "F(x2) = " + y2 + "\r\n\r\n";

            int i = 0;

            while (Math.Abs(rightBorder - leftBorder) > accuracy)
            {
                i++;

                if ((y1 < y2))
                {
                    log += "# " + i + " y1 < y2\r\n";

                    leftBorder = x2;
                    x2         = x1;
                    x1         = leftBorder + (rightBorder - leftBorder) * tau;

                    log += "x1 = " + x1 + "\r\n";
                    log += "x2 = " + x2 + "\r\n";
                }
                else if ((y1 > y2))
                {
                    log += "# " + i + " y1 > y2\r\n";

                    rightBorder = x1;
                    x1          = x2;
                    x2          = rightBorder - (rightBorder - leftBorder) * tau;

                    log += "x1 = " + x1 + "\r\n";
                    log += "x2 = " + x2 + "\r\n";
                }

                y1 = FunctionClass.Function1(x1);
                y2 = FunctionClass.Function1(x2);

                xm = (leftBorder + rightBorder) / 2;
                ym = FunctionClass.Function1(xm);

                log += "# " + i + "   " + xm + "\r\n\r\n";
            }

            return(xm);
        }
        private double Bisection(out string log, double leftBorder, double rightBorder, double accuracy)
        {
            log = "Метод половинного деления:\r\n\r\n" +
                  "Входные данные:\r\n" +
                  "     Левая граница a = " + leftBorder + "\r\n" +
                  "     Правая граница b = " + rightBorder + "\r\n" +
                  "     Точность eps = " + accuracy + "\r\n\r\n" +
                  "Итерации:\r\n\r\n";

            double x1 = leftBorder + (rightBorder - leftBorder) / 4;
            double xm = (leftBorder + rightBorder) / 2;
            double x2 = rightBorder - (rightBorder - leftBorder) / 4;

            double y1 = FunctionClass.Function1(x1);
            double ym = FunctionClass.Function1(xm);
            double y2 = FunctionClass.Function1(x2);

            log += "a = " + leftBorder + " " + "b = " + rightBorder + " " + "xm = " + xm + " " + "x1 = " + x1 + " " + "x2 = " + x2 + "\r\n";
            log += "F(a) = " + FunctionClass.Function1(leftBorder) + " " + "F(b) = " + FunctionClass.Function1(rightBorder) + " " + "F(xm) = " + ym + " " + "F(x1) = " + y1 + " " + "F(x2) = " + y2 + "\r\n\r\n";

            int i = 0;

            while (Math.Abs(rightBorder - leftBorder) > accuracy)
            {
                i++;

                if ((y1 > ym) && (ym < y2))
                {
                    log += "# " + i + " y1 > ym && ym < y2\r\n";

                    leftBorder  = x1;
                    rightBorder = x2;

                    log += "a = " + leftBorder + " " + "b = " + rightBorder + "\r\n";

                    x1 = leftBorder + (rightBorder - leftBorder) / 4;
                    x2 = rightBorder - (rightBorder - leftBorder) / 4;

                    log += "x1 = " + x1 + " " + "x2 = " + x2 + "\r\n";
                }
                else if ((y1 > ym) && (ym > y2))
                {
                    log += "# " + i + " y1 > ym && ym > y2\r\n";

                    leftBorder = xm;

                    log += "a = " + leftBorder + "\r\n";

                    x1 = leftBorder + (rightBorder - leftBorder) / 4;
                    x2 = rightBorder - (rightBorder - leftBorder) / 4;
                    xm = (leftBorder + rightBorder) / 2;

                    log += "x1 = " + x1 + " " + "xm = " + xm + " " + "x2 = " + x2 + "\r\n";

                    ym = FunctionClass.Function1(xm);
                }
                else if ((y1 < ym) && (ym < y2))
                {
                    log += "# " + i + " y1 < ym && ym < y2\r\n";

                    rightBorder = xm;

                    log += "b = " + rightBorder + "\r\n";

                    x1 = leftBorder + (rightBorder - leftBorder) / 4;
                    x2 = rightBorder - (rightBorder - leftBorder) / 4;
                    xm = (leftBorder + rightBorder) / 2;

                    log += "x1 = " + x1 + " " + "xm = " + xm + " " + "x2 = " + x2 + "\r\n";

                    ym = FunctionClass.Function1(xm);
                }

                y1 = FunctionClass.Function1(x1);
                y2 = FunctionClass.Function1(x2);

                log += "y1 = " + y1 + " " + "ym = " + ym + " " + "y2 = " + y2 + "\r\n";
                log += "xm = " + xm + "\r\n\r\n";
            }

            return(xm);
        }