private void CurrencyBtn_Click(object sender, EventArgs e) { OutputTxt.Text = ""; Digraph graph = new Digraph(); Parser p = new Parser(); graph = p.Parse(FilePathTxt.Text, ref OutputTxt); CurrencyVertex from = graph.nodes.Find(x => x.Symbol == FromTxt.Text); CurrencyVertex to = graph.nodes.Find(x => x.Symbol == ToTxt.Text); if (from == null) { OutputTxt.Text = "There is no such currency in the input file: " + FromTxt.Text; } else if (to == null) { OutputTxt.Text = "There is no such currency in the input file: " + ToTxt.Text; } else if (!double.TryParse(ExchangeAmountTxt.Text, out double moneyAtSource)) { OutputTxt.Text = "Initial amount of money has to be a number"; } else if (from.Equals(to)) { OutputTxt.Text = "There is no need to convert " + from.Symbol + " to " + to.Symbol + ":)"; } else { var exchange = new BestExchange(graph); try { List <CurrencyVertex> path = exchange.Find(from, to, moneyAtSource, out double moneyAtFinish); if (path == null) { OutputTxt.Text = "There is no exchange possible between given currencies"; } else { var outputText = exchange.GenerateOutput(path); OutputTxt.Text = outputText; } } catch (OutOfMemoryException) { OutputTxt.Text = "There is an infinite arbitrage on the way!"; } } GraphImg.Focus(); }
public List <CurrencyVertex> Find(CurrencyVertex src, CurrencyVertex to, double moneyAtStart, out double moneyAtFinish) { src.MoneyAt = moneyAtStart; src.MinDistance = 0; moneyAtFinish = 0; foreach (var edge in edges) { edge.FinishVertex.Prev = edge.StartVertex; } for (int i = 0; i < vertices.Count - 1; ++i) { foreach (var edge in edges) { if (edge.StartVertex.MinDistance == int.MaxValue) { continue; } double newMoneyAtDest; double newDistance; if (edge.FeeType == (int)ExchangeEdge.ChargeType.Percent) { newMoneyAtDest = edge.StartVertex.MoneyAt * edge.Weight * (1 - edge.Charge); newDistance = Inverse(newMoneyAtDest); if (newDistance < edge.FinishVertex.MinDistance) { edge.FinishVertex.MinDistance = newDistance; edge.FinishVertex.Prev = edge.StartVertex; edge.FinishVertex.MoneyAt = newMoneyAtDest; } } else if (edge.FeeType == (int)ExchangeEdge.ChargeType.Standing) { newMoneyAtDest = edge.StartVertex.MoneyAt * edge.Weight - edge.Charge; newDistance = Inverse(newMoneyAtDest); if (newDistance < edge.FinishVertex.MinDistance) { edge.FinishVertex.MinDistance = newDistance; edge.FinishVertex.Prev = edge.StartVertex; edge.FinishVertex.MoneyAt = newMoneyAtDest; } } } } path.Add(to); CurrencyVertex last = vertices.Find(x => x.Equals(to)); CurrencyVertex first = vertices.Find(x => x.Equals(src)); while (last.Prev != first) { last = last.Prev; if (last == null) { return(null); } path.Add(last); } path.Add(src); path.Reverse(); moneyAtFinish = vertices.Find(x => x.Equals(to)).MoneyAt; return(path); }
public List <CurrencyVertex> Find(double moneyAtStart) { for (int i = 0; i < vertices.Count; i++) { vertices[i].MinDistance = 0; vertices[i].MoneyAt = moneyAtStart; for (int j = 0; j < vertices.Count - 1; ++j) { foreach (var edge in edges) { if (edge.StartVertex.MinDistance == int.MaxValue) { continue; } double newMoneyAtDest; double newDistance; if (edge.FeeType == (int)ExchangeEdge.ChargeType.Percent) { newMoneyAtDest = edge.StartVertex.MoneyAt * edge.Weight * (1 - edge.Charge); newDistance = Inverse(newMoneyAtDest); if (newDistance < edge.FinishVertex.MinDistance) { edge.FinishVertex.MinDistance = newDistance; edge.FinishVertex.Prev = edge.StartVertex; edge.FinishVertex.MoneyAt = newMoneyAtDest; } } else if (edge.FeeType == (int)ExchangeEdge.ChargeType.Standing) { newMoneyAtDest = edge.StartVertex.MoneyAt * edge.Weight - edge.Charge; newDistance = Inverse(newMoneyAtDest); if (newDistance < edge.FinishVertex.MinDistance) { edge.FinishVertex.MinDistance = newDistance; edge.FinishVertex.Prev = edge.StartVertex; edge.FinishVertex.MoneyAt = newMoneyAtDest; } } } } foreach (var edge in edges) { if (edge.FeeType == (int)ExchangeEdge.ChargeType.Percent) { double moneyAtFinish = 0; moneyAtFinish = edge.StartVertex.MoneyAt * edge.Weight * (1 - edge.Charge); edge.ArbWeight = -Math.Log(moneyAtFinish / edge.StartVertex.MoneyAt); edge.Weight = edge.ArbWeight; } else if (edge.FeeType == (int)ExchangeEdge.ChargeType.Standing) { double moneyAtFinish = 0; moneyAtFinish = edge.StartVertex.MoneyAt * edge.Weight - edge.Charge; edge.ArbWeight = -Math.Log(moneyAtFinish / edge.StartVertex.MoneyAt); edge.Weight = edge.ArbWeight; } } vertices[i].ArbMinDistance = 0; for (int k = 0; k < vertices.Count - 1; ++k) { foreach (var edge in edges) { if (edge.StartVertex.ArbMinDistance == int.MaxValue) { continue; } double newArbDistance = edge.StartVertex.ArbMinDistance + edge.Weight; if (newArbDistance < edge.FinishVertex.ArbMinDistance) { edge.FinishVertex.ArbMinDistance = newArbDistance; edge.FinishVertex.ArbPrev = edge.StartVertex; } } } List <CurrencyVertex> cycle = new List <CurrencyVertex>(); foreach (var edge in edges) { if (HasCycle(edge) && edge.StartVertex.ArbMinDistance != int.MaxValue) { CurrencyVertex vertex = edge.StartVertex; while (!vertex.Equals(edge.FinishVertex) && !vertex.Visited) { cycle.Add(vertex); vertex.Visited = true; vertex = vertex.ArbPrev; } cycle.Add(edge.FinishVertex); cycle.Reverse(); return(cycle); } } } return(null); }