Note that there are some explanatory texts on larger screens.

plurals
  1. POC# Memoization of functions with arbitrary number of arguments
    text
    copied!<p>I'm trying to create a memoization interface for functions with arbitrary number of arguments, but <strike>I'm failing miserably</strike> I feel like my solution is not very flexible. I tried to define an interface for a function which gets memoized automatically upon execution and each function will have to implement this interface. Here is an example with a two parameter Exponential Moving Average function:</p> <pre><code>class EMAFunction:IFunction { Dictionary&lt;List&lt;object&gt;, List&lt;object&gt;&gt; map; class EMAComparer : IEqualityComparer&lt;List&lt;object&gt;&gt; { private int _multiplier = 97; public bool Equals(List&lt;object&gt; a, List&lt;object&gt; b) { List&lt;object&gt; aVals = (List&lt;object&gt;)a[0]; int aPeriod = (int)a[1]; List&lt;object&gt; bVals = (List&lt;object&gt;)b[0]; int bPeriod = (int)b[1]; return (aVals.Count == bVals.Count) &amp;&amp; (aPeriod == bPeriod); } public int GetHashCode(List&lt;object&gt; obj) { // Don't compute hash code on null object. if (obj == null) { return 0; } List&lt;object&gt; vals = (List&lt;object&gt;) obj[0]; int period = (int) obj[1]; return (_multiplier * period.GetHashCode()) + vals.Count; } } public EMAFunction() { NumParams = 2; Name = "EMA"; map = new Dictionary&lt;List&lt;object&gt;, List&lt;object&gt;&gt;(new EMAComparer()); } #region IFunction Members public int NumParams { get; set; } public string Name { get; set; } public object Execute(List&lt;object&gt; parameters) { if (parameters.Count != NumParams) throw new ArgumentException("The num params doesn't match!"); if (!map.ContainsKey(parameters)) { //map.Add(parameters, List&lt;double&gt; values = new List&lt;double&gt;(); List&lt;object&gt; asObj = (List&lt;object&gt;)parameters[0]; foreach (object val in asObj) { values.Add((double)val); } int period = (int)parameters[1]; asObj.Clear(); List&lt;double&gt; ema = TechFunctions.ExponentialMovingAverage(values, period); foreach (double val in ema) { asObj.Add(val); } map.Add(parameters, asObj); } return map[parameters]; } public void ClearMap() { map.Clear(); } #endregion } </code></pre> <p>Here are my tests of the function:</p> <pre><code>private void MemoizeTest() { DataSet dataSet = DataLoader.LoadData(DataLoader.DataSource.FROM_WEB, 1024); List&lt;String&gt; labels = dataSet.DataLabels; Stopwatch sw = new Stopwatch(); IFunction emaFunc = new EMAFunction(); List&lt;object&gt; parameters = new List&lt;object&gt;(); int numRuns = 1000; long sumTicks = 0; parameters.Add(dataSet.GetValues("open")); parameters.Add(12); // First call for(int i = 0; i &lt; numRuns; ++i) { emaFunc.ClearMap();// remove any memoization mappings sw.Start(); emaFunc.Execute(parameters); sw.Stop(); sumTicks += sw.ElapsedTicks; sw.Reset(); } Console.WriteLine("Average ticks not-memoized " + (sumTicks/numRuns)); sumTicks = 0; // Repeat call for (int i = 0; i &lt; numRuns; ++i) { sw.Start(); emaFunc.Execute(parameters); sw.Stop(); sumTicks += sw.ElapsedTicks; sw.Reset(); } Console.WriteLine("Average ticks memoized " + (sumTicks/numRuns)); } </code></pre> <p><strong>Update:</strong><br> Thanks for pointing out my n00bish error... I <strong>always</strong> forget to call Reset on the stopwatch! </p> <p>I've seen <a href="https://stackoverflow.com/questions/633508/two-argument-memoization">another approach to memoization</a> as well... it doesn't offer n-argument memoization, but my approach with the Interface is not much more advantageous since I have to write a class for each function. Is there a reasonable way that I can merge these ideas into something more robust? <b>I want to make it easier to memoize a function without making the user write a class for each function that they intend to use.</b></p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload