You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Python实现整数参数复杂函数最小化,解决吉他调弦优化问题

最优解决方案推荐

你当前的场景参数搜索空间极小,完全不需要使用线性规划求解器,也不需要手动实现复杂优化算法,优先选择暴力枚举即可,实现成本最低,耗时也可以忽略。


方案1:暴力枚举(最适合当前场景)

你的5个偏移参数o1-o5如果取值范围是-5到5,总共有11^5=16万种左右的组合,现代CPU跑完所有组合不到1秒,直接遍历即可,代码示例如下:

import itertools
import numpy as np
from scipy import stats

# 和弦定义
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])
chords = np.array([d,bm, bm2, em, a7, d2, gm, g, a72, d3])

# 得分计算函数(已修正原代码中stats.mode的调用错误)
def scorechord(o1, o2, o3, o4, o5):
    newchords = np.empty([10,6])
    score=0
    for i in range(len(chords)):
        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)
        if imax-imin>4 and imin!=0 and imax!=0:
            score+=100
        # 原代码此处写的stats.mode(i[0])是错误的,i[0]是单个数值,求众数无意义
        if stats.mode(i, keepdims=True)[0][0]!=imin:
            score+=10
        for j in range(5):
            if not np.isnan(abs(i[j+1]-i[j])):
                score+=abs(i[j+1]-i[j])
    return score

# 定义参数取值范围,可根据你的实际需求调整
param_range = range(-5, 6)
best_score = float('inf')
best_params = None

# 遍历所有参数组合
for o1, o2, o3, o4, o5 in itertools.product(param_range, repeat=5):
    current_score = scorechord(o1, o2, o3, o4, o5)
    if current_score < best_score:
        best_score = current_score
        best_params = (o1, o2, o3, o4, o5)

print(f"最优调弦偏移:o1={best_params[0]}, o2={best_params[1]}, o3={best_params[2]}, o4={best_params[3]}, o5={best_params[4]}")
print(f"最优得分:{best_score}")

另外你之前PuLP代码里把每个参数的lowBound和upBound都设为了-5,相当于所有参数固定为常数,属于笔误,根据实际需求调整上面的param_range即可。


方案2:黑盒整数优化(适用于后续参数范围扩大的场景)

如果后续你增加了参数数量,或者参数范围扩大到暴力枚举效率太低,可以直接使用支持整数约束的黑盒优化工具,不需要改写你的目标函数,比如Scipy自带的differential_evolution:

from scipy.optimize import differential_evolution

# 每个参数的取值边界
bounds = [(-5, 5), (-5, 5), (-5, 5), (-5, 5), (-5, 5)]
# 指定所有参数都是整数
integrality = [True, True, True, True, True]

# 适配为接受单个数组入参的目标函数
def objective(params):
    o1, o2, o3, o4, o5 = params
    return scorechord(o1, o2, o3, o4, o5)

# 执行优化
result = differential_evolution(objective, bounds, integrality=integrality, seed=42)
print("最优调弦偏移:", result.x)
print("最优得分:", result.fun)

PuLP报错的原因说明

PuLP是线性规划求解器,仅支持线性的目标函数和约束,你的得分函数里包含求最值、求绝对值、条件判断等非线性逻辑,PuLP无法直接识别。如果要强制适配PuLP,需要用大量辅助变量和线性约束改写所有非线性逻辑,实现成本极高,对你的场景完全没有必要。

内容的提问来源于stack exchange,提问作者kciur

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 10:48:02