FLEXSCHE製品のご紹介

FLEXSCHEバージョン17

FLEXSCHEバージョン17.0を2017年7月24日にリリースしました。およそ190項目にもおよぶ機能拡張が施されています。そのうちの主だったものをご紹介します。(バージョン16.0とバージョン17.0の差分)

全体的な高速化

乾いた雑巾をさらに絞りました。

大量データのスケジューリング処理、描画処理、入出力処理などは、CPUに莫大な負荷を掛けます。そこで、実際のデータを処理したときに繰り返し実行されるコードを統計的に特定し、その部分に掛かる負荷を総合的に取り除き、また細部を丹念にチューニングすることによって、さらなる高速化を実現しました。多くのデータで1~2割程度以上の改善が認められるでしょう。

例えば、標準サンプルデータ「10万作業」のリスケジュール処理の平均時間は、バージョン16の4.0秒からバージョン17の2.8秒に短縮しました(30%の高速化)。また、別のより大きく複雑なデータでは、62秒が53秒になりました(15%の高速化)。スケジューリング以外の処理も高速化しています。
※これらの実測値は、CPUとしてIntel Core i7-6700Kを搭載したPCで計測したものです。

さらに、ガントチャートをズームして膨大な作業が描画される場合には、描画内容を簡略化することでレスポンスを向上させるといった工夫を施しました。ガントチャートの拡大・縮小・スクロールなどが目に見えて向上しています。

作業場計画オプション

「作業場計画オプション」は、作業場に配置する製造物同士の干渉をも制約としたスケジューリングをするためのオプション製品です。バージョン17では、この作業場計画オプションを大幅に機能強化しました。

配置制限

作業毎に、作業場内の特定の領域内に配置しなければならないという制約や、逆に特定領域内に配置してはならないという制約などを設定できるようになりました。たとえば、作業場内の特定範囲の天井が低いため背の高いワークはそこに配置してはならないというような、実情に合わせたきめ細かな計画を立案できます。

隙間を考慮した計画

ワークの周りに所定の大きさの隙間を空けるよう計画することができるようになりました。ワーク形状をCADからインポートしており作業スペースを含めていない場合や、ワークの周りに作業者が通れる空間を確保したい場合などに有用です。

形状入力時の操作性向上

形状の入力で、ドローソフト(お絵描きツール)のようにマウスで簡単に頂点を追加していくことができるようになりました。背景に参考にする画像を表示させてその上でプロットしていくこともできます。

作業場パネルの背景に画像を表示

作業場の背景に画像を表示できるようになりました。実際の作業場の画像と重ねて表示することでワークの配置場所をより簡単に把握できるようになります。

運用強化

形状や配置の異常をデータ検証メソッドで検出できるようになりました。また、作業実績テーブルで配置場所の実績情報を入力できるようになりました。

FLEXSCHE CarryOut

FLEXSCHE CarryOut(キャリーアウト)は、製造現場での計画遂行を支援する仕組みです。バージョン17ではさらに機能が強化されました。

サーバー上で作業実績を反映して計画更新

作業指図を実行可能な状態に維持できるようになりました。

従来は、上流工程の遅れや突発的なトラブルの影響を把握することが難しく、製造現場での場当たり的な判断に頼らざるをえない場合も多かったでしょう。作業の遅れやトラブルを反映した実行可能な計画を得るためには、いったん計画担当者まで戻してリスケジューリングする必要があり、現実には困難でしょう。特に計画立案の頻度が1日に1回、1週間に1回と限られている場合はなおさらです。

バージョン17では、CarryOutサーバー上で現在の状況を反映していつでも計画を更新できるので、いつでも実行可能な最新の指図を得ることができるようになりました。計画更新のためのスケジューリングルールは、FLEXSCHE GPと同様に自由に構築することができます。

なお、下記の「適応時間制約」により柔軟な時間バッファを予め組み込んでおくことで、作業の遅れやトラブルが発生しても影響を受けにくい安定した製造を実現できます。

クライアント画面のカスタマイズ

ユーザーや資源ごとにクライアント(タブレット)の画面レイアウトや表示項目を自由にカスタマイズできるようになりました。個々のユーザーに適した項目名に変えたり、見せたい情報だけを表示することができます。

標準の画面レイアウト

レイアウトや項目を変更し、
現場で閲覧するための図面を埋め込んだ

ユーザーインターフェース

表示まわりに多くの改良を施し、より柔軟に、より便利になりました。

ガントチャートのバーとテキストの描画方法のバリエーション

ガントチャートの望ましい見せ方は、人それぞれの好みや目的に応じてさまざまでしょう。

バージョン17では、資源ガントチャートとオーダーガントチャートの作業バーおよび文字の見せ方を整理し、バリエーションが大幅に増えました。さらに、限られたスペースに多くの文字情報を効率的かつ見易く描画するためのロジックも組み込まれています。

マイルストンの強化

シンボルのカスタマイズ

マイルストンのシンボル画像を自由に与えることができるようになりました。任意の画像ファイルをマイルストンシンボルとして利用できます。

オーダーガントにも表示

オーダーガントチャートにもマイルストンを表示できるようになりました。

描画の高速化とオーダーからの指定方法の拡張

特定のジョブガント行の特定の日時に、など、より自由にマイルストンを表示できるようになりました。また、描画処理の見直しによりパフォーマンスが向上しました。大量のマイルストンイメージを表示したとき、従来よりも描画が高速になりました。

サインボード行の強化

利用できるサインボード行の種類が増えました。

サインボード行として利用できるものの種類が増えました。新たに追加されたのは、作業、作業グラフ、工程グラフ、工程階層、仕様に対するサインボード行です。これまで以上に柔軟にチャートを構成して、見たい情報を直接表示することができるようになります。

オーダーガントチャート行左部を段毎に表示

一般に、1つのオーダーガントチャート行が複数の段で構成されることがありますが、その場合に、チャート行左部の表示内容を、段毎に切り替えることができるようになりました。この仕組みを利用して、たとえば図のような「品目工程別ガントチャート」を実現することもできます。

※複数カラムの場合にのみ有効です。

FLEXSCHE Editorの機能拡張

フィールド内にチェックボックス

チェックボックスにすることで文字列で表示するよりも見やすく、操作もチェックするだけなので簡単になります。

テーブルウィンドウからスナップショットを参照

テーブルウィンドウでスナップショットのデータを読み取り専用で表示できるようになりました。ある時点での計画データをガントチャートではなくマスタデータの視点から見比べられるようになります。

選択候補に正式名称を表示

仕様や品目、資源などを指定するフィールドに正式名称を表示できるようになりました。機械的につけられたコードではなくわかりやすく命名した正式名称を表示することで、よりデータを確認しやすくなります。

FLEXSCHE d-MPS(需給バランス調整オプション)の機能拡張

MPSエディタにユーザー定義の行

月次・日次の値を計算式で定義した行を追加することができます。例えばある時点でのMPSの計画をスナップショットに保存して、予定生産量と現時点の生産量を見比べるといったことも可能になります。

スケジューリングとモデリング

適応時間制約

作業の遅れなどがあらかじめ与えた工程間のバッファを食いつぶす様子を簡単にモデル化できるようになりました

工場の中にボトルネックとなる工程があるような場合に、工場全体のスループットを最大化するためには、ボトルネック工程を最大限に稼動させなければなりません。その際、ボトルネック工程が、前工程で発生した突然のトラブル(設備の故障など)や統計的な変動(サイクルタイムのバラつきなど)により止まったり速度を落とすことのないように、ボトルネック工程の前にあらかじめ時間的余裕を設けて計画するという手法が広く知られています。その余裕時間のことを「バッファ時間」といいます。

適応時間制約の仕組みを利用することで、このような計画手法に対応した、計画時には「バッファ時間」を含めて計画し、実行フェーズに入ったら遅れをバッファで吸収するようなモデリングとスケジューリングが簡単にできるようになりました。

原材料候補

代替原料がある場合など、スケジューリング時に状況に応じて選択させることができるようになりました

