예제 #1
0
        public static Tuple<Matrix, string> PenaltyMethod(Function f, Equation[] q, Matrix x0, double e, double r0, double C)
        {
            string matrixStartLine = "[", matrixElementsSeparator = ", ", matrixEndLine = "]";

            List<Function> qm = new List<Function>(), qp = new List<Function>();
            StringBuilder sb = new StringBuilder("<h1>Метод штрафных функций</h1></br>");

            foreach (var qi in q)
            {
                if (qi.Sign == "<=")
                {
                    qp.Add(qi.AllToLeft());
                }
                if (qi.Sign == "=")
                {
                    qm.Add(qi.AllToLeft());
                }
            }

            sb.AppendFormat("<b>Функция</b> f = {0}</br><b>Ограничения:</b></br>", f.ToMathML());
            int i = 0;
            qm.ForEach(qi => sb.AppendFormat("&nbsp&nbsp&nbsp&nbspq({0}) = {1} = 0</br>", i++, qi.ToMathML()));
            i = 0;
            qp.ForEach(qi => sb.AppendFormat("&nbsp&nbsp&nbsp&nbspq({0}) = {1} <= 0</br>", i++, qi.ToMathML()));

            int k = 0;

            string[] vars = f.Variables;
            Matrix varsNames = new Matrix(vars.Length);

            for (i = 0; i < vars.Length; i++)
            {
                varsNames[i] = new FunctionMatrixElement(1, vars[i]);
            }

            sb.AppendFormat("Шаг 1. Задаём: <math><mrow><msub><mi>x</mi><mn>0</mn></msub></mrow><mo>=</mo><mrow>{0}</mrow><mo></math>,штраф <math><msub><mi>r</mi><mn>0</mn></msub><mo>=</mo></math>{1}, C = {2}, e = {3}, k = {4}</br>", x0.ToMathML(), r0, C, e, k);

            List<Matrix> x = new List<Matrix>();
            List<double> r = new List<double>();
            Function Sm = new Function();
            Function Sp = new Function();
            qm.ForEach(qi => Sm += qi.Pow(2));
            #warning Врятли без этого оно будет работать
            //qp.ForEach(qi => Sp += qi.AddFunction(new SliceFunction()).Pow(2));
            Function P = new Variable("rk") / 2.0 * (Sm + Sp);

            x.Add(x0);
            r.Add(r0);
            Matrix answer = x0;
            while (true)
            {
                sb.AppendFormat("---------------------------{0} иттерация-------------------\n", k);
                sb.AppendFormat("{0}\n", P);
                Function F = f + P.SetVariableValue("rk", r[k]);

                sb.AppendFormat("Шаг 2. Вспомогательная функция = {0}\n", F);

                Matrix minX = SecondOrderMethods.NuthonMethod(F, x[k], e, e, 5).Item1;

                sb.AppendFormat("Шаг 3. Минимум функции F:\n\tx[0] = x[{0}] = {1}\n\tX* = {2}\n",
                                        k,
                                        x[k].Transposition().ToString(matrixStartLine, matrixElementsSeparator, matrixEndLine),
                                        minX.Transposition().ToString(matrixStartLine, matrixElementsSeparator, matrixEndLine)
                );

                sb.AppendFormat("Шаг 4. Условие окончания: P(x*(r[{0}],r[{0}]) <=? e = {1}\n", k, e);
                double p = new Function(P.SetVariableValue("rk", r[k])).SetVariablesValuesWithFixedOrder(minX, varsNames).ToDouble();

                sb.AppendFormat("       {0} {1} {2}\n", p, p <= e ? "<=" : ">", e);
                if (p <= e)
                {
                    answer = minX;
                    sb.AppendFormat("Следовательно x* = {0}", answer.Transposition().ToString(matrixStartLine, matrixElementsSeparator, matrixEndLine));
                    break;
                }
                else
                {
                    r.Add(C * r[k]);
                    x.Add(minX);
                    k++;
                }
            }

            return new Tuple<Matrix, string>(answer, sb.ToString());
        }
