soufir commited on
Commit
9544344
Β·
verified Β·
1 Parent(s): 1d3fe97

Update src/streamlit_app.py

Browse files
Files changed (1) hide show
  1. src/streamlit_app.py +39 -114
src/streamlit_app.py CHANGED
@@ -5,7 +5,7 @@ import numpy as np
5
  st.set_page_config(page_title="SPK Lokasi Kedai Kopi", layout="wide")
6
 
7
  st.title("πŸ“Š Sistem Pendukung Keputusan Lokasi Kedai Kopi")
8
- st.markdown("Metode: *AHP*, **TOPSIS**, dan **Profile Matching**")
9
 
10
  # --- Step 1: Pilih Metode ---
11
  st.sidebar.header("βš™ Pengaturan")
@@ -26,110 +26,30 @@ if not criteria or not alternatives:
26
  # ---------------------------
27
  if method == "AHP":
28
  st.subheader("πŸ”— Perbandingan Berpasangan Antar Kriteria (AHP)")
29
-
30
- # pairwise_criteria_data = np.ones((len(criteria), len(criteria)))
31
- # for i in range(len(criteria)):
32
- # for j in range(i + 1, len(criteria)):
33
- # pairwise_criteria_data[i, j] = 1.0
34
-
35
-
36
- #setup
37
- n = len(alternatives)
38
-
39
- # Step 1: Buat matriks input kosong hanya untuk segitiga atas
40
- upper_input = pd.DataFrame("", index=alternatives, columns=alternatives)
41
-
42
- for i in range(n):
43
- for j in range(n):
44
- if i >= j:
45
- upper_input.iloc[i, j] = "-" # Tidak bisa diedit
46
- elif i < j:
47
- upper_input.iloc[i, j] = ""
48
-
49
- st.subheader("πŸ“ Input Segitiga Atas (Nilai Perbandingan Alternatif)")
50
- user_input = st.data_editor(upper_input, key="input_matrix", num_rows="fixed")
51
-
52
- # Step 2: Buat matriks lengkap (isi diagonal 1, segitiga bawah = 1/segitiga atas)
53
- final_pairwise_criteria_matrix = pd.DataFrame(np.ones((n, n)), index=alternatives, columns=alternatives)
54
- valid = True
55
-
56
- try:
57
- for i in range(n):
58
- for j in range(n):
59
- if i == j:
60
- filled_matrix.iloc[i, j] = 1.0
61
- elif i < j:
62
- val = float(user_input.iloc[i, j])
63
- filled_matrix.iloc[i, j] = val
64
- filled_matrix.iloc[j, i] = round(1 / val, 4)
65
- except:
66
- valid = False
67
- st.warning("❗ Pastikan semua nilai input valid dan merupakan angka (float/int).")
68
-
69
- # Step 3: Tampilkan matriks lengkap jika valid
70
- if valid:
71
- st.subheader("πŸ“ Matriks Lengkap dengan Nilai Resiprokal")
72
- st.dataframe(final_pairwise_criteria_matrix)
73
- else:
74
- st.info("Masukkan hanya nilai pada segitiga atas, misalnya angka seperti 3, 1/5, dsb.")
75
-
76
- # soufiii
77
- # n = len(alternatives)
78
- # pairwise_criteria_data = pd.DataFrame(np.ones((n, n)), index=alternatives, columns=alternatives)
79
- # for i in range(n):
80
- # for j in range(n):
81
- # if i == j:
82
- # input_matrix.iloc[i, j] = 1.0
83
- # elif i < j:
84
- # input_matrix.iloc[i, j] = np.nan
85
- # else:
86
- # input_matrix.iloc[i, j] = None # segitiga bawah disembunyikan
87
-
88
- # # Step 2: Tampilkan hanya input segitiga atas
89
- # st.subheader("πŸ“ Masukkan Nilai Perbandingan Berpasangan (segitiga atas saja)")
90
- # edited_matrix = st.data_editor(pairwise_criteria_data, key="pairwise_input")
91
-
92
- # # Step 3: Proses segitiga bawah (otomatis hitung invers)
93
- # filled_matrix = edited_matrix.copy()
94
- # valid = True
95
-
96
- # for i in range(n):
97
- # for j in range(n):
98
- # if i == j:
99
- # filled_matrix.iloc[i, j] = 1.0
100
- # elif i < j:
101
- # if pd.notna(edited_matrix.iloc[i, j]):
102
- # filled_matrix.iloc[j, i] = round(1 / edited_matrix.iloc[i, j], 4)
103
- # else:
104
- # valid = False
105
-
106
- # # Step 4: Tampilkan hasil lengkap jika valid
107
- # if valid:
108
- # st.subheader("πŸ“ Matriks Lengkap dengan Nilai Resiprokal")
109
- # st.dataframe(filled_matrix)
110
- # else:
111
- # st.warning("⚠️ Harap isi semua nilai pada segitiga atas sebelum melanjutkan.")
112
- # #sampai sini
113
-
114
-
115
- # pairwise_criteria_df = pd.DataFrame(pairwise_criteria_data, index=criteria, columns=criteria)
116
-
117
- # edited_pairwise_criteria_matrix = st.data_editor(
118
- # pairwise_criteria_df,
119
- # use_container_width=True,
120
- # key="pairwise_comparison_criteria_matrix",
121
- # hide_index=False,
122
- # )
123
-
124
- # # Reciprocity for criteria matrix
125
- # final_pairwise_criteria_matrix = edited_pairwise_criteria_matrix.copy()
126
- # for i in range(len(criteria)):
127
- # for j in range(i + 1, len(criteria)):
128
- # val = final_pairwise_criteria_matrix.iloc[i, j]
129
- # if val == 0:
130
- # val = 1e-9
131
- # final_pairwise_criteria_matrix.iloc[j, i] = 1 / val
132
- # final_pairwise_criteria_matrix.iloc[i, i] = 1.0
133
 
