EsUtil.Algorithm.MultiColumnLayoutEngine 1.0.0

dotnet add package EsUtil.Algorithm.MultiColumnLayoutEngine --version 1.0.0
                    
NuGet\Install-Package EsUtil.Algorithm.MultiColumnLayoutEngine -Version 1.0.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="EsUtil.Algorithm.MultiColumnLayoutEngine" Version="1.0.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="EsUtil.Algorithm.MultiColumnLayoutEngine" Version="1.0.0" />
                    
Directory.Packages.props
<PackageReference Include="EsUtil.Algorithm.MultiColumnLayoutEngine" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add EsUtil.Algorithm.MultiColumnLayoutEngine --version 1.0.0
                    
#r "nuget: EsUtil.Algorithm.MultiColumnLayoutEngine, 1.0.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package EsUtil.Algorithm.MultiColumnLayoutEngine@1.0.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=EsUtil.Algorithm.MultiColumnLayoutEngine&version=1.0.0
                    
Install as a Cake Addin
#tool nuget:?package=EsUtil.Algorithm.MultiColumnLayoutEngine&version=1.0.0
                    
Install as a Cake Tool

VerticalMultiColumnLayout - ユーザー向け利用仕様書

概要

MultiColumnLayoutEngine は、複数のアイテムを複数列に配置し、最大列高さ(MinHeight)を最小化するレイアウト最適化ライブラリです。

Web UI、グリッドレイアウト、カード配置など、複雑なマルチカラムレイアウトが必要なアプリケーションに最適です。


主要機能

3 つのアルゴリズム

アルゴリズム 計算量 品質 特徴 推奨用途
DynamicProgramming(DP) O(n² × m) 最適解 100% 最高品質 小~中規模(~1000 件)、品質最優先
Greedy(貪欲法) O(n × m) 95%+ 高速計算 大規模(1000+ 件)、速度重視
BinarySearch O(n × log(h)) 99%+ バランス型 全般推奨、品質と速度のバランス最適

パフォーマンスベンチマーク(リリースビルド .NET 10)

【アイテム数ごとの計算時間(Solve メソッド実行時)】

アイテム数    DP法(ms)    Greedy法(ms)  BinarySearch(ms)  反復回数  品質G(%)  品質B(%)
10 件        0.018       0.002         0.003             1 回      97.4%     100.0%
30 件        0.210       0.004         0.005             0 回      90.9%     100.0%
60 件        0.599       0.007         0.008             1 回      97.2%     100.0%
100 件       1.585       0.010         0.011             2 回      97.6%     100.0%
300 件       5.153       0.019         0.021             2 回      98.1%     100.0%
600 件       29.257      0.028         0.034             4 回      98.7%     100.0%
1,000 件     114.898     0.042         0.045             4 回      97.9%     100.0%
10,000 件    --          0.111         0.291             8 回      99.7%     --
100,000 件   --          0.568         3.065             11 回     99.8%     --
1,000,000 件 --          6.965         36.739            12 回     99.9%     --
10,000,000 件 --         70.625        --                --        --        --

※ "--" は計測対象外または計算不可

品質分析

DP 法(DynamicProgramming)

  • 精度:最適解保証(100%)
  • 適用範囲:小~中規模(~1000 件)
  • 限界:1000 件超えで計算時間が急増し非実用的
  • メモリ効率:O(n × m)
  • 推奨シナリオ:品質最優先の小規模データセット(~100 件)

Greedy 法

  • 精度:90%+
  • スケール性:アイテム数が増加するほど品質向上傾向
  • 大規模対応:1,000,000 件でも 6.215 ms で計算完了
  • メモリ効率:O(n)
  • 推奨シナリオ:
    • 速度重視の大規模データセット(1,000+ 件)
    • 実用品質(90%+)で十分な用途

BinarySearch 法

  • 精度:99%+
  • 安定性:最高(品質の最小保証)
  • 大規模対応:1,000,000 件でも 35.508 ms で計算完了
  • メモリ効率:O(n)
  • 推奨シナリオ:全般推奨、品質と速度のバランス最適
    • デフォルト選択肢(Solve の method デフォルト値)
    • 品質 100% が必須な用途
    • 全スケール対応(10 件~1,000,000 件+)

選択ガイドライン