原料の候補が複数あるとき、従来は「このオーダーではこっちを使う」というように人があらかじめ決めておく必要がありました(セレクタを使う方法)。

選択をスケジューラに任せて品目を動的に変える方法もありましたが、「この資源(設備)で作業するのであればこっちを使う」というような限定的なものでした(品目選択を使う方法)。

バージョン17では、候補となる資源と品目のすべての組み合わせにおいて、どれを選ぶと良いかをスケジューリングルールから評価できるようになりました。例えば「原料Aを優先的に使うけれども、足りなければ原料Bを使っても良い」というようなルールを決めておくことで、各オーダーに対してどの資源、どの品目を使うかをスケジューラが状況に応じて判断してくれるようになります。

選択される側に複数のセレクタを指定

工程バリエーションの表現がよりシンプルに

セレクタとは、従来よりFLEXSCHEに備わっている仕組みであり、必要とする原料や前工程に名前(="セレクタ")を与え、オーダーごとに選択することができます。この例では、高々2つの工程で製品を作りますが、4種類の原料が必要か("A1"、"A2"、"B1"、"B2")、"工程1"を行う必要があるか("L1")を自由に選択してオーダーに列挙することができます。この例ではこのようにして3つの作業のパターンを作り出しています。

この方法では組み合わせを自由(上の例では数10パターン存在する)に表現できる一方、

  • 組み合わせを表現するためにいちいち列挙しなくてはならず煩雑
  • 実際に許されていない組み合わせも表現できてしまう

という欠点もあります。

そこでバージョン17では、許されている組み合わせパターンに名前を与え、工程を定義する際にそれを(必要であれば列挙して)工程に設定することもできるようになりました。この例では、3つの組み合わせパターンに"T1"、"T2"、"T3"という名前を与え、それらが必要とする箇所にセレクタとして設定しています。パターン"T2"と"T3"はいずれも"工程1"を必要とするので、これらを列挙したセレクタ文字列"T2|T3"を工程間に設定しています。このようにすることで、オーダーからは単純に組み合わせパターンの名前を指定すればよく、また許されていない組み合わせを誤って指定してしまうこともなくなります。

自動ロット引当メソッド強化

自動ロット引当メソッド(上級オプション「オーダー自動引当て」の機能)を更に強化しました。

数量制限

ロット間の引当数量に対する上限を計算式で指定できるようになりました。たとえば、数量的には供給側と需要側とを1:1で引き当てることができる場合にも、あえて1:Nで引き当てて並列して製造させることによりリードタイムを短縮する、ということを実現できます。

相手ロットを動的に選択

引当相手の選択をより柔軟に行えるようになりました。たとえば「なるべく残り数量とぴったり合う相手と引き当てる」ということを実現できます。

安全在庫量水準推移に対応

従来も、将来急遽発生するかもしれない需要のために安全在庫量の分を引き当てずに残しておくことができましたが、さらに、安全在庫量が時期によって変化する場合にも時期に応じた量を残すことができるようになりました。

FLEXSCHE EDIF(データインターフェース)

FLEXSCHE EDIFは、外部データソース(データベースやCSVファイル)とFLEXSCHEの間で柔軟にデータ交換するための仕組みです。レイアウトを自由に定義できるExcel帳票を出力する機能も備えています。

バージョン17では、FLEXSCHE EDIFの機能をさらに強化しました。

ADO.NETに対応し、高速化と対象データベースの拡大

ADO.NETプロバイダーに対応することでEDIF差分エクスポートでは最大60倍の高速化を実現しました(Oracle 20万作業の差分エクスポートの場合)。また新たにMySQL、DB2、PostgreSQLといったADO.NETプロバイダーをサポートしているデータベースでEDIFを実行できるようになりました。

レコードの書き出し順序を指定(ソート)

レコードの書き出し順序を計算式で指定できるようになりました。従来はFLEXSCHE内部のレコード順固定でしたが、納期順、数量順など任意の順序で出力が可能です。

テーブルマッピング「作業(更新)」を追加

コメントなどの一部の特定項目に限り、既存の作業に対して差分インポートができるようになりました。外部データの情報を既存の作業にまとめて書き込むことができます。

