bar*_*ssa 16 python optimization combinations numbers mathematical-optimization
有三个整数x,y并且z(每个> = 1)和给定的上限整数n<10 ^ 6.还有,n = x + y + z和output = cos(x) + cos(y) + cos(z).
练习是最大化output.
我为此编写了一个简单的脚本,但时间复杂度为O(n ^ 3).有什么方法可以简化这个吗?
from math import cos
n = 50
x = 1
y = 1
z = 1
total = cos(x) + cos(y) + cos(z)
for x in xrange(n):
for y in xrange(n):
for z in xrange(n):
if x + y + z == n:
temp = cos(x) + cos(y) + cos(z)
if temp > total: total = temp
print round(total, 9)
Run Code Online (Sandbox Code Playgroud)
fug*_*ede 13
正如Jean-FrançoisFabre在评论中指出的那样,你可以用很多技巧来提高性能,但首先
a和b确定的价值c,a小于或等于N/3,b并在1和之间c绑定ba(N - a)//2 + 1),那么否则brutforcy解决方案会相对快速地终止cos(a)(因此也适用于任何给定的N = 500):
import numpy as np
from numba import jit
@jit
def maximize(N):
cos = np.cos(np.arange(N))
m = -3
for a in range(1, N//3 + 1):
cosa = cos[a]
if m - 2 > cosa:
continue
for b in range(a, (N - a)//2 + 1):
c = N - a - b
res = cosa + cos[b] + cos[c]
if res > m:
m = res
bestabc = (a, b, c)
return m, bestabc
maximize(1000000) # (2.9787165245899025, (159775, 263768, 576457))
Run Code Online (Sandbox Code Playgroud)
理想情况下,您只想计算一次可能的组合.忽略几何属性cos,并将其视为从数字到数字的简单映射(例如,将其用作随机属性,如@Jean在其第二条评论中所述).
首先,你必须意识到,在挑选了2个数字之后,第三个被给出.你可以选择'智能'来避免多余的选择:
from math import cos
import time
import numpy as np
from numba import jit
def calc(n):
x = 1
y = 1
z = 1
total = cos(x) + cos(y) + cos(z)
for x in range(n, int((n/3 - 1)),-1): #I only want to pick X from n-2 to n/3 -1 , after that we will repeat.
cosx = cos(x)
for y in range(max(int(((n-x)/2))-1,1),min(int(n-x),int(n/3))): #I would only pick number that will not be choosen for the z
z = n-x-y #Infer the z, taking the rest in account
temp = cosx + cos(y) + cos(z)
if temp > total: total = temp
return total
tic = time.clock()
total = calc(10000)
print(time.clock()-tic)
print (total)
Run Code Online (Sandbox Code Playgroud)
将1.3467099999999999(在我的机器上).
正如@fuglede所提到的,使用numba进行进一步优化是值得的.
编辑:
保存所有以前计算的cos值更实际,然后重新计算它们,当你访问np数组时,你不是简单地访问内存中的一个点,而是使用ndarray函数.使用python内置cos实际上更快:
import numpy as np
from math import cos
import time
import timeit
cos_arr = np.cos(np.arange(10000000))
tic = time.time()
def calc1():
total = 0
for j in range(100):
for i in range(10000000):
total += cos_arr[i]
def calc2():
total = 0
for j in range(100):
for i in range(10000000):
total += cos(i)
time1 = timeit.Timer(calc1).timeit(number=1)
time2 = timeit.Timer(calc2).timeit(number=1)
print(time1)
print(time2)
Run Code Online (Sandbox Code Playgroud)
随着输出:
127.9849290860002
108.21062094399986
Run Code Online (Sandbox Code Playgroud)
如果我在计时器内移动数组创建,它甚至更慢.
| 归档时间: |
|
| 查看次数: |
712 次 |
| 最近记录: |