134
  # Hitung bobot kriteria AHP
135
  weights_ahp_criteria = pd.Series(dtype='float64')
@@ -139,25 +59,28 @@ if method == "AHP":
139
  norm_matrix = numeric_criteria_matrix / numeric_criteria_matrix.sum()
140
  weights_ahp_criteria = norm_matrix.mean(axis=1)
141
  weights_ahp_criteria /= weights_ahp_criteria.sum()
142
-
143
  st.write("🎯 Bobot Kriteria dari AHP:")
144
  st.dataframe(weights_ahp_criteria.round(3).to_frame(name="Bobot AHP"))
145
 
146
- # Konsistensi kriteria
147
- RI = {1:0, 2:0, 3:0.58, 4:0.90, 5:1.12, 6:1.24, 7:1.32, 8:1.41, 9:1.45, 10:1.49}
148
  n_criteria = len(criteria)
149
- weighted_sum_vector_criteria = numeric_criteria_matrix @ weights_ahp_criteria
150
- lambda_max_criteria = (weighted_sum_vector_criteria / weights_ahp_criteria).mean()
 
 
 
151
  CI_criteria = (lambda_max_criteria - n_criteria) / (n_criteria - 1) if n_criteria > 1 else 0
 
152
  CR_criteria = np.nan
153
  if n_criteria in RI and RI[n_criteria] > 0:
154
  CR_criteria = CI_criteria / RI[n_criteria]
155
 
156
  st.subheader("βœ… Analisis Konsistensi Kriteria AHP")
157
- st.write(f"$\lambda_{{max}} = {lambda_max_criteria:.2f}$")
158
- st.write(f"CI = {CI_criteria:.3f}")
159
  if not np.isnan(CR_criteria):
160
- st.write(f"CR = {CR_criteria:.3f}")
161
  if CR_criteria < 0.1:
162
  st.success("Konsistensi Rasio Kriteria AHP *BAIK* (< 0.1)")
163
  else:
@@ -220,9 +143,11 @@ if method == "AHP":
220
  except Exception as e:
221
  st.error(f"Error menghitung bobot alternatif pada kriteria {criterion}: {e}")
222
 
 
 
223
  else:
224
  # TOPSIS dan Profile Matching
225
- st.subheader("πŸ“‹ Input Nilai Alternatif terhadap Kriteria (Untuk TOPSIS/Profile Matching)")
226
  empty_data = pd.DataFrame(np.nan, index=alternatives, columns=criteria)
227
  df = st.data_editor(empty_data, use_container_width=True, key="input_matrix")
228
  if df.isnull().values.any():
 
5
  st.set_page_config(page_title="SPK Lokasi Kedai Kopi", layout="wide")
6
 
