Free cookie consent management tool by TermsFeed Policy Generator

source: branches/2994-AutoDiffForIntervals/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/AlgebraicSparseVector.cs @ 17303

Last change on this file since 17303 was 17303, checked in by gkronber, 5 years ago

#2994 continued refactoring and extended unit tests. Interval calculation still fails for some edge cases (mainly for undefined behaviour). VectorEvaluator and VectorAutoDiffEvaluator produce the same results as the LinearInterpreter. TODO: check gradient calculation

File size: 5.8 KB
RevLine 
[17295]1using System;
2using System.Collections.Generic;
3using System.Diagnostics;
4using System.Linq;
5
6namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
7  /// <summary>
8  /// A sparse vector of algebraic types. Elements are accessed via a key of type K
9  /// </summary>
10  /// <typeparam name="K">Key type</typeparam>
11  /// <typeparam name="T">Element type</typeparam>
12  [DebuggerDisplay("SparseVector: {ToString()}")]
13  public sealed class AlgebraicSparseVector<K, T> : IAlgebraicType<AlgebraicSparseVector<K, T>> where T : IAlgebraicType<T> {
14    [DebuggerBrowsable(DebuggerBrowsableState.Never)]
15    private Dictionary<K, T> elems;
16    public IReadOnlyDictionary<K, T> Elements => elems;
17
18
19    public AlgebraicSparseVector(AlgebraicSparseVector<K, T> original) {
20      elems = original.elems.ToDictionary(kvp => kvp.Key, kvp => kvp.Value.Clone());
21    }
22
23    /// <summary>
24    ///
25    /// </summary>
26    /// <param name="keys"></param>
27    /// <param name="values">values are cloned</param>
28    public AlgebraicSparseVector(K[] keys, T[] values) {
29      if (keys.Length != values.Length) throw new ArgumentException("lengths of keys and values doesn't match in SparseVector");
30      elems = new Dictionary<K, T>(keys.Length);
31      for (int i = 0; i < keys.Length; ++i) {
32        elems.Add(keys[i], values[i].Clone());
33      }
34    }
35
36    public AlgebraicSparseVector() {
37      this.elems = new Dictionary<K, T>();
38    }
39
40    // keep only elements from a
41    private void AssignFromSource(AlgebraicSparseVector<K, T> a, Func<T, T, T> mapAssign) {
42      // remove elems from this which don't occur in a
43      List<K> keysToRemove = new List<K>();
44      foreach (var kvp in elems) {
45        if (!a.elems.ContainsKey(kvp.Key)) keysToRemove.Add(kvp.Key);
46      }
47      foreach (var o in keysToRemove) elems.Remove(o); // -> zero
48
49      foreach (var kvp in a.elems) {
50        if (elems.TryGetValue(kvp.Key, out T value))
51          mapAssign(kvp.Value, value);
52        else
53          elems.Add(kvp.Key, mapAssign(kvp.Value, kvp.Value.Zero));
54      }
55    }
56
57    [DebuggerBrowsable(DebuggerBrowsableState.Never)]
58    public AlgebraicSparseVector<K, T> Zero => new AlgebraicSparseVector<K, T>();
59    [DebuggerBrowsable(DebuggerBrowsableState.Never)]
60    public AlgebraicSparseVector<K, T> One => throw new NotSupportedException();
61
62    public AlgebraicSparseVector<K, T> Scale(T s) { foreach (var kvp in elems) { kvp.Value.Mul(s); } return this; }
63    public AlgebraicSparseVector<K, T> Scale(double s) { foreach (var kvp in elems) { kvp.Value.Scale(s); } return this; }
64
65    public AlgebraicSparseVector<K, T> Assign(AlgebraicSparseVector<K, T> a) { elems.Clear(); AssignFromSource(a, (src, dest) => dest.Assign(src)); return this; }
66    public AlgebraicSparseVector<K, T> AssignInv(AlgebraicSparseVector<K, T> a) { AssignFromSource(a, (src, dest) => dest.AssignInv(src)); return this; }
67    public AlgebraicSparseVector<K, T> AssignNeg(AlgebraicSparseVector<K, T> a) { AssignFromSource(a, (src, dest) => dest.AssignNeg(src)); return this; }
68    public AlgebraicSparseVector<K, T> AssignLog(AlgebraicSparseVector<K, T> a) { AssignFromSource(a, (src, dest) => dest.AssignLog(src)); return this; }
69    public AlgebraicSparseVector<K, T> AssignExp(AlgebraicSparseVector<K, T> a) { AssignFromSource(a, (src, dest) => dest.AssignExp(src)); return this; }
70    public AlgebraicSparseVector<K, T> AssignIntPower(AlgebraicSparseVector<K, T> a, int p) { AssignFromSource(a, (src, dest) => dest.AssignIntPower(src, p)); return this; }
71    public AlgebraicSparseVector<K, T> AssignIntRoot(AlgebraicSparseVector<K, T> a, int r) { AssignFromSource(a, (src, dest) => dest.AssignIntRoot(src, r)); return this; }
72    public AlgebraicSparseVector<K, T> AssignSin(AlgebraicSparseVector<K, T> a) { AssignFromSource(a, (src, dest) => dest.AssignSin(src)); return this; }
73    public AlgebraicSparseVector<K, T> AssignCos(AlgebraicSparseVector<K, T> a) { AssignFromSource(a, (src, dest) => dest.AssignCos(src)); return this; }
74    public AlgebraicSparseVector<K, T> AssignTanh(AlgebraicSparseVector<K, T> a) { AssignFromSource(a, (src, dest) => dest.AssignTanh(src)); return this; }
75    public AlgebraicSparseVector<K, T> AssignAbs(AlgebraicSparseVector<K, T> a) { AssignFromSource(a, (src, dest) => dest.AssignAbs(src)); return this; }
76    public AlgebraicSparseVector<K, T> AssignSgn(AlgebraicSparseVector<K, T> a) { AssignFromSource(a, (src, dest) => dest.AssignSgn(src)); return this; }
77    public AlgebraicSparseVector<K, T> Add(AlgebraicSparseVector<K, T> a) {
78      foreach (var kvp in a.elems) {
79        if (elems.TryGetValue(kvp.Key, out T value))
80          value.Add(kvp.Value);
81        else
82          elems.Add(kvp.Key, kvp.Value.Clone()); // 0 + a
83      }
84      return this;
85    }
86
87    public AlgebraicSparseVector<K, T> Sub(AlgebraicSparseVector<K, T> a) {
88      foreach (var kvp in a.elems) {
89        if (elems.TryGetValue(kvp.Key, out T value))
90          value.Sub(kvp.Value);
91        else
92          elems.Add(kvp.Key, kvp.Value.Zero.Sub(kvp.Value)); // 0 - a
93      }
94      return this;
95    }
96
97    public AlgebraicSparseVector<K, T> Mul(AlgebraicSparseVector<K, T> a) {
98      var keys = elems.Keys.ToArray();
99      foreach (var k in keys) if (!a.elems.ContainsKey(k)) elems.Remove(k); // 0 * a => 0
100      foreach (var kvp in a.elems) {
101        if (elems.TryGetValue(kvp.Key, out T value))
102          value.Mul(kvp.Value); // this * a
103      }
104      return this;
105    }
106
107    public AlgebraicSparseVector<K, T> Div(AlgebraicSparseVector<K, T> a) {
108      return Mul(a.Clone().Inv());
109    }
110
111    public AlgebraicSparseVector<K, T> Clone() {
112      return new AlgebraicSparseVector<K, T>(this);
113    }
114
115    public override string ToString() {
116      return "[" + string.Join(" ", elems.Select(kvp => kvp.Key + ": " + kvp.Value)) + "]";
117    }
118  }
119}
Note: See TracBrowser for help on using the repository browser.