实验一 复杂工程问题

该实验旨在通过解决排课问题来理解和应用非线性规划。使用Pandas库处理数据,定义了Teacher、StudentGroup和Classroom类来构建数据结构。算法遵循教师、班级和教室的约束,确保不超过限制。实验还涉及代码规范和效率,但未实现优化。最后,展示了输入查询后的教师、班级和教室的课表结果。
摘要由CSDN通过智能技术生成

实验一:有约束的极值求解

实验目的

(1)通过排课问题理解非线性规划问题;
(2)熟悉有约束的极值求解方法;
(3)了解排课算法优化算法;
(4)熟悉list,dataFrame等数据结构
(5)养成高质量代码编写习惯。

实验要求:

(1)编码规范
(2)代码高效
(3)注释充分,程序可读性好
(4)程序无bug
(5)方法接口规范定义

实验内容

根据以下约束和排班原则进行排课算法设计
(1)同一个任课教师在一个教学时间段只能进行一门课程教学
(2)同一个班级在一个教学时间段只能进行一门课程教学
(3)同一个教室在一个教学时间段只能进行一门课程教学
(4)排课教室必须满足学生人数要求
(5)一个教师每天不能超过6节课
(6)每个学生班级每天不能超过8节课
(7)每个教学班同一门课程每天不能超过2节课
(8)总共不能超过10教室

实验步骤

1.算法设计

1.1数据结构设计
import pandas as pd
from pandas import DataFrame
import numpy as np
import random

file_name = '软件工程教学任务列表.xls'
pd.set_option('display.max_columns', 500)
# 开课任务
assign_info = pd.read_excel(file_name, sheet_name='教学任务', header=0)
# 教室信息
classroom_info = pd.read_excel(file_name, sheet_name='教室信息', header=0)
# 时间:
course_time_day = ['8:30~9:15', '9:20~10:05', '10:25~11:10', '11:15~12:00', '14:00~14:45', '14:50~15:35', '15:55~16:40','16:45~17:30']
# 星期
week = ['周一', '周二', '周三', '周四', '周五']


# 老师:名字,课程,课程表
class Teacher():
    def __init__(self, name):
        self.name = name
        self.courseInfos = []
        self.table = DataFrame('', index=course_time_day, columns=week)

    def add_course_info(self, courseInfo):
        self.courseInfos.append(courseInfo)


# 学生:数量
class StudentGroup(Teacher):
    student_num = 0
    pass


# 教室:编号,课程信息,容纳人数,课程表
class Classroom():
    def __init__(self, roomId, room_set_num):
        self.roomId = roomId
        self.courseInfos = []
        self.room_set_num = room_set_num
        self.table = DataFrame('', index=course_time_day, columns=week)

    def add_course_info(self, courseInfo):
        self.courseInfos.append(courseInfo)
1.2 算法流程设计

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xzYV9qyk-1681868985728)(流程图1.png)]

1.3 功能模块设计

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Gu6NgFBf-1681868985729)(功能模块图1.png)]

2.数据与处理

对教学任务信息,教室信息,教师信息,教学班级信息进行处理,组织排课算法需要的各数据和排课结果表,并对相关变量进行初始化

# -*- coding: utf-8 -*-
# 行
index_row = assign_info.index.tolist()
# 列
index_col = assign_info.columns.tolist()
# 教学班列表
name_group = list(set(assign_info['教学班名称'].values))
# 教师列表
name_teacher = list(set(assign_info['授课教师'].values))
# 教室列表
name_classroom=list(set(classroom_info['名称'].values))
# 教师列表
teachers = []
for name in name_teacher:
    teacher = Teacher(name)
    for index in index_row:
        if assign_info.loc[index, '授课教师'] == name:
            course_info = {
                'name_group': assign_info.loc[index, '教学班名称'],
                'name_course': assign_info.loc[index, '课程名称'],
                'course_time_day': None,
                'course_time_week': None,
                'classroom': None,
            }
            teacher.add_course_info(course_info)
    teachers.append(teacher)
