【问题标题】:How to apply inequality constraints in Mystic如何在 Mystic 中应用不等式约束
【发布时间】:2020-03-29 06:02:58
【问题描述】:

我正在尝试使用 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_penaltygenerate_constraint 函数的示例,并认为我可以使用以下方法实现约束,但没有成功:

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

一般来说,任何关于如何应用惩罚约束的建议或使用 Mystic 的建议都将不胜感激。 Github 上有很多例子,但很难看出哪一个适合借鉴。我已经使用 SLSQP 实现了 Scipy 最小化的解决方案,但它在所需的规模上太慢了。

【问题讨论】:

    标签: python-3.x optimization non-convex mystic


    【解决方案1】:

    我认为您要问的问题类似于以下内容...尽管其中并没有太多的不平等约束-只有一个。我没有使用数百万个项目...因为这会花费很多时间,并且可能需要进行很多参数调整...但我在下面使用了 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))
    

    【讨论】:

    猜你喜欢
    • 2021-08-06
    • 2023-02-22
    • 2023-03-16
    • 2019-04-10
    • 1970-01-01
    • 2014-04-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多