计划优化问题试图以更好的方式呈现解决方案 - Python / Gekko

问题描述 投票:0回答:1

所以我的音乐学校举办了一个音乐节,让所有学生乐队一起演奏。由于有一些家庭成员跨越不同的乐队,我正在尝试创建一个解决方案来优化乐队的时间表 - 尽量减少有亲戚的乐队之间的时间总和。现在我想我已经找到了解决方案。不知道这是否是最好的,但看起来确实有效。现在我正在尝试找到更好的方式来呈现解决方案。

相关信息:

英语不是我的母语; 我不是程序员,我在下面的代码中所做的一切都是我过去 2 天能够学到的有关 python 的知识。

现在程序正在输出乐队 ID 的列表以及它们将执行的插槽。

有 2 个新的改进,我很想了解如何做:

  1. 在某些时候,不要定义频段数量 (n),而是从用户处获取频段列表,并进行一些计数来定义 (n) --(您将在第二点中理解原因);

  2. 不输出乐队 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}")
python optimization linear-programming gekko
1个回答
0
投票

为了获取乐队作为用户输入,我创建了

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()
© www.soinside.com 2019 - 2024. All rights reserved.