예제 #2
0
        public static Tuple<Matrix, string> BarrierMethod(Function f, Equation[] q, Matrix x0, double e, double r0, double C)
        {
            List<Function> qm = new List<Function>(), qp = new List<Function>();
            StringBuilder sb = new StringBuilder("<h1>Метод барьерных функций</h1></br>");

            foreach (var qi in q)
            {
                if (qi.Sign == "<=")
                {
                    qp.Add(qi.AllToLeft());
                }
                if (qi.Sign == "=")
                {
                    qm.Add(qi.AllToLeft());
                }
            }

            sb.AppendFormat("<b>Функция</b> f = {0}</br><b>Ограничения:</b></br>", f.ToMathML());
            int i = 0;
            qm.ForEach(qi => sb.AppendFormat("&nbsp&nbsp&nbsp&nbspq({0}) = {1} = 0</br>", i++, qi.ToMathML()));
            i = 0;
            qp.ForEach(qi => sb.AppendFormat("&nbsp&nbsp&nbsp&nbspq({0}) = {1} <= 0</br>", i++, qi.ToMathML()));

            int k = 0;

            string[] vars = f.Variables;
            Matrix varsNames = new Matrix(vars.Length);

            for (i = 0; i < vars.Length; i++)
            {
                varsNames[i] = new FunctionMatrixElement(1, vars[i]);
            }

            sb.AppendFormat("Шаг 1. Задаём: <math><mrow><msub><mi>x</mi><mn>0</mn></msub></mrow><mo>=</mo><mrow>{0}</mrow><mo></math>,штраф <math><msub><mi>r</mi><mn>0</mn></msub><mo>=</mo></math>{1}, C = {2}, e = {3}, k = {4}</br>", x0.ToMathML(), r0, C, e, k);

            List<Matrix> x = new List<Matrix>();
            List<double> r = new List<double>();
            Function Sq = new Function();
            foreach(var qi in q) {
                Sq += qi.AllToLeft().Pow(-1);
            }

            Function P = new Variable("rk") * Sq;

            x.Add(x0);
            r.Add(r0);
            Matrix answer = x0;
            while (true)
            {
                sb.AppendFormat("---------------------------<b>{0} иттерация</b>-------------------</br>", k);

                Function F = f - P.SetVariableValue("rk", r[k]);

                sb.AppendFormat("Шаг 2. Вспомогательная функция = {0}</br>", F.ToMathML());
                //Function der = F.Derivative();

                //Matrix minX = SecondOrderMethods.NuthonMethod(F, x[k], e, e, 5).Item1;
                Matrix minX = MinimisationMethods.PenaltyMethod(F, q.ToArray(), x[k], e, r0, C).Item1;

                sb.AppendFormat("Шаг 3. Минимум функции F:</br>&nbsp&nbsp&nbsp&nbsp&nbsp<math><msub><mi>x</mi><mn>0</mn></msub><mo>=</mo><msub><mi>x</mi><mn>{0}</mn></msub><mo>=</mo></math>{1}</br>&nbsp&nbsp&nbsp&nbspX* = {2}</br>",
                                        k,
                                        x[k].ToMathML(),
                                        minX.ToMathML()
                );

                sb.AppendFormat("Шаг 4. Условие окончания: <math><mi>P</mi><mfenced><msup><mi>x</mi><mn>*</mn></msup><mfenced><msub><mi>r</mi><mn>{0}</mn></msub></mfenced><mo>,</mo><msub><mi>r</mi><mn>{0}</mn></msub></mfenced><mo><=?</mo><mi>e</mi><mo>=</mo><mi>{1}</mi></math></br>", k, e);
                double p = Math.Abs(new Function(P.SetVariableValue("rk", r[k])).SetVariablesValuesWithFixedOrder(minX, varsNames).ToDouble());

                sb.AppendFormat("&nbsp&nbsp&nbsp&nbsp{0} {1} {2}</br>", p, p <= e ? "<=" : ">", e);
                if (p <= e)
                {
                    answer = minX;
                    sb.AppendFormat("Следовательно x* = {0}", answer.ToMathML());
                    break;
                }
                else
                {
                    r.Add(r[k] / C);
                    x.Add(minX);
                    k++;
                }
            }

            return new Tuple<Matrix, string>(answer, sb.ToString());
        }
