所以我的音乐学校举办了一个音乐节,让所有学生乐队一起演奏。由于有一些家庭成员跨越不同的乐队,我正在尝试创建一个解决方案来优化乐队的时间表 - 尽量减少有亲戚的乐队之间的时间总和。现在我想我已经找到了解决方案。不知道这是否是最好的,但看起来确实有效。现在我正在尝试找到更好的方式来呈现解决方案。
相关信息:
英语不是我的母语; 我不是程序员,我在下面的代码中所做的一切都是我过去 2 天能够学到的有关 python 的知识。
现在程序正在输出乐队 ID 的列表以及它们将执行的插槽。
有 2 个新的改进,我很想了解如何做:
在某些时候,不要定义频段数量 (n),而是从用户处获取频段列表,并进行一些计数来定义 (n) --(您将在第二点中理解原因);
不输出乐队 ID,而是输出乐队名称(从用户从第 1 点输入的列表中)
这会让它对我来说更加有趣且用户友好。
还有另一个改进,我将留到另一个时刻,因为现在我认为我无法理解(女巫将目标函数转换为我们从用户输入中获得的东西,而不是我手动完成,但是我什至不知道从哪里开始) Laszlo Hunyadi 帮助我完成了下面的代码。
这是我现在使用的代码:
from gekko import GEKKO
import numpy as np
m = GEKKO()
#variables and constrains
n = 10 #n of bands
s = 10 #n of slots to play
t = 25 #time in minutes one band spend on the stage
x = m.Array(m.Var,(n,s),value=0,lb=0,ub=1,integer=True) #matrix of all bands(rows) x slots (columns)
for j in range(s):
m.Equation(m.sum([x[i,j] for i in range(n)])<=1) #since this is the decision I made it binary and sum<=1 to 1 slot can only be ocupied by one band
for i in range(n):
m.Equation(m.sum([x[i,j] for j in range(s)])==1) #since this is the decision I made it binary and sum=1 to 1 band only ocuppie one slot
z = [k for k in range(1,s+1)] #array with slot index to use to calc time
w = z*x*t #time the band will perform ;; used in objetive function
#objective
#in this exemple the band (1,4) and the band (1,5) have a relationship, and so do (3,2) and (1,9), so the objetive function bellow will try to minimize the sum of the time between bands that have relationship
y = m.abs2(w.item(1, 4)-w.item(1, 5))+ m.abs2(w.item(3, 2)-w.item(1, 9))
m.Minimize(y)
#solver
m.options.SOLVER = 1
m.solve()
#prints the schedule
schedule = [(i+1, j+1) for i in range(n) for j in range(s) if x[i,j][0] == 1]
schedule.sort(key=lambda x: x[1])
for band, slot in schedule:
print(f"Band {band} is scheduled to play in slot {slot}")
为了获取乐队作为用户输入,我创建了
get_bands()
。它将提示用户输入名称并将它们存储在列表中。如果写入“done”,则列表已完成。
新创建的
get_relationships
提示用户输入具有关系的带对,并将它们作为元组存储在列表中。 格式如下:“band1 band2”。要完成元组列表,请写“done”。
从现在起
n
由用户输入的乐队名称的列表的长度确定。
from gekko import GEKKO
import numpy as np
def get_bands():
bands = []
print("Enter the band names (type 'done' to finish):")
while True:
band = input("Band name: ")
if band.lower() == 'done':
break
bands.append(band)
return bands
def get_relationships(bands):
relationships = []
print("Enter the relationships between the bands (format: 'band1 band2', type 'done' to finish):")
while True:
rel = input("Relationship: ")
if rel.lower() == 'done':
break
band1, band2 = rel.split()
relationships.append((band1, band2))
return relationships
def main():
bands = get_bands()
relationships = get_relationships(bands)
n = len(bands)
s = 10
t = 25
m = GEKKO()
x = m.Array(m.Var, (n, s), value=0, lb=0, ub=1, integer=True)
for j in range(s):
m.Equation(m.sum([x[i, j] for i in range(n)]) <= 1)
for i in range(n):
m.Equation(m.sum([x[i, j] for j in range(s)]) == 1)
z = [k for k in range(1, s + 1)]
times = [m.Intermediate(m.sum([x[i, j] * (j + 1) * t for j in range(s)])) for i in range(n)]
y = m.sum([m.abs2(times[bands.index(band1)] - times[bands.index(band2)]) for band1, band2 in relationships])
m.Minimize(y)
m.options.SOLVER = 1
m.solve(disp=True)
schedule = [(bands[i], j + 1) for i in range(n) for j in range(s) if x[i, j][0] == 1]
schedule.sort(key=lambda x: x[1])
for band, slot in schedule:
print(f"{band} is scheduled to play in slot {slot}")
if __name__ == "__main__":
main()