using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
namespace SimplexMethod
{
class Problem
{
List<double> func_coeffs;
List<List<double>> conditions;
List<string> signs;
List<double> constraints;
private string solution;
public Problem()
{
func_coeffs = new List<double>();
conditions = new List<List<double>>();
signs = new List<string>();
constraints = new List<double>();
}
public void setFuncCoeffs(IEnumerable<double> coeffs)
{
foreach (var c in coeffs)
{
func_coeffs.Add(c);
}
}
public void addConditions(IEnumerable<double> coeffs)
{
var cond_coeffs = new List<double>();
foreach (var c in coeffs)
{
cond_coeffs.Add(c);
}
conditions.Add(cond_coeffs);
}
public void setSigns(IEnumerable<string> coeffs)
{
foreach (var c in coeffs)
{
signs.Add(c);
}
}
public void setConstraints(IEnumerable<int> coeffs)
{
foreach (var c in coeffs)
{
constraints.Add(c);
}
}
public void canonize()
{
for (int i = 0; i < signs.Count; i++)
{
var s = signs[i];
switch (s)
{
case ">=":
func_coeffs.Add(0);
for (int j = 0; j < conditions.Count; j++)
{
if (i == j)
{
conditions[j].Add(-1);
}
else
{
conditions[j].Add(0);
}
}
for (int j = 0; j < conditions[i].Count; j++)
{
conditions[i][j] = -conditions[i][j];
}
constraints[i] = -constraints[i];
break;
case "<=":
func_coeffs.Add(0);
for (int j = 0; j < conditions.Count; j++)
{
if (i == j)
{
conditions[j].Add(1);
}
else
{
conditions[j].Add(0);
}
}
break;
}
signs[i] = "=";
}
}
private void printFunctionValue()
{
var base_elems = getBaseElemenents();
double result = 0;
foreach (var el in base_elems)
{
result += constraints[el.Key] * func_coeffs[el.Value];
}
solution += "F(x) = " + Math.Round(result, 2);
solution += "<br>";
}
private void printTask()
{
var result = new StringBuilder();
result.Append("F(x) = ");
var coeff = "";
for (int i = 0; i < func_coeffs.Count; i++)
{
coeff = func_coeffs[i] == 0 ? "+ " + func_coeffs[i].ToString() : func_coeffs[i].ToString();
result.Append(coeff + " * x<sub>" + (i + 1).ToString() + "</sub> ");
}
result.Append("<br>");
for (int i = 0; i < conditions.Count; i++)
{
var conds = conditions[i];
for (int j = 0; j < func_coeffs.Count; j++)
{
coeff = conds[j] >= 0 ? "+ " + conds[j].ToString() : conds[j].ToString();
result.Append(coeff + " * x<sub>" + (j + 1).ToString() + "</sub> ");
}
result.Append(signs[i] + " ");
result.Append(constraints[i]);
result.Append("<br>");
}
result.Append("<br>");
solution += result.ToString();
}
private void printR(Dictionary<int, double> r)
{
foreach (var el in r)
{
solution += "R<sub>" + (el.Key + 1).ToString() + "</sub> = " + Math.Round(el.Value, 2) + "<br>";
}
solution += "<br>";
}
public string solve()
{
canonize();
printTask();
solution += getHtml() + "</br>";
while (iterate() == false)
{
solution += getHtml() + "</br>";
}
//for (int i = 0; i < 10; i++)
//{
// iterate();
// solution += getHtml() + "</br>";
//}
return solution;
}
public string getHtml()
{
var result = new StringBuilder();
result.Append("<table border=\"1\" width=\"50%\">");
result.Append(getHtmlHeader());
result.Append(getHtmlRows());
result.Append("</table>");
return result.ToString();
}
private string getHtmlRows()
{
var result = new StringBuilder();
var baseElems = getBaseElemenents();
var eq_number = 0;
foreach (var elem in baseElems.Values)
{
result.Append("<tr align=\"center\">");
result.Append("<td>");
result.Append(func_coeffs[elem]);
result.Append("</td>");
result.Append("<td>");
result.Append("X<sub>" + (elem + 1).ToString() + "</sub>");
result.Append("</td>");
foreach (var c in conditions[eq_number])
{
result.Append("<td>");
result.Append(Math.Round(c, 2));
result.Append("</td>");
}
result.Append("<td>");
result.Append(Math.Round(constraints[eq_number], 2));
result.Append("</td>");
result.Append("</tr>");
eq_number++;
}
return result.ToString();
}
private bool iterate()
{
var baseElems = getBaseElemenents();
var r = new Dictionary<int, double>();
var r_values = new List<int>();
for (int i = 0; i < func_coeffs.Count; i++)
{
if (baseElems.Values.Contains(i)) continue;
var val = func_coeffs[i];
foreach (var el in baseElems)
{
val -= conditions[el.Key][i] * func_coeffs[el.Value];
}
r.Add(i, val);
}
printFunctionValue();
printR(r);
if (isSolved(r)) return true;
var el_to_add = getMaxIndex(r);
var min_ratio = double.MaxValue;
var row_to_remove = -1;
for (int i = 0; i < conditions.Count; i++)
{
var ratio = constraints[i] / conditions[i][el_to_add];
if (ratio > 0 && ratio < min_ratio)
{
row_to_remove = i;
min_ratio = ratio;
}
}
Debug.Assert(row_to_remove >= 0, "WTF???");
var coeff = conditions[row_to_remove][el_to_add];
for (int i = 0; i < conditions[row_to_remove].Count; i++)
{
conditions[row_to_remove][i] /= coeff;
}
constraints[row_to_remove] = constraints[row_to_remove] / coeff;
for (int i = 0; i < conditions.Count; i++)
{
if (i == row_to_remove) continue;
coeff = conditions[i][el_to_add];
for (int j = 0; j < conditions[i].Count; j++)
{
conditions[i][j] -= coeff * conditions[row_to_remove][j];
}
constraints[i] -= coeff * constraints[row_to_remove];
}
return false;
}
private bool isSolved(Dictionary<int, double> r)
{
Debug.Assert(r.Count > 0, "R is empty");
foreach (var el in r)
{
if (el.Value > 0) return false;
}
// need to add somthing there
var base_elements = getBaseElemenents();
foreach (var el in base_elements.Keys)
{
if (constraints[el] < 0)
{
return false;
}
}
return true;
}
private int getMaxIndex(Dictionary<int, double> dict)
{
var max = double.MinValue;
var key = -1;
foreach (var el in dict)
{
if (el.Value > max)
{
key = el.Key;
max = el.Value;
}
}
Debug.Assert(key >= 0, "not found");
return key;
}
private int getMinIndex(Dictionary<int, double> dict)
{
var min = double.MaxValue;
var key = -1;
foreach (var el in dict)
{
if (el.Value < min)
{
key = el.Key;
min = el.Value;
}
}
Debug.Assert(key >= 0, "not found");
return key;
}
private Dictionary<int, int> getBaseElemenents()
{
var result = new Dictionary<int, int>(); //key - equasion number, val - base element number
foreach (var coeffs in conditions)
{
foreach (var c in coeffs)
{
if (c == 1)
{
result.Add(conditions.IndexOf(coeffs), coeffs.IndexOf(c));
break;
}
}
}
return result;
}
private string getHtmlHeader()
{
var result = new StringBuilder();
result.Append("<tr>");
result.Append("<th>");
result.Append("C<sub>b</sub>");
result.Append("</th>");
result.Append("<th>");
result.Append("X<sub>b</sub>");
result.Append("</th>");
for (int i = 1; i < func_coeffs.Count + 1; i++)
{
result.Append("<th>");
result.Append("X<sub>" + i + "</sub>");
result.Append("</th>");
}
result.Append("<th>");
result.Append("b");
result.Append("</th>");
result.Append("</tr>");
return result.ToString();
}
public void invertFuncSigns()
{
for (int i = 0; i < func_coeffs.Count; i++)
{
func_coeffs[i] *= -1;
}
}
}
class Program
{
static string output_path = @"C:\Users\Сергей Рябко\Desktop\test.html";
static void Main(string[] args)
{
var problem = new Problem();
problem.setFuncCoeffs(new double[] { 12, 16 });
problem.addConditions(new double[] { 2, 6 });
problem.addConditions(new double[] { 5, 4 });
problem.addConditions(new double[] { 2, 3 });
problem.setSigns(new string[] { ">=", ">=", ">=" });
problem.invertFuncSigns();
problem.setConstraints(new int[] { 24, 31, 18 });
var html = problem.solve();
System.IO.File.WriteAllText(output_path, html);
System.Diagnostics.Process.Start(output_path);
}
}
}