LoginSignup
0
0

More than 1 year has passed since last update.

Math.NETのベクトルをMemoryPackでシリアライズする

Last updated at Posted at 2023-03-01

概要

Math.NETのベクトルVector<T>と行列Matrix<T>を高速なシリアライザであるMemoryPackで扱う方法についてまとめました。

動作条件と注意点

本記事は.NET Standard2.1版のMemoryPackが使用される.NET 5および.NET 6での動作確認をしています。
.NET 7ではCS8987によりコンパイルエラーが出ます。

コード

公式のCustomFormetterの書き方 に則りVector<T>T[]として(つまり密ベクトルとして)シリアライズできるようにラッパー、フォーマッターを実装します。

using MathNet.Numerics.LinearAlgebra;
using MemoryPack;

// シリアライズ前にFormatterを登録します(Vector<double>をシリアライズ可能にする)
MemoryPackFormatterProvider.Register(new VectorFormatter<double>());

var v = Vector<double>.Build.Random(5);
var s = new Sample(v);

var bin = MemoryPackSerializer.Serialize(s);
var val = MemoryPackSerializer.Deserialize<Sample>(bin);

Console.WriteLine(s);
Console.WriteLine(val);
Console.ReadLine();

// Vector<T>を含むシリアライズ対象クラス
[MemoryPackable]
public partial class Sample
{
    [MemoryPackAllowSerialize]
    public Vector<double> X { get; set; }

    [MemoryPackConstructor]
    public Sample(Vector<double> x)
    {
        X = x;
    }

    public override string ToString()
    {
        return X.ToVectorString();
    }
}

// Vector<T>をシリアライズするためのWrapper
[MemoryPackable]
public partial class SerializableVector<T> where T : struct, IEquatable<T>, IFormattable
{
    [MemoryPackIgnore]
    public readonly Vector<T> Data;

    [MemoryPackInclude]
    T[] source => Data.ToArray();

    [MemoryPackConstructor]
    SerializableVector(T[] source)
    {
        Data = Vector<T>.Build.DenseOfArray(source);
    }

    public SerializableVector(Vector<T> data)
    {
        Data = data;
    }
}

// カスタムフォーマッター
public class VectorFormatter<T> : MemoryPackFormatter<Vector<T>> where T : struct, IEquatable<T>, IFormattable
{
    public override void Deserialize(ref MemoryPackReader reader, ref Vector<T>? value)
    {
        if (reader.PeekIsNull())
        {
            value = null;
            return;
        }

        var wrapped = reader.ReadPackable<SerializableVector<T>>();
        value = wrapped?.Data;
    }

    public override void Serialize<TBufferWriter>(ref MemoryPackWriter<TBufferWriter> writer, ref Vector<T>? value)
    {
        if (value == null)
        {
            writer.WriteNullObjectHeader();
            return;
        }

        writer.WritePackable(new SerializableVector<T>(value));
    }
}

行列は?

ベクトルの時と同様にMatrix<T>T[,]とみなしてラッパーとフォーマッターを作成すればシリアライズが可能です。疎行列の場合には別途工夫が必要になると思います。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0