reorganise directories

upd chapter_01/binary.py
This commit is contained in:
2025-03-26 01:27:35 +00:00
parent ab09aa5269
commit 4cd7bb7d18
43 changed files with 54 additions and 53 deletions

5
chapter_09/README.md Normal file
View File

@@ -0,0 +1,5 @@
# Shortest path for weighted graph (cost associated edges)
- Dijkstra's algorithm works when all weights are non-negative
- If there are negative weights use Bellman-Ford.
- The book demonstrates a function that operates on a list. Priority queue + min heap added for completeness.

BIN
chapter_09/dijkstra1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

BIN
chapter_09/dijkstra2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

BIN
chapter_09/dijkstra3.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

78
chapter_09/rama.py Normal file
View File

@@ -0,0 +1,78 @@
import logging
import math
logging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger(__name__)
### setup the graph
graph = {}
graph["start"] = {}
graph["start"]["a"] = 6
graph["start"]["b"] = 2
graph["a"] = {}
graph["a"]["fin"] = 1
graph["b"] = {}
graph["b"]["a"] = 3
graph["b"]["fin"] = 5
graph["fin"] = {}
### set up costs
costs = {}
costs["a"] = 6
costs["b"] = 2
costs["fin"] = math.inf
### setup parents
parents = {}
parents["a"] = "start"
parents["b"] = "start"
parents["fin"] = None
### our processed queue
processed = set()
### algorithm
def find_lowest_cost_node(costs):
lowest_cost = math.inf
lowest_cost_node = None
for node in costs:
cost = costs[node]
if cost < lowest_cost and node not in processed:
lowest_cost = cost
lowest_cost_node = node
return lowest_cost_node
node = find_lowest_cost_node(costs) # find lowest-cost node not already processed
while node is not None:
cost = costs[node]
neighbors = graph[node]
logger.debug(f"node: {node} cost: {cost} neighbor: {neighbors}")
for n in neighbors.keys():
new_cost = cost + neighbors[n]
if costs[n] > new_cost:
costs[n] = new_cost
parents[n] = node
processed.add(node)
logger.debug(f"processed: {processed}")
node = find_lowest_cost_node(costs)
route = []
next = "fin"
while next != "start":
route.append(next)
next = parents[next]
route.append("start")
print(f"route: {list(reversed(route))}")

View File

@@ -0,0 +1,60 @@
import heapq
import logging
import math
logging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger(__name__)
graph = {
"start": {"a": 5, "b": 2},
"a": {"b": 8, "c": 4, "d": 2},
"b": {"a": 8, "d": 7},
"c": {"d": 6, "fin": 3},
"d": {"fin": 1},
"fin": {},
}
def dijkstra(graph, node):
costs = {node: math.inf for node in graph}
costs[node] = 0
parents = {node: None for node in graph}
queue = [(0, node)]
visited = set()
while queue:
current_cost, current_node = heapq.heappop(queue)
if current_node in visited:
continue
logger.debug(f"node {current_node} with cost {current_cost} popped from pqueue")
visited.add(current_node)
for next_node, weight in graph[current_node].items():
new_cost = current_cost + weight
if new_cost < costs[next_node]:
costs[next_node] = new_cost
parents[next_node] = current_node
heapq.heappush(queue, (new_cost, next_node))
logger.debug(
f"node {next_node} with new cost {new_cost} appended to pqueue"
)
return costs, parents
costs, parents = dijkstra(graph, "start")
print(f"lowest cost from start to fin: {costs['fin']}")
def get_full_route():
route = []
next = "fin"
while next != "start":
route.append(next)
next = parents[next]
route.append("start")
return list(reversed(route))
print(f"full route: {get_full_route()}")

View File

@@ -0,0 +1,46 @@
import heapq
import logging
import math
logging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger(__name__)
graph = {
"start": {"a": 10},
"a": {"c": 20},
"b": {"a": 1, "c": 1},
"c": {"b": 1, "fin": 30},
"fin": {},
}
def dijkstra(graph, node):
costs = {node: math.inf for node in graph}
costs[node] = 0
parents = {node: None for node in graph}
queue = [(0, node)]
visited = set()
while queue:
current_cost, current_node = heapq.heappop(queue)
if current_node in visited:
continue
logger.debug(f"node {current_node} with cost {current_cost} popped from pqueue")
visited.add(current_node)
for next_node, weight in graph[current_node].items():
new_cost = current_cost + weight
if new_cost < costs[next_node]:
costs[next_node] = new_cost
parents[next_node] = current_node
heapq.heappush(queue, (new_cost, next_node))
logger.debug(
f"node {next_node} with new cost {new_cost} appended to pqueue"
)
return costs, parents
costs, parents = dijkstra(graph, "start")
print(f"lowest cost from start to fin: {costs['fin']}")