# 学生班级列表
student_groups = []
for name in name_group:  # 班级名
    group = StudentGroup(name)
    for index in index_row:
        if assign_info.loc[index, '教学班名称'] == name:
            course_info = {
                'name_teacher': assign_info.loc[index, '授课教师'],
                'name_course': assign_info.loc[index, '课程名称'],
                'study_time_course': assign_info.loc[index, '周课时'],
                'course_time_day': None,
                'course_time_week': None,
                'classroom': None,
            }
            group.student_num = assign_info.loc[index, '人数上限']
            group.add_course_info(course_info)
    student_groups.append(group)
# 教室列表
classrooms=[]
for roomName in name_classroom:
    for index in classroom_info.index.tolist():
        if classroom_info.loc[index,'名称']==roomName:
            roomId=classroom_info.loc[index,'序号']
            room_set_num=classroom_info.loc[index,'容量']
            classroom=Classroom(roomId,room_set_num)
            classrooms.append(classroom)

3.算法实现

按照每天最短教学时间及日课时差最小原则进行排课

# 排课
# 遍历任务列表
for i in index_row:
    task = assign_info.loc[int(i), :]
    course_name = task['课程名称']
    # 遍历班级列表找到这个班级
    for student_group in student_groups:
        if student_group.name != task['教学班名称']:
            continue
        else:
            table_g = student_group.table
            w = table_g.columns.tolist()
            random.shuffle(w)
            for index_col_table in w:
                for index_row_table in table_g.index.tolist():
                    # 判断班级当天课是否超过8节 且同样的课是否超过两节
                    student_daily_course_num = 0
                    # 用于判断同样的课是否超过两节
                    student_daily_course_info = {}
                    # 遍历学生当天第1节课-第10节课,将课表信息存储下来
                    for row in table_g.index:
                        if table_g.loc[row, index_col_table] == '':
                            continue
                        else:
                            course_info = table_g.loc[row, index_col_table]
                            if course_info in student_daily_course_info.keys():
                                student_daily_course_info[course_info] += 1
                            else:
                                student_daily_course_info[course_info] = 1
                            student_daily_course_num += 1
                    # 判断当天是否超过两节
                    isFull = False
                    course_num = 0
                    for key in student_daily_course_info.keys():
                        if course_name in key:
                            course_num += student_daily_course_info[key]
                            if course_num >= 2:
                                isFull = True
                                break
                        else:
                            continue
                    # 判断一天是否超过8节
                    if student_daily_course_num >= 8 or isFull:
                        break
                    else:
                        # 判断当前时间段是否有课
                        # 有课
                        if table_g.loc[index_row_table, index_col_table] != '':
                            continue
                        # 没课
                        else:
                            # 判断学时是否以及排完
                            course_info_num = 0
                            course_index = 0
                            for course_info_s in student_group.courseInfos:
                                if course_info_s['name_course'] != course_name:
                                    continue
                                else:
                                    course_index = student_group.courseInfos.index(course_info_s)
                                    course_info_num = course_info_s['study_time_course']
                                    break

                            if course_info_num <= 0:
                                break
                            else:
                                # 学生可以排课,遍历老师列表,找到老师
                                for teacher in teachers:
                                    if teacher.name is not task['授课教师']:
                                        continue
                                    else:
                                        # 提取老师的课程表
                                        table_t = teacher.table
                                        teacher_daily_course_num = 0
                                        for row in table_t.index:
                                            if table_t.loc[row, index_col_table]:
                                                teacher_daily_course_num += 1
                                        if teacher_daily_course_num >= 3:
                                            break
                                        else:
                                            # 判断这节课老师是否有课,若没有则可以排课
                                            if table_t.loc[index_row_table, index_col_table] != '':  # 有课
                                                break
                                            else:
                                                # 遍历教室,看看哪间教室可以用
                                                random.shuffle(classrooms)
                                                for classroom in classrooms:
                                                    table_r = classroom.table
                                                    if table_r.loc[
                                                        index_row_table, index_col_table] != '' or classroom.room_set_num < student_group.student_num:
                                                        continue
                                                    else:
                                                        # 都符合要求可以排课!
                                                        # 学生课表 加课
                                                        table_g.loc[
                                                            index_row_table, index_col_table] = course_name + '/' + teacher.name + '/' + str(
                                                            classroom_info['名称'][course_index])

                                                        # 周学时减1
                                                        student_group.courseInfos[course_index][
                                                            'study_time_course'] -= 1
                                                        # 老师课表 加课
                                                        table_t.loc[
                                                            index_row_table, index_col_table] = course_name + '/' + student_group.name + ''
                                                        # 教室课表 加课
                                                        table_r.loc[
                                                            index_row_table, index_col_table] = course_name + '/' + student_group.name

                                                        break
                                            break

