File size: 5,540 Bytes
88bc40d
 
3d02e0c
 
7fd1509
3d02e0c
 
88bc40d
7fd1509
 
 
 
 
 
 
 
 
88bc40d
315a74e
88bc40d
315a74e
3d02e0c
 
315a74e
 
 
 
 
 
 
 
 
 
3d02e0c
f17bddf
3d02e0c
 
 
 
f17bddf
 
3d02e0c
 
f17bddf
3d02e0c
 
 
 
f17bddf
 
3d02e0c
315a74e
3d02e0c
315a74e
3d02e0c
 
 
4dd2be4
315a74e
3d02e0c
 
f17bddf
315a74e
f17bddf
3d02e0c
 
f17bddf
 
 
 
 
3d02e0c
315a74e
f17bddf
3d02e0c
f17bddf
 
 
 
 
 
 
3d02e0c
 
315a74e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
f17bddf
3d02e0c
 
 
4dd2be4
 
 
3d02e0c
54e640f
4dd2be4
 
 
 
 
 
 
315a74e
 
 
 
3d02e0c
 
 
315a74e
3d02e0c
 
315a74e
3d02e0c
f17bddf
3d02e0c
 
 
 
 
 
 
 
54e640f
315a74e
3d02e0c
54e640f
3d02e0c
54e640f
 
 
 
 
 
3d02e0c
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
import streamlit as st
import pandas as pd
from ortools.sat.python import cp_model

# Initialize session state if not already done
if "timetable" not in st.session_state:
    st.session_state.timetable = pd.DataFrame(columns=["Day", "Time", "Subject", "Teacher", "Room"])

if "subjects" not in st.session_state:
    st.session_state.subjects = {}

if "teachers" not in st.session_state:
    st.session_state.teachers = []

if "rooms" not in st.session_state:
    st.session_state.rooms = []

# App title
st.title("Subject Timetable Generator")

# Sidebar inputs to add data
st.sidebar.header("Add Data")

# Add subjects with weekly slots
subject = st.sidebar.text_input("Enter Subject Name")
weekly_slots = st.sidebar.number_input("Number of Weekly Slots", min_value=1, max_value=10, step=1)
if st.sidebar.button("Add Subject"):
    if subject and weekly_slots > 0:
        st.session_state.subjects[subject] = weekly_slots
        st.success(f"Added Subject: {subject} with {weekly_slots} slots per week")
    else:
        st.error("Please provide a valid subject and weekly slots.")

# Add teachers
teacher = st.sidebar.text_input("Enter Teacher Name")
if st.sidebar.button("Add Teacher"):
    if teacher:
        st.session_state.teachers.append(teacher)
        st.success(f"Added Teacher: {teacher}")
    else:
        st.error("Teacher name cannot be empty!")

# Add rooms
room = st.sidebar.text_input("Enter Room Name")
if st.sidebar.button("Add Room"):
    if room:
        st.session_state.rooms.append(room)
        st.success(f"Added Room: {room}")
    else:
        st.error("Room name cannot be empty!")

# Show current data
st.write("### Current Data")
st.write("**Subjects:**", st.session_state.subjects)
st.write("**Teachers:**", st.session_state.teachers)
st.write("**Rooms:**", st.session_state.rooms)

# Timetable generation logic with debugging
def generate_timetable(subjects, teachers, rooms, time_slots, days):
    model = cp_model.CpModel()
    schedule = {}

    # Create variables for each subject-teacher-room-time-slot combination
    for subject, slots in subjects.items():
        for teacher in teachers:
            for room in rooms:
                for day in days:
                    for time_slot in time_slots:
                        schedule[(subject, teacher, room, day, time_slot)] = model.NewBoolVar(
                            f"{subject}_{teacher}_{room}_{day}_{time_slot}"
                        )

    # Constraints: Each subject should have the required number of weekly slots
    for subject, slots in subjects.items():
        model.Add(
            sum(
                schedule[(subject, teacher, room, day, time_slot)]
                for teacher in teachers
                for room in rooms
                for day in days
                for time_slot in time_slots
            ) == slots
        )

    # Constraints: No teacher or room should be double-booked
    for teacher in teachers:
        for day in days:
            for time_slot in time_slots:
                model.Add(
                    sum(
                        schedule[(subject, teacher, room, day, time_slot)]
                        for subject in subjects
                        for room in rooms
                    ) <= 1  # A teacher can only be in one class at a time
                )

    for room in rooms:
        for day in days:
            for time_slot in time_slots:
                model.Add(
                    sum(
                        schedule[(subject, teacher, room, day, time_slot)]
                        for subject in subjects
                        for teacher in teachers
                    ) <= 1  # A room can only be used for one subject at a time
                )

    # Solve the model
    solver = cp_model.CpSolver()
    status = solver.Solve(model)

    # Debugging: Print the solver status and results
    if status != cp_model.OPTIMAL:
        st.error(f"Solver failed to find a solution. Solver status: {status}")
        return []

    result = []
    for key, var in schedule.items():
        if solver.Value(var) == 1:
            result.append(key)

    return result

# Time slots and days for timetable
time_slots = [f"{hour}:00 - {hour+1}:00" for hour in range(8, 18)]  # 8 AM to 6 PM
days = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"]

# Generate timetable button
if st.button("Generate Timetable"):
    timetable = generate_timetable(
        st.session_state.subjects, st.session_state.teachers, st.session_state.rooms, time_slots, days
    )
    if timetable:
        # Store the generated timetable
        for entry in timetable:
            subject, teacher, room, day, time_slot = entry
            st.session_state.timetable = pd.concat(
                [st.session_state.timetable, pd.DataFrame([[day, time_slot, subject, teacher, room]],
                                                          columns=["Day", "Time", "Subject", "Teacher", "Room"])],
                ignore_index=True
            )
        st.success("Timetable generated successfully!")
    else:
        st.error("Failed to generate timetable. Check constraints!")

# Display the generated timetable
st.write("### Generated Timetable")
if not st.session_state.timetable.empty:
    st.dataframe(st.session_state.timetable)
    st.download_button(
        "Download Timetable (CSV)",
        data=st.session_state.timetable.to_csv(index=False),
        file_name="timetable.csv",
        mime="text/csv"
    )
else:
    st.write("No timetable generated yet.")