Compare commits

...

2 Commits

Author SHA1 Message Date
0dab59e81e NP-Complete: First working version 2025-12-07 18:00:19 -05:00
d3e7ce3189 Arbitrages: Added README 2025-12-07 17:34:55 -05:00
5 changed files with 239 additions and 0 deletions

79
Arbitrages/README.md Normal file
View File

@@ -0,0 +1,79 @@
# Homework 6: Arbitrages
## Finding an Arbitrage
In currency exchange markets units of one currency, such as US Dollars, can be exchanged for units of a different currency, like Italian Lira. These exchanges are set by the market's exchange rate, which typically fluctuates throughout the day. For example, at the time of this assignment's writing, the exchange rate between the US Dollar (USD) and the Great British Pound (GBP) was 1 USD to 0.77 GBP. This means that $150 is worth $150\cdot0.77=115.5\ \text{GBP}$ and $150\ \text{GPB} = 150 / 0.77 = \$194.81$. The exchange rates are dynamic and constantly change.
This change in currency is based on how trades are progressing through the market, and the changing dynamic nature of the exchange leads to a particular inefficiency in short-time frame based trading. For example, consider the following exchange rates:
- 1 USD = 0.82 Euro
- 1 Euro = 129.7 Japanese Yen
- 1 Japanese Yen = 12 Turkish Lira
- 1 Turkish Lira = 0.0008 USD.
So if we start with 1 USD, and make all of the exchanges above, we get $1\cdot0.82\cdot129.7\cdot12\cdot.0008 = \$1.021$. In other words, by making four exchanges starting from $1.00 we end up with $1.02, a 2% profit. This situation, where a cycle of currency exchanges starting and ending in the same currency leads to a net gain in the starting currency (rather than breaking even) is called arbitrage.
Notice that arbitrage occurs when the product of all of the exchanges in a cycle is greater than 1. Your job is to find and detect arbitrage in a given exchange and determine what sequence of exchanges need to be made.
We are going to reduce this problem to the problem of finding negative weight cycles in a graph. There are two problems to overcome.
1. Our formulation of the problem requires a product of the exchange rates, but shortest path algorithms work with the sum of the weights of a bunch of edges.
2. Negative weight cycles are "smaller" whereas we are attempting to maximize a profit.
The first problem can be overcome using the following trick: the logarithm function is monotonic, which means that log(x) increases when x increases. Furthermore, the logarithm function can be used to convert products into sums because $\log(a\cdot{b}) = \log(a) + \log(b)$. Thus, if we want to maximize $a\cdot{b}$, this is the same as maximizing $\log(a) + \log(b)$. Also, consider that $a\cdot{b} > 1$ if and only if $\log(a) + \log(b) > 0$. Thus a cycle of exchange rates $r1\cdot{r2}\cdot{r3}\cdot...\cdot{rn} > 1$ if and only if $\log(r1) + \log(r2) + ... + \log(rn) > 0$.
But now the second problem is that we want to detect negative weight cycles because Bellman-Ford can do that for us, but above we described a positive weight cycle. Now we can use the following trick--simply negate each log value. $\log(r1) + \log(r2) + ... + \log(rn) > 0$ if and only if $(-\log(r1)) + (-\log(r2)) + ... + (-\log(rn)) < 0$. Now, you should be able to see how to build a graph, with some appropriate weights, and use it to find arbitrage cycles directly!
### Input
The first line of the input will contain a single integer m describing how many exchange rates are in the exchange. The next _m_ lines will be given by _cIn_ _cOut_ _r_ where _cIn_ is the code for the starting currency (like USD or GPB), _cOut_ is the code for the ending currency, and _r_ is the exchange rate (i.e. "USD GBP 0.75" codes for 1 USD = 0.75 GBP).
### Output and Rubrics
This assignment is worth 15 points.
- 9 points (partial) -- code identifies an the presence or absence of an arbitrage correctly on published test cases
- 3 points (partial) -- code identifies an the presence or absence of an arbitrage correctly on hidden test cases
- 2 points (full credit) -- code outputs the actual exchanges correctly and in the format specified on the public test cases
- 1 point (full credit) -- code outputs the actual exchanges correctly and in the format specified on the hidden test cases
For full credit, when an arbitrage is detected, in addition to the output above, your code should output the actual exchanges that need to be made by showing each currency code in the exchange separated by " => " on a second line, and a third line containing the actual change as a multiplicative factor with the format "X factor increase", which should be **formatted to 5 decimal points**.
<table>
<tr>
<td>Sample Input</td>
<td>Partial Credit Output</td>
<td>Full Credit Output</td>
</tr>
<tr>
<td><pre>
4
USD EUR 0.82
EUR JPY 129.7
JPY TRY 12
TRY USD 0.0008</pre></td>
<td><pre>Arbitrage Detected</pre></td>
<td><pre>
Arbitrage Detected
USD => EUR => JPY => TRY => USD
1.02100 factor increase</pre></td>
</tr>
</table>
<table>
<tr>
<td>Sample Input</td>
<td>Sample Output (for both partial and full credit options)</td>
</tr>
<tr>
<td><pre>
2
USD GBP 1.0
GBP USD 1.0</pre></td>
<td><pre>No Arbitrage Detected</pre></td>
</tr>
</table>
### Submission
Submit this assignment as `cs412_arbitrages_a.py` to Gradescope.

65
NP-Complete/README.md Normal file
View File

