[英]How to apply inequality constraints in Mystic
我正在嘗試使用 Mystic 最大化受不等式約束的目標,但我正在努力了解如何應用懲罰約束。 該問題是非凸的,涉及最大化目標,其中只有一個變量會發生變化 (x)。 我正在嘗試 Mystic,因為我聽說它適用於大規模優化,並且 x 是一個包含數百萬個項目(大小為 N)的一維數組。
有三個一維數組 a、b 和 c,它們都有 N 個值,(a 和 b 中的值在 0-1 之間)。 x 中的每一項都會大於 >= 0
def objective(x, a, b, c): # maximise
d = 1 / (1 + np.exp(-a * (x)))
return np.sum(d * (b * c - x))
def constraint(x, f=1000): # must be >=0
return f - x.sum()
bounds = [(0, None)]
我見過使用generate_penalty
和generate_constraint
函數的例子,並認為我可以使用以下方法實現約束,但沒有成功:
equations = """
1000 - np.sum(x) >= 0
"""
通常,任何有關如何應用懲罰約束或使用 Mystic 的建議的建議都會受到贊賞。 Github 上有很多例子,但很難看出哪一個適合借鑒。 我已經使用 SLSQP 實現了 Scipy 最小化的解決方案,但在所需的規模上它太慢了。
我認為您所問的問題類似於以下內容……盡管其中並沒有太多不等式約束——只有一個。 我沒有使用數百萬個項目......因為這會花費很多時間,並且可能需要進行大量的參數調整......但我在下面使用了 N=100。
import numpy as np
import mystic as my
N = 100 #1000 # N=len(x)
M = 1e10 # max of c_i
K = 1000 # max of sum(x)
Q = 4 # 40 # npop = N*Q
G = 200 # gtol
# arrays of fixed values
a = np.random.rand(N)
b = np.random.rand(N)
c = np.random.rand(N) * M
# build objective
def cost_factory(a, b, c, max=False):
i = -1 if max else 1
def cost(x):
d = 1. / (1 + np.exp(-a * x))
return i * np.sum(d * (b * c - x))
return cost
objective = cost_factory(a, b, c, max=True)
bounds = [(0., K)] * N
def penalty_norm(x): # < 0
return np.sum(x) - K
# build penalty: sum(x) <= K
@my.penalty.linear_inequality(penalty_norm, k=1e12)
def penalty(x):
return 0.0
# uncomment if want hard constraint of sum(x) == K
#@my.constraints.normalized(mass=1000)
def constraints(x):
return x
然后在運行腳本...
if __name__ == '__main__':
mon = my.monitors.VerboseMonitor(10)
#from pathos.pools import ThreadPool as Pool
#from pathos.pools import ProcessPool as Pool
#p = Pool()
#Powell = my.solvers.PowellDirectionalSolver
# use class-based solver interface
"""
solver = my.solvers.DifferentialEvolutionSolver2(len(bounds), N*Q)
solver.SetGenerationMonitor(mon)
solver.SetPenalty(penalty)
solver.SetConstraints(constraints)
solver.SetStrictRanges(*my.tools.unpair(bounds))
solver.SetRandomInitialPoints(*my.tools.unpair(bounds))
solver.SetTermination(my.termination.ChangeOverGeneration(1e-8,G))
solver.Solve(objective, CrossProbability=.9, ScalingFactor=.8)
result = [solver.bestSolution]
print('cost: %s' % solver.bestEnergy)
"""
# use one-line interface
result = my.solvers.diffev2(objective, x0=bounds, bounds=bounds, penalty=penalty, constraints=constraints, npop=N*Q, ftol=1e-8, gtol=G, disp=True, full_output=True, cross=.9, scale=.8, itermon=mon)#, map=p.map)
# use ensemble of fast local solvers
#result = my.solvers.lattice(objective, len(bounds), N*Q, bounds=bounds, penalty=penalty, constraints=constraints, ftol=1e-8, gtol=G, disp=True, full_output=True, itermon=mon)#, map=p.map)#, solver=Powell)
#p.close(); p.join(); p.clear()
print(np.sum(result[0]))
我還注釋掉了一些並行計算的使用,但很容易取消注釋。
我認為您可能需要非常努力地調整求解器才能找到此特定問題的全局最大值。 它還需要有足夠的並行元素……由於 N 的大小。
但是,如果您想使用符號約束作為輸入,您可以這樣做:
eqn = ' + '.join("x{i}".format(i=i) for i in range(N)) + ' <= {K}'.format(K=K)
constraint = my.symbolic.generate_constraint(my.symbolic.generate_solvers(my.symbolic.simplify(eqn)))
或者,對於軟約束(即懲罰):
penalty = my.symbolic.generate_penalty(my.symbolic.generate_conditions(eqn))
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.