1 | using System;
|
---|
2 | using System.Collections.Generic;
|
---|
3 | using System.Diagnostics;
|
---|
4 | using System.Linq;
|
---|
5 |
|
---|
6 | namespace 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 | } |
---|