使用python最小化整数参数的复杂函数?

2024-06-26 14:45:20 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图找到一种方法来优化特定和弦的吉他调音,以更好地适应一只手,而我在实际的优化部分遇到了一些麻烦。下面是我的代码的开始,我的目标函数定义了一个“分数”,与单手弹奏每个和弦的效果相关:

# defining chords by string and fret
d=np.array([5,7,7,4,5,np.nan])
bm=np.array([7,7,7,np.nan,5,7])
bm2=np.array([7,7,8,np.nan,6,7])
em=np.array([7,8,9,5,7,np.nan])
a7=np.array([5,5,6,5,0,np.nan])
d2=np.array([5,7,7,7,9,np.nan])
gm=np.array([6,8,7,8,10,np.nan])
g=np.array([7,8,7,np.nan,2,3])
a72=np.array([5,5,6,2,4,np.nan])
d3=np.array([5,7,7,7,5,np.nan])

#array of all chords
chords = np.array([d,bm, bm2, em, a7, d2, gm, g, a72, d3])

#objective function
def scorechord(o1, o2, o3, o4, o5):
    """
    shift strings 1-5 by amounts o1-o5
    positive number indicates string has been tuned down one half step
    returns a number associated with best chord structures for hand
    """
    newchords = np.empty([10,6])
    score=0
    for i in range(len(chords)):
        #shift notes on string by offset amount
        newchords[i][0]=chords[i][0]+o1
        newchords[i][1]=chords[i][1]+o2
        newchords[i][2]=chords[i][2]+o3
        newchords[i][3]=chords[i][3]+o4
        newchords[i][4]=chords[i][4]+o5
        newchords[i][5]=chords[i][5]
    for i in newchords:
        imin=np.nanmin(i)
        imax=np.nanmax(i)
        #want max/min fret close enough for hand
        if imax-imin>4 and imin!=0 and imax!=0:
            score+=100
        #best place to bar chord is lowest note
        if stats.mode(i[0])[0]!=imin:
            score+=10
        #want notes to overall be close together
        for j in range(5):
            if np.isnan(abs(i[j+1]-i[j]))==False:
                score+=abs(i[j+1]-i[j])
    return score

我会使用scipy优化,但不能将其限制为整数值;我尝试了使用纸浆,但在将Lp变量传递到函数中时遇到了问题。据我所知,您通常应该显式地编写函数,而不是调用它来解决该问题,但我不知道如何使用如此复杂的函数来实现这一点(我也开始担心,即使我让它工作起来,这个函数也可能无法解决)

这是一次尝试:

Lp_prob = p.LpProblem('Problem', p.LpMinimize)

o1=p.LpVariable("o1", lowBound = -5, upBound = -5)
o2=p.LpVariable("o2", lowBound = -5, upBound = -5)
o3=p.LpVariable("o3", lowBound = -5, upBound = -5)
o4=p.LpVariable("o4", lowBound = -5, upBound = -5)
o5=p.LpVariable("o5", lowBound = -5, upBound = -5)

Lp_prob += scorechord(o1,o2,o3,o4,o5)

返回错误“float()参数必须是字符串或数字,而不是“LpAffineExpression”

我不知道该怎么做——有没有另一种方式来写出我的功能,纸浆将能够理解它,或者另一个包来考虑尝试?或者,是时候全力以赴,亲手编写一个优化函数了


Tags: 函数fornpnanarrayscorechordso2