vincentiusyoshuac commited on
Commit
cdfa78b
·
verified ·
1 Parent(s): 5497b6a

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +147 -160
app.py CHANGED
@@ -1,203 +1,190 @@
1
  import streamlit as st
2
- import networkx as nx
3
  import pandas as pd
4
  import numpy as np
5
- from datetime import timedelta
6
- from typing import List, Dict, Tuple
 
 
7
 
8
- class TaskOptimizer:
9
  def __init__(self):
10
- self.task_graph = nx.DiGraph()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11
 
12
- def build_dependency_graph(self, tasks: pd.DataFrame) -> nx.DiGraph:
13
  """
14
- Bangun graph ketergantungan antar tugas
15
  """
 
 
 
 
 
16
  G = nx.DiGraph()
17
 
18
- # Tambahkan nodes (tugas)
19
  for idx, task in tasks.iterrows():
20
  G.add_node(task['Task Name'],
21
  duration=task['Duration'],
22
  complexity=self._complexity_to_weight(task['Complexity']))
23
 
24
- # Tambahkan edges (ketergantungan)
25
- for i in range(len(tasks)):
26
- for j in range(i+1, len(tasks)):
27
- # Logika sederhana untuk dependency
28
- if tasks.iloc[i]['End Date'] < tasks.iloc[j]['Start Date']:
29
- G.add_edge(tasks.iloc[i]['Task Name'], tasks.iloc[j]['Task Name'])
30
 
31
- return G
32
-
33
- def _complexity_to_weight(self, complexity: str) -> float:
34
- """Konversi kompleksitas ke bobot waktu"""
35
- complexity_map = {
36
- 'Low': 1.0,
37
- 'Medium': 1.5,
38
- 'High': 2.0
39
- }
40
- return complexity_map.get(complexity, 1.0)
41
-
42
- def calculate_critical_path(self, tasks: pd.DataFrame) -> Dict:
43
- """
44
- Hitung jalur kritis dengan mempertimbangkan kompleksitas
45
- """
46
- G = self.build_dependency_graph(tasks)
47
-
48
- # Hitung earliest start dan latest finish
49
- earliest_start = {}
50
- latest_finish = {}
51
-
52
- # Forward pass
53
- topological_order = list(nx.topological_sort(G))
54
- for node in topological_order:
55
- predecessors = list(G.predecessors(node))
56
-
57
- if not predecessors:
58
- earliest_start[node] = 0
59
- else:
60
- earliest_start[node] = max(
61
- earliest_start[pred] + G.nodes[pred]['duration']
62
- for pred in predecessors
63
- )
64
-
65
- # Backward pass
66
- total_project_duration = max(earliest_start.values())
67
- for node in reversed(topological_order):
68
- successors = list(G.successors(node))
69
-
70
- if not successors:
71
- latest_finish[node] = total_project_duration
72
- else:
73
- latest_finish[node] = min(
74
- latest_finish[succ] - G.nodes[node]['duration']
75
- for succ in successors
76
- )
77
-
78
- # Identifikasi tugas kritis
79
- critical_tasks = [
80
- node for node in G.nodes
81
- if abs(latest_finish[node] - earliest_start[node]) < 0.1
82
- ]
83
-
84
- return {
85
- 'critical_tasks': critical_tasks,
86
- 'total_project_duration': total_project_duration,
87
- 'earliest_start': earliest_start,
88
- 'latest_finish': latest_finish
89
- }
90
-
91
- def optimize_task_schedule(self, tasks: pd.DataFrame) -> pd.DataFrame:
92
- """
93
- Optimasi penjadwalan tugas dengan algoritma cerdas
94
- """
95
- # Analisis jalur kritis
96
- critical_path_analysis = self.calculate_critical_path(tasks)
97
-
98
- # Buat salinan dataframe untuk dioptimasi
99
- optimized_tasks = tasks.copy()
100
 
