【问题标题】:Automatically reduce piecewise function components - Pyomo自动减少分段函数组件 - Pyomo
【发布时间】:2019-07-10 14:49:20
【问题描述】:

在 pyomo 中,我有一个通过 pyomo.environ.Piecewise 定义的分段线性约束。我不断收到类似

的警告
Piecewise component '<component name>' has detected slopes of consecutive piecewise segments to be within <tolerance> of one another. Refer to the Piecewise help documentation for information on how to disable this warning.

我知道我可以增加容差并消除警告,但我想知道如果两个连续斜率低于给定值,是否有一种通用方法(通过 Pyomo 或 numpy)来减少“段”的数量容忍度。

我显然可以自己实现这一点,但我想避免重新发明轮子。

【问题讨论】:

    标签: python numpy pyomo piecewise


    【解决方案1】:

    好的,这就是我想出的。绝对没有针对性能进行优化,但我的情况取决于几点。它还缺少对输入的更多验证(例如,x 已排序且唯一)。

    def reduce_piecewise(x, y, abs_tol):
        """
        Remove unnecessary points from piece-wise curve.
    
        Points are remove if the slopes of consecutive segments
        differ by less than `abs_tol`.
    
        x points must be sorted and unique.
        Consecutive y points can be the same though!
    
        Parameters
        ----------
        x : List[float]
            Points along x-axis.
        y : List[float]
        abs_tol : float
            Tolerance between consecutive segments.
    
        Returns
        -------
        (np.array, np.array)
            x and y points - reduced.
        """
        if not len(x) == len(y):
            raise ValueError("x and y must have same shape")
    
        x_reduced = [x[0]]
        y_reduced = [y[0]]
    
        for i in range(1, len(x) - 1):
            left_slope  = (y[i] - y_reduced[-1])/(x[i] - x_reduced[-1])
            right_slope = (y[i+1] - y[i])/(x[i+1] - x[i])
            if abs(right_slope - left_slope) > abs_tol:
                x_reduced.append(x[i])
                y_reduced.append(y[i])
    
        x_reduced.append(x[-1])
        y_reduced.append(y[-1])
    
        return np.array(x_reduced), np.array(y_reduced)
    

    这里有一些例子:

    >>> x = np.array([0, 1, 2, 3])
    >>> y = np.array([0, 1, 2, 3])
    >>> reduce_piecewise(x, y, 0.01)
    (array([0, 3]), array([0, 3]))
    
    >>> x = np.array([0, 1, 2, 3, 4, 5])
    >>> y = np.array([0, 2, -1, 3, 4.001, 5]) # 4.001 should be removed
    >>> reduce_piecewise(x, y, 0.01)
    (array([0, 1, 2, 3, 5]), array([ 0.,  2., -1.,  3.,  5.]))
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-08-07
      • 2021-08-04
      • 1970-01-01
      • 2020-05-11
      • 1970-01-01
      • 2019-03-15
      • 2020-03-29
      • 1970-01-01
      相关资源
      最近更新 更多