Excel帳票のシート名を計算式で指定できるように

Excel帳票の出力シート名は従来は固定的でしたが、計算式で指定できるようになりました。

入門ガイド追加

EDIF、Excel帳票に関する入門ガイドを追加しました。ガイドに従って操作することでEDIFの機能とExcel帳票の機能を体験することができます。

計算式関連

名前付き引数

関数を呼び出す際の引数を、本来の順番に関係なく、引数名と値の組で指定できるようになりました。特に、関数に多くの省略可能引数がある場合に便利です。

従来の記法:
.NeighborOperations( LinkType.In, , , true )
新たに使えるようになった記法:
.NeighborOperations( LinkType.In, overConnection:true )

ナップサック問題を解く関数

組合せ問題の1つ「ナップサック問題」を解く関数List.SolveKnapsackを利用できるようになりました。例えば、これを自動ロット引当メソッドで利用することで、複数の供給ロットにまたがって引き当ててはいけない場合に、なるべく無駄が少なくなるような組合せを選ぶことができます。

{600,300,150,220,450,500}.SolveKnapsack(1000)
結果=> {600,150,220}

プログラミング関連(開発者向け)

FSFモードレスフォームをアドイン等から更新したり閉じたり

FLEXSCHE Scripting Formは、スクリプト(JavaScript/VBScript)の記述だけで手軽にフォーム(ダイアログ、パネル、ビュー)を作成するための仕組みです。しかし従来、パネルやビューを閉じたり、表示内容を更新したりする契機は、パネルやビューに対してマウスなどで直接操作したときに限られていました。

バージョン17では、フォーム外のアドインなどからも操作できるようになり、活用範囲が大幅に広がりました。

構造化記述メソッドから外部メソッド呼出しメソッドのスクリプトを生成

条件分岐やループなど、複雑な制御構造を持つ高度なスケジューリングルールを記述するための「構造化記述メソッド」では、処理の流れをダイアログ上で入力します。規模が小さいうちは便利ですが、大きくなってくるとプログラミングに慣れた開発者にとっては、テキストエディタを使ったコーディングの方が望ましい場合も多いでしょう。特に試行錯誤を要するなルール作成においては、スクリプティングの方が効率的です。とはいえ、既存の構造化記述メソッドの定義と等価なスクリプトコード(外部メソッド)をゼロから書くことは、かなり面倒な作業です。

そこでバージョン17では、既存の構造化記述メソッドから等価なJavaScriptコードの雛形ファイルを生成し、それを呼び出す新たな「外部メソッド呼び出しメソッド」が追加できるようになりました。そのまま動作するコードが生成されるわけではありませんが、変換作業の大部分が肩代わりされるので、いくらかの手直しで動作させることができるでしょう。

実装例を表示する

