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("    q({0}) = {1} = 0</br>", i++, qi.ToMathML())); i = 0; qp.ForEach(qi => sb.AppendFormat("    q({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()); }
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("    q({0}) = {1} = 0</br>", i++, qi.ToMathML())); i = 0; qp.ForEach(qi => sb.AppendFormat("    q({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>     <math><msub><mi>x</mi><mn>0</mn></msub><mo>=</mo><msub><mi>x</mi><mn>{0}</mn></msub><mo>=</mo></math>{1}</br>    X* = {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("    {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()); }
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 }