|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using ZeroLevel.Services.Serialization;
|
|
|
|
|
|
|
|
|
|
namespace ZeroLevel.Services.Semantic.Helpers
|
|
|
|
|
{
|
|
|
|
|
public sealed class SparceVector
|
|
|
|
|
: IBinarySerializable
|
|
|
|
|
{
|
|
|
|
|
private readonly static int[] EmptyIndexes = new int[0];
|
|
|
|
|
private readonly static double[] EmptyValues = new double[0];
|
|
|
|
|
|
|
|
|
|
private int[] indexes;
|
|
|
|
|
private double[] values;
|
|
|
|
|
private double power;
|
|
|
|
|
|
|
|
|
|
public SparceVector()
|
|
|
|
|
{
|
|
|
|
|
indexes = EmptyIndexes;
|
|
|
|
|
values = EmptyValues;
|
|
|
|
|
power = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public SparceVector(double[] vector)
|
|
|
|
|
{
|
|
|
|
|
var l = new List<int>();
|
|
|
|
|
for (int i = 0; i < vector.Length; i++)
|
|
|
|
|
{
|
|
|
|
|
if (Math.Abs(vector[i]) > double.Epsilon)
|
|
|
|
|
{
|
|
|
|
|
l.Add(i);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
indexes = l.ToArray();
|
|
|
|
|
values = new double[l.Count];
|
|
|
|
|
power = 0;
|
|
|
|
|
for (int i = 0; i < l.Count; i++)
|
|
|
|
|
{
|
|
|
|
|
values[i] = vector[indexes[i]];
|
|
|
|
|
power += values[i] * values[i];
|
|
|
|
|
}
|
|
|
|
|
power = Math.Sqrt(power);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public SparceVector(double[] vector, int[] indicies)
|
|
|
|
|
{
|
|
|
|
|
indexes = indicies;
|
|
|
|
|
values = vector;
|
|
|
|
|
power = 0;
|
|
|
|
|
for (int i = 0; i < indexes.Length; i++)
|
|
|
|
|
{
|
|
|
|
|
power += values[i] * values[i];
|
|
|
|
|
}
|
|
|
|
|
power = Math.Sqrt(power);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public double Measure(SparceVector other)
|
|
|
|
|
{
|
|
|
|
|
double sum = 0.0d;
|
|
|
|
|
|
|
|
|
|
int li = 0, ri = 0;
|
|
|
|
|
int lv, rv;
|
|
|
|
|
|
|
|
|
|
while (li < this.indexes.Length &&
|
|
|
|
|
ri < other.indexes.Length)
|
|
|
|
|
{
|
|
|
|
|
lv = this.indexes[li];
|
|
|
|
|
rv = other.indexes[ri];
|
|
|
|
|
if (lv == rv)
|
|
|
|
|
{
|
|
|
|
|
// у обоих векторов совпадение по индексам
|
|
|
|
|
sum += this.values[li] * other.values[ri];
|
|
|
|
|
li++; ri++;
|
|
|
|
|
}
|
|
|
|
|
else if (lv < rv)
|
|
|
|
|
{
|
|
|
|
|
li++;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
ri++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return sum / (this.power * other.power);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void Serialize(IBinaryWriter writer)
|
|
|
|
|
{
|
|
|
|
|
writer.WriteDouble(this.power);
|
|
|
|
|
writer.WriteCollection(indexes);
|
|
|
|
|
writer.WriteCollection(values);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void Deserialize(IBinaryReader reader)
|
|
|
|
|
{
|
|
|
|
|
this.power = reader.ReadDouble();
|
|
|
|
|
this.indexes = reader.ReadInt32Collection().ToArray();
|
|
|
|
|
this.values = reader.ReadDoubleCollection().ToArray();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|