// External method
// Class name : @optimize
// Entry name : optimize
// このひな形コードをそのまま実行することはできません。コード中に現れる計算式や変数を
// 適切に書き換えてください。
// ・代入文の左辺値をtakt計算式からJavaScriptの計算式に書き換えられない場合は、
//  SDSpace.Calculate()で評価するように書き換えてください。
//  計算式内で変数を参照している場合は、CreateTypedExpressionでISDExpression
//  インスタンスを作って、ISDExpression.AddVariable()で値を与えることができます。
// ・制御構造内で同じ計算式が繰り返し評価される場合は、ISDExpressionインスタンスを
//  使いまわすことで、無駄な式解析処理を省くことができます。
// ・スケジューリングメソッドから構造化記述メソッド内で宣言した変数を参照している
//  場合は、メソッドのパラメタとして宣言し、IGPExecutableEntity.ParameterValue()で
//  値を明示的に与えるように書き換えてください。
// ・コードを書き換えた後、[ツール]-[アドイン再登録]を実行すると外部メソッドが
//  利用可能になります
function _optimize( gpManager, settings )
{
/*
  // select target, record list as 'opers' / オブジェクトマーキング
  var method_00 = gpManager.CreateExecutableEntity( Script.Null,
	'scheduling-method', '4FFFD14593C84439A4D62E5DB227F36E' );
  // clear flag 'operToMove' for opers / オブジェクトマーキング
  var method_01 = gpManager.CreateExecutableEntity( Script.Null,
	'scheduling-method', 'A8D3706703CE4E8EB6AC0C0A8375B484' );
  // record let, dt on NumSpec / プロパティ設定
  var method_02 = gpManager.CreateExecutableEntity( Script.Null,
	'scheduling-method', '634157C095E24B1BB93F689F84C31BE6' );
  // RecordAsBest0-0(Unassign) and unassign pendings / 作業割付け解除
  var method_03 = gpManager.CreateExecutableEntity( Script.Null, 'scheduling-method',
	'B2527E9FCBD043A1A42219C034CD78C9' );
  // calc LST (1) and record 'lst' and 'mwtH' for each resource / 作業主導ディスパッチング
  var method_04 = gpManager.CreateExecutableEntity( Script.Null, 'scheduling-method',
	'98D62C9A03144FA492FEB6C0C570B700' );
  // calc LST (2) / 作業割付け解除
  var method_05 = gpManager.CreateExecutableEntity( Script.Null, 'scheduling-method',
	'9D217769F85245EEAE162106294A9E0C' );
  // RecordAsBest0-1(Reassign) / 作業主導ディスパッチング
  var method_06 = gpManager.CreateExecutableEntity( Script.Null, 'scheduling-method',
	'E5124B4CBBF34A25A012F999664BF18D' );
  // 作業割付け解除
  var method_07 = gpManager.CreateExecutableEntity( Script.Null, 'scheduling-method',
	'15629FBD5DEF4A2290111B8E61B8C0BA' );
  // move operToMove to resToMove at timeToMove / 作業主導ディスパッチング
  var method_08 = gpManager.CreateExecutableEntity( Script.Null, 'scheduling-method',
	'9E8CD555763143958204A9071AFFA958' );
  // relocate resToMove / フォワード再割付け
  var method_09 = gpManager.CreateExecutableEntity( Script.Null, 'scheduling-method',
	'701D79C8FD4C4B1E929C712B13589D57' );
  // record dt on NumSpec for opers on resToMove / プロパティ設定
  var method_10 = gpManager.CreateExecutableEntity( Script.Null, 'scheduling-method',
	'1FAA32D06BA044E59D913B681ED77490' );
  // record as tabu / プロパティ設定
  var method_11 = gpManager.CreateExecutableEntity( Script.Null, 'scheduling-method',
	'948A309CBBF648A59E8C2BBA583C4584' );
  // Record As Best / フォワード再割付け
  var method_12 = gpManager.CreateExecutableEntity( Script.Null, 'scheduling-method',
	'D2120074768E4DFDA3323B42151E209A' );
  // (debug) record evalBest on Project.Property / プロパティ設定
  var method_13 = gpManager.CreateExecutableEntity( Script.Null, 'scheduling-method',
	'55B91F351A27429C834E15DD2A5C59F4' );
  // (debug) record eval on Project.Property / プロパティ設定
  var method_14 = gpManager.CreateExecutableEntity( Script.Null, 'scheduling-method',
	'CDDADFCCE3054BA588F9E8171CDD1674' );
  // clear tabu / プロパティ設定
  var method_15 = gpManager.CreateExecutableEntity( Script.Null, 'scheduling-method',
	'F739DD31ACAF4D12B952438EC9CDEEC2' );
 【中略】
  var cMetaRepeat;
  var cRepeat;
  var debug;
  var evalBest;
  var opersTabu;
  var ress;
  method_00.Execute(); // select target, record list as 'opers'
  cMetaRepeat = 3;
  cRepeat = 500;
  debug = true;
  if( $debug )
	method_01.Execute(); // clear flag 'operToMove' for opers
  method_02.Execute(); // record let, dt on NumSpec
  ress = $opers.Union([.AssignedResource]);
  evalBest = $opers._Eval01 + $ress.Sum([$opers._EvalForRes($_object)]);
  if( $evalBest > 0 )
  {
	var iMetaRepeat;
	var iRepeat;
	method_03.Execute(); // RecordAsBest0-0(Unassign) and unassign pendings
	method_04.Execute(); // calc LST (1) and record 'lst' and 'mwtH' for each resource
	method_05.Execute(); // calc LST (2)
	method_06.Execute(); // RecordAsBest0-1(Reassign)
	iMetaRepeat = 0;
	while( $iMetaRepeat < $cMetaRepeat and $evalBest > 0 )
	{
	  if( true )
	  {
		var cRes;
		var eval;
		var iRes;
		cRes = $ress.Count;
		iRes = 0;
		while( $iRes < $cRes )
		{
		  var opersOnRes;
		  var resToMove;
		  resToMove = $ress.At($iRes);
		  opersOnRes = $resToMove.AssignedOperations.Select([.Flag('target')]);
		  while( true )
		  {
			var operToMove;
			var timeToMove;
			operToMove = $opersOnRes.Select([not .Flag('tabu')
			  and ._dEval3_ToJoinLeft <= 0]).MinAt([.ManufactureStartTime]);
			if( not $operToMove.DoesExist )
			  break;
			timeToMove = $operToMove._TimeToJoin($resToMove);
			if( $timeToMove.IsNormal and $timeToMove < $operToMove.StartTime )
			{
			  method_07.Execute(); // 作業割付け解除
			  method_08.Execute(); // move operToMove to resToMove at timeToMove
			  method_09.Execute(); // relocate resToMove
			  method_10.Execute(); // record dt on NumSpec for opers on resToMove
			}
			if( true )
			  method_11.Execute(); // record as tabu
		  }
		  iRes = $iRes + 1;
		}
		eval = $opers._Eval01 + $ress.Sum([$opers._EvalForRes($_object)]);
		if( $eval < $evalBest )
		{
		  method_12.Execute(); // Record As Best
		  evalBest = $eval;
		  if( $debug )
			method_13.Execute(); // (debug) record evalBest on Project.Property
		}
		if( $debug )
		  method_14.Execute(); // (debug) record eval on Project.Property
	  }
	  if( true )
	  {
		method_15.Execute(); // clear tabu
		opersTabu = OperationList.Empty;
	  }
	  iRepeat = 0;
	  while( $iRepeat < $cRepeat and $evalBest > 0 )
	  {
		var eval;
		var operToImprove;
		var operToMove;
		operToImprove = $opers.Select([.NumSpec('dt')<0 and not .Flag('tabu')])
		 .MinAt([.ManufactureStartTime]);
		if( not $operToImprove.DoesExist )
		  break;
 【後略】

テーブルウィンドウのサブキーにEditingとEditedを追加

テーブルウィンドウの本体部のアドインのサブキーにEditingとEditedを追加しました。フィールドが編集される直前と直後にアドインを追加することができます。 例えば編集前のアドインでは禁則文字やフォーマットのチェックなどを行い、値を変換して入力を受け付けたり、入力自体をキャンセルするアドインを作ることができます。 編集後のアドインでは編集によって影響を受けるデータやビューに対して更新をかけるといったことが可能になります。

その他

zip版FLEXSCHE

社内の情報システムの管理上の事情により、FLEXSCHEの評価版や新バージョンの機能を試すことを目的として安易にインストールできない場合が少なくありません。たとえそのような制限が無くとも、いったんインストールしたバージョンをアンインストールして元に戻すことは煩雑で避けたいことでしょう。

バージョン17のzip版FLEXSCHEならば、わざわざインストールせずともzip形式圧縮ファイルを展開して任意のフォルダに配置するだけでFLEXSCHEを実行することができます。zip版FLEXSCHEはシステム(レジストリなど)に何も書き込まないので、複数バージョンを配置しても互いに干渉することがなく、「いろいろ試してみる」という用途に向いています。ただし、.NETアドインが動作しない、オートメーションクライアントから操作できないなど、いくつかの制限事項(起動時に表示されます)があるので、実運用を目的としてお使いいただくことはできません。

FLEXSCHE製品のご紹介

PAGETOP