简化大条件语句

Simplify huge conditional statement

提问人:Lu4 提问时间:2/1/2019 最后编辑:CommunityLu4 更新时间:2/15/2019 访问量:180

问:

抽象

生活中有时你的信号很嘈杂,你想从这里开始

enter image description here

对此

enter image description here

有许多现有的方法可以使数据平滑:局部线性和多项式回归,不同类型的移动平均线:

https://en.wikipedia.org/wiki/Kernel_smoother

https://homepages.inf.ed.ac.uk/rbf/HIPR2/gsmooth.htm

https://www.stat.wisc.edu/~mchung/softwares/hk/hk.html

https://matthew-brett.github.io/teaching/smoothing_intro.html

如何在numpy中有效地计算高斯核矩阵?

如何平滑 3D 体素世界的方块?

但是,我发现对于我的情况,最适合的方法是高斯核平滑。它在桌面上对我来说就像一个魅力,但当切换到移动设备时,由于计算要求高,算法使设备停滞不前。

其中一个原因是,在平滑之前,我必须将采样率与其他信号相等,这大大增加了采样率,从而增加了处理所需的数据量。

这也导致了这样一个事实,即高斯核的大小必须是数万个分量,这直接影响了算法的复杂性,对于我幼稚的方法来说,它需要滤波器中的数万个元素相乘,并与来自信号的数万个分量相乘和求和,以接收平滑数据的一个分量。

有一种方法可以有效地进行高斯核平滑,这需要使用傅里叶变换,这需要非常复杂才能有效实现。

因此,与其沿着这条路走,我认为你实际上可以更有效地进行平滑处理,而无需深入研究傅里叶变换的复杂性。

基本上,任何信号都只是按时间排序的货币对的集合。当使用线性插值进行插值时,它始终可以用多边形链表示,并且您实际上可以通过分析方式平滑多边的一个分量(即线段)。我不会深入探讨如何在解析定义的线段上实际计算解析定义的核的卷积积分。这里值得一提的是,结果是一个巨大的分段函数:[time, value]

enter image description here

这产生了一些陈述:if