예제 #3
0
        public Equation EquationSolutionByVariable(string name, Function equationAnswer = null)
        {
            if (equationAnswer == null)
                equationAnswer = new Function(0);
            Equation equation = new Equation(
                this - equationAnswer,
                new Function(0)
            );

            Function curX, nextX = new Function(1);
            double eps = 0.0001;
            Function derivative = new Function(equation.LeftPart.Derivative());
            do
            {
                curX = nextX;
                var up = equation.LeftPart.SetVariableValue(name, curX);
                var down = derivative.SetVariableValue(name, curX);
                nextX = curX - up / down;
            }
            while (Math.Abs((curX - nextX).ToDouble()) > eps);
            return new Equation(new Function(1, name), nextX);

#warning Посидим пока без решений уравнений
            #region Как в школе учили
            /*
            double degree = equation.LeftPart.Degree * equation.LeftPart.variables.Max(delegate(VariablesMulriplication vs)
            {
                if (vs.HasVariable(name))
                {
                    return vs.GetVariableByName(name).Degree;
                }
                return 0;
            });

            switch (degree.ToString())
            {
                case "1":
                    equation.LeftPart.variables.ForEach(delegate(VariablesMulriplication vs)
                    {
                        if (vs.HasVariable(name))
                        {
                            if (vs.Constant < 0)
                            {
                                equation.InverseSign();
                            }
                            var newV = vs.GetVariableByName(name);
                            //leftPart.AddVariablesMul(newV);
                            equation.LeftPart *= newV / vs;
                            equation.RightPart *= newV / vs;
                        }
                        else
                        {
                            //rightPart = rightPart.Mul(new EquationMatrixElement(new VariablesMulriplication(1) / vs)) as EquationMatrixElement;
                            equation.RightPart -= vs;
                        }
                    });
                    equation.LeftPart = new Function(1, name);
                    break;
                // Квадратное уравнение
                case "2":
                    // Всё умножения, содержащие нужную переменную в 1 степени
                    var v = equation.LeftPart.GetElementsWithVariable(name, 1);
                    // И во 2
                    var v2 = equation.LeftPart.GetElementsWithVariable(name, 2);
                    // Если есть только 2 степень
                    if (v.VarsCount == 0)
                    {
                        // берём коэффициенты при 2 степени, т.е. делим всё, что есть со 2 степенью на эту переменную во второй степени
                        var elements = v2 / new Variable(name, 2);

                        // правая часть - это всё без переменной во 2 степени с минусом и делённое на коэффициент при переменной во 2 степеи
                        var right = equation.LeftPart.GetElementsWithoutVariable(name, 2) / elements * -1;

                        // берём корень
                        equation.RightPart = new Function(right.Sqrt());
                        equation.LeftPart = new Function(1, name);
                        // всё
                        return equation;
                    }
                    else
                    {
                        // коэффциент при второй степени
                        Function a = v2 / new Variable(name, 2);
                        // при первой
                        Function b = v / new Variable(name, 1);
                        // и всё, что осталось
                        Function c = equation.LeftPart - (v + v2);

                        // доделываем всё это дело до квадрата суммы

                        // Находим какое должно быть c, чтобы это было квадрат суммы
                        Function neededC = new Function((b / (a.Sqrt() * 2)).Pow(2));

                        // находим остаток, например нужно c = 5, а есть c = -4, делаем 5 + (-4 - 5) = -4
                        var rightC = c - neededC;
                        if (rightC.VarsCount > 0 || rightC.ToDouble() <= 0)
                        {
                            // Переносим вправо и берём корень
                            equation.RightPart = rightC.Inverse().Sqrt() as Function;

                            // узнаём ли у нас квадрат суммы или разности

                            // Слева остаётся квадрат суммы, типа взяли корень, осталось sqrt(a) +(-) sqrt(neededC) = sqrt(-rightC)
                            // Делаем так, чтобы осталось только наша переменная
                            equation.RightPart -= b / (a.Sqrt() * 2);
                            equation.RightPart /= a.Sqrt();


                            equation.LeftPart = new Function(1, name);
                            return equation;
                        }

                        // Если это не сумма квадратов, решаем квадратное уравнение
                        Function d = b.Pow(2) - a * c * 4;
                        if (d.VarsCount > 0 || d.ToDouble() >= 0)
                        {
                            Function x1 = b.Inverse() + d.Sqrt() / (a * 2);
                            Function x2 = b.Inverse() - d.Sqrt() / (a * 2);
                            equation.RightPart = x1;
                            equation.LeftPart = new Function(1, name);
                            return equation;
                        }
                        else
                        {
                            throw new Exception("Нет решений. Я еще не знаю комплексных чисел. =)");
                        }
                    }
                default:
                    break;
            }

            return equation;*/
            #endregion
        }