gikoha’s blog

個人的メモがわり

macdonald問題のGMPLによる解

 

macdonald問題の GMPL による解

  • ひきつづき GMPLのお勉強
  • データの元となる CSV の作成
    • macdonald公式の栄養表を CSVに変換する
    • curl -O "https://www.mcdonalds.co.jp/quality/allergy_Nutrition/nutrient/index.html"
    • perl cpan から HTML::TagParser をインストールしておく
    • perl makecsv.pl > macdonald.csv
#!/usr/bin/perl
use warnings;
use strict;
use HTML::TagParser;

# curl -O "https://www.mcdonalds.co.jp/quality/allergy_Nutrition/nutrient/index.html"

my $html = HTML::TagParser->new( 'index.html' ); # Change this to your file

print "itemname,weight,energy,protein,lipid,carbonate,natrium,kalium,calcium,phosphorus,fe,vita,vitb1,vitb2,niacin,vitc,chol,fiber,nacl\n";

my $nrow = 0;
for my $tr ( $html->getElementsByTagName("tr" ) ) {
    my $ncol = 0;
    for my $td ( $tr->subTree->getElementsByTagName("td") ) {
        last if $ncol == 19;
        my $c =  $td->innerText();
        if ($c =~ /^備考1/)
        {
            exit(0);    # abort program
        }
        print "," if $ncol++ != 0;
        print $c;
    }
    print "\n" if $nrow>2;
    $nrow++;
}
  • GMPLには if {} 文がないため、for で代用する
  • たとえば NaCl>8g protein>40g calorie>1400kcalを満たす最低カロリーの組み合わせを選ぶプログラムは下記
  • 実行: glpsol -m reader.mod
    • reader.mod:7: duplicate tuple 'カフェラテ(M)' detected などと出る際は複数出現しているエントリをcsvから削除する必要がある
  • reader.modは下記
set I;
var x{I} ,integer, >=0;
param ene{I};
param prot{I};
param nacl{I};

table data IN "CSV" "macdonald.csv" : 
    I <- [itemname], ene ~ energy, prot ~ protein, nacl ~ nacl;

minimize CALORIE: sum{i in I} ene[i]*x[i];
s.t. CONSTRAINT1: sum{i in I} nacl[i]*x[i] >= 8.0;
s.t. CONSTRAINT2: sum{i in I} prot[i]*x[i] >= 40.0;
s.t. CONSTRAINT3: sum{i in I} ene[i]*x[i] >= 1400.0;

# printf {i in I} "%s %.1f %.1f %.1f\n", i, ene[i], prot[i], nacl[i];

solve;

for { i in I }
{
    for {{0}: x[i]>0} {  #  GMPL には if block がないため、 if x[i]>0 のかわりに forを使う
        printf "%s   %d個  %.1f %.1f %.1f\n", i, x[i], x[i]*ene[i], x[i]*prot[i], x[i]*nacl[i];
    }
}
end;

macdonald.csv

itemname,weight,energy,protein,lipid,carbonate,natrium,kalium,calcium,phosphorus,fe,vita,vitb1,vitb2,niacin,vitc,chol,fiber,nacl
えびフィレオ®,174,395,12.5,17.4,47.7,919,119,64,102,0.8,8,0.09,0.06,1,1,66,2.9,2.3
ごはんてりやき,213,545,14.5,29.4,55.8,986,237,33,149,0.9,10,0.16,0.16,3.3,1,56,0.8,2.5
ごはんフィッシュ 和風黒胡椒,194,430,15.4,15.7,57.3,944,206,102,248,0.4,52,0.08,0.1,1,0,45,1.5,2.4
...省略...

実行例

GLPSOL--GLPK LP/MIP Solver 5.0
...
Time used:   0.0 secs
Memory used: 0.8 Mb (866271 bytes)
塩・コショウ   7個  7.0 0.0 4.2
アールグレイ アイスティー(ストレート)(L)   2個  6.0 0.0 0.0
アールグレイ アイスティー(ミルク)(M)   27個  351.0 5.4 0.0
コカ・コーラ ゼロ(L)   19個  0.0 0.0 1.9
ホットティー(ミルク)(M)   1個  14.0 0.5 0.0
リキッドレモン   1個  1.0 0.0 0.0
ダージリンティー(M)   99個  0.0 19.8 0.0
ダージリンティー(テイクアウト用)(M)   1個  0.0 0.3 0.0
チョコフラッペ(L)   1個  574.0 7.8 1.1
チョコフラッペ(M)   1個  447.0 6.3 0.8
Model has been successfully processed
  • 飲み物禁止とするべきか..