public static Double Solution(Double x, Double w, Double x1, Double y1, Double x2, Double y2)
{
    Double result;

    if (x + w < x2 && w + x1 <= x)
    {
        result = (x * y1 - x2 * y1 - x * y2 + x1 * y2) / (x1 - x2);
    }
    else if (x1 < x + w && x < x1 && x + w < x2)
    {
        result = Math.Pow(w + x - x1, 2) * ((w + x + 2 * x1 - (3 * x2)) * y1 - (w + x - x1) * y2) * Math.Pow(w, -2) / (x1 - x2) / 6;
    }
    else if (x == x1 && x + w < x2)
    {
        result = y1 / 2 + w * (y1 - y2) / (x1 - x2) / 6;
    }
    else if (x + w < x2 && x1 < x && x < w + x1)
    {
        result = Math.Pow(w, -2) / (x1 - x2) * (Math.Pow(w, 3) * (y1 - y2) + 3 * w * w * (-x2 * y1 + x * (y1 - y2) + x1 * y2) - Math.Pow(x - x1, 2) * ((x + 2 * x1 - (3 * x2)) * y1 + (-x + x1) * y2) + 3 * w * (x - x1) * ((x + x1 - (2 * x2)) * y1 + (-x + x1) * y2)) / 6;
    }
    else if (x2 <= x + w && x < x1)
    {
        result = (x1 - x2) * (2 * y1 * x1 + x2 * y1 + x1 * y2 + 2 * x2 * y2 - 3 * w * (y1 + y2) - 3 * x * (y1 + y2)) * Math.Pow(w, -2) / 6;
    }
    else if (x2 <= x && w + x1 <= x && x < w + x2)
    {
        result = -Math.Pow(w - x + x2, 2) * ((w - x + x2) * y1 + (-w + x - 3 * x1 + (2 * x2)) * y2) * Math.Pow(w, -2) / (x1 - x2) / 6;
    }
    else if (x2 <= x && x < w + x1)
    {
        result = -(x1 - x2) * (2 * y1 * x1 + x2 * y1 + x1 * y2 + 2 * x2 * y2 + 3 * w * (y1 + y2) - 3 * x * (y1 + y2)) * Math.Pow(w, -2) / 6;
    }
    else if (x == x1 && (x + w == x2 && (x2 <= x && x + w < x1 && w + x2 <= x || x < w + x1) || x < w + x1 && x2 <= x + w && x < x2))
    {
        result = (-x1 + x2) * (3 * w * (y1 + y2) + (x1 - x2) * (y1 + 2 * y2)) * Math.Pow(w, -2) / 6;
    }
    else if (x < x2 && x2 <= x + w && w + x1 <= x)
    {
        result = Math.Pow(w, -2) / (x1 - x2) * (Math.Pow(w, 3) * (-y1 + y2) + 3 * w * w * (-x2 * y1 + x * (y1 - y2) + x1 * y2) + Math.Pow(x - x2, 2) * ((-x + x2) * y1 + (x - 3 * x1 + (2 * x2)) * y2) + 3 * w * (x - x2) * (-2 * x1 * y2 + x * (-y1 + y2) + x2 * (y1 + y2))) / 6;
    }
    else if (x < x2 && x2 <= x + w && x1 < x && x < w + x1)
    {
        result = Math.Pow(w, -2) / (x1 - x2) * (-2 * Math.Pow(x1, 3) * y1 + 3 * x1 * x1 * x2 * y1 + Math.Pow(x2, 3) * y1 - Math.Pow(x1, 3) * y2 - 3 * x1 * (x2 * x2) * y2 + 2 * Math.Pow(x2, 3) * y2 + 2 * Math.Pow(x, 3) * (-y1 + y2) - 3 * w * Math.Pow(x1 - x2, 2) * (y1 + y2) + 6 * x * x * (x2 * y1 - x1 * y2) + 3 * x * (2 * x1 * x2 * (-y1 + y2) + x1 * x1 * (y1 + y2) - (x2 * x2) * (y1 + y2))) / 6;
    }
    else
    {
        result = 0.0e0;
    }

    return result;
}

这是它的视觉外观:enter image description here

您还可以通过这些线段的平滑函数求和来组合这些线段

enter image description here

从而将计算复杂度降低到您拥有的点数:

问题

如果上面的语句看起来效率低下,并且存在数值稳定性问题。当定义的线段获得大数字时,结果会爆炸。我正在尝试处理这些问题,但这比我预期的要难。即使仔细地扩展方程,也会在计算中引入一些奇怪的错误。因此,我认为咨询 StackOverflow 是个好主意,可能会获得有关如何优化此语句并使其在数字上更加稳定的更多想法。x1,y1,x2,y2

先谢谢你,

C# 优化 boolean-logic boolean-expression

评论

4赞 AKX 2/1/2019
需要优化吗?当然,读起来很丑陋,但我只想添加一条评论,说“这是用<这里的工具>自动生成的,不要碰”
1赞 mjwills 2/1/2019
计算代表什么?为什么你觉得有必要简化它?你最好只向它添加注释(和有意义的参数名称)吗?
0赞 Damien_The_Unbeliever 2/1/2019
几乎可以肯定的是,您应该使用当前方程的数学简化来简化它,而不是试图简化生成的代码。
1赞 Fabio 2/1/2019
你为它写了测试吗?
1赞 Lu4 2/15/2019
@Gimly我在引擎盖下使用三角核密度,我已经尝试了高斯、矩形、余弦、sigmoid 和许多自定义变体,但并非所有变体都可用于此任务。应该注意的是,仅靠核密度函数对您没有帮助。它不会平滑和插值您的信号,但此功能可以。您只需将段插入其中,即可在您希望的任何时候获得流畅的输出。我只需要让它更强大、更稳定......

答: 暂无答案