TravelWander / app.py
vincentiusyoshuac's picture
Update app.py
5376ed0 verified
raw
history blame
4.49 kB
import streamlit as st
import folium
from geopy.geocoders import Nominatim
from geopy.distance import geodesic
from itertools import combinations
import numpy as np
# Algoritma Held-Karp untuk TSP
def held_karp_tsp(dist_matrix):
n = len(dist_matrix)
inf = float('inf')
memo = {}
# Initialize memo table for subsets of size 2
for i in range(1, n):
memo[(1 << i, i)] = dist_matrix[0][i]
# Fill memo table for larger subsets
for subset_size in range(2, n):
for subset in combinations(range(1, n), subset_size):
bits = 0
for bit in subset:
bits |= 1 << bit
for next_city in subset:
prev_bits = bits & ~(1 << next_city)
min_dist = inf
for k in subset:
if k == next_city:
continue
current_dist = memo[(prev_bits, k)] + dist_matrix[k][next_city]
if current_dist < min_dist:
min_dist = current_dist
memo[(bits, next_city)] = min_dist
# Find optimal tour
bits = (2 ** n - 1) - 1
min_tour_cost = inf
last_city = None
for k in range(1, n):
tour_cost = memo[(bits, k)] + dist_matrix[k][0]
if tour_cost < min_tour_cost:
min_tour_cost = tour_cost
last_city = k
# Backtrack to find the full tour
tour = [0]
bits = (2 ** n - 1) - 1
for _ in range(n - 1):
tour.append(last_city)
bits &= ~(1 << last_city)
next_city = min(
[(memo[(bits, k)] + dist_matrix[k][last_city], k) for k in range(n) if (bits, k) in memo],
key=lambda x: x[0],
)[1]
last_city = next_city
tour.append(0)
return min_tour_cost, tour
# Mendapatkan koordinat kota dari nama
def get_coordinates(city_name):
geolocator = Nominatim(user_agent="tsp_app")
location = geolocator.geocode(city_name)
if location:
return (location.latitude, location.longitude)
else:
return None
# Menghitung jarak antar semua pasangan kota
def create_distance_matrix(coordinates):
valid_coordinates = [c for c in coordinates if c is not None]
n = len(valid_coordinates)
dist_matrix = np.zeros((n, n))
for i in range(n):
for j in range(i + 1, n):
dist_matrix[i][j] = geodesic(valid_coordinates[i], valid_coordinates[j]).kilometers
dist_matrix[j][i] = dist_matrix[i][j]
return dist_matrix
# Fungsi untuk menampilkan peta rute
def plot_route(map_obj, coordinates, route):
for i in range(len(route) - 1):
start = coordinates[route[i]]
end = coordinates[route[i + 1]]
folium.Marker(location=start, tooltip=f'City {route[i] + 1}').add_to(map_obj)
folium.Marker(location=end, tooltip=f'City {route[i + 1] + 1}').add_to(map_obj)
folium.PolyLine([start, end], color="blue", weight=2.5, opacity=1).add_to(map_obj)
# Add markers for start and end points
folium.Marker(location=coordinates[0], tooltip='Start', icon=folium.Icon(color="green")).add_to(map_obj)
folium.Marker(location=coordinates[route[-2]], tooltip='End', icon=folium.Icon(color="red")).add_to(map_obj)
return map_obj
# Streamlit UI
st.title("Traveling Salesman Problem Solver")
# Input kota
st.subheader("Pilih Kota")
city_count = st.number_input("Jumlah kota", min_value=2, step=1)
city_names = []
for i in range(int(city_count)):
city_name = st.text_input(f"Kota {i+1}", key=f"city_{i}")
city_names.append(city_name)
if st.button("Optimasi Rute"):
coordinates = [get_coordinates(city) for city in city_names]
valid_coordinates = [c for c in coordinates if c is not None]
if len(valid_coordinates) < 2:
st.error("Ada kota yang tidak ditemukan. Pastikan nama kota benar.")
else:
# Buat distance matrix
dist_matrix = create_distance_matrix(valid_coordinates)
min_cost, optimal_route = held_karp_tsp(dist_matrix)
# Tampilkan hasil
st.write(f"Biaya total minimum: {min_cost:.2f} km")
st.write("Rute optimal:", " -> ".join([city_names[i] for i in optimal_route]))
# Buat peta
map_obj = folium.Map(location=valid_coordinates[0], zoom_start=5)
plot_route(map_obj, valid_coordinates, optimal_route)
# Render map
st_folium = st.components.v1.html(folium.Map._repr_html_(map_obj), width=700, height=500)