すべてのプロダクト
Search
ドキュメントセンター

Optimization Solver:物流:コスト最小化ネットワークフロー問題

最終更新日:Jan 12, 2026

産業背景

物流はサプライチェーンマネジメントの鍵であり、多くの場合、輸送、倉庫保管、荷役、配送などの複数の活動が関わります。貨物輸送の効率と信頼性を向上させ、物流コストを削減するために、輸送計画をどのように合理的に策定すればよいでしょうか。この最適化問題は、数理計画法を用いてモデル化し、解決することができます。

例えば、ある企業が製品を工場から配送センターへ、そして様々な倉庫へ輸送する必要があるとします。各倉庫への輸送コストは異なり、各ルートには容量制限があります。目標は、総コストを最小化する輸送計画を作成することです。

image.png

ビジネス調査、データ定量化、および数理モデリング

最適化技術を使用する場合、ビジネスのニーズをより詳細に調査し、関連するビジネスロジックとデータを整理し、それらを定量化する必要があります。その後、数理計画法を用いてモデリングを行うことができます。

詳細については、「」をご参照ください。このセクションでは、関連する数式のみをリストします。

image.svg

上記の数式では、s は各サイトで利用可能な商品を表し、d は各サイトで必要な商品を表し、i と j は輸送ラインの開始サイトと終了サイトを表し、k は中間サイトを表します。

上記の数式に対する制約:

  1. あるサイトで利用可能な商品の合計と、そのサイトに輸送された商品の合計は、そのサイトで必要な商品の合計と、そのサイトから輸送された商品の合計に等しくなります。

  2. 各輸送ラインには、配送能力の上限があります。

ソースコード

MindOpt は、複数のプログラミング言語やモデリング言語から呼び出すことができます。以下に例を示します。

MindOpt APL モデリング言語の呼び出し

MindOpt APL のソースコード ( にアクセスしてドライランを実行できます):

##====MindOpt APL のソースコード====

clear model;

# モデリング -------
# net2.mapl
# データ
set CITIES := {"HN", "NE", "SE", "LN", "JL", "HLJ", "JS", "ZJ"} ;

set LINKS := {<"HN", "NE">, <"HN", "SE">, <"NE", "LN">, <"NE","JL">, <"NE","HLJ">, <"SE","LN">, <"SE","JL">, <"SE", "JS">, <"SE", "ZJ">};

param supply[CITIES] := <"HN"> 450 default 0;

param demand[CITIES] := <"JS"> 90,  <"ZJ"> 70, <"JL"> 120,  <"LN"> 120, <"HLJ"> 50 default 0;

set C := {"cost", "capacity"};

param data[LINKS * C] :=
            | "cost",  "capacity"|
|"HN", "NE" |    3.5,    250    |
|"HN", "SE" |    2.5,    250    |
|"NE", "LN" |    1.5,    100    |
|"NE", "JL" |    1.7,    100    |
|"NE", "HLJ"|    2.0,    100    |
|"SE", "LN" |    2.6,    100    |
|"SE", "JL" |    2.7,    100    |
|"SE", "JS" |    1.3,    100    |
|"SE", "ZJ" |    1.5,    100    |;

# データが正しいかどうかを確認します。
forall {<i> in CITIES } check supply[i] >= 0;
forall {<i> in CITIES } check demand[i] >= 0;
check sum {<i> in CITIES } supply[i] >= sum {<j> in CITIES} demand[j]; # 供給が需要を上回っています。

# モデル
var Ship[<i, j> in LINKS] >= 0 <= data[i, j, "capacity"];

minimize Total_Cost: sum {<i, j> in LINKS } data[i, j, "cost"] * Ship[i, j];

subto Balance: 
   forall {<k> in CITIES }
       supply[k] + sum {<i, k> in LINKS} Ship[i, k] >= demand[k] + sum {<k, j> in LINKS} Ship[k,j]; # 各サイトの供給が需要を満たしています。


print "------------- Solving using Optimization Solver---------------";
option solver mindopt; # (任意) 問題を解決するために使用するソルバーを指定します。デフォルトでは Optimization Solver が使用されます。
#option mindopt_options 'print=0'; # ソルバーの出力レベルを設定して、出力を簡素化します。
solve; # 問題を解決します。

