オンザフライパーサー/事前世代のスペース/時間のトレードオフの考慮事項
-
14-11-2019 - |
質問
オンザフライパーサーを使用するというスペース関連の利点は、事前生成されたルックアップテーブルの時間関連の利点を上回りますか?
長いバージョン:
私は化学基準ツールを作成しており、特定のパターンに適合する式に自動的に名前を付ける機能を含めています。例えばC[n]H[2n+2] => [n]ane
; [n]
はLHSの整数です。そしてRHS上の名前の配列へのインデックス。 (meth
、eth
、...)
私が見ることができる限り、これは2つの方法のうちの1つで実装することができます:
-
私は
formula <=> name
ペアのキー/値デュアルルックアップ辞書を事前生成します。アプリケーションが起動したとき(起動が遅く)、またはアプリケーションで公開されている静的リスト(遅いダウンロード)。 -
式は、カスタムビルドパーサーによってその場で評価されます。 アプローチ1。 name=>式ルックアップは、桁違いの順序でより簡単になる。しかし、ジェネレータは、アプリケーションと一緒に数十のデータを送りたいとしたら、PRESETを持ち、かなり低く、
n
の値を持たなければなりません。配合これは、式がいくつかの用語を持つことができるという事実です。
C[n]H[2n+1]OC[n']H[2n'+1]
などこれらのそれぞれについて、可能な一致の数はn
と幾何学的に増加します。さらに、このアプローチを使用すると、誰ものビジネスのようなRAMを食べます。アプローチ2。は、かなり小さなルックアップテーブルを使用して、かなり大きな値の
n
をサポートしますが、名前=>式ルックアップをやや複雑にします。アプリケーションでの出荷用のファイルへの事前世代と比較して、新しいデータファイルを出荷する必要なしに世代ロジックのエラーを正しく修正できます。これはまた、それがいくつかの規則のためのカーソルテストと照合されることを必要とし、それがFIT フィットすることができるかどうかを判断する。これは、たくさんの規則がある場合は、インターフェイス内の顕著なスローダウンが発生する可能性がある時間がかかります。
問題は次のとおりです。
-
私が考慮した、または私が考慮していないアプローチに失敗したトレードオフの考慮事項はありますか?
-
オンザフライパーサーを使用することの利点は、実装の複雑さの増加を正当化することの利点を示しますか?
-
解決
あなたは2番目のアプローチで行くべきです。
1つの可能な解決策は貪欲なアルゴリズムです。一連の変換を正規表現(パターンのテストに使用される)と、Regexp Matchオブジェクトが与えられた関数として定義し、変換された文字列を返します。
正規表現は、直接欲しいものを処理するのに十分なほど強力ではありません。代わりにあなたは次のようなことをする必要があります:
m = re.match(r"C\[(\d+)\]H\[(\d+)]\]", formula)
if m:
C_count, H_count = int(m.group(1)), int(m.group(2))
match_size = len(m.group(0))
if C_count*2+2 == H_count:
replacement = alkane_lookup[C_count]
elif C_count*2 == H_count:
replacement = alkene_lookup[C_count]
...
else:
replacement = m.group(0) # no replacement available
.
(他の可能性のためにもっとたくさん)
その後、次のように見えるループにそれを埋め込みます。
formula = "...."
new_formula = ""
while formula:
match_size, replacement = find_replacement(formula)
new_formula += replacement
formula = formula[match_size:]
.
(一致する場合は扱う必要があります。1つの可能な方法は、find_replacement()の最後にあるすべての可能な要素のリストを含めることです。これは次の要素とカウントだけを返します。)
これは貪欲なアルゴリズムで、最小の解決策を保証しません。それはより複雑ですが、化学者自身が正しい形の異なる考えを持っているので、私はそれについてとても心配しないでしょう。