アイテム数 推奨アルゴリズム 理由
10~100 件 DP 法 最高品質、計算時間も許容範囲
100~500 件 BinarySearch DP と同等品質、更に高速
500~1,000 件 BinarySearch DP が非実用的、BS で 100% 品質
1,000~10,000 BinarySearch 高速(0.306 ms)、100% 品質
10,000~100,000 BinarySearch 実用的(2.987 ms)、100% 品質
100,000+ Greedy or BS BS:35.508 ms, 100% 品質 <br/> Greedy:6.215 ms, 99.9% 品質 <br/> (速度重視なら Greedy 推奨)

最適化手法

  • ArrayPool による GC メモリ割り当て削減(DP テーブル、セグメント配列)
  • stackalloc による GC 圧力ゼロ化(32 要素以下の一時バッファ)
  • ReadOnlySpan による参照型アクセス最適化
  • キャッシング機構 による複数アルゴリズム間の重複計算回避
  • MethodImpl.AggressiveInlining による小規模メソッド最適化
  • MethodImpl.AggressiveOptimization によるホットパス最適化
  • ホットパス変数キャッシング による CPU メモリレイテンシ削減

使用方法

基本的な使用例

using EsUtil.Algorithm.MultiColumnLayoutEngine;

// 1. アイテムリストを作成
var items = new List<(double Width, double Height)>
{
    (50.0, 100.0),   // 幅 50、高さ 100
    (60.0, 120.0),   // 幅 60、高さ 120
    (70.0, 140.0)    // 幅 70、高さ 140
};

// 2. レイアウトインスタンスを作成
var layout = new MultiColumnLayoutEngine(
    items: items,
    space: (Row: 5.0, Column: 10.0),  // 行間 5、列間 10
    columnLimit: 5                    // 最大 5 列
);

// 3. レイアウトを計算(BinarySearch で高精度&高速)
var (usedWidth, minHeight) = layout.Solve(
    widthLimit: 200.0,
    method: Method.BinarySearch
);

Console.WriteLine($"使用幅: {usedWidth}, 最大高さ: {minHeight}");

// 4. 各列のセグメント情報を取得
var columnSegments = layout.GetLastColumnSegments();
foreach (var (startIdx, endIdx) in columnSegments)
{
    Console.WriteLine($"列: アイテム {startIdx} ~ {endIdx}");
}

// 5. 各アイテムの描画座標を計算
var itemLayouts = layout.GetLastItemLayouts();
foreach (var (i, (x, y, w, h)) in itemLayouts.Select((item, i) => (i, item)))
{
    Console.WriteLine($"アイテム {i}: X={x}, Y={y}, Width={w}, Height={h}");
}

アルゴリズム選択ガイド

BinarySearch 法(推奨)
var (usedWidth, minHeight) = layout.Solve(200.0, Method.BinarySearch);
// メリット: 99%+ 精度、全サイズで高速、デフォルト推奨
// デメリット: なし
Greedy 法(高速計算)
var (usedWidth, minHeight) = layout.Solve(200.0, Method.Greedy);
// メリット: 高速、O(n × m) 計算量
// デメリット: 品質低下(95%+)
DP 法(最高品質)
var (usedWidth, minHeight) = layout.Solve(200.0, Method.DynamicProgramming);
// メリット: 最適解保証(100% 品質)
// デメリット: 1000 件超えで計算不可、メモリ大量消費

API リファレンス

コンストラクタ

public MultiColumnLayoutEngine(
    IReadOnlyList<(double Width, double Height)> items,
    (double Row, double Column) space,
    int columnLimit = 10,
    BinarySearchOptions? options = null
);

パラメータ:

  • items: 各アイテムの (幅, 高さ) リスト(必須、順序維持)
  • space: 行間スペース (Row) と列間スペース (Column)(非負値)
  • columnLimit: 使用可能な列数の上限(デフォルト: 10、正の値)
  • options: アルゴリズム制御オプション(BinarySearch 用、null 許可)

Solve メソッド

public (double UsedWidth, double MinHeight) Solve(
    double widthLimit,
    Method method = Method.BinarySearch
);

戻り値:

  • UsedWidth: 実際に使用した幅(widthLimit 以下)
  • MinHeight: 最大列高さ(最小化された値)

計算式:

列の高さ = Σ(アイテム高さ) + (アイテム数 - 1) × space.Row
列の幅 = max(アイテム幅)
MinHeight = max(全列の高さ)
UsedWidth = Σ(列幅) + (列数 - 1) × space.Column

