Created
June 18, 2024 16:32
-
-
Save apple-phi/f974c6ba72b6585746d6dd5ea79da2e3 to your computer and use it in GitHub Desktop.
Part II module selection heuristic
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[Area.Mechanical] | |
min = 4 | |
required = [{core = 4}] | |
core = """4A2 Computational Fluid Dynamics | |
4A3 Turbomachinery I | |
4A7 Aircraft Aerodynamics and Design | |
4A9 Molecular Thermodynamics | |
4A10 Flow Instability | |
4A12 Turbulence and Vortex Dynamics | |
4A13 Combustion and Engines | |
4B5 Quantum and Nano-technologies | |
4B13 Electronic Sensors and Instrumentation | |
4B19 Renewable Electrical Power | |
4C2 Designing with Composites | |
4C3 Advanced Functional Materials and Devices | |
4C4 Design Methods | |
4C5 Design Case Studies | |
4C6 Advanced Linear Vibrations | |
4C7 Random and Non-linear Vibrations | |
4C8 Vehicle Dynamics | |
4C9 Continuum Mechanics | |
4C11 Data-driven and Learning Based Methods in Mechanics and Materials | |
4D6 Dynamics in Civil Engineering | |
4D2 Advanced Structural Design | |
4F1 Control System Design | |
4G1 Mathematical Biology of the Cell | |
4G5 Materials and Molecules: Modelling, Simulation and Machine Learning | |
4G6 Cellular and Molecular Biomechanics | |
4I10 Nuclear Reactor Engineering | |
4I11 Advanced Fission and Fusion Systems | |
4I14 Biosensors and Bioelectronics | |
4M12 Partial Differential Equations and Variational Methods | |
4M16 Nuclear Power Engineering | |
4M17 Practical Optimization | |
4M19 Advanced Building Physics | |
4M22 Climate Change Mitigation | |
4M23 Electricity and Environment (TPE22) | |
4M24 Computational Statistics and Machine Learning""" | |
[Area.Energy] | |
min = 4 | |
required = [{core = 4}] | |
core = """4A2 Computational Fluid Dynamics | |
4A3 Turbomachinery | |
4A9 Molecular Thermodynamics | |
4A13 Combustion and Engines | |
4B19 Renewable Electric Power | |
4D13 Architectural Engineering | |
4I10 Nuclear Reactor Engineering | |
4I11 Advanced Fission and Fusion Systems | |
4M16 Nuclear Power Engineering | |
4M22 Climate Change Mitigation | |
4M23 Electricity and Environment""" | |
[Area.Aero] | |
min = 4 | |
required = [{core = 4}, {core=3, companion = 2}] | |
core = """4A2 Computational Fluid Dynamics | |
4A3 Turbomachinery I | |
4A4 Aircraft Stability and Control | |
4A7 Aircraft Aerodynamics and Design | |
4A9 Molecular Thermodynamics | |
4A10 Flow Instability | |
4A12 Turbulence and Vortex Dynamics | |
4A13 Combustion and Engines | |
4A15 Acoustics""" | |
companion = """4B13 Electronic Sensors and Instrumentation | |
4B23 Optical Fibre Communication | |
4B24 Radio frequency Systems | |
4C2 Designing with Composites | |
4C4 Design Methods | |
4C5 Design Case Studies | |
4C6 Advanced Linear Vibrations | |
4C7 Random and Non-linear Vibrations | |
4C9 Continuum Mechanics | |
4F1 Control System Design | |
4F2 Robust and Non-linear Control | |
4F3 An Optimisation Based Approve to Control | |
4M24 Computational Statistics and Machine Learning""" | |
[Area.Civil] | |
min = 4 | |
required = [{core = 4}] | |
core = """4C11 Data-driven and Learning Based Methods in Mechanics and Materials | |
4D2 Advanced Structural Design | |
4D4 Construction Engineering | |
4D5 Foundation Engineering | |
4D6 Dynamics in Civil Engineering | |
4D7 Concrete and Prestressed Concrete | |
4D9 Offshore Geotechnical Engineering | |
4D10 Structural Steelwork | |
4D13 Architectural Engineering | |
4D16 Construction Management | |
4M19 Advanced Building Physics | |
4M22 Climate Change Mitigation | |
4M24 Computational Statistics and Machine Learning""" | |
[Area.EEE] | |
min = 4 | |
required = [{core = 4}] | |
core = """4B2 Power Micro Electronics | |
4B5 Quantum and Nano-technologies | |
4B11 Photonic Systems | |
4B13 Electronic Sensors and Instrumentation | |
4B19 Renewable Electrical Power | |
4B23 Optical Fibre Communication | |
4B24 Radio Frequency Systems | |
4B25 Embedded Systems for the Internet of Things | |
4B27 Internet of Everything | |
4C3 Advanced Functional Materials and Devices | |
4F5 Advanced Information Theory and Coding | |
4I14 Biosensors and Bioelectronics""" | |
[Area.ICE] | |
min = 4 | |
required = [{core = 4}] | |
core = """4B23 Optical Fibre Communication | |
4B25 Embedded Systems for the Internet of Things | |
4C11 Data-driven and Learning Based Methods in Mechanics and Materials | |
4F1 Control System Design | |
4F2 Robust and Non-linear Control | |
4F3 An Optimisation Based Approach to Control | |
4F5 Advanced Information Theory and Coding | |
4F8 Image Processing and Image Coding | |
4F10 Deep Learning and Structured data | |
4F12 Computer Vision | |
4F13 Probabilistic Machine Learning | |
4F14 Computer Systems | |
4G10 Brain Machine Interfaces | |
4M17 Practical Optimization | |
4M21 Software Engineering and Design | |
4M24 Computational Statistics and Machine Learning | |
4M26 Algorithms and Data Structures""" | |
[Area.EIS] | |
min = 6 | |
required = [{core = 6}] | |
core = """4B2 Power micro electronics | |
4B5 Quantum and Nano-technologies | |
4B11 Photonic systems | |
4B13 Electronic sensors and instrumentation | |
4B19 Renewable electrical power | |
4B23 Optical Fibre Communication | |
4B24 Radio Frequency Systems | |
4B25 Embedded Systems for the Internet of Things | |
4B27 Internet of Everything | |
4C3 Advanced Functional Materials and Devices | |
4F1 Control system design | |
4F2 Robust and non-linear control | |
4F3 An Optimisation Based Approve to Control | |
4F5 Advanced Information Theory and Coding | |
4F8 Image processing and image coding | |
4F10 Deep Learning and Structured data | |
4F12 Computer vision | |
4F13 Probabilistic Machine learning | |
4F14 Computer systems | |
4G10 Brain Machine Interfaces | |
4M12 Partial differential equations and variational methods | |
4M17 Practical optimization | |
4M21 Software Engineering and Design | |
4M26 Algorithms and data structures""" | |
[Area.Control] | |
min = 4 | |
required = [{core = 4}] | |
core = """4A4 Aircraft stability and control | |
4B11 Photonic systems | |
4B13 Electronic sensors and instrumentation | |
4B24 Radio Frequency Systems | |
4B25 Embedded Systems for the Internet of Things | |
4B27 Internet of Everything | |
4C6 Advanced linear vibrations | |
4C7 Random and non-linear vibrations | |
4F1 Control system design | |
4F2 Robust and non-linear control | |
4F3 An Optimisation Based Approve to Control | |
4F5 Advanced Information Theory and Coding | |
4F8 Image processing and image coding | |
4F10 Deep Learning and Structured data | |
4F12 Computer vision | |
4F13 Probabilistic Machine learning | |
4G10 Brain Machine Interfaces | |
4M21 Software Engineering and Design""" | |
[Area.Bio] | |
min = 4 | |
required = [{core = 2}] | |
core = """4G1 Mathematical Biology of the Cell | |
4G3 Computational Neuroscience | |
4G5 Materials and Molecules: Modelling, Simulation and Machine Learning | |
4G6 Cellular and Molecular Biomechanics | |
4G7 Control and Molecular Biomechanics | |
4G9 Biomedical Engineering | |
4G10 Brain Machine Interfaces | |
4I14 Biosensors and Bioelectronics""" | |
companion = """4B13 Electronic Sensors and Instrumentation | |
4C4 Design Methods | |
4C5 Design Case Studies | |
4C9 Continuum Mechanics | |
4F8 Image Processing and Image Coding | |
4F12 Computer Vision | |
4F13 Probabilistic Machine Learning | |
4I8 Medical Physics""" | |
[Modules] | |
4A2 = {assumed = ["3A1", "3A3"], useful = []} | |
4A3 = {assumed = ["3A1", "3A3"], useful = []} | |
4A4 = {assumed = [], useful = []} | |
4A7 = {assumed = ["3A1", "3A3"], useful = []} | |
4A9 = {assumed = [], useful = ["3A1", "3A5"]} | |
4A10 = {assumed = ["3A1"], useful = []} | |
4A12 = {assumed = ["3A1"], useful = ["3A3"]} | |
4A13 = {assumed = [], useful = ["3A5", "3A6"]} | |
4A15 = {assumed = [], useful = []} | |
4B2 = {assumed = [], useful = ["3B3", "3B5"]} | |
4B5 = {assumed = ["3B5"], useful = []} | |
4B11 = {assumed = [], useful = ["3B6"]} | |
4B13 = {assumed = ["3B1"], useful = []} | |
4B19 = {assumed = ["3B3", "3B4", "3B6"], useful = []} | |
4B23 = {assumed = [], useful = ["3F4", "3B6"]} | |
4B24 = {assumed = ["3B1"], useful = []} | |
4B25 = {assumed = [], useful = ["3B2"]} | |
4B27 = {assumed = [], useful = []} | |
4C2 = {assumed = [], useful = []} | |
4C3 = {assumed = [], useful = ["3B5"]} | |
4C4 = {assumed = [], useful = []} | |
4C5 = {assumed = [], useful = ["4C4"]} | |
4C6 = {assumed = ["3C6"], useful = []} | |
4C7 = {assumed = [], useful = ["3C6"]} | |
4C8 = {assumed = [], useful = ["3C5", "3C6"]} | |
4C9 = {assumed = ["3C7"], useful = ["3D7"]} | |
4C11 = {assumed = ["3C7"], useful = ["3D7"]} | |
4D2 = {assumed = ["3D3", "3D4"], useful = []} | |
4D4 = {assumed = [], useful = ["3D1", "3D2", "4D16"]} | |
4D5 = {assumed = ["3D2"], useful = []} | |
4D6 = {assumed = [], useful = ["3D2", "3D4", "3D7"]} | |
4D7 = {assumed = ["2P8", "3D3"], useful = []} | |
4D9 = {assumed = ["3D2"], useful = []} | |
4D10 = {assumed = ["3D4"], useful = ["3D3"]} | |
4D13 = {assumed = [], useful = ["3D3", "3D4", "3D8"]} | |
4D16 = {assumed = [], useful = []} | |
4E1 = {assumed = [], useful = []} | |
4E3 = {assumed = [], useful = []} | |
4E5 = {assumed = [], useful = []} | |
4E6 = {assumed = [], useful = []} | |
4E11 = {assumed = [], useful = []} | |
4E12 = {assumed = [], useful = []} | |
4F1 = {assumed = [], useful = ["3F1", "3F2"]} | |
4F2 = {assumed = ["3F2"], useful = []} | |
4F3 = {assumed = [], useful = ["3F1", "3F2"]} | |
4F5 = {assumed = ["3F7"], useful = ["3F1", "3F4"]} | |
4F8 = {assumed = ["3F1"], useful = ["3F3", "3F7"]} | |
4F10 = {assumed = [], useful = ["3F1", "3F3", "3F8"]} | |
4F12 = {assumed = [], useful = []} | |
4F13 = {assumed = [], useful = ["3F3"]} | |
4F14 = {assumed = [], useful = []} # Assumes Part I Digital circuits and computing | |
4G1 = {assumed = [], useful = []} | |
4G3 = {assumed = [], useful = ["3G2", "3G3"]} | |
4G5 = {assumed = [], useful = []} | |
4G6 = {assumed = [], useful = ["3C7"]} | |
4G7 = {assumed = [], useful = ["3G1", "3G2", "3G3", "3F0"]} | |
4G9 = {assumed = [], useful = []} | |
4G10 = {assumed = [], useful = ["3M1", "3G3", "3F2", "3F8"]} | |
4I1 = {assumed = [], useful = []} | |
4I8 = {assumed = [], useful = ["3G4"]} | |
4I10 = {assumed = ["4M16"], useful = []} | |
4I11 = {assumed = ["4M16"], useful = []} | |
4I14 = {assumed = [], useful = ["3G3"]} | |
4M1 = {assumed = [], useful = []} | |
4M3 = {assumed = [], useful = []} | |
4M12 = {assumed = [], useful = []} | |
4M16 = {assumed = [], useful = []} | |
4M17 = {assumed = ["3M1"], useful = []} | |
4M19 = {assumed = ["3D8"], useful = []} | |
4M21 = {assumed = [], useful = []} | |
4M22 = {assumed = [], useful = []} | |
4M23 = {assumed = [], useful = []} | |
4M24 = {assumed = ["3F3", "3F8", "3M1"], useful = []} | |
4M26 = {assumed = [], useful = []} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import tomlkit as tk | |
import pulp | |
with open("data.toml") as f: | |
data = tk.load(f) | |
# Define the problem | |
prob = pulp.LpProblem("Maximize_Specializations", pulp.LpMaximize) | |
# Extract modules and specializations | |
modules = set() | |
specializations = {} | |
for area, details in data["Area"].items(): | |
core_modules = details["core"].split("\n") | |
companion_modules = ( | |
details.get("companion", "").split("\n") if "companion" in details else [] | |
) | |
modules.update(core_modules) | |
modules.update(companion_modules) | |
specializations[area] = { | |
"min": details["min"], | |
"required": details["required"], | |
"core": core_modules, | |
"companion": companion_modules, | |
} | |
# Variables | |
x = pulp.LpVariable.dicts("Module", modules, 0, 1, pulp.LpBinary) | |
y = pulp.LpVariable.dicts("Specialization", specializations.keys(), 0, 1, pulp.LpBinary) | |
# Variables for 3rd year modules | |
prev_modules = set() | |
for mod in modules: | |
prev_modules.update(data["Modules"][mod.split(" ")[0]]["assumed"]) | |
y_prev = pulp.LpVariable.dicts("PrevModule", prev_modules, 0, 1, pulp.LpBinary) | |
# Objective function | |
prob += ( | |
pulp.lpSum([y[spec] for spec in specializations]), | |
"Maximize the number of specializations", | |
) | |
# Constraints | |
for spec, details in specializations.items(): | |
min_modules = details["min"] | |
core_modules = details["core"] | |
companion_modules = details["companion"] | |
# Minimum total modules constraint | |
prob += ( | |
pulp.lpSum([x[mod] for mod in core_modules + companion_modules]) | |
>= min_modules * y[spec], | |
f"MinModules_{spec}", | |
) | |
# Additional required constraints | |
for req in details["required"]: | |
core_req = req.get("core", 0) | |
companion_req = req.get("companion", 0) | |
if core_req > 0: | |
prob += ( | |
pulp.lpSum([x[mod] for mod in core_modules]) >= core_req * y[spec], | |
f"CoreReq_{spec}_{core_req}", | |
) | |
if companion_req > 0: | |
prob += ( | |
pulp.lpSum([x[mod] for mod in companion_modules]) | |
>= companion_req * y[spec], | |
f"CompanionReq_{spec}_{companion_req}", | |
) | |
# Add the constraint to limit the total number of modules chosen to 8 | |
prob += pulp.lpSum([x[mod] for mod in modules]) <= 8, "MaxModules" | |
# Add constraints for assumed modules from the previous year | |
for mod in modules: | |
for assumed_mod in data["Modules"][mod.split(" ")[0]]["assumed"]: | |
prob += y_prev[assumed_mod] >= x[mod], f"Assumed_{mod}_{assumed_mod}" | |
# Add the constraint to select exactly 9 modules from the previous year | |
prob += pulp.lpSum([y_prev[mod] for mod in prev_modules]) == 9, "PrevModules" | |
# Solve the problem | |
prob.solve() | |
# Output the results | |
print("Status:", pulp.LpStatus[prob.status]) | |
for v in prob.variables(): | |
print(v.name, "=", v.varValue) | |
# Print the selected modules and specializations | |
selected_modules = [mod for mod in modules if x[mod].varValue == 1] | |
qualified_specializations = [spec for spec in specializations if y[spec].varValue == 1] | |
selected_prev_modules = [mod for mod in prev_modules if y_prev[mod].varValue == 1] | |
print("Selected Modules:", selected_modules) | |
print("Qualified Specializations:", qualified_specializations) | |
print("Selected Previous Year Modules:", selected_prev_modules) | |
# Print how each specialization's requirements are met | |
for spec in qualified_specializations: | |
print(f"Area.{spec}") | |
details = specializations[spec] | |
min_modules = details["min"] | |
core_modules = details["core"] | |
companion_modules = details["companion"] | |
# Check minimum total modules requirement | |
selected_modules_count = sum( | |
x[mod].varValue for mod in core_modules + companion_modules | |
) | |
print( | |
f" Minimum total modules ({min_modules}): {selected_modules_count} modules selected" | |
) | |
# Check additional requirements | |
for req in details["required"]: | |
core_req = req.get("core", 0) | |
companion_req = req.get("companion", 0) | |
if core_req > 0: | |
selected_core_modules = sum(x[mod].varValue for mod in core_modules) | |
print( | |
f" Core modules requirement ({core_req}): {selected_core_modules} core modules selected" | |
) | |
if companion_req > 0: | |
selected_companion_modules = sum( | |
x[mod].varValue for mod in companion_modules | |
) | |
print( | |
f" Companion modules requirement ({companion_req}): {selected_companion_modules} companion modules selected" | |
) | |
for mod in core_modules + companion_modules: | |
if x[mod].varValue == 1: | |
prerequisites = data["Modules"][mod.split(" ")[0]]["assumed"] | |
print(f" - {mod}" + (f" {prerequisites}" if prerequisites else "")) | |
import matplotlib.pyplot as plt | |
import numpy as np | |
modules = list(data["Modules"].keys()) | |
prev_modules = list(sorted(prev_modules)) | |
# Initialize the matrix for the table | |
matrix = np.zeros((len(modules), len(prev_modules))) | |
# Populate the matrix based on the relationships | |
for i, (mod_4, details_4) in enumerate(data["Modules"].items()): | |
for j, mod_3 in enumerate(prev_modules): | |
if mod_3 in details_4["assumed"]: | |
matrix[i, j] = 2 # assumed relationship | |
if mod_3 in details_4["useful"]: | |
matrix[i, j] = 1 # useful relationship | |
# Create the plot | |
fig = plt.figure(1) | |
ax = plt.subplot() | |
# Define the colors for the matrix | |
cmap = plt.cm.get_cmap("coolwarm", 3) | |
cax = ax.matshow(matrix.T, cmap=cmap) | |
ax = cax.axes | |
# Set the axis labels | |
ax.set_yticks(np.arange(len(prev_modules))) | |
ax.set_xticks(np.arange(len(modules))) | |
ax.set_yticklabels(prev_modules) | |
ax.set_xticklabels([m.split(" ")[0] for m in modules], rotation=90) | |
# Add a colorbar | |
# cbar = fig.colorbar(cax, ticks=[0, 1, 2]) | |
# cbar.ax.set_yticklabels(["No relation", "Assumed", "Useful"], rotation=90) | |
# Display the plot | |
# plt.subplots_adjust(left=0.2, right=0.8, top=0.8, bottom=0.2) | |
# plt.tight_layout() | |
plt.grid(True, linewidth=0.2) | |
plt.show() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment