first commit
@@ -0,0 +1,250 @@
|
||||
#!/usr/bin/env python
|
||||
# coding: utf-8
|
||||
|
||||
# In[33]:
|
||||
|
||||
|
||||
# Data
|
||||
amounts = [12.35, 12.35*2, 12.35*3, 12.35*4, 12.35*5, 12.35*6, 12.35*7, 12.35*8, 12.35*9, 12.35*10]
|
||||
|
||||
coin_list = [
|
||||
[0.2, 0.1, 0.05],
|
||||
[1, 0.2, 0.1, 0.05],
|
||||
[2, 1, 0.2, 0.1, 0.05],
|
||||
[5, 2, 1, 0.2, 0.1, 0.05],
|
||||
[5, 2, 1, 0.5, 0.2, 0.1, 0.05],
|
||||
[5, 2, 1, 0.5, 0.2, 0.1, 0.05, 0.02],
|
||||
[5, 2, 1, 0.5, 0.2, 0.1, 0.05, 0.02, 0.01]
|
||||
]
|
||||
|
||||
import time
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
|
||||
# In[34]:
|
||||
|
||||
|
||||
# Greedy
|
||||
def greedy_make_change(amount, coins):
|
||||
i = 0
|
||||
change = []
|
||||
|
||||
while amount > 0 and len(coins) > i:
|
||||
# print(str(round(amount//coins[i])) + " Coins of " + str(coins[i]) + "€")
|
||||
for j in range(round(amount//coins[i])):
|
||||
change.append(coins[i])
|
||||
amount = round(amount%coins[i], 2)
|
||||
i = i+1
|
||||
if amount > 0:
|
||||
print(f"Cannot make exact change for {amount:.2f}€")
|
||||
return change
|
||||
|
||||
|
||||
# In[35]:
|
||||
|
||||
|
||||
# Iterative
|
||||
|
||||
# Function to count occurrences of items in a list
|
||||
def count_occurrences(array):
|
||||
counts = {}
|
||||
for item in array:
|
||||
if item in counts:
|
||||
counts[item] += 1 # If the item is already in the dictionary, increment its count
|
||||
else:
|
||||
counts[item] = 1 # If the item is not in the dictionary, add it with a count of 1
|
||||
return counts
|
||||
|
||||
# Function to calculate all combinations of coins to make a specific amount
|
||||
def calculate_change_combinations(amount, coins):
|
||||
# Convert euro amounts to cents for calculations
|
||||
amount_cents = int(amount * 100)
|
||||
coin_values_cents = [int(coin * 100) for coin in coins]
|
||||
|
||||
# Initialize a list to store combinations and their counts
|
||||
combinations = []
|
||||
stack = [(0, [], 0)] # (current amount in cents, current combination, current coin index)
|
||||
|
||||
while stack:
|
||||
current_amount, current_combination, current_coin_index = stack.pop()
|
||||
|
||||
# If the current combination sums up to the target amount, add it to the list
|
||||
if current_amount == amount_cents:
|
||||
combinations.append(current_combination)
|
||||
# If the current amount is less than the target amount and there are more coins to consider
|
||||
elif current_amount < amount_cents and current_coin_index < len(coin_values_cents):
|
||||
coin = coin_values_cents[current_coin_index]
|
||||
max_count = (amount_cents - current_amount) // coin # Maximum count of the current coin
|
||||
|
||||
# Try adding different counts of the current coin to explore possibilities
|
||||
for count in range(max_count + 1):
|
||||
new_amount = current_amount + count * coin
|
||||
new_combination = current_combination + [coins[current_coin_index]] * count
|
||||
# Push the new state onto the stack for further exploration
|
||||
stack.append((new_amount, new_combination, current_coin_index + 1))
|
||||
|
||||
# Print the total number of combinations
|
||||
# print(f"Total number of combinations: {len(combinations)}")
|
||||
return combinations
|
||||
|
||||
|
||||
# In[36]:
|
||||
|
||||
|
||||
# Recursive
|
||||
def make_change_recursive(amount, coins, start, current_change, result):
|
||||
if amount == 0:
|
||||
result.append(current_change[:])
|
||||
return
|
||||
|
||||
for i in range(start, len(coins)):
|
||||
coin_cents = round(coins[i] * 100)
|
||||
if amount >= coin_cents:
|
||||
current_change.append(coins[i])
|
||||
make_change_recursive(amount - coin_cents, coins, i, current_change, result)
|
||||
current_change.pop()
|
||||
|
||||
return result
|
||||
|
||||
|
||||
# In[50]:
|
||||
|
||||
|
||||
greedy_times_coin_list = []
|
||||
greedy_labels_coin_list = []
|
||||
|
||||
coins_list_copy = coin_list.copy()
|
||||
|
||||
for coins in coins_list_copy:
|
||||
start = time.perf_counter()
|
||||
greedy_make_change(amounts[0], coins)
|
||||
end = time.perf_counter()
|
||||
greedy_times_coin_list.append(end - start)
|
||||
greedy_labels_coin_list.append(str(len(coins)))
|
||||
|
||||
greedy_times_amount_list = []
|
||||
greedy_labels_amount_list = []
|
||||
|
||||
# Plot a graph
|
||||
plt.figure(figsize=(10, 6))
|
||||
|
||||
# NO BAR
|
||||
plt.plot(greedy_labels_coin_list[1:], greedy_times_coin_list[1:], marker='o', linestyle='solid')
|
||||
plt.xlabel('Coins')
|
||||
plt.ylabel('Time (s)')
|
||||
plt.title('Greedy Algorithm using different coins to make change for 12.35€')
|
||||
|
||||
plt.show()
|
||||
|
||||
for amount in amounts:
|
||||
start = time.perf_counter()
|
||||
greedy_make_change(amount, coin_list[-1])
|
||||
end = time.perf_counter()
|
||||
greedy_times_amount_list.append(end - start)
|
||||
greedy_labels_amount_list.append(str(amount))
|
||||
|
||||
# NO BAR
|
||||
plt.plot(greedy_labels_amount_list[1:], greedy_times_amount_list[1:], marker='o', linestyle='solid')
|
||||
plt.xlabel('Amount')
|
||||
plt.ylabel('Time (s)')
|
||||
plt.title('Greedy Algorithm using 9 coins to make change for different amounts')
|
||||
|
||||
plt.show()
|
||||
|
||||
|
||||
# In[47]:
|
||||
|
||||
|
||||
iterative_times_coin_list = []
|
||||
iterative_labels_coin_list = []
|
||||
|
||||
coins_list_copy = coin_list.copy()
|
||||
|
||||
for coins in coins_list_copy[:5]:
|
||||
start = time.perf_counter()
|
||||
calculate_change_combinations(amounts[0], coins)
|
||||
end = time.perf_counter()
|
||||
iterative_times_coin_list.append(end - start)
|
||||
iterative_labels_coin_list.append(str(len(coins)))
|
||||
|
||||
# Plot a graph
|
||||
plt.figure(figsize=(10, 6))
|
||||
|
||||
# NO BAR
|
||||
plt.plot(iterative_labels_coin_list[1:], iterative_times_coin_list[1:], marker='o', linestyle='solid')
|
||||
plt.xlabel('Coins')
|
||||
plt.ylabel('Time (s)')
|
||||
plt.title('Iterative Algorithm generating all the possibilities using different coins to make change for 12.35€')
|
||||
|
||||
plt.show()
|
||||
|
||||
|
||||
# The complexity increase more when we add coins that are smaller. We can see that adding 0.02 and 0.01 have more impact than adding 2, and 5.
|
||||
|
||||
# In[46]:
|
||||
|
||||
|
||||
recursive_times_coin_list = []
|
||||
recursive_labels_coin_list = []
|
||||
|
||||
coins_list_copy = coin_list.copy()
|
||||
|
||||
for coins in coins_list_copy[:5]:
|
||||
# print(coins)
|
||||
start = time.perf_counter()
|
||||
make_change_recursive(amounts[0]*100, coins, 0, [], [])
|
||||
end = time.perf_counter()
|
||||
recursive_times_coin_list.append(end - start)
|
||||
recursive_labels_coin_list.append(str(len(coins)))
|
||||
|
||||
# Plot a graph
|
||||
plt.figure(figsize=(10, 6))
|
||||
|
||||
# NO BAR
|
||||
plt.plot(recursive_labels_coin_list[1:], recursive_times_coin_list[1:], marker='o', linestyle='solid')
|
||||
plt.xlabel('Coins')
|
||||
plt.ylabel('Time (s)')
|
||||
plt.title('Recursive Algorithm generating all the possibilities using different coins to make change for 12.35€')
|
||||
|
||||
plt.show()
|
||||
|
||||
|
||||
# Complexity seems polynomial or exponential, but it is not possible to test using this problem as it takes to much time to run on all the list of coins.
|
||||
|
||||
# In[45]:
|
||||
|
||||
|
||||
# Export all results to json
|
||||
|
||||
import json
|
||||
|
||||
# Greedy
|
||||
greedy_results = {
|
||||
"greedy_times_coin_list": greedy_times_coin_list,
|
||||
"greedy_labels_coin_list": greedy_labels_coin_list,
|
||||
"greedy_times_amount_list": greedy_times_amount_list,
|
||||
"greedy_labels_amount_list": greedy_labels_amount_list
|
||||
}
|
||||
|
||||
with open('greedy_results.json', 'w') as fp:
|
||||
json.dump(greedy_results, fp)
|
||||
|
||||
# Iterative
|
||||
iterative_results = {
|
||||
"iterative_times_coin_list": iterative_times_coin_list,
|
||||
"iterative_labels_coin_list": iterative_labels_coin_list
|
||||
}
|
||||
|
||||
with open('iterative_results.json', 'w') as fp:
|
||||
json.dump(iterative_results, fp)
|
||||
|
||||
# Recursive
|
||||
recursive_results = {
|
||||
"recursive_times_coin_list": recursive_times_coin_list,
|
||||
"recursive_labels_coin_list": recursive_labels_coin_list
|
||||
}
|
||||
|
||||
with open('recursive_results.json', 'w') as fp:
|
||||
json.dump(recursive_results, fp)
|
||||
|
||||
|
||||
@@ -0,0 +1,271 @@
|
||||
```python
|
||||
# Data
|
||||
amounts = [12.35, 12.35*2, 12.35*3, 12.35*4, 12.35*5, 12.35*6, 12.35*7, 12.35*8, 12.35*9, 12.35*10]
|
||||
|
||||
coin_list = [
|
||||
[0.2, 0.1, 0.05],
|
||||
[1, 0.2, 0.1, 0.05],
|
||||
[2, 1, 0.2, 0.1, 0.05],
|
||||
[5, 2, 1, 0.2, 0.1, 0.05],
|
||||
[5, 2, 1, 0.5, 0.2, 0.1, 0.05],
|
||||
[5, 2, 1, 0.5, 0.2, 0.1, 0.05, 0.02],
|
||||
[5, 2, 1, 0.5, 0.2, 0.1, 0.05, 0.02, 0.01]
|
||||
]
|
||||
|
||||
import time
|
||||
import matplotlib.pyplot as plt
|
||||
```
|
||||
|
||||
|
||||
```python
|
||||
# Greedy
|
||||
def greedy_make_change(amount, coins):
|
||||
i = 0
|
||||
change = []
|
||||
|
||||
while amount > 0 and len(coins) > i:
|
||||
# print(str(round(amount//coins[i])) + " Coins of " + str(coins[i]) + "€")
|
||||
for j in range(round(amount//coins[i])):
|
||||
change.append(coins[i])
|
||||
amount = round(amount%coins[i], 2)
|
||||
i = i+1
|
||||
if amount > 0:
|
||||
print(f"Cannot make exact change for {amount:.2f}€")
|
||||
return change
|
||||
|
||||
```
|
||||
|
||||
|
||||
```python
|
||||
# Iterative
|
||||
|
||||
# Function to count occurrences of items in a list
|
||||
def count_occurrences(array):
|
||||
counts = {}
|
||||
for item in array:
|
||||
if item in counts:
|
||||
counts[item] += 1 # If the item is already in the dictionary, increment its count
|
||||
else:
|
||||
counts[item] = 1 # If the item is not in the dictionary, add it with a count of 1
|
||||
return counts
|
||||
|
||||
# Function to calculate all combinations of coins to make a specific amount
|
||||
def calculate_change_combinations(amount, coins):
|
||||
# Convert euro amounts to cents for calculations
|
||||
amount_cents = int(amount * 100)
|
||||
coin_values_cents = [int(coin * 100) for coin in coins]
|
||||
|
||||
# Initialize a list to store combinations and their counts
|
||||
combinations = []
|
||||
stack = [(0, [], 0)] # (current amount in cents, current combination, current coin index)
|
||||
|
||||
while stack:
|
||||
current_amount, current_combination, current_coin_index = stack.pop()
|
||||
|
||||
# If the current combination sums up to the target amount, add it to the list
|
||||
if current_amount == amount_cents:
|
||||
combinations.append(current_combination)
|
||||
# If the current amount is less than the target amount and there are more coins to consider
|
||||
elif current_amount < amount_cents and current_coin_index < len(coin_values_cents):
|
||||
coin = coin_values_cents[current_coin_index]
|
||||
max_count = (amount_cents - current_amount) // coin # Maximum count of the current coin
|
||||
|
||||
# Try adding different counts of the current coin to explore possibilities
|
||||
for count in range(max_count + 1):
|
||||
new_amount = current_amount + count * coin
|
||||
new_combination = current_combination + [coins[current_coin_index]] * count
|
||||
# Push the new state onto the stack for further exploration
|
||||
stack.append((new_amount, new_combination, current_coin_index + 1))
|
||||
|
||||
# Print the total number of combinations
|
||||
# print(f"Total number of combinations: {len(combinations)}")
|
||||
return combinations
|
||||
```
|
||||
|
||||
|
||||
```python
|
||||
# Recursive
|
||||
def make_change_recursive(amount, coins, start, current_change, result):
|
||||
if amount == 0:
|
||||
result.append(current_change[:])
|
||||
return
|
||||
|
||||
for i in range(start, len(coins)):
|
||||
coin_cents = round(coins[i] * 100)
|
||||
if amount >= coin_cents:
|
||||
current_change.append(coins[i])
|
||||
make_change_recursive(amount - coin_cents, coins, i, current_change, result)
|
||||
current_change.pop()
|
||||
|
||||
return result
|
||||
|
||||
```
|
||||
|
||||
|
||||
```python
|
||||
greedy_times_coin_list = []
|
||||
greedy_labels_coin_list = []
|
||||
|
||||
coins_list_copy = coin_list.copy()
|
||||
|
||||
for coins in coins_list_copy:
|
||||
start = time.perf_counter()
|
||||
greedy_make_change(amounts[0], coins)
|
||||
end = time.perf_counter()
|
||||
greedy_times_coin_list.append(end - start)
|
||||
greedy_labels_coin_list.append(str(len(coins)))
|
||||
|
||||
greedy_times_amount_list = []
|
||||
greedy_labels_amount_list = []
|
||||
|
||||
# Plot a graph
|
||||
plt.figure(figsize=(10, 6))
|
||||
|
||||
# NO BAR
|
||||
plt.plot(greedy_labels_coin_list[1:], greedy_times_coin_list[1:], marker='o', linestyle='solid')
|
||||
plt.xlabel('Coins')
|
||||
plt.ylabel('Time (s)')
|
||||
plt.title('Greedy Algorithm using different coins to make change for 12.35€')
|
||||
|
||||
plt.show()
|
||||
|
||||
for amount in amounts:
|
||||
start = time.perf_counter()
|
||||
greedy_make_change(amount, coin_list[-1])
|
||||
end = time.perf_counter()
|
||||
greedy_times_amount_list.append(end - start)
|
||||
greedy_labels_amount_list.append(str(amount))
|
||||
|
||||
# NO BAR
|
||||
plt.plot(greedy_labels_amount_list[1:], greedy_times_amount_list[1:], marker='o', linestyle='solid')
|
||||
plt.xlabel('Amount')
|
||||
plt.ylabel('Time (s)')
|
||||
plt.title('Greedy Algorithm using 9 coins to make change for different amounts')
|
||||
|
||||
plt.show()
|
||||
```
|
||||
|
||||
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
|
||||
```python
|
||||
iterative_times_coin_list = []
|
||||
iterative_labels_coin_list = []
|
||||
|
||||
coins_list_copy = coin_list.copy()
|
||||
|
||||
for coins in coins_list_copy[:5]:
|
||||
start = time.perf_counter()
|
||||
calculate_change_combinations(amounts[0], coins)
|
||||
end = time.perf_counter()
|
||||
iterative_times_coin_list.append(end - start)
|
||||
iterative_labels_coin_list.append(str(len(coins)))
|
||||
|
||||
# Plot a graph
|
||||
plt.figure(figsize=(10, 6))
|
||||
|
||||
# NO BAR
|
||||
plt.plot(iterative_labels_coin_list[1:], iterative_times_coin_list[1:], marker='o', linestyle='solid')
|
||||
plt.xlabel('Coins')
|
||||
plt.ylabel('Time (s)')
|
||||
plt.title('Iterative Algorithm generating all the possibilities using different coins to make change for 12.35€')
|
||||
|
||||
plt.show()
|
||||
```
|
||||
|
||||
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
The complexity increase more when we add coins that are smaller. We can see that adding 0.02 and 0.01 have more impact than adding 2, and 5.
|
||||
|
||||
|
||||
```python
|
||||
recursive_times_coin_list = []
|
||||
recursive_labels_coin_list = []
|
||||
|
||||
coins_list_copy = coin_list.copy()
|
||||
|
||||
for coins in coins_list_copy[:5]:
|
||||
# print(coins)
|
||||
start = time.perf_counter()
|
||||
make_change_recursive(amounts[0]*100, coins, 0, [], [])
|
||||
end = time.perf_counter()
|
||||
recursive_times_coin_list.append(end - start)
|
||||
recursive_labels_coin_list.append(str(len(coins)))
|
||||
|
||||
# Plot a graph
|
||||
plt.figure(figsize=(10, 6))
|
||||
|
||||
# NO BAR
|
||||
plt.plot(recursive_labels_coin_list[1:], recursive_times_coin_list[1:], marker='o', linestyle='solid')
|
||||
plt.xlabel('Coins')
|
||||
plt.ylabel('Time (s)')
|
||||
plt.title('Recursive Algorithm generating all the possibilities using different coins to make change for 12.35€')
|
||||
|
||||
plt.show()
|
||||
```
|
||||
|
||||
[0.2, 0.1, 0.05]
|
||||
[1, 0.2, 0.1, 0.05]
|
||||
[2, 1, 0.2, 0.1, 0.05]
|
||||
[5, 2, 1, 0.2, 0.1, 0.05]
|
||||
[5, 2, 1, 0.5, 0.2, 0.1, 0.05]
|
||||
|
||||
|
||||
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
Complexity seems polynomial or exponential, but it is not possible to test using this problem as it takes to much time to run on all the list of coins.
|
||||
|
||||
|
||||
```python
|
||||
# Export all results to json
|
||||
|
||||
import json
|
||||
|
||||
# Greedy
|
||||
greedy_results = {
|
||||
"greedy_times_coin_list": greedy_times_coin_list,
|
||||
"greedy_labels_coin_list": greedy_labels_coin_list,
|
||||
"greedy_times_amount_list": greedy_times_amount_list,
|
||||
"greedy_labels_amount_list": greedy_labels_amount_list
|
||||
}
|
||||
|
||||
with open('greedy_results.json', 'w') as fp:
|
||||
json.dump(greedy_results, fp)
|
||||
|
||||
# Iterative
|
||||
iterative_results = {
|
||||
"iterative_times_coin_list": iterative_times_coin_list,
|
||||
"iterative_labels_coin_list": iterative_labels_coin_list
|
||||
}
|
||||
|
||||
with open('iterative_results.json', 'w') as fp:
|
||||
json.dump(iterative_results, fp)
|
||||
|
||||
# Recursive
|
||||
recursive_results = {
|
||||
"recursive_times_coin_list": recursive_times_coin_list,
|
||||
"recursive_labels_coin_list": recursive_labels_coin_list
|
||||
}
|
||||
|
||||
with open('recursive_results.json', 'w') as fp:
|
||||
json.dump(recursive_results, fp)
|
||||
|
||||
```
|
||||
|
After Width: | Height: | Size: 30 KiB |
|
After Width: | Height: | Size: 43 KiB |
|
After Width: | Height: | Size: 29 KiB |
|
After Width: | Height: | Size: 30 KiB |
@@ -0,0 +1 @@
|
||||
{"greedy_times_coin_list": [2.7266999495623168e-05, 4.290000106266234e-06, 4.249999619787559e-06, 4.71700059279101e-06, 5.1530005293898284e-06, 5.198000508244149e-06, 5.539999619941227e-06], "greedy_labels_coin_list": ["3", "4", "5", "6", "7", "8", "9"], "greedy_times_amount_list": [1.591299951542169e-05, 4.618999810190871e-06, 5.142000190971885e-06, 4.219999937049579e-06, 5.545999556488823e-06, 4.925000212097075e-06, 5.834999683429487e-06, 5.122999937157147e-06, 5.883000085304957e-06, 4.184000317764003e-06], "greedy_labels_amount_list": ["12.35", "24.7", "37.05", "49.4", "61.75", "74.1", "86.45", "98.8", "111.14999999999999", "123.5"]}
|
||||
|
After Width: | Height: | Size: 30 KiB |
@@ -0,0 +1 @@
|
||||
{"iterative_times_coin_list": [0.23977153500072745, 0.7593725659999109, 1.4812359939996895, 1.3827171279999675, 6.808871098000054], "iterative_labels_coin_list": ["3", "4", "5", "6", "7"]}
|
||||
|
After Width: | Height: | Size: 29 KiB |
@@ -0,0 +1 @@
|
||||
{"recursive_times_coin_list": [0.12517524299983052, 0.44915761500033113, 0.8362728540005264, 0.9114188160001504, 4.504991862000679], "recursive_labels_coin_list": ["3", "4", "5", "6", "7"]}
|
||||
|
After Width: | Height: | Size: 30 KiB |
@@ -0,0 +1,188 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 4,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Node 0 : [5, 7]\n",
|
||||
"Node 1 : [7, 5]\n",
|
||||
"Node 2 : [3]\n",
|
||||
"Node 3 : [5, 6, 2, 7]\n",
|
||||
"Node 4 : [7, 8]\n",
|
||||
"Node 5 : [0, 7, 3, 1]\n",
|
||||
"Node 6 : [3]\n",
|
||||
"Node 7 : [0, 5, 3, 8, 1, 4]\n",
|
||||
"Node 8 : [7, 4]\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"# Diapo 22\n",
|
||||
"\n",
|
||||
"N = [0,1,2,3,4,5,6,7,8]\n",
|
||||
"E = [(0,5), (0,7), (5,7), (5,3) , (3,6), (3,2), (7,3), (7,8), (7,1), (7,4), (4,8), (5,1)]\n",
|
||||
"\n",
|
||||
"# First, and for the sake of simplification, we will count the number of\n",
|
||||
"# segments / edges separating different points / nodes (of a graph)\n",
|
||||
"\n",
|
||||
"counted = [ [] for i in range(len(N))]\n",
|
||||
"\n",
|
||||
"for e in E:\n",
|
||||
" if e[0] != e[1]:\n",
|
||||
" if e[0] not in counted[e[1]]:\n",
|
||||
" counted[e[1]].append(e[0])\n",
|
||||
" if e[1] not in counted[e[0]]:\n",
|
||||
" counted[e[0]].append(e[1])\n",
|
||||
"\n",
|
||||
"# Print counted\n",
|
||||
"for i in range(len(N)):\n",
|
||||
" print(\"Node\", i, \":\", counted[i])\n",
|
||||
"\n",
|
||||
"# We want to write a program which, given a subset of these nodes\n",
|
||||
"# and edges, computes the list of nodes ordered in ascending order\n",
|
||||
"# of distances to a given particular node.\n",
|
||||
"# » For node 0 and the subset N0 = {1,3,4,5,7} and the associated edges E0 = {(0,5),\n",
|
||||
"# (0,7), (5,7), (7, 3), (7,1), (7,4), (5,1)}\n",
|
||||
"# and the expected result is L0 = {0,5,7,1,3,4}"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 9,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"[0, 0, 0, 0, 0, 1, 0, 1, 0]\n",
|
||||
"[0, 0, 0, 0, 0, 1, 0, 1, 0]\n",
|
||||
"[0, 0, 0, 1, 0, 0, 0, 0, 0]\n",
|
||||
"[0, 0, 1, 0, 0, 1, 1, 1, 0]\n",
|
||||
"[0, 0, 0, 0, 0, 0, 0, 1, 1]\n",
|
||||
"[1, 1, 0, 1, 0, 0, 0, 1, 0]\n",
|
||||
"[0, 0, 0, 1, 0, 0, 0, 0, 0]\n",
|
||||
"[1, 1, 0, 1, 1, 1, 0, 0, 1]\n",
|
||||
"[0, 0, 0, 0, 1, 0, 0, 1, 0]\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"# Generate matrix from nodes and edges\n",
|
||||
"def graph_to_matrix(N, E):\n",
|
||||
" M = [ [0 for i in range(len(N))] for j in range(len(N))]\n",
|
||||
" for e in E:\n",
|
||||
" M[e[0]][e[1]] = 1\n",
|
||||
" M[e[1]][e[0]] = 1\n",
|
||||
" return M\n",
|
||||
"\n",
|
||||
"# Print matrix\n",
|
||||
"matrix = graph_to_matrix(N, E)\n",
|
||||
"for i in range(len(N)):\n",
|
||||
" print(matrix[i])"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 6,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def transitive_closure(matrix):\n",
|
||||
" modification = True\n",
|
||||
" while modification:\n",
|
||||
" modification = False\n",
|
||||
" for i in range(len(matrix)):\n",
|
||||
" for j in range(len(matrix)):\n",
|
||||
" for k in range(len(matrix)):\n",
|
||||
" if matrix[i][j] > 0 and matrix[j][k] > 0 and matrix[i][k] == 0:\n",
|
||||
" matrix[i][k] = matrix[i][j] + matrix[j][k]\n",
|
||||
" modification = True\n",
|
||||
" else:\n",
|
||||
" modification = False\n",
|
||||
"\n",
|
||||
" return matrix\n",
|
||||
"\n",
|
||||
"def compute(node, subset, edges):\n",
|
||||
" linked_edges = []\n",
|
||||
"\n",
|
||||
" for edge in edges:\n",
|
||||
" # Get only the edges linked to the node or between the node of the subset\n",
|
||||
" if edge[0] == node or edge[1] == node:\n",
|
||||
" linked_edges.append(edge)\n",
|
||||
" elif edge[0] in subset and edge[1] in subset:\n",
|
||||
" linked_edges.append(edge)\n",
|
||||
"\n",
|
||||
" # Generate matrix from nodes and edges\n",
|
||||
" matrix = graph_to_matrix(subset + [node], linked_edges)\n",
|
||||
" matrix = transitive_closure(matrix)\n",
|
||||
"\n",
|
||||
" # Make symmetrical\n",
|
||||
" for i in range(len(matrix)):\n",
|
||||
" for j in range(len(matrix)):\n",
|
||||
" if matrix[i][j] > 0:\n",
|
||||
" matrix[j][i] = matrix[i][j]\n",
|
||||
"\n",
|
||||
" # Compute the distance between the node and each other\n",
|
||||
" \n",
|
||||
" distances = [0 for i in range(len(subset))]\n",
|
||||
" for i in range(len(subset+1)):\n",
|
||||
" if(i == node):\n",
|
||||
" distances[i] = (0, 0)\n",
|
||||
" distances[i] = (i, matrix[node][i]) \n",
|
||||
"\n",
|
||||
" # Sort the distances\n",
|
||||
" distances.sort(key=lambda x: x[1])\n",
|
||||
"\n",
|
||||
" # Return the sorted list of nodes\n",
|
||||
" return [x[0] for x in distances]\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 7,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"[(0, 5), (0, 7), (5, 7), (5, 3), (7, 3), (7, 1), (7, 4), (5, 1)]"
|
||||
]
|
||||
},
|
||||
"execution_count": 7,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"compute(0, [1,3,4,5,7], E)"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3 (ipykernel)",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 3
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.10.12"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 2
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
```python
|
||||
# Diapo 22
|
||||
|
||||
N = [0,1,2,3,4,5,6,7,8]
|
||||
E = [(0,5), (0,7), (5,7), (5,3) , (3,6), (3,2), (7,3), (7,8), (7,1), (7,4), (4,8), (5,1)]
|
||||
|
||||
# First, and for the sake of simplification, we will count the number of
|
||||
# segments / edges separating different points / nodes (of a graph)
|
||||
|
||||
counted = [ [] for i in range(len(N))]
|
||||
|
||||
for e in E:
|
||||
if e[0] != e[1]:
|
||||
if e[0] not in counted[e[1]]:
|
||||
counted[e[1]].append(e[0])
|
||||
if e[1] not in counted[e[0]]:
|
||||
counted[e[0]].append(e[1])
|
||||
|
||||
# Print counted
|
||||
for i in range(len(N)):
|
||||
print("Node", i, ":", counted[i])
|
||||
|
||||
# We want to write a program which, given a subset of these nodes
|
||||
# and edges, computes the list of nodes ordered in ascending order
|
||||
# of distances to a given particular node.
|
||||
# » For node 0 and the subset N0 = {1,3,4,5,7} and the associated edges E0 = {(0,5),
|
||||
# (0,7), (5,7), (7, 3), (7,1), (7,4), (5,1)}
|
||||
# and the expected result is L0 = {0,5,7,1,3,4}
|
||||
```
|
||||
|
||||
Node 0 : [5, 7]
|
||||
Node 1 : [7, 5]
|
||||
Node 2 : [3]
|
||||
Node 3 : [5, 6, 2, 7]
|
||||
Node 4 : [7, 8]
|
||||
Node 5 : [0, 7, 3, 1]
|
||||
Node 6 : [3]
|
||||
Node 7 : [0, 5, 3, 8, 1, 4]
|
||||
Node 8 : [7, 4]
|
||||
|
||||
|
||||
|
||||
```python
|
||||
# Generate matrix from nodes and edges
|
||||
def graph_to_matrix(N, E):
|
||||
M = [ [0 for i in range(len(N))] for j in range(len(N))]
|
||||
for e in E:
|
||||
M[e[0]][e[1]] = 1
|
||||
M[e[1]][e[0]] = 1
|
||||
return M
|
||||
|
||||
# Print matrix
|
||||
matrix = graph_to_matrix(N, E)
|
||||
for i in range(len(N)):
|
||||
print(matrix[i])
|
||||
```
|
||||
|
||||
[0, 0, 0, 0, 0, 1, 0, 1, 0]
|
||||
[0, 0, 0, 0, 0, 1, 0, 1, 0]
|
||||
[0, 0, 0, 1, 0, 0, 0, 0, 0]
|
||||
[0, 0, 1, 0, 0, 1, 1, 1, 0]
|
||||
[0, 0, 0, 0, 0, 0, 0, 1, 1]
|
||||
[1, 1, 0, 1, 0, 0, 0, 1, 0]
|
||||
[0, 0, 0, 1, 0, 0, 0, 0, 0]
|
||||
[1, 1, 0, 1, 1, 1, 0, 0, 1]
|
||||
[0, 0, 0, 0, 1, 0, 0, 1, 0]
|
||||
|
||||
|
||||
|
||||
```python
|
||||
def transitive_closure(matrix):
|
||||
modification = True
|
||||
while modification:
|
||||
modification = False
|
||||
for i in range(len(matrix)):
|
||||
for j in range(len(matrix)):
|
||||
for k in range(len(matrix)):
|
||||
if matrix[i][j] > 0 and matrix[j][k] > 0 and matrix[i][k] == 0:
|
||||
matrix[i][k] = matrix[i][j] + matrix[j][k]
|
||||
modification = True
|
||||
else:
|
||||
modification = False
|
||||
|
||||
return matrix
|
||||
|
||||
def compute(node, subset, edges):
|
||||
linked_edges = []
|
||||
|
||||
for edge in edges:
|
||||
# Get only the edges linked to the node or between the node of the subset
|
||||
if edge[0] == node or edge[1] == node:
|
||||
linked_edges.append(edge)
|
||||
elif edge[0] in subset and edge[1] in subset:
|
||||
linked_edges.append(edge)
|
||||
|
||||
# Generate matrix from nodes and edges
|
||||
matrix = graph_to_matrix(subset + [node], linked_edges)
|
||||
matrix = transitive_closure(matrix)
|
||||
|
||||
# Make symmetrical
|
||||
for i in range(len(matrix)):
|
||||
for j in range(len(matrix)):
|
||||
if matrix[i][j] > 0:
|
||||
matrix[j][i] = matrix[i][j]
|
||||
|
||||
# Compute the distance between the node and each other
|
||||
|
||||
distances = [0 for i in range(len(subset))]
|
||||
for i in range(len(subset+1)):
|
||||
if(i == node):
|
||||
distances[i] = (0, 0)
|
||||
distances[i] = (i, matrix[node][i])
|
||||
|
||||
# Sort the distances
|
||||
distances.sort(key=lambda x: x[1])
|
||||
|
||||
# Return the sorted list of nodes
|
||||
return [x[0] for x in distances]
|
||||
|
||||
```
|
||||
|
||||
|
||||
```python
|
||||
compute(0, [1,3,4,5,7], E)
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
[(0, 5), (0, 7), (5, 7), (5, 3), (7, 3), (7, 1), (7, 4), (5, 1)]
|
||||
|
||||
|
||||
@@ -0,0 +1,110 @@
|
||||
#!/usr/bin/env python
|
||||
# coding: utf-8
|
||||
|
||||
# In[4]:
|
||||
|
||||
|
||||
# Diapo 22
|
||||
|
||||
N = [0,1,2,3,4,5,6,7,8]
|
||||
E = [(0,5), (0,7), (5,7), (5,3) , (3,6), (3,2), (7,3), (7,8), (7,1), (7,4), (4,8), (5,1)]
|
||||
|
||||
# First, and for the sake of simplification, we will count the number of
|
||||
# segments / edges separating different points / nodes (of a graph)
|
||||
|
||||
counted = [ [] for i in range(len(N))]
|
||||
|
||||
for e in E:
|
||||
if e[0] != e[1]:
|
||||
if e[0] not in counted[e[1]]:
|
||||
counted[e[1]].append(e[0])
|
||||
if e[1] not in counted[e[0]]:
|
||||
counted[e[0]].append(e[1])
|
||||
|
||||
# Print counted
|
||||
for i in range(len(N)):
|
||||
print("Node", i, ":", counted[i])
|
||||
|
||||
# We want to write a program which, given a subset of these nodes
|
||||
# and edges, computes the list of nodes ordered in ascending order
|
||||
# of distances to a given particular node.
|
||||
# » For node 0 and the subset N0 = {1,3,4,5,7} and the associated edges E0 = {(0,5),
|
||||
# (0,7), (5,7), (7, 3), (7,1), (7,4), (5,1)}
|
||||
# and the expected result is L0 = {0,5,7,1,3,4}
|
||||
|
||||
|
||||
# In[9]:
|
||||
|
||||
|
||||
# Generate matrix from nodes and edges
|
||||
def graph_to_matrix(N, E):
|
||||
M = [ [0 for i in range(len(N))] for j in range(len(N))]
|
||||
for e in E:
|
||||
M[e[0]][e[1]] = 1
|
||||
M[e[1]][e[0]] = 1
|
||||
return M
|
||||
|
||||
# Print matrix
|
||||
matrix = graph_to_matrix(N, E)
|
||||
for i in range(len(N)):
|
||||
print(matrix[i])
|
||||
|
||||
|
||||
# In[6]:
|
||||
|
||||
|
||||
def transitive_closure(matrix):
|
||||
modification = True
|
||||
while modification:
|
||||
modification = False
|
||||
for i in range(len(matrix)):
|
||||
for j in range(len(matrix)):
|
||||
for k in range(len(matrix)):
|
||||
if matrix[i][j] > 0 and matrix[j][k] > 0 and matrix[i][k] == 0:
|
||||
matrix[i][k] = matrix[i][j] + matrix[j][k]
|
||||
modification = True
|
||||
else:
|
||||
modification = False
|
||||
|
||||
return matrix
|
||||
|
||||
def compute(node, subset, edges):
|
||||
linked_edges = []
|
||||
|
||||
for edge in edges:
|
||||
# Get only the edges linked to the node or between the node of the subset
|
||||
if edge[0] == node or edge[1] == node:
|
||||
linked_edges.append(edge)
|
||||
elif edge[0] in subset and edge[1] in subset:
|
||||
linked_edges.append(edge)
|
||||
|
||||
# Generate matrix from nodes and edges
|
||||
matrix = graph_to_matrix(subset + [node], linked_edges)
|
||||
matrix = transitive_closure(matrix)
|
||||
|
||||
# Make symmetrical
|
||||
for i in range(len(matrix)):
|
||||
for j in range(len(matrix)):
|
||||
if matrix[i][j] > 0:
|
||||
matrix[j][i] = matrix[i][j]
|
||||
|
||||
# Compute the distance between the node and each other
|
||||
|
||||
distances = [0 for i in range(len(subset))]
|
||||
for i in range(len(subset+1)):
|
||||
if(i == node):
|
||||
distances[i] = (0, 0)
|
||||
distances[i] = (i, matrix[node][i])
|
||||
|
||||
# Sort the distances
|
||||
distances.sort(key=lambda x: x[1])
|
||||
|
||||
# Return the sorted list of nodes
|
||||
return [x[0] for x in distances]
|
||||
|
||||
|
||||
# In[7]:
|
||||
|
||||
|
||||
compute(0, [1,3,4,5,7], E)
|
||||
|
||||