internal Core(Func <TItem, TItem, TDistance> distance, SmallWorld <TItem, TDistance> .Parameters parameters) { Distance = distance; Parameters = parameters; var initialSize = Math.Max(1024, parameters.InitialItemsSize); Nodes = new List <Node>(initialSize); Items = new List <TItem>(initialSize); switch (Parameters.NeighbourHeuristic) { case NeighbourSelectionHeuristic.SelectSimple: { Algorithm = new Algorithms.Algorithm3 <TItem, TDistance>(this); break; } case NeighbourSelectionHeuristic.SelectHeuristic: { Algorithm = new Algorithms.Algorithm4 <TItem, TDistance>(this); break; } } if (Parameters.EnableDistanceCacheForConstruction) { DistanceCache = new DistanceCache <TDistance>(); DistanceCache.Resize(parameters.InitialDistanceCacheSize, false); } DistanceCalculationsCount = 0; }
/// <summary> /// Initializes a new instance of the <see cref="Core"/> class. /// </summary> /// <param name="distance">The distance function in the items space.</param> /// <param name="parameters">The parameters of the world.</param> /// <param name="items">The original items.</param> internal Core(Func <TItem, TItem, TDistance> distance, SmallWorld <TItem, TDistance> .Parameters parameters, IReadOnlyList <TItem> items) { this.distance = distance; this.Parameters = parameters; this.Items = items; switch (this.Parameters.NeighbourHeuristic) { case SmallWorld <TItem, TDistance> .NeighbourSelectionHeuristic.SelectSimple: this.Algorithm = new Node.Algorithm3 <TItem, TDistance>(this); break; case SmallWorld <TItem, TDistance> .NeighbourSelectionHeuristic.SelectHeuristic: this.Algorithm = new Node.Algorithm4 <TItem, TDistance>(this); break; } if (this.Parameters.EnableDistanceCacheForConstruction) { this.distanceCache = new DistanceCache <TDistance>(this.Items.Count); } this.distanceCacheHitCount = 0; this.distanceCalculationsCount = 0; }
/// <summary> /// Deserializes the graph from byte array. /// </summary> /// <param name="items">The items to assign to the graph's verticies.</param> /// <param name="bytes">The serialized parameters and edges.</param> public static SmallWorld <TItem, TDistance> DeserializeGraph(IReadOnlyList <TItem> items, Func <TItem, TItem, TDistance> distance, IProvideRandomValues generator, Stream stream) { var p0 = stream.Position; string hnswHeader; try { hnswHeader = MessagePackBinary.ReadString(stream); } catch (Exception E) { if (stream.CanSeek) { stream.Position = p0; } //Resets the stream to original position throw new InvalidDataException($"Invalid header found in stream, data is corrupted or invalid", E); } if (hnswHeader != SERIALIZATION_HEADER) { if (stream.CanSeek) { stream.Position = p0; } //Resets the stream to original position throw new InvalidDataException($"Invalid header found in stream, data is corrupted or invalid"); } // readStrict: true -> removed, as not available anymore on MessagePack 2.0 - also probably not necessary anymore // see https://github.com/neuecc/MessagePack-CSharp/pull/663 var parameters = MessagePackSerializer.Deserialize <Parameters>(stream); //Overwrite previous InitialDistanceCacheSize parameter, so we don't waste time/memory allocating a distance cache for an already existing graph parameters.InitialDistanceCacheSize = 0; var world = new SmallWorld <TItem, TDistance>(distance, generator, parameters); world.Graph.Deserialize(items, stream); return(world); }
/// <summary> /// Initializes a new instance of the <see cref="Graph{TItem, TDistance}"/> class. /// </summary> /// <param name="distance">The distance function.</param> /// <param name="parameters">The parameters of the world.</param> internal Graph(Func <TItem, TItem, TDistance> distance, SmallWorld <TItem, TDistance> .Parameters parameters) { this.distance = distance; this.Parameters = parameters; }