View File

@@ -0,0 +1,46 @@
import heapq
import logging
import math
logging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger(__name__)
graph = {
"start": {"a": 2, "b": 2},
"a": {"b": 2},
"b": {"c": 2, "fin": 2},
"c": {"fin": 2},
"fin": {},
}
def dijkstra(graph, node):
costs = {node: math.inf for node in graph}
costs[node] = 0
parents = {node: None for node in graph}
queue = [(0, node)]
visited = set()
while queue:
current_cost, current_node = heapq.heappop(queue)
if current_node in visited:
continue
logger.debug(f"node {current_node} with cost {current_cost} popped from pqueue")
visited.add(current_node)
for next_node, weight in graph[current_node].items():
new_cost = current_cost + weight
if new_cost < costs[next_node]:
costs[next_node] = new_cost
parents[next_node] = current_node
heapq.heappush(queue, (new_cost, next_node))
logger.debug(
f"node {next_node} with new cost {new_cost} appended to pqueue"
)
return costs, parents
costs, parents = dijkstra(graph, "start")
print(f"lowest cost from start to fin: {costs['fin']}")

View File

@@ -0,0 +1,71 @@
import logging
import math
logging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger(__name__)
graph = {
"start": {"a": 5, "b": 2},
"a": {"b": 8, "c": 4, "d": 2},
"b": {"a": 8, "d": 7},
"c": {"d": 6, "fin": 3},
"d": {"fin": 1},
"fin": {},
}
costs = {
"a": 5,
"b": 2,
"c": math.inf,
"d": math.inf,
"fin": math.inf,
}
parents = {
"a": "start",
"b": "start",
"c": None,
"d": None,
"fin": None,
}
processed = set()
def find_lowest_cost_node(costs):
lowest_cost = math.inf
lowest_cost_node = None
for node in costs:
cost = costs[node]
if cost < lowest_cost and node not in processed:
lowest_cost = cost
lowest_cost_node = node
return lowest_cost_node
node = find_lowest_cost_node(costs)
while node is not None:
cost = costs[node]
neighbors = graph[node]
for n in neighbors.keys():
new_cost = cost + neighbors[n]
if costs[n] > new_cost:
costs[n] = new_cost
parents[n] = node
processed.add(node)
node = find_lowest_cost_node(costs)
print(f"lowest cost route: {costs['fin']}")
def get_full_route():
route = []
next = "fin"
while next != "start":
route.append(next)
next = parents[next]
route.append("start")
return list(reversed(route))
print(f"route: {get_full_route()}")

View File

@@ -0,0 +1,55 @@
import logging
import math
logging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger(__name__)
graph = {
"start": {"a": 10},
"a": {"c": 20},
"b": {"a": 1, "c": 1},
"c": {"b": 1, "fin": 30},
"fin": {},
}
costs = {
"a": 10,
"b": math.inf,
"c": math.inf,
"fin": math.inf,
}
parents = {
"a": "start",
"b": None,
"c": None,
"fin": None,
}
processed = set()
def find_lowest_cost_node(costs):
lowest_cost = math.inf
lowest_cost_node = None
for node in costs:
cost = costs[node]
if cost < lowest_cost and node not in processed:
lowest_cost = cost
lowest_cost_node = node
return lowest_cost_node
node = find_lowest_cost_node(costs)
while node is not None:
cost = costs[node]
neighbors = graph[node]
for n in neighbors.keys():
new_cost = cost + neighbors[n]
if costs[n] > new_cost:
costs[n] = new_cost
parents[n] = node
processed.add(node)
node = find_lowest_cost_node(costs)
print(f"lowest cost route: {costs['fin']}")

View File

@@ -0,0 +1,55 @@
import logging
import math
logging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger(__name__)
graph = {
"start": {"a": 2, "b": 2},
"a": {"b": 2},
"b": {"c": 2, "fin": 2},
"c": {"fin": 2},
"fin": {},
}
costs = {
"a": 2,
"b": 2,
"c": math.inf,
"fin": math.inf,
}
parents = {
"a": "start",
"b": "start",
"c": None,
"fin": None,
}
processed = set()
def find_lowest_cost_node(costs):
lowest_cost = math.inf
lowest_cost_node = None
for node in costs:
cost = costs[node]
if cost < lowest_cost and node not in processed:
lowest_cost = cost
lowest_cost_node = node
return lowest_cost_node
node = find_lowest_cost_node(costs)
while node is not None:
cost = costs[node]
neighbors = graph[node]
for n in neighbors.keys():
new_cost = cost + neighbors[n]
if costs[n] > new_cost:
costs[n] = new_cost
parents[n] = node
processed.add(node)
node = find_lowest_cost_node(costs)
print(f"lowest cost route: {costs['fin']}")