101
- # Prioritaskan tugas kritis
102
- critical_tasks = critical_path_analysis['critical_tasks']
103
- optimized_tasks['Priority'] = optimized_tasks['Task Name'].apply(
104
- lambda x: 'Critical' if x in critical_tasks else 'Normal'
105
  )
106
 
107
- # Optimasi alokasi sumber daya
108
- optimized_tasks['Efficiency'] = optimized_tasks.apply(
109
- lambda row: self._calculate_task_efficiency(row, critical_path_analysis),
110
- axis=1
111
- )
112
 
113
- # Urutkan ulang berdasarkan efisiensi dan prioritas
114
- optimized_tasks = optimized_tasks.sort_values(
115
  ['Priority', 'Efficiency'],
116
  ascending=[False, False]
117
  )
118
 
119
- return optimized_tasks
120
 
121
- def _calculate_task_efficiency(self, task, critical_path_analysis):
122
- """
123
- Hitung efisiensi tugas berdasarkan kompleksitas dan jalur kritis
124
- """
 
 
 
 
 
 
125
  complexity_factor = {
126
  'Low': 1.0,
127
  'Medium': 1.5,
128
  'High': 2.0
129
  }
130
 
131
- # Pertimbangkan posisi tugas di jalur kritis
132
- is_critical = task['Task Name'] in critical_path_analysis['critical_tasks']
133
-
134
- # Hitung skor efisiensi
135
- efficiency_score = (
136
- complexity_factor.get(task['Complexity'], 1.0) *
137
- (2 if is_critical else 1)
 
 
 
 
 
 
138
  )
139
-
140
- return efficiency_score
141
 
142
- class AIProjectOptimizer:
143
  def __init__(self):
144
- self.task_optimizer = TaskOptimizer()
145
-
146
- def optimize_project(self, tasks: pd.DataFrame) -> Tuple[pd.DataFrame, dict]:
147
- """
148
- Jalankan optimasi keseluruhan proyek
149
- """
150
- # Optimasi penjadwalan
151
- optimized_tasks = self.task_optimizer.optimize_task_schedule(tasks)
152
-
153
- # Analisis jalur kritis
154
- critical_path_analysis = self.task_optimizer.calculate_critical_path(tasks)
155
-
156
- return optimized_tasks, critical_path_analysis
157
-
158
- # Contoh integrasi di Streamlit
159
- def render_optimization_section(tasks: pd.DataFrame):
160
- st.header("🚀 Optimizer Proyek AI")
161
 
162
- if st.button("Optimasi Proyek"):
163
- optimizer = AIProjectOptimizer()
164
-
165
- try:
166
- optimized_tasks, critical_path_info = optimizer.optimize_project(tasks)
167
-
168
- # Tampilkan hasil optimasi
169
- st.subheader("Tugas Teroptimasi")
170
- st.dataframe(optimized_tasks)
 
 
 
171
 
172
- # Informasi jalur kritis
173
- st.subheader("Analisis Jalur Kritis")
174
- col1, col2 = st.columns(2)
175
 
176
- with col1:
177
- st.metric("Durasi Total Proyek",
178
- f"{critical_path_info['total_project_duration']} hari")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
179
 
180
- with col2:
181
- st.write("Tugas Kritis:")
182
- st.code(", ".join(critical_path_info['critical_tasks']))
183
-
184
- # Visualisasi efisiensi
185
- st.subheader("Distribusi Efisiensi Tugas")
186
- efficiency_dist = optimized_tasks['Efficiency'].value_counts()
187
- st.bar_chart(efficiency_dist)
188
-
189
- except Exception as e:
190
- st.error(f"Gagal mengoptimasi: {e}")
 
 
 
 
 
 
 
 
 
 
 
 
 
191
 
192
- # Contoh penggunaan di main app
193
  def main():
