[17295] | 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 | } |
---|