@@ -0,0 +1,65 @@
# Lab 17: NP-Completeness
## NP-Complete Problems
### Part A: Unsatisfiable 3-SAT (3 points)
Answer the following questions:
- Given a 3SAT problem with 3 binary variables (x1, x2, and x3), what is the min number of clauses that you would need to create an unsatisfiable sentence?
- Create a 3SAT sentence with 3 binary variable that is not satisfiable using the minimum number of clauses identified in part 1.
Turn these in directly here in Canvas.
### Part B -- Python's Itertools (3 points)
Python provides a powerful package called itertools (see this webpage for details: [https://docs.python.org/3/library/itertools.html](https://docs.python.org/3/library/itertools.html)). This package provides an easy and memory efficient method of producing iterables that represent combination or permutations of items.
- Construct a python program that uses the itertools function to print out all possible assignments of a 3 boolean variables. You will need to use the product function within itertools. If you need more help with the product function, look up itertools' documentation on the web.
- Augment your python program so that it contains a function that accepts 3 variables (x1, x2, and x3). This function must return the truth value of the 3-SAT sentence you created in Part A:2 (should just be a return statement evaluating the expression). Call this function with all the possible settings and show that your sentence is indeed not satisfiable. In other words, if your function returns true, print the settings that produced a true answer, otherwise print a message verifying that it always returned false.
- Create another function that is a copy of the one created in #2 but is missing one of the 3-SAT clauses. Using a similar for loop to #2, call this function with all possible settings of the boolean variables and print out the case where it finds a true assignment (a satisfying assignment).
Attach this program to this assignment, call it: `cs412_np_3satcheck.py`
### Part C -- Practice Reduction (3 points)
Given the following 3-SAT sentence, construct the graph that would serve as input to the independent set problem.
$(a\lor{b}\lor{c})\land(\lnot{a}\lor{b}\lor{c})\land(a\lor\lnot{b}\lor{c})\land(\lnot{a}\lor\lnot{b}\lor\lnot{c})$
- Draw this graph on a piece of paper and take a picture of it (and attach it to this assignment).
- Write a brief (one sentence) description of the decision problem that needs to be solved by the independent set problem to show that this 3-SAT sentence has a valid assignment.
- Identify the largest independent set in the graph created in step #1. If you select the variable "a" that is in the first clause, write that down as A1 (where the one identifies the clause that the variable came from). You can write this on your piece of paper with the graph (just make sure it is included in the picture) OR you can write it in the response section in Canvas.
### Part D -- Prove that Independent Set is in NP (3 points)
Write a program that accepts a description of an undirected graph G and a list of vertices and verifies (in polynomial time) that the list of vertices is indeed an independent set).
Here is some example input:
```
4
0 1
1 0 3
2
3 1
0 3 2
```
The first line tells you how many vertices are in the graph G. The lines that follow contain the edge list for edge vertex. Finally, a proposed independent set is listed. Your program should output TRUE if the set listed in an independent set or FALSE if it is not an independent set (for example, 0 1 should not be an independent set).
Attached this program to this assignment and call it `cs412_np_independent_set.py`
### Part E -- Show that Hamiltonian Paths are NP-Complete (3 points)
In this section, you need to construct the required components to show that finding a Hamiltonian path is NP-Complete (there are 3 components). Illustrate the reduction sequence as we did on the slides (as a picture) and using the <=p syntax and the boxes. **Note: You do NOT need to show the steps required to change the input (the reduction), just the sketch of the order and what would need to be accomplished.** For the other steps, write a sentence or two and if necessary, argue that these steps can be accomplished in polynomial time.
Submit these items in a section labels Part E in your writeup.
### What and Where to Submit:
Submit the following 3 files here in Canvas:
- `cs412_np_3satcheck.py`
- `cs412_np_independent_set.py`
- `cs412_nplab.pdf`

View File

@@ -0,0 +1,51 @@
"""
name: Nicholas Tamassia
Honor Code and Acknowledgments:
This work complies with the JMU Honor Code.
Comments here on your code and submission.
"""
from itertools import product
from typing import Callable
type Three_SAT = Callable[[bool, bool, bool], bool]
def three_sat_missing(x1: bool, x2: bool, x3: bool) -> bool:
combos = product([x1, not x1], [x2, not x2], [x3, not x3])
# Remove the last clause
missing_combo = list(combos)[:-1]
return all(a or b or c for a, b, c in missing_combo)
def three_sat(x1: bool, x2: bool, x3: bool) -> bool:
return all(
a or b or c for a, b, c in product([x1, not x1], [x2, not x2], [x3, not x3])
)
# All modules for CS 412 must include a main method that allows it
# to imported and invoked from other python scripts
def main():
settings = product([False, True], repeat=3)
sentences_satisfied: dict[Three_SAT, bool] = {}
sentences_satisfied[three_sat] = False
sentences_satisfied[three_sat_missing] = False
for setting in settings:
for sentence in sentences_satisfied:
if sentence(*setting):
print(f"{setting} satisfied {sentence.__name__}")
sentences_satisfied[sentence] = True
for sentence, satisfied in sentences_satisfied.items():
if not satisfied:
print(f"{sentence.__name__} is not satisfiable")
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,38 @@
"""
name: Nicholas Tamassia
Honor Code and Acknowledgments:
This work complies with the JMU Honor Code.
Comments here on your code and submission.
"""
def independent_set(proposed_set: set[int], graph: dict[int, set[int]]) -> bool:
for vertex in proposed_set:
for adjecent in graph[vertex]:
if adjecent in proposed_set:
return False
return True
# All modules for CS 412 must include a main method that allows it
# to imported and invoked from other python scripts
def main():
n = int(input())
graph: dict[int, set[int]] = {}
for _ in range(n):
vertecies = list(map(int, input().split()))
graph[vertecies[0]] = set(vertecies[1:])
proposed_set = set(map(int, input().split()))
print("TRUE" if independent_set(proposed_set, graph) else "FALSE")
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,6 @@
4
0 1
1 0 3
2
3 1
0 3 2