194
- # Implementasi utama Streamlit
195
- st.title("AI Project Optimizer")
196
-
197
- # Asumsi sudah ada dataframe tasks
198
- tasks = pd.DataFrame() # Load dari session state atau input
199
-
200
- render_optimization_section(tasks)
201
 
202
  if __name__ == "__main__":
203
  main()
 
1
  import streamlit as st
 
2
  import pandas as pd
3
  import numpy as np
4
+ from datetime import datetime, timedelta
5
+ import networkx as nx
6
+ import plotly.express as px
7
+ from transformers import pipeline
8
 
9
+ class AIProjectOptimizer:
10
  def __init__(self):
11
+ # Model AI untuk generasi dan klasifikasi
12
+ try:
13
+ self.text_generator = pipeline('text-generation', model='distilgpt2')
14
+ self.task_classifier = pipeline('zero-shot-classification',
15
+ model='facebook/bart-large-mnli')
16
+ except Exception as e:
17
+ st.warning(f"Gagal memuat model AI: {e}")
18
+ self.text_generator = None
19
+ self.task_classifier = None
20
+
21
+ def generate_sample_tasks(self) -> pd.DataFrame:
22
+ """
23
+ Generate contoh tugas default jika tidak ada data
24
+ """
25
+ default_tasks = [
26
+ {
27
+ 'Task Name': f'Tugas {i}',
28
+ 'Start Date': datetime.now() + timedelta(days=i*5),
29
+ 'End Date': datetime.now() + timedelta(days=(i+1)*5),
30
+ 'Duration': 5,
31
+ 'Complexity': np.random.choice(['Low', 'Medium', 'High']),
32
+ 'Progress': np.random.randint(0, 100),
33
+ 'Cost': np.random.randint(1000, 10000)
34
+ } for i in range(5)
35
+ ]
36
+ return pd.DataFrame(default_tasks)
37
 
38
+ def optimize_project(self, tasks: pd.DataFrame):
39
  """
40
+ Optimasi proyek dengan handling kasus kosong
41
  """
42
+ # Gunakan sample tasks jika input kosong
43
+ if tasks is None or tasks.empty:
44
+ tasks = self.generate_sample_tasks()
45
+
46
+ # Graph untuk dependency
47
  G = nx.DiGraph()
48
 
49
+ # Tambahkan nodes
50
  for idx, task in tasks.iterrows():
51
  G.add_node(task['Task Name'],
52
  duration=task['Duration'],
53
  complexity=self._complexity_to_weight(task['Complexity']))
54
 
55
+ # Tambahkan edges sederhana
56
+ for i in range(len(tasks)-1):
57
+ G.add_edge(tasks.iloc[i]['Task Name'], tasks.iloc[i+1]['Task Name'])
 
 
 
58
 
59
+ # Hitung jalur kritis
60
+ try:
61
+ critical_path = list(nx.dag_longest_path(G))
62
+ except nx.NetworkXError:
63
+ critical_path = list(G.nodes)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
64
 
65
+ # Optimasi tasks
66
+ tasks['Priority'] = tasks['Task Name'].apply(
67
+ lambda x: 'Critical' if x in critical_path else 'Normal'
 
68
  )
69
 
70
+ # Hitung efisiensi
71
+ tasks['Efficiency'] = tasks.apply(self._calculate_task_efficiency, axis=1)
 
 
 
72
 
73
+ # Urutkan berdasar prioritas dan efisiensi
74
+ optimized_tasks = tasks.sort_values(
75
  ['Priority', 'Efficiency'],
76
  ascending=[False, False]
77
  )
78
 
79
+ return optimized_tasks, critical_path
80
 
81
+ def _complexity_to_weight(self, complexity: str) -> float:
82
+ """Konversi kompleksitas ke bobot"""
83
+ return {
84
+ 'Low': 1.0,
85
+ 'Medium': 1.5,
86
+ 'High': 2.0
87
+ }.get(complexity, 1.0)
88
+
89
+ def _calculate_task_efficiency(self, task):
90
+ """Hitung efisiensi tugas"""
91
  complexity_factor = {
92
  'Low': 1.0,
93
  'Medium': 1.5,
94
  'High': 2.0
95
  }
