barakplasma commited on
Commit
d41b3a3
·
1 Parent(s): 134aec6
Files changed (1) hide show
  1. app.py +78 -0
app.py ADDED
@@ -0,0 +1,78 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import json
3
+ from ortools.sat.python import cp_model
4
+
5
+ def solve_task_order(requirements_text):
6
+ # Split and clean the input
7
+ requirements_text = requirements_text.lower()
8
+ lines = [l.strip() for l in requirements_text.strip().splitlines() if l.strip()]
9
+ if not lines:
10
+ return "No requirements specified."
11
+
12
+ prerequisites = []
13
+ all_tasks = set()
14
+ for req in lines:
15
+ if "requires" not in req:
16
+ return f"Error: Each line must be like 'TaskA requires TaskB'. Bad line: {req}"
17
+ before, _, after = req.partition(" requires ")
18
+ before, after = before.strip(), after.strip()
19
+ prerequisites.append((before, after))
20
+ all_tasks |= {before, after}
21
+ task_list = sorted(all_tasks)
22
+ task_to_idx = {task: i for i, task in enumerate(task_list)}
23
+ n_tasks = len(task_list)
24
+
25
+ # Model
26
+ model = cp_model.CpModel()
27
+ order = [model.NewIntVar(0, n_tasks - 1, f'order_{task}') for task in task_list]
28
+ model.AddAllDifferent(order)
29
+ constraints_satisfied = []
30
+ for before, after in prerequisites:
31
+ bidx = task_to_idx[before]
32
+ aidx = task_to_idx[after]
33
+ ok = model.NewBoolVar(f'prereq_{before}_after_{after}')
34
+ model.Add(order[aidx] < order[bidx]).OnlyEnforceIf(ok)
35
+ model.Add(order[aidx] >= order[bidx]).OnlyEnforceIf(ok.Not())
36
+ constraints_satisfied.append(ok)
37
+ model.Maximize(sum(constraints_satisfied))
38
+ solver = cp_model.CpSolver()
39
+ status = solver.Solve(model)
40
+ if status not in (cp_model.OPTIMAL, cp_model.FEASIBLE):
41
+ return "No feasible schedule could be found (cycle or conflict?)"
42
+ idx_to_task = {solver.Value(o): task for o, task in zip(order, task_list)}
43
+ schedule = [idx_to_task[i] for i in range(n_tasks)]
44
+ # Format output: numbered list, and json
45
+ display = "\n".join(f"{i+1}. {task}" for i, task in enumerate(schedule))
46
+ output_json = json.dumps(schedule, indent=2)
47
+ satisfied = int(solver.ObjectiveValue())
48
+ summary = f"Number of constraints satisfied: {satisfied} / {len(prerequisites)}"
49
+ return f"{display}\n\nJSON:\n{output_json}\n\n{summary}"
50
+
51
+ example_input = """\
52
+ Sleep requires dinner
53
+ Sleep requires toothbrushing
54
+ Dinner requires prep
55
+ Dinner requires clean_dining_room
56
+ Prep requires shopping
57
+ Shopping requires money
58
+ Clean_dining_room requires cleaning_time
59
+ """
60
+
61
+ title = "Task Order Solver (Google OR-Tools Scheduler)"
62
+ description = (
63
+ "Enter requirements like 'A requires B' (one per line). "
64
+ "The scheduler will order tasks so that as many requirements as possible are satisfied. "
65
+ "100% satisfaction is guaranteed if there are no cycles."
66
+ )
67
+
68
+ iface = gr.Interface(
69
+ fn=solve_task_order,
70
+ inputs=gr.Textbox(lines=12, label="Paste 'A requires B' constraints here"),
71
+ outputs=gr.Textbox(label="Task order (Numbered, JSON, Stats)"),
72
+ title=title,
73
+ description=description,
74
+ examples=[[example_input]],
75
+ )
76
+
77
+ if __name__ == "__main__":
78
+ iface.launch()