print "-----------------Display---------------";
display; # 結果を表示します。
print "The lowest shipping cost after optimization = " , sum {<i, j> in LINKS } data[i, j, "cost"] * Ship[i, j];

結果と結果の使用方法

ログはコードによって異なります。次のセクションでは、ログの一部を提供します。

...
Model summary.
 - Num. variables     : 9
 - Num. constraints   : 5
 - Num. nonzeros      : 15
 - Bound range        : [5.0e+01,4.5e+02]
 - Objective range    : [1.3e+00,3.5e+00]
 - Matrix range       : [1.0e+00,1.0e+00]
...
Simplex method terminated. Time : 0.008s


OPTIMAL; objective 2123.00
...
----------------- Result ---------------
The lowest shipping cost after optimization = 2123

最適解は 2123 です。決定変数の値など、より詳細な情報を表示したり、制約を検証したりするには、`print` コマンドを使用します。また、プログラムによって作成される .sol ファイルから変数の値を取得することもできます。あるいは、display コマンドを呼び出して、すべての変数の値を取得することもできます。

たとえば、次のコマンドを実行して、あるサイトで利用可能な商品の合計と、そのサイトに輸送された商品の合計は、そのサイトで必要な商品の合計と、そのサイトから輸送された商品の合計に等しいという制約を検証します。

forall {<k> in CITIES } 
 print 'サイト {} から供給される商品とそこに輸送される商品の合計は {} です'%k ,
 supply[k] + sum {<i, k> in LINKS} Ship[i, k];
print "-------------------";    
forall {<k> in CITIES } 
 print 'サイト {} で必要とされる商品とそこから輸送される商品の合計は {} です'%k ,
 demand[k] + sum {<k, j> in LINKS} Ship[k,j];

結果:

The sum of products supplied by site HN and products shipped into it is 450
The sum of products supplied by site NE and products shipped into it is 250
The sum of products supplied by site SE and products shipped into it is 200
The sum of products supplied by site LN and products shipped into it is 120
The sum of products supplied by site JL and products shipped into it is 120
The sum of products supplied by site HLJ and products shipped into it is 50
The sum of products supplied by site JS and products shipped into it is 90
The sum of products supplied by site ZJ and products shipped into it is 70
-------------------
The sum of products needed by site HN and products shipped out of it is 450
The sum of products needed by site NE and products shipped out of it is 250
The sum of products needed by site SE and products shipped out of it is 200
The sum of products needed by site LN and products shipped out of it is 120
The sum of products needed by site JL and products shipped out of it is 120
The sum of products needed by site HLJ and products shipped out of it is 50
The sum of products needed by site JS and products shipped out of it is 90
The sum of products needed by site ZJ and products shipped out of it is 70

次のコードを実行して、物流サービスにおける輸送問題のソリューションとして結果を CSV フォーマットで表示します:

print "{},{},{} "% "Start site","Intermediate site","Quantity of goods" : "Results.csv";
close "Results.csv";

forall {<i, j> in LINKS}
    print "{},{},{}" % i,j,Ship[i,j]  >> "Results.csv";

close "Results.csv";

次の結果が返されます。

image.png

結果は、工場から各倉庫への商品の輸送にかかる最低コストが 2123 であることを示しています。次の輸送スキームが推奨されます:

  • 工場 HN から配送センター NE への商品出荷量は 250、配送センター SE へは 200 です。

    • NE 配送センターから、LN 倉庫へ 100 ユニット、JL 倉庫へ 100 ユニット、HLJ 倉庫へ 50 ユニットを輸送します。

    • 配送センター SE から倉庫 LN への商品出荷量は 20、倉庫 JL へは 20、倉庫 JS へは 90、倉庫 ZJ へは 70 です。

      • これにより、各倉庫の合計は、LN で 120 ユニット、JL で 120、HLJ で 50、JS で 90、ZJ で 70 となります。

        • 2 つの配送センターから倉庫までの総輸送コストは 2123 です。

image.png