using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
///
/// A sparse vector of algebraic types. Elements are accessed via a key of type K
///
/// Key type
/// Element type
[DebuggerDisplay("SparseVector: {ToString()}")]
public sealed class AlgebraicSparseVector : IAlgebraicType> where T : IAlgebraicType {
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private Dictionary elems;
public IReadOnlyDictionary Elements => elems;
public AlgebraicSparseVector(AlgebraicSparseVector original) {
elems = original.elems.ToDictionary(kvp => kvp.Key, kvp => kvp.Value.Clone());
}
///
///
///
///
/// values are cloned
public AlgebraicSparseVector(K[] keys, T[] values) {
if (keys.Length != values.Length) throw new ArgumentException("lengths of keys and values doesn't match in SparseVector");
elems = new Dictionary(keys.Length);
for (int i = 0; i < keys.Length; ++i) {
elems.Add(keys[i], values[i].Clone());
}
}
public AlgebraicSparseVector() {
this.elems = new Dictionary();
}
// keep only elements from a
private void AssignFromSource(AlgebraicSparseVector a, Func mapAssign) {
// remove elems from this which don't occur in a
List keysToRemove = new List();
foreach (var kvp in elems) {
if (!a.elems.ContainsKey(kvp.Key)) keysToRemove.Add(kvp.Key);
}
foreach (var o in keysToRemove) elems.Remove(o); // -> zero
foreach (var kvp in a.elems) {
if (elems.TryGetValue(kvp.Key, out T value))
mapAssign(kvp.Value, value);
else
elems.Add(kvp.Key, mapAssign(kvp.Value, kvp.Value.Zero));
}
}
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
public AlgebraicSparseVector Zero => new AlgebraicSparseVector();
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
public AlgebraicSparseVector One => throw new NotSupportedException();
public AlgebraicSparseVector Scale(T s) { foreach (var kvp in elems) { kvp.Value.Mul(s); } return this; }
public AlgebraicSparseVector Scale(double s) { foreach (var kvp in elems) { kvp.Value.Scale(s); } return this; }
public AlgebraicSparseVector Assign(AlgebraicSparseVector a) { elems.Clear(); AssignFromSource(a, (src, dest) => dest.Assign(src)); return this; }
public AlgebraicSparseVector AssignInv(AlgebraicSparseVector a) { AssignFromSource(a, (src, dest) => dest.AssignInv(src)); return this; }
public AlgebraicSparseVector AssignNeg(AlgebraicSparseVector a) { AssignFromSource(a, (src, dest) => dest.AssignNeg(src)); return this; }
public AlgebraicSparseVector AssignLog(AlgebraicSparseVector a) { AssignFromSource(a, (src, dest) => dest.AssignLog(src)); return this; }
public AlgebraicSparseVector AssignExp(AlgebraicSparseVector a) { AssignFromSource(a, (src, dest) => dest.AssignExp(src)); return this; }
public AlgebraicSparseVector AssignIntPower(AlgebraicSparseVector a, int p) { AssignFromSource(a, (src, dest) => dest.AssignIntPower(src, p)); return this; }
public AlgebraicSparseVector AssignIntRoot(AlgebraicSparseVector a, int r) { AssignFromSource(a, (src, dest) => dest.AssignIntRoot(src, r)); return this; }
public AlgebraicSparseVector AssignSin(AlgebraicSparseVector a) { AssignFromSource(a, (src, dest) => dest.AssignSin(src)); return this; }
public AlgebraicSparseVector AssignCos(AlgebraicSparseVector a) { AssignFromSource(a, (src, dest) => dest.AssignCos(src)); return this; }
public AlgebraicSparseVector AssignTanh(AlgebraicSparseVector a) { AssignFromSource(a, (src, dest) => dest.AssignTanh(src)); return this; }
public AlgebraicSparseVector AssignAbs(AlgebraicSparseVector a) { AssignFromSource(a, (src, dest) => dest.AssignAbs(src)); return this; }
public AlgebraicSparseVector AssignSgn(AlgebraicSparseVector a) { AssignFromSource(a, (src, dest) => dest.AssignSgn(src)); return this; }
public AlgebraicSparseVector Add(AlgebraicSparseVector a) {
foreach (var kvp in a.elems) {
if (elems.TryGetValue(kvp.Key, out T value))
value.Add(kvp.Value);
else
elems.Add(kvp.Key, kvp.Value.Clone()); // 0 + a
}
return this;
}
public AlgebraicSparseVector Sub(AlgebraicSparseVector a) {
foreach (var kvp in a.elems) {
if (elems.TryGetValue(kvp.Key, out T value))
value.Sub(kvp.Value);
else
elems.Add(kvp.Key, kvp.Value.Zero.Sub(kvp.Value)); // 0 - a
}
return this;
}
public AlgebraicSparseVector Mul(AlgebraicSparseVector a) {
var keys = elems.Keys.ToArray();
foreach (var k in keys) if (!a.elems.ContainsKey(k)) elems.Remove(k); // 0 * a => 0
foreach (var kvp in a.elems) {
if (elems.TryGetValue(kvp.Key, out T value))
value.Mul(kvp.Value); // this * a
}
return this;
}
public AlgebraicSparseVector Div(AlgebraicSparseVector a) {
return Mul(a.Clone().Inv());
}
public AlgebraicSparseVector Clone() {
return new AlgebraicSparseVector(this);
}
public override string ToString() {
return "[" + string.Join(" ", elems.Select(kvp => kvp.Key + ": " + kvp.Value)) + "]";
}
}
}