打开/关闭菜单
打开/关闭个人菜单
未登录
如果您进行任何编辑,您的IP地址会公开展示。

水域自动化笔记ST13血魔法

来自Seati Wiki
JesseM1024留言 | 贡献2024年9月6日 (五) 10:42的版本 (创建页面,内容为“== 超链接 == 占位符 == 调包 == <pre>import numpy as np from scipy.optimize import minimize import matplotlib.pyplot as plt from tqdm import tqdm</pre> == 参数计算函数 == <pre>def get_altar_cap(N_capacity=0, N_aug_capa=0, N_capa_lv2=0, N_aug_capa_lv2=0, base = 10000): '''N_capacity=0, N_aug_capa=0, N_capa_lv2=0, N_aug_capa_lv2=0, base = 10000, printing = True''' capacity = np.floor(base*(1+N_capacity*0.2+N_capa_lv2*0.4)*(1.075**N_aug_capa…”)
(差异) ←上一版本 | 最后版本 (差异) | 下一版本→ (差异)

超链接

占位符

调包

import numpy as np
from scipy.optimize import minimize
import matplotlib.pyplot as plt
from tqdm import tqdm

参数计算函数

def get_altar_cap(N_capacity=0, N_aug_capa=0, N_capa_lv2=0, N_aug_capa_lv2=0, base = 10000):
    '''N_capacity=0, N_aug_capa=0, N_capa_lv2=0, N_aug_capa_lv2=0, base = 10000, printing = True'''
    capacity = np.floor(base*(1+N_capacity*0.2+N_capa_lv2*0.4)*(1.075**N_aug_capa)*(1.1556228712619**N_aug_capa_lv2))
    #why aug cap 2 is so strange?
    return capacity

def get_altar_gtpct(N_acc = 0, N_acc_lv2 = 0, IFS_surge_num = 0, default = 20):
    '''N_acc = 0, N_acc_lv2 = 0, IFS_surge_num = 0, default = 20'''
    GTpCT = np.max([1,(default-N_acc-2*N_acc_lv2)])/(1+2*IFS_surge_num)
    return GTpCT

def get_altar_dislocIO(N_disloc = 0, N_disloc_lv2 = 0):
    return np.floor(20*(1.2**N_disloc*1.4**N_disloc_lv2))

def get_altar_dislocIOperGT(N_disloc = 0, N_disloc_lv2 = 0, GTperCT = 20):
    return np.floor(20*(1.2**N_disloc*1.4**N_disloc_lv2)) / GTperCT
    
def get_altar_IO(capacity = 10000, N_disloc = 0, N_disloc_lv2 = 0):
    IO = np.min([capacity/10, np.floor(20*(1.2**N_disloc*1.4**N_disloc_lv2))])
    return IO

def get_altar_IOperGT(capacity = 10000, N_disloc = 0, N_disloc_lv2 = 0, GTperCT = 20):
    IO = np.min([capacity/10, np.floor(20*(1.2**N_disloc*1.4**N_disloc_lv2))])
    return np.min([capacity/10, IO/GTperCT])

def get_altar_maxproc(max_rate = 50*5, N_speed = 0, N_speed_lv2 = 0):
    return max_rate * (1 + 0.2*N_speed + 0.4*N_speed_lv2)

最优化求解

对于altar_level = 5(五级祭坛),gear_lim = 108(强化符文数,若无则设为0)的祭坛,求解最大化的祭坛充能速率,满足不等式约束条件(>=0)与等式约束条件(==0)

在我的笔记本上N_init=10k时,计算时长约为14min,以下为求解足量强化符文数的代码与初始化。要注意,SLSQP方法是初始值敏感的,错误的初始估计会导致严重偏差的结果

altar_level = 5
gear_lim = 108
N_init = 10000

rune_slot = [0,4,28,56,108]
rune_limit = rune_slot[altar_level-1]

def target_func(x):
    return - get_altar_maxproc(N_speed = x[8], N_speed_lv2 = x[9])


ineq_cons = {'type': 'ineq',
             'fun' : lambda x: np.array([19-x[4]-2*x[5],
                                         rune_limit - np.sum(x),
                                         gear_lim - (x[2]+x[3]+x[5]+x[7]+x[9]),
                                         get_altar_IOperGT(capacity = get_altar_cap(N_capacity=x[0], N_aug_capa=x[1], 
                                                                                    N_capa_lv2=x[2], N_aug_capa_lv2=x[3]), 
                                                           N_disloc = x[4], N_disloc_lv2 = x[5],
                                                           GTperCT = get_altar_gtpct(N_acc = x[6], N_acc_lv2 = x[7], IFS_surge_num = 2) )
                                        - get_altar_maxproc(N_speed = x[8], N_speed_lv2 = x[9])
                                        ])}

eq_cons = {'type' : 'eq',
           'fun' : lambda x: np.array([np.sum(x) - rune_limit,
                                       x[2]+x[3]+x[5]+x[7]+x[9] - gear_lim,
                                       get_altar_dislocIOperGT(N_disloc = x[4], N_disloc_lv2 = x[5], 
                                                               GTperCT = get_altar_gtpct(N_acc = x[6], N_acc_lv2 = x[7], IFS_surge_num = 2))
                                       - get_altar_cap(N_capacity=x[0], N_aug_capa=x[1], N_capa_lv2=x[2], N_aug_capa_lv2=x[3]) / 10
                                       ])}



best_proc_rate = 0
float_solution = []
ava_count = 0
for i in tqdm(range(N_init), desc='SLSQP'):
    N_capacity = 0+1*np.random.rand()
    N_capa_lv2 = 10+5*np.random.rand()
    N_aug_capa = 0+1*np.random.rand()
    N_aug_capa_lv2 = 2+3*np.random.rand()
    N_disloc = 0+1*np.random.rand()
    N_disloc_lv2 = 10+10*np.random.rand()
    N_acc = 0+2*np.random.rand()
    N_acc_lv2 = 8+1*np.random.rand()
    N_speed = 0+1*np.random.rand()
    N_speed_lv2 = 108 - np.sum([N_capacity, N_aug_capa, N_capa_lv2, N_aug_capa_lv2,
                                N_disloc, N_disloc_lv2, N_acc, N_acc_lv2, N_speed])
    
    if i % 3 == 0 and len(float_solution)!=0:
        x0 = float_solution
    else:
        
        x0 = np.array([N_capacity, N_aug_capa, N_capa_lv2, N_aug_capa_lv2,
                       N_disloc, N_disloc_lv2, N_acc, N_acc_lv2, N_speed, N_speed_lv2])
    
    bounds = [(0, 108) for _ in range(len(x0))]  
    
    sol = minimize(target_func, x0, method='SLSQP', 
                   constraints=[eq_cons, ineq_cons], options={'maxiter': 10000, 'ftol': 1e-9, 'disp': False},
                   bounds=bounds)

    x = sol.x
    IO = get_altar_IOperGT(capacity = get_altar_cap(N_capacity=x[0], N_aug_capa=x[1],N_capa_lv2=x[2], N_aug_capa_lv2=x[3]), 
                           N_disloc = x[4], N_disloc_lv2 = x[5],
                           GTperCT = get_altar_gtpct(N_acc = x[6], N_acc_lv2 = x[7], IFS_surge_num = 2) )
    ava_solution = (-sol.fun <= IO)
    
    if -sol.fun > best_proc_rate and ava_solution:
        ava_count+=1
        float_solution = sol.x
        best_proc_rate = -sol.fun
        sol_opt = sol

对于无强化符文的最优解搜寻,需要将gear_lim设为0.1,使用如下初始化

    N_capacity = 7+2*np.random.rand()
    N_capa_lv2 = 0
    N_aug_capa = 0.5+1*np.random.rand()
    N_aug_capa_lv2 = 0
    N_disloc = 24+8*np.random.rand()
    N_disloc_lv2 = 0
    N_acc = 12+8*np.random.rand()
    N_acc_lv2 = 0
    N_speed = 108-N_capacity-N_aug_capa-N_disloc-N_acc
    N_speed_lv2 = 0

连续结果显示

代码格

x = sol_opt.x
IO = get_altar_IOperGT(capacity = get_altar_cap(N_capacity=x[0], N_aug_capa=x[1],N_capa_lv2=x[2], N_aug_capa_lv2=x[3]), 
                       N_disloc = x[4], N_disloc_lv2 = x[5],
                       GTperCT = get_altar_gtpct(N_acc = x[6], N_acc_lv2 = x[7], IFS_surge_num = 2) )

print(f"available rate: {ava_count / N_init*100} %")
print("Optimal Variables: ", sol_opt.x)
print("io: ", IO)
print("Maximum Value of the Objective Function: ", -sol_opt.fun)
print(sum(x))

样例输出

available rate: 0.1 %
Optimal Variables:  [ 0.38715085  0.30000646 10.48624571  2.16824612  0.43213499 12.72563799
  1.91935781  8.82011957  0.92436075 69.83673975]
io:  7372.1
Maximum Value of the Objective Function:  7279.892012605729
108.0

手动修改

要将SLSQP返回的浮点数结果转换为整数结果,可以写一格自动化代码,但是也可以手改,手动修改数组的元素运行代码看是否满足条件即可

代码格

x = [0,0, 4, 8, 0, 13, 1, 9, 0, 73]
print(sum(x))
print('cap', get_altar_cap(N_capacity=x[0], N_aug_capa=x[1],N_capa_lv2=x[2], N_aug_capa_lv2=x[3]))
print('io', get_altar_IOperGT(capacity = get_altar_cap(N_capacity=x[0], N_aug_capa=x[1],N_capa_lv2=x[2], N_aug_capa_lv2=x[3]), 
                       N_disloc = x[4], N_disloc_lv2 = x[5],
                       GTperCT = get_altar_gtpct(N_acc = x[6], N_acc_lv2 = x[7], IFS_surge_num = 2) ))

print('proc rate', get_altar_maxproc(N_speed = x[8], N_speed_lv2 = x[9]))

样例输出

108
cap 82699.0
io 7935.0
proc rate 7550.000000000001