Как я могу максимизировать функцию? - PullRequest
0 голосов
/ 12 апреля 2019

Как я могу максимизировать целевую функцию?

У меня есть список клиентов, и каждого из них можно «активировать» тремя различными способами.

n= 1000
df = pd.DataFrame(list(range(0,n)), columns = ['Customer_ID'])
df['A'] = np.random.randint(2, size=n)
df['B'] = np.random.randint(2, size=n)
df['C'] = np.random.randint(2, size=n)
df['check_somma'] = df['A']+df['B']+df['C']
for index, rows in df[df['check_somma'] == 0].iterrows():
    i = np.random.randint(3)
    if i == 0:
        df.loc[index,['A']]= 1
    if i == 1:
        df.loc[index,['B']]= 1
    if i == 2:
        df.loc[index,['C']]= 1
df['check_somma'] = df['A']+df['B']+df['C']
df['A_k'] = np.random.rand(n,1)
df['B_k'] = np.random.rand(n,1)
df['C_k'] = np.random.rand(n,1)
df['A_k'] = df['A_k'] * df['A']
df['B_k'] = df['B_k'] * df['B']
df['C_k'] = df['C_k'] * df['C']

Каждый клиент может бытьактивируется либо на «A», либо на «B», либо на «C», и только если логическое значение, относящееся к типу активации, равно 1.

На входе у меня есть счетчик окончательных активаций.es:

Target_A = 500
Target_B = 250
Target_C = 250

С этим кодом я хочу минимизировать расстояние между счетом реальной активации и входными данными.

A = LpVariable.dicts("A", range(0, n), lowBound=0, upBound=1, cat='Boolean')
B = LpVariable.dicts("B", range(0, n), lowBound=0, upBound=1, cat='Boolean')
C = LpVariable.dicts("C", range(0, n), lowBound=0, upBound=1, cat='Boolean')

prob = LpProblem("problem",LpMaximize)

#objective
prob += lpSum(A)+lpSum(B)+lpSum(C)

#constraints
prob += Target_A >= lpSum(A)
prob += Target_B >= lpSum(B)
prob += Target_C >= lpSum(C)

for idx in range(0, n):
    prob += A[idx] + B[idx] + C[idx] <= 1 #cant activate more than 1
    prob += A[idx] <= df['A'][idx] #cant activate if 0
    prob += B[idx] <= df['B'][idx] 
    prob += C[idx] <= df['C'][idx]

prob.solve() 

как я могу минимизировать расстояние от входного распределения(как показано в коде выше) и в то же время максимизировать вес активаций 'A_k', 'B_k', 'C_k'?

ps. Случайные значения в коде являются входными данными для оптимизатора ипредставлять возможность или не активировать клиента таким образом.Я могу связать клиента только с одним «путем», чтобы соблюдать конечную цель

1 Ответ

1 голос
/ 12 апреля 2019

Взяв код из здесь , вам нужно всего лишь изменить 1 строку: целевую функцию. Чтобы в первую очередь отдавать приоритет абсолютной разнице, и только в случае ничьей отдавать приоритет решению с большим весом, мы просто масштабируем разницу в целевой функции так, чтобы даже получение на 1 меньшую разницу было бы лучше, чем любое улучшение веса , Мы можем сделать это, масштабируя количество клиентов + 1, так как сумма весов никогда не может быть больше n.

Так что просто используйте старый код и измените целевую функцию на:

prob += (O1 + O2 + O3) * (n + 1) - lpSum([A[idx] * df['A_k'][idx] + B[idx] * df['B_k'][idx] + C[idx] * df['C_k'][idx] for idx in range(0, n)])

Теперь вам нужно вручную проверить переменные и их присвоение, чтобы узнать значение разницы, поскольку целевое решение представляет собой другую вещь.

...