4.算法优化(选做)

本部分为选做:(1)可以使用蚁群算法等对排课算法进行优化,得到更优的排课方案;
(2)合理设计算法模块,使程序支持多种排课原则,比如按最短教学时间优先,(2)课程任务分布均匀优先(3)教师要求优先

#code

5.结果输出

(1)教师课表
(2)学生班级课表
(3)教室课表

#结果显示
clazz_name = (input("请输入班级名称:"))
print(clazz_name,":")
for clazz in student_groups:
    if clazz.name == clazz_name:
        display(clazz.table)
        
teacher_name = (input("请输入老师名称:"))
print("老师:",teacher_name)
for teacher in teachers:
    if teacher.name == teacher_name:
        display(teacher.table)

classroom_name = (input("请输入教室名称:"))
print("教室:",classroom_name)
for c in range(15):
    if str(classroom_info['名称'][c]) == classroom_name:
        display(classroom.table)
班级:大数据(本)20-1 :
周一周二周三周四周五
8:30~9:15数据仓库与数据挖掘/教师2/10209应用统计学/教师1/10207数据仓库与数据挖掘/教师2/10209应用统计学/教师1/10207
9:20~10:05数据仓库与数据挖掘/教师2/10209应用统计学/教师1/10207数据仓库与数据挖掘/教师2/10209操作系统原理/教师5/10515
10:25~11:10数据可视化分析/教师4/10407数据采集与网络爬虫/教师3/10210操作系统原理/教师5/10515
11:15~12:00数据可视化分析/教师4/10407数据采集与网络爬虫/教师3/10210
14:00~14:45数据可视化分析/教师4/10407
14:50~15:35数据可视化分析/教师4/10407
15:55~16:40操作系统原理/教师5/10515
16:45~17:30
老师: 教师1
周一周二周三周四周五
8:30~9:15应用统计学/班级:大数据(本)20-1应用统计学/班级:大数据(本)20-1
9:20~10:05应用统计学/班级:大数据(本)20-1
10:25~11:10Linux程序设计/班级:软件(本)19-34
11:15~12:00Linux程序设计/班级:软件(本)19-34
14:00~14:45Linux程序设计/班级:软件(本)19-34
14:50~15:35
15:55~16:40
16:45~17:30
教室: 10207
周一周二周三周四周五
8:30~9:15面向对象程序设计/班级:软件(本)21-34
9:20~10:05
10:25~11:10C语言程序设计应用/班级:软件(本)21-34
11:15~12:00
14:00~14:45
14:50~15:35
15:55~16:40
16:45~17:30

实验总结

  1. 知识总结:
    • set() 函数创建一个无序不重复元素集
    • for循环遍历列表
    • loc函数定位行列
    • random.shuffle将列表中的元素打乱顺序实现随机性,也可以使用data.reset_index(drop=True)
  2. 实验总结:
    • 因为学校排课的不合理,我们之前并没有具体从零学习过Python知识,对于Python很多基础知识都不太了解
    • 在学习数据分析时有接触过pandas库,在此次实验中加深了理解,并且在网上学习了dataframe的常用函数方法
    • 对有约束的极值求解算法有了初步掌握
    • 能力有限,没有实现算法优化
    • 代码量比较大,根据参考代码慢慢理清了思维逻辑
16:45~17:30

实验总结

  1. 知识总结:
    • set() 函数创建一个无序不重复元素集
    • for循环遍历列表
    • loc函数定位行列
    • random.shuffle将列表中的元素打乱顺序实现随机性,也可以使用data.reset_index(drop=True)
  2. 实验总结:
    • 因为学校排课的不合理,我们之前并没有具体从零学习过Python知识,对于Python很多基础知识都不太了解
    • 在学习数据分析时有接触过pandas库,在此次实验中加深了理解,并且在网上学习了dataframe的常用函数方法
    • 对有约束的极值求解算法有了初步掌握
    • 能力有限,没有实现算法优化
    • 代码量比较大,根据参考代码慢慢理清了思维逻辑
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值