【问题标题】:How to optimise the code considering different input sizes?如何考虑不同的输入大小优化代码?
【发布时间】:2019-10-18 13:01:52
【问题描述】:

我想以最有效的方式计算蒸汽属性,考虑标量、向量和矩阵作为两个参数的输入选项。我担心的是,我必须使用 if 块相对于输入(标量、向量或矩阵)的大小,使代码变得很长。我是一个简单的机械工程师,对 python 很陌生,任何关于如何优化代码的帮助都非常感谢。这是代码:

from iapws.iapws97 import _Region4
import numpy as np

def h_x(P,x): 
    ''' spec enthalpy in liquid, steam and wet (two-phase flow) regions
    P - pressure in bar
    x - drayness steam fraction [-]
    h - specific heat of wet region returned [kJ/kW]
    '''

    mm = len(np.shape(x))
    if mm == 0:
        h_  = _Region4(P/10,0)['h'] 
        h__ = _Region4(P/10,1)['h'] 
        # return h_ + x * (h__ - h_)
        return h_ + x * (h__ - h_)        
    elif mm == 1:
        return np.array([ _Region4(i/10,0)['h'] + j * ( _Region4(i/10,1)['h'] - _Region4(i/10,0)['h'] ) for i,j in zip(P,x) ])    
    elif mm == 2:
        mmm,nnn = x.shape
        h     = np.ndarray(shape=(mmm,nnn)) #(mm,nn)
        for i in range(mmm):
            for j in range(nnn):
                h_  = _Region4(P[i,j]/10,0)['h']
                h__ = _Region4(P[i,j]/10,1)['h']
                h[i,j]   = h_ + x[i,j] * (h__ - h_)
        return h        
    else:
        print('h_x input must be scalar, vector or 2D matrix!')

# code testing
P = np.array([[.0234,.0193,0.244],[.0244,.0185,0.254]])
x = np.array([[.812,.782,.620],[.912,.882,.820]])
h_x(P,x)

【问题讨论】:

  • 我不知道效率,但代码方面...我会将所有内容转换为 2D 矩阵...因此计算代码将是一个块。 scalar -> [[ scalar ]], [ scalar1, scalar1 ] - > [[[ scalar1, scalar1 ]]

标签: python python-3.x performance optimization


【解决方案1】:

你真的只做一种计算,但用两种不同的方式。您可以使用内置的map 将其拉出并将其应用于函数作为输入的任何内容。如果失败了,那么你有一个单一的(不可迭代的)值,你可以直接应用你的计算。

# Define a dummy func to make code work
def _Region4(a, b):
    return {'h': a + 3 * b}

import numpy as np

def calculate(P, x):
    '''
    Spec enthalpy in liquid, steam and wet (two-phase flow) regions
    P - pressure in bar
    x - drayness steam fraction [-]
    h - specific heat of wet region returned [kJ/kW]
    '''
    h_  = _Region4(P/10,0)['h'] 
    h__ = _Region4(P/10,1)['h'] 
    return h_ + x * (h__ - h_) 

def h_x(P,x):
    shape = np.shape(x)
    dimensions = len(shape)
    # Check for wrong input
    if dimensions > 2:
        raise ValueError('h_x input must be scalar, vector or 2D matrix!')
    # Try a general mapping
    try:
        return np.array(list(map(calculate, P.flat, x.flat))).reshape(shape)
    # if it fails then you got a pair of scalar
    except AttributeError:
        return calculate(P, x)

P = np.array([[.023,.23,.05],[.023,.23,.05]])
x = np.array([[.92,.98,.99],[.92,.98,.99]])
print(h_x(P, x))
"""
Out:
    [[2.7623 2.963  2.975 ]
    [2.7623 2.963  2.975 ]]
"""
print(h_x(3, 4))
"""
Out:
    12.3
"""

【讨论】:

  • 谢谢,正在使用您的代码。如果输入是标量和向量,例如P = np.array([.023,.23,.05]) x = np.array([.92,.98,.99]) 代码工作正常计算输出没有错误。如果输入是矩阵,例如P = np.array([[.023,.23,.05],[.023,.23,.05]]) x = np.array([[.92,.98,.99],[. 92,.98,.99]]) 它抛出错误: ValueError: 具有多个元素的数组的真值不明确。使用 a.any() 或 a.all() 这与我在 i 和 j 上的两个 for 循环中避免的错误相同,最终使代码变得很长。也许还有其他想法?谢谢。
  • 我找到了 numpy vars 的这个 .flat 属性。所以这很好用: mm,nn = P.shape hh=np.array(list(map(calculate, P.flat, x.flat))) # .flat 变量遍历所有数组元素 hh=np.reshape( hh,(mm,nn))
  • 我想我已经明白了。似乎可以将标量、向量和矩阵打包成一行,即 np.array(list(map(calculate,P.flat,x.flat) )).reshape(P.shape) 其中 .flat 使输入变平然后 .reshape(P.shape) 产生与输入参数相同的结果。重要的是参数 (P,x) 被定义为 np.array()。在这种情况下,标量也具有 iter 属性并被 map() 接受,因此不需要 len(np.shape(x)) 和 np.reshape() 行。
  • 对我来说,它适用于二维阵列,无需展平和重塑。我将添加我正在使用的完整代码供您查看。
  • 我明白为什么它会为你打破,你的 flatten 解决方案是正确的。我对 _Region4 使用了一个虚拟方法,但你的方法对数据做了其他事情并且它中断了。用该信息更新了答案中的代码,它应该可以工作。
猜你喜欢
  • 1970-01-01
  • 2018-05-22
  • 1970-01-01
  • 2016-05-12
  • 1970-01-01
  • 1970-01-01
  • 2021-03-09
  • 1970-01-01
  • 2012-07-28
相关资源
最近更新 更多