Какой оптимизатор scipy мне следует использовать для решения задачи программирования полиномиальной цели? - PullRequest
0 голосов
/ 25 марта 2020

Lai, KK, Yu, L. & Wang, S. (2006, июнь). Оптимизация портфеля на основе средней дисперсии, асимметрии, эксцесса. В первых международных мульти-симпозиумах по компьютерным и вычислительным наукам (IMSCCS'06) (том 2, с. 292-297). IEEE.

P2-P5 1 : https://i.stack.imgur.com/0TWbr.png

[ P6] [2]: https://i.stack.imgur.com/WisD9.png

Я решил вышеупомянутые проблемы (P2-P6) отдельно с SLSQP, но понял, что решения, возможно, не были глобальным решением, так как SLSQP это локальный оптимизатор. Следовательно, я дал shgo снимок для P4, который не заканчивался ни в моем собственном терминале, ни в google colab (с использованием графического процессора) через 6-10 часов. Даже при установке параметров критерия остановки = {maxtime: 1} это не прекращалось для shgo. Может ли кто-нибудь сказать мне, что я сделал неправильно или предоставить мне альтернативные идеи / решатели? Я только начал читать документацию mysti c, и мой резервный план состоит в том, чтобы выполнить симуляцию Монте-Карло для догадок и найти оптимальный.

При этом код:

import os as os
path = os.path.dirname(os.path.realpath('__file__'))
from coskew import coskew
from cokurt import cokurt
from scipy.optimize import minimize, LinearConstraint, NonlinearConstraint, Bounds
from scipy.optimize import shgo
from scipy.optimize import differential_evolution
import numpy as np
import datetime

    def polynomial_goal_programming(l0, df):

        m3 = coskew(df)
        m4 = cokurt(df)

        # Step 1: Mathematical Optimization of Four Subproblems
        def obj_mean(weights):
            return -(np.sum(df.mean() * weights))

        def obj_var(weights):
            return np.dot(weights.T, np.dot(df.cov(), weights))   

        def obj_skew(weights):
            return -(np.dot(weights.T, np.dot(m3,np.kron(weights,weights))))

        def obj_kurt(weights):
            return np.dot(weights.T, np.dot(m4,np.kron(weights,np.kron(weights,weights))))

        def check_sum(weights):    
            '''
            Returns 0 if sum of weights is 1.0
            np.array(x[0]+x[1]+x[2]+x[3]+x[4]+x[5]+x[6]+x[7]+x[8]+x[9]+x[10]+x[11]-1)
            '''
            return np.sum(weights) - 1

        # Initial Guess (equal distribution)
        x0 = [1/len(df.columns)] * len(df.columns)

        # 0-1 bounds for each weight -> no short selling
        bounds = [(0, 1),] * len(df.columns) #float('inf')
        #bounds = Bounds([0.]* len(df.columns), [1.]* len(df.columns))

        # Constraints
        cons = ({'type':'eq','fun': check_sum})

        #lc = NonlinearConstraint(np.ones(len(df.columns)), lb=1, ub=1)

        # Sequential Least SQuares Programming (SLSQP) -> pgp_simulation 15k no difference 
        opt_mean = minimize(obj_mean,x0,method='SLSQP',bounds=bounds,constraints=cons)
        opt_var = minimize(obj_var,x0,method='SLSQP',bounds=bounds,constraints=cons)
        #opt_skew = minimize(obj_skew,x0,method='SLSQP',bounds=bounds,constraints=cons)
        time = datetime.timedelta(seconds=60)
        opt_skew = shgo(obj_skew,bounds=bounds,constraints=cons,options=({'maxtime':time}))
        #opt_skew = differential_evolution(obj_skew,bounds=bounds,constraints=(lc))
        opt_kurt = minimize(obj_kurt,x0,method='SLSQP',bounds=bounds,constraints=cons)
        #opt_kurt = shgo(obj_kurt,bounds=bounds,constraints=cons, n=1, iters=1)
        opt = (-opt_mean.fun, opt_var.fun, -opt_skew.fun, opt_kurt.fun)


        # Step 2: PGP
        args = opt + l0

        def obj(z0, a0,a1,a2,a3,a4,a5,a6,a7):
            return np.power(1+np.abs(z0[0]/a0),a4) \
                    + np.power(1+np.abs(z0[1]/a1),a5) \
                    + np.power(1+np.abs(z0[2]/a2),a6) \
                    + np.power(1+np.abs(z0[3]/a3),a7)

        def constraint1(z0, a0,a1,a2,a3,a4,a5,a6,a7):
            weights = z0[4:]
            return np.sum(df.mean() * weights) + z0[0] - a0

        def constraint2(z0, a0,a1,a2,a3,a4,a5,a6,a7):
            weights = z0[4:]
            return np.dot(weights.T, np.dot(df.cov(), weights)) - z0[1] - a1

        def constraint3(z0, a0,a1,a2,a3,a4,a5,a6,a7):
            weights = z0[4:]
            return np.dot(weights.T, np.dot(m3,np.kron(weights,weights))) + z0[2] - a2

        def constraint4(z0, a0,a1,a2,a3,a4,a5,a6,a7):
            weights = z0[4:]
            return np.dot(weights.T, np.dot(m4,np.kron(weights,np.kron(weights,weights)))) - z0[3] - a3

        def check_sum(z0, a0,a1,a2,a3,a4,a5,a6,a7):    

            '''
            Returns 0 if sum of weights is 1.0
            '''
            weights = z0[4:]
            return np.sum(weights) - 1

        # Initial Guess Goal and Weight Variables
        d0 = [0]*4

        # 0-1 bounds for each weight -> no short selling
        d0_bnds = [(0, 50)] * 4 #float('inf') 
        bnds = d0_bnds + bounds

        con1 = {'type':'eq','fun': constraint1, 'args':args}
        con2 = {'type':'eq','fun': constraint2, 'args':args}
        con3 = {'type':'eq','fun': constraint3, 'args':args}
        con4 = {'type':'eq','fun': constraint4, 'args':args}
        cons = {'type':'eq','fun': check_sum, 'args':args}

        multi_cons = (con1, con2, con3, con4, cons)
        opt_result = minimize(obj,d0+x0,args=args,method='SLSQP',bounds=bnds,constraints=multi_cons)
        #opt_result = shgo(obj,bounds=bnds,args=args,constraints=multi_cons,n=1,iters=1,options={maxtime:1}) 

        return opt_result
...