Restore DFS and IDA* to Task 3 interactive replay (all 4 algorithms)
Browse files
app.py
CHANGED
|
@@ -672,15 +672,54 @@ with T3:
|
|
| 672 |
if nb not in seen: seen.add(nb); q.append((nb,p+[nb]))
|
| 673 |
return None,0.0,expl
|
| 674 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 675 |
# config row
|
| 676 |
-
cfg1, cfg2, cfg3, cfg4 = st.columns([1.
|
| 677 |
all_n = list(NODES_R.keys())
|
| 678 |
sn = cfg1.selectbox("Start", all_n, index=0, key="r_sn")
|
| 679 |
en = cfg2.selectbox("End", all_n, index=19, key="r_en")
|
| 680 |
-
algo = cfg3.radio("Algorithm", ["A*","BFS"], key="r_algo", horizontal=True)
|
| 681 |
rp_speed = cfg4.slider("Speed", 1, 8, 3, format="%dx", key="rp_spd")
|
|
|
|
| 682 |
|
| 683 |
-
fn =
|
| 684 |
if sn != en:
|
| 685 |
path_r, cost_r, expl_r = fn(sn, en)
|
| 686 |
else:
|
|
|
|
| 672 |
if nb not in seen: seen.add(nb); q.append((nb,p+[nb]))
|
| 673 |
return None,0.0,expl
|
| 674 |
|
| 675 |
+
def _dfs(s,g):
|
| 676 |
+
stack=[(s,[s])]; seen={s}; expl=[]
|
| 677 |
+
while stack:
|
| 678 |
+
n,p=stack.pop(); expl.append(n)
|
| 679 |
+
if n==g: return p,round(sum(_ew(p[i],p[i+1]) for i in range(len(p)-1)),2),expl
|
| 680 |
+
for nb,_ in reversed(ADJ[n]):
|
| 681 |
+
if nb not in seen: seen.add(nb); stack.append((nb,p+[nb]))
|
| 682 |
+
return None,0.0,expl
|
| 683 |
+
|
| 684 |
+
def _idastar(s,g):
|
| 685 |
+
h=lambda n:_nd(n,g); expl=[]; path=[s]
|
| 686 |
+
def search(gc,bound):
|
| 687 |
+
n=path[-1]; f=gc+h(n)
|
| 688 |
+
if f>bound: return f
|
| 689 |
+
if n==g: return -1
|
| 690 |
+
expl.append(n); mn=math.inf
|
| 691 |
+
for nb,w in sorted(ADJ[n],key=lambda x:h(x[0])):
|
| 692 |
+
if nb not in path:
|
| 693 |
+
path.append(nb); t=search(gc+w,bound)
|
| 694 |
+
if t==-1: return -1
|
| 695 |
+
if t<mn: mn=t
|
| 696 |
+
path.pop()
|
| 697 |
+
return mn
|
| 698 |
+
bound=h(s)
|
| 699 |
+
while True:
|
| 700 |
+
t=search(0,bound)
|
| 701 |
+
if t==-1:
|
| 702 |
+
return list(path),round(sum(_ew(path[i],path[i+1]) for i in range(len(path)-1)),2),expl
|
| 703 |
+
if t==math.inf: return None,0.0,expl
|
| 704 |
+
bound=t
|
| 705 |
+
|
| 706 |
+
ALGO_DESC = {
|
| 707 |
+
"A*": "Guided heuristic — expands fewest nodes, always optimal",
|
| 708 |
+
"BFS": "Level-by-level — optimal shortest hops, explores broadly",
|
| 709 |
+
"DFS": "Deep dive — fast but not guaranteed to find shortest path",
|
| 710 |
+
"IDA*": "Iterative A* — optimal like A*, uses almost no memory",
|
| 711 |
+
}
|
| 712 |
+
|
| 713 |
# config row
|
| 714 |
+
cfg1, cfg2, cfg3, cfg4 = st.columns([1.2, 1.2, 2.2, 1.2])
|
| 715 |
all_n = list(NODES_R.keys())
|
| 716 |
sn = cfg1.selectbox("Start", all_n, index=0, key="r_sn")
|
| 717 |
en = cfg2.selectbox("End", all_n, index=19, key="r_en")
|
| 718 |
+
algo = cfg3.radio("Algorithm", ["A*","BFS","DFS","IDA*"], key="r_algo", horizontal=True)
|
| 719 |
rp_speed = cfg4.slider("Speed", 1, 8, 3, format="%dx", key="rp_spd")
|
| 720 |
+
st.caption(f"**{algo}** — {ALGO_DESC[algo]}")
|
| 721 |
|
| 722 |
+
fn = {"A*":_astar, "BFS":_bfs, "DFS":_dfs, "IDA*":_idastar}[algo]
|
| 723 |
if sn != en:
|
| 724 |
path_r, cost_r, expl_r = fn(sn, en)
|
| 725 |
else:
|