通用线性分段查找表

时间:2010-07-01 21:52:06

标签: c# optimization lookup

我正在寻找一个通用的优化查找对象,该对象采用函数f(x)并使用x的范围和总体间隔的可配置参数创建线性分段近似。

显然这并不难写,但鉴于它对许多昂贵的函数(触发,产量,距离)很有用,我认为通用的可能已经存在。请告诉我。

另一个有用的功能是序列化/反序列化查找表,因为相当精确的100,000点+表可能需要几分钟才能构建。

1 个答案:

答案 0 :(得分:4)

我不相信.NET类库中存在任何直接的东西。第三方库中可能存在某些内容(like C5 perhaps)。

创建可接受范围的函数的泛型版本在C#中有点棘手,因为没有统一类型或接口提供算术运算符。然而,通过一些创造力,可以制作一些东西:

// generic linear lookup class, supports any comparable type T
public class LinearLookup<T>  where T : IComparable<T>
{
    private readonly List<T> m_DomainValues = new List<T>();

    public LinearLookup( Func<T,T> domainFunc, Func<T,T> rangeFunc, 
          T lowerBound, T upperBound )
    {
        m_DomainValues = Range( domainFunc, rangeFunc, 
                                lowerBound, upperBound )
                           .ToList();
    }

    public T Lookup( T rangeValue )
    {
        // this could be improved for numeric types
        var index = m_DomainValues.BinarySearch( rangeValue );
        if( index < 0 )
            index = (-index)-1;
        return m_DomainValues[index];
    }

    private static IEnumerable<T> Range( Func<T,T> domainFunc, 
         Func<T,T> rangeFunc, T lower, T upper )
    {
        var rangeVal = lower;
        do
        {
            yield return domainFunc( rangeVal );

            rangeVal = rangeFunc( rangeVal );

        } while( rangeVal.CompareTo( upper ) < 0 );
    }
}

此类将在[lower,upper>>范围内预先计算函数domainFunc的一组域值。它使用二进制搜索进行查找 - 允许使用任何类似类型的折衷方案 - 不仅仅是以数字类型构建。函数rangeFunc允许增量由外部代码控制。因此,这是Math.Sin在{0,PI / 2>范围内的线性查找。增量为0.01:

var sinLookup = new LinearLookup( Math.Sin, x => x + 0.01d, 0, Math.PI/2 );
var lookupPI4 = sinLookup[Math.PI/4]; // fetch the value sin(π/4)