7
  st.title("πŸ“Š Sistem Pendukung Keputusan Lokasi Kedai Kopi")
8
+ st.markdown("Metode: *AHP, **TOPSIS, dan **Profile Matching*")
9
 
10
  # --- Step 1: Pilih Metode ---
11
  st.sidebar.header("βš™ Pengaturan")
 
26
  # ---------------------------
27
  if method == "AHP":
28
  st.subheader("πŸ”— Perbandingan Berpasangan Antar Kriteria (AHP)")
29
+
30
+ pairwise_criteria_data = np.ones((len(criteria), len(criteria)))
31
+ for i in range(len(criteria)):
32
+ for j in range(i + 1, len(criteria)):
33
+ pairwise_criteria_data[i, j] = 1.0
34
+
35
+ pairwise_criteria_df = pd.DataFrame(pairwise_criteria_data, index=criteria, columns=criteria)
36
+
37
+ edited_pairwise_criteria_matrix = st.data_editor(
38
+ pairwise_criteria_df,
39
+ use_container_width=True,
40
+ key="pairwise_comparison_criteria_matrix",
41
+ hide_index=False,
42
+ )
43
+
44
+ # Reciprocity for criteria matrix
45
+ final_pairwise_criteria_matrix = edited_pairwise_criteria_matrix.copy()
46
+ for i in range(len(criteria)):
47
+ for j in range(i + 1, len(criteria)):
48
+ val = final_pairwise_criteria_matrix.iloc[i, j]
49
+ if val == 0:
50
+ val = 1e-9
51
+ final_pairwise_criteria_matrix.iloc[j, i] = 1 / val
52
+ final_pairwise_criteria_matrix.iloc[i, i] = 1.0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
53
 
54
  # Hitung bobot kriteria AHP
55
  weights_ahp_criteria = pd.Series(dtype='float64')
 
59
  norm_matrix = numeric_criteria_matrix / numeric_criteria_matrix.sum()
60
  weights_ahp_criteria = norm_matrix.mean(axis=1)
61
  weights_ahp_criteria /= weights_ahp_criteria.sum()
62
+
63
  st.write("🎯 Bobot Kriteria dari AHP:")
64
  st.dataframe(weights_ahp_criteria.round(3).to_frame(name="Bobot AHP"))
65
 
66
+ RI = {1: 0.00, 2: 0.00, 3: 0.58, 4: 0.90, 5: 1.12, 6: 1.24, 7: 1.32, 8: 1.41, 9: 1.45, 10: 1.49}
 
67
  n_criteria = len(criteria)
68
+ # Weighted Sum Vector (WSV)
69
+ wsv = numeric_criteria_matrix.dot(weights_ahp_criteria)
70
+ # Ξ»_max manual: rata-rata dari WSV[i] / W[i]
71
+ lambda_max_criteria = (wsv / weights_ahp_criteria).mean()
72
+ # CI manual
73
  CI_criteria = (lambda_max_criteria - n_criteria) / (n_criteria - 1) if n_criteria > 1 else 0
74
+
75
  CR_criteria = np.nan
76
  if n_criteria in RI and RI[n_criteria] > 0:
77
  CR_criteria = CI_criteria / RI[n_criteria]
78
 
79
  st.subheader("βœ… Analisis Konsistensi Kriteria AHP")
80
+ st.write(f"$\\lambda_{{max}} = {lambda_max_criteria:.10f}$")
81
+ st.write(f"CI = {CI_criteria:.10f}")
82
  if not np.isnan(CR_criteria):
83
+ st.write(f"CR = {CR_criteria:.10f}")
84
  if CR_criteria < 0.1:
85
  st.success("Konsistensi Rasio Kriteria AHP *BAIK* (< 0.1)")
86
  else:
 
143
  except Exception as e:
144
  st.error(f"Error menghitung bobot alternatif pada kriteria {criterion}: {e}")
145
 
146
+ elif method == "None":
147
+ st.subheader("Pilih Metode terlebih dahulu")
148
  else:
149
  # TOPSIS dan Profile Matching
150
+ st.subheader("πŸ“‹ Input Nilai Alternatif terhadap Kriteria")
151
  empty_data = pd.DataFrame(np.nan, index=alternatives, columns=criteria)
152
  df = st.data_editor(empty_data, use_container_width=True, key="input_matrix")
153
  if df.isnull().values.any():