補助メソッド

// 最後の Solve() 実行時の結果を取得
public (double UsedWidth, double MinHeight) GetLastResult();

// 最後の Solve() 実行時の各列のセグメント情報を取得
public (int StartIdx, int EndIdx)[] GetLastColumnSegments();

// 各アイテムの描画座標とサイズを計算
public IReadOnlyList<(double X, double Y, double Width, double Height)> GetLastItemLayouts();

// 単列配置(フォールバック)を計算
public (double UsedWidth, double MinHeight) SolveSingleColumnLayout();

// 最大アイテム幅が widthLimit を超えるか判定
public bool IsValidWidth(double widthLimit);

// 最後の BinarySearch 実行時の反復回数を取得
public int GetLastBSearchIterationCount();

// キャッシュをクリア(複数 Solve() 呼び出し時の最適化を無効化)
public void ClearCache();

オプション設定(BinarySearch 用)

var options = new BinarySearchOptions(
    Epsilon: 1e-3,          // 収束判定許容誤差(デフォルト: 1e-3)
    MaxIterations: 100,     // 最大反復回数(デフォルト: 100)
    LowerBoundRatio: 0.95   // 下限比率(デフォルト: 0.95)
);

var layout = new MultiColumnLayoutEngine(
    items: items,
    space: (5.0, 10.0),
    columnLimit: 10,
    options: options
);

var (usedWidth, minHeight) = layout.Solve(200.0);

パラメータ説明:

  • Epsilon:二分探索の収束条件。小さいほど精度向上(但し反復回数増加)
  • MaxIterations:無限ループ防止の上限値。通常は 100 回で充分
  • LowerBoundRatio:初期下限値の比率。Greedy 結果 × (1 - この値)

レコード構造体の更新方法: BinarySearchOptions はレコード構造体なので、一部の値を更新するには with キーワードを使用します。

// デフォルトオプションを取得
var defaultOptions = BinarySearchOptions.Default;

// Epsilon のみを変更
var customOptions = defaultOptions with { Epsilon = 1e-4 };

// 複数の値を変更
var advancedOptions = defaultOptions with { 
    Epsilon = 1e-4, 
    MaxIterations = 200 
};

エラーハンドリング

入力値検証

不正な入力値は ArgumentException をスロー:

try
{
    var layout = new MultiColumnLayoutEngine(
        items: new List<(double, double)> { (0.0, 100.0) },  // 幅が 0 は無効
        space: (-1.0, 0.0),                                  // 負のスペースは無効
        columnLimit: 0                                       // 列数は正の値必須
    );
}
catch (ArgumentException ex)
{
    Console.WriteLine($"エラー: {ex.Message}");
}

検証項目:

  • items が null でないか
  • 各アイテムの幅・高さが正の値か(NaN、無限大は無効)
  • space.Row、space.Column が非負か(NaN、無限大は無効)
  • columnLimit が正の値か
  • options が指定される場合、各パラメータが妥当か

出力値検証

計算結果の妥当性チェック(自動):

try
{
    var (usedWidth, minHeight) = layout.Solve(100.0);
    // 検証: UsedWidth ≤ widthLimit
    // 検証: MinHeight ≤ 単列配置高さ
}
catch (InvalidOperationException ex)
{
    Console.WriteLine($"検証エラー: {ex.Message}");
}

パフォーマンス最適化

大規模データセット向け

// 大規模データセット(100,000 件以上)
var largeItems = Enumerable.Range(0, 1000000)
    .Select(i => (Width: (i % 100) + 10.0, Height: (i % 200) + 20.0))
    .ToList();

var layout = new MultiColumnLayoutEngine(
    items: largeItems,
    space: (Row: 0.0, Column: 0.0),
    columnLimit: 20
);

// BinarySearch で高速計算(ArrayPool で GC 圧力ゼロ)
var (usedWidth, minHeight) = layout.Solve(500.0, Method.BinarySearch);
Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • net8.0

    • No dependencies.

NuGet packages (1)

Showing the top 1 NuGet packages that depend on EsUtil.Algorithm.MultiColumnLayoutEngine:

Package Downloads
EsUtil.WinUI3.Controls.MultiColumnPanel

WinUI 3 custom controls including MultiColumnPanel for optimized multi-column layouts

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.0 128 2/9/2026