96
 
97
+ # Skor efisiensi dengan faktor kompleksitas
98
+ return complexity_factor.get(task['Complexity'], 1.0)
99
+
100
+ def visualize_project(self, tasks: pd.DataFrame):
101
+ """Visualisasi proyek"""
102
+ # Gantt Chart
103
+ fig = px.timeline(
104
+ tasks,
105
+ x_start='Start Date',
106
+ x_end='End Date',
107
+ y='Task Name',
108
+ color='Complexity',
109
+ title='Project Timeline'
110
  )
111
+ return fig
 
112
 
113
+ class StreamlitProjectApp:
114
  def __init__(self):
115
+ self.optimizer = AIProjectOptimizer()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
116
 
117
+ def run(self):
118
+ st.title("🚀 AI Project Optimizer")
119
+
120
+ # Sidebar untuk input tugas
121
+ st.sidebar.header("Input Proyek")
122
+
123
+ # Input tugas manual
124
+ with st.sidebar.form("task_input"):
125
+ task_name = st.text_input("Nama Tugas")
126
+ start_date = st.date_input("Tanggal Mulai")
127
+ duration = st.number_input("Durasi (Hari)", min_value=1, value=5)
128
+ complexity = st.selectbox("Kompleksitas", ['Low', 'Medium', 'High'])
129
 
130
+ submit = st.form_submit_button("Tambah Tugas")
 
 
131
 
132
+ if submit:
133
+ # Tambahkan ke session state
134
+ if 'tasks' not in st.session_state:
135
+ st.session_state.tasks = pd.DataFrame(columns=[
136
+ 'Task Name', 'Start Date', 'End Date',
137
+ 'Duration', 'Complexity', 'Progress', 'Cost'
138
+ ])
139
+
140
+ new_task = pd.DataFrame([{
141
+ 'Task Name': task_name,
142
+ 'Start Date': start_date,
143
+ 'End Date': start_date + timedelta(days=duration),
144
+ 'Duration': duration,
145
+ 'Complexity': complexity,
146
+ 'Progress': 0,
147
+ 'Cost': duration * 500
148
+ }])
149
+
150
+ st.session_state.tasks = pd.concat([
151
+ st.session_state.tasks,
152
+ new_task
153
+ ], ignore_index=True)
154
+
155
+ # Tampilkan daftar tugas
156
+ if hasattr(st.session_state, 'tasks') and not st.session_state.tasks.empty:
157
+ st.subheader("Daftar Tugas")
158
+ st.dataframe(st.session_state.tasks)
159
 
160
+ # Tombol Optimasi
161
+ if st.button("Optimasi Proyek"):
162
+ try:
163
+ optimized_tasks, critical_path = self.optimizer.optimize_project(
164
+ st.session_state.tasks
165
+ )
166
+
167
+ # Tampilkan hasil optimasi
168
+ st.subheader("Tugas Teroptimasi")
169
+ st.dataframe(optimized_tasks)
170
+
171
+ # Visualisasi
172
+ st.subheader("Visualisasi Proyek")
173
+ fig = self.optimizer.visualize_project(optimized_tasks)
174
+ st.plotly_chart(fig)
175
+
176
+ # Informasi jalur kritis
177
+ st.subheader("Jalur Kritis")
178
+ st.write("Tugas Kritis:", critical_path)
179
+
180
+ except Exception as e:
181
+ st.error(f"Gagal mengoptimasi: {e}")
182
+ else:
183
+ st.info("Tambahkan tugas untuk memulai optimasi")
184
 
 
185
  def main():
186
+ app = StreamlitProjectApp()
187
+ app.run()
 
 
 
 
 
188
 
189
  if __name__ == "__main__":
190
  main()