如何在Mystic中应用不平等约束 [英] How to apply inequality constraints in Mystic

查看:128
本文介绍了如何在Mystic中应用不平等约束的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用Mystic将不平等约束下的目标最大化,但是正在努力寻找如何应用惩罚约束的方法.问题是非凸性的,涉及最大化只有一个变量将要变化的目标(x).我正在尝试Mystic,因为我听说它对于大规模优化非常有用,并且x是一个包含数百万个项目(大小为N)的一维数组.

I'm trying to maximise an objective subject to an inequality constraint using Mystic but am struggling to see how to apply the penalty constraints. The problem is non-convex and involves maximising the objective where there is only one variable that will be changing (x). I'm trying Mystic because I've heard that it is good for large scale optimisation, and x is a 1D array contain millions of items (size N).

存在三个由数字a,b和c组成的一维数组,每个数组都具有N个值(a和b中的值在0-1之间). x中的每个项目都将大于> = 0

There are three 1-D arrays of numbers a, b, and c all with N number of values, (the values in a and b are between 0-1). Each item in x will be greater >= 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_penaltygenerate_constraint函数的示例,并认为我可以使用以下内容来实现约束,但未成功:

I've seen examples where the generate_penalty and generate_constraint functions are used and thought I could implement the constraint using the following, but it was unsuccessful:

equations = """
1000 - np.sum(x) >= 0
"""

通常,任何有关如何应用惩罚约束的建议或通常使用Mystic的建议都将受到赞赏. Github上有很多示例,但是很难看出其中哪一个是合适的.我已经使用SLSQP使用Scipy Minimum实现了一个解决方案,但是在所需的规模上它太慢了.

Generally any advice on how to apply the penalty constraints or advice with using Mystic generally would be appreciated. There are lots of examples on Github but it's difficult to see which of them would be appropriate to draw from. I've implemented a solution with Scipy minimise using SLSQP but it is too slow at the scale required.

推荐答案

我认为您要提出的问题看起来类似于以下内容……尽管其中实际上并没有太多的不平等约束,而仅仅是一个.我没有使用数百万个项目...这将花费很多时间,并且可能需要进行大量的参数调整...但是我在下面使用了N = 100.

I think the problem you are asking looks something like the following... although there's not really too many inequality constraints in it -- just one. I'm not using millions of items... as that would take a lot of time, and probably a good bit of parameter tuning... but I used N=100 below.

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]))

我也评论了并行计算的一些用法,但是很容易取消注释.

I've also commented out some use of parallel computing, but it's easy to uncomment.

我认为您可能必须非常努力地调整求解器,才能找到该特定问题的全局最大值.由于N的大小,它还需要有足够的并行元素.

I think you might have to work pretty hard tuning the solver to get it to find the global maximum for this particular problem. It also needs to have enough parallel elements... due to the large size of N.

但是,如果您想使用符号约束作为输入,则可以这样做:

However, if you wanted to use symbolic constraints as an input, you'd do it like this:

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)))

或者,对于软约束(即惩罚):

or, for the soft constraint (i.e. penalty):

penalty = my.symbolic.generate_penalty(my.symbolic.generate_conditions(eqn))

这篇关于如何在Mystic中应用不平等约束的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