2010-07-01 9 views
5

Estoy buscando un objeto genérico de búsqueda optimizado que adopta una función f (x) y crea una aproximación lineal por partes con parámetros configurables para el rango de xy los intervalos de población.Generic Linear Piecewise Lookup Table

Obviamente esto no es difícil de escribir, pero dado que es útil para muchas funciones costosas (trigonometría, rendimiento, distancia), pensé que podría existir una genérica. Por favor hagamelo saber.

Otra característica útil sería serializar/deserializar la tabla de búsqueda, ya que una tabla bastante precisa de 100.000 puntos + puede tardar varios minutos en construirse.

+0

¿Cómo sabe 100.000 es suficiente? ¿demasiado? o muy poco? Tendrá que caracterizar la función que está aproximando y hacer que la implementación funcione bien para esas características. http://en.wikipedia.org/wiki/Approximation_theory – rwong

Respuesta

4

No creo que exista nada en las librerías de clases .NET directamente. Algo puede existir en una biblioteca de terceros (like C5 perhaps).

Crear una versión genérica de una función que pueda aceptar rangos es un poco complicado en C#, ya que no existe un tipo unificador o interfaz que proporcione operadores aritméticos. Sin embargo, con un poco de creatividad, es posible diseñar algo:

// 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); 
    } 
} 

Esta clase calcular previamente un conjunto de valores del dominio de la función domainFunc sobre el rango [inferior, superior>. Utiliza la búsqueda binaria para la búsqueda, un compromiso que permite utilizar cualquier tipo comparable, no solo construido en tipos numéricos. La función rangeFunc permite que el incremento sea controlado por un código externo. Por lo tanto, aquí hay una búsqueda lineal para Math.Sin sobre el rango [0, PI/2> con un incremento de 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)