Files
CS412-Applied-Algorithms/Arbitrages/cs412_arbitrages_a.py

84 lines
2.0 KiB
Python

"""
name: Nicholas Tamassia
Honor Code and Acknowledgments:
This work complies with the JMU Honor Code.
Comments here on your code and submission.
"""
import math
from collections import defaultdict
def find_arbitrage(graph: dict[str, dict[str, float]]) -> list[str] | None:
weights: dict[str, float] = {c: math.inf for c in graph}
prev: dict[str, str | None] = {c: None for c in graph}
start: str = list(graph.keys())[0]
weights[start] = 0
for _ in range(len(graph) - 1):
for src in graph:
for dest, rate in graph[src].items():
weight: float = -math.log(rate)
if weights[src] + weight < weights[dest]:
weights[dest] = weights[src] + weight
prev[dest] = src
node: str | None = None
for src in graph:
for dest, rate in graph[src].items():
weight: float = -math.log(rate)
if weights[src] + weight < weights[dest]:
node = dest
prev[dest] = src
break
if node is not None:
break
if node is None:
return
for _ in range(len(graph)):
node = prev[node]
path = [node]
while True:
node = prev[node]
path.append(node)
if node == path[0]:
break
path.reverse()
return path
def main():
n: int = int(input().strip())
graph: dict[str, dict[str, float]] = defaultdict(dict)
for _ in range(n):
vals: list[str] = input().strip().split()
src: str = vals[0]
dest: str = vals[1]
rate: float = float(vals[2])
graph[src][dest] = rate
path = find_arbitrage(graph)
if path is not None:
print("Arbitrage Detected")
print(" => ".join(path))
factor = 1.0
for i in range(len(path) - 1):
factor *= graph[path[i]][path[i + 1]]
print(f"{factor:.5f} factor increase")
else:
print("No Arbitrage Detected")
if __name__ == "__main__":
main()