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

Last change on this file since 17298 was 17298, checked in by gkronber, 3 years ago

#2994: small changes after refactoring

File size: 6.9 KB
Line 
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> AssignMin(AlgebraicSparseVector<K, T> other) {
112      // assumes that keys without a matching key in other are zero and vice versa
113      foreach (var kvp in elems) if (!other.elems.ContainsKey(kvp.Key)) kvp.Value.AssignMin(kvp.Value.Zero); // min(v, 0)
114      foreach (var kvp in other.elems) {
115        if (elems.TryGetValue(kvp.Key, out T value))
116          value.AssignMin(kvp.Value);
117        else
118          elems.Add(kvp.Key, kvp.Value.Zero.AssignMin(kvp.Value));
119      }
120      return this;
121    }
122
123    public AlgebraicSparseVector<K, T> AssignMax(AlgebraicSparseVector<K, T> other) {
124      // assumes that keys without a matching key in other are zero and vice versa
125      foreach (var kvp in elems) if (!other.elems.ContainsKey(kvp.Key)) kvp.Value.AssignMax(kvp.Value.Zero); // max(v, 0)
126      foreach (var kvp in other.elems) {
127        if (elems.TryGetValue(kvp.Key, out T value))
128          value.AssignMax(kvp.Value);
129        else
130          elems.Add(kvp.Key, kvp.Value.Zero.AssignMax(kvp.Value));
131      }
132      return this;
133    }
134
135
136    public AlgebraicSparseVector<K, T> Clone() {
137      return new AlgebraicSparseVector<K, T>(this);
138    }
139
140    public override string ToString() {
141      return "[" + string.Join(" ", elems.Select(kvp => kvp.Key + ": " + kvp.Value)) + "]";
142    }
143  }
144}
Note: See TracBrowser for help on using the repository browser.