自炊 -Singularity-

この記事は CCS †裏† Advent Calendar 2022 の 22 日目の記事として作成されました。

前日の記事はあきひよくんの日記です。

ラブライブ、キラキラしていて眩しい……
語尾がにゃのキャラは知ってるかも。







null です。


私は一人暮らしであるにもかかわらず、自炊を1年以上していません。

というか調理器具がありません。フライパンも鍋も捨てたので



自炊をしなくなった理由の一つとして、献立を考えるのが面倒というのがあります。



そこで今回は、 AI に献立を考えてもらうことにしました。



Chat GPT 編



Q.
自炊をしたいのですが、良い献立が思いつきません。献立を考えてください。

A.
いろいろな献立を考えられますが、最初に考えることは、あなたが好む食材や料理のスタイルです。また、自炊をするときは、栄養バランスも考えるとよいでしょう。

その上で、いくつかの献立のアイデアを提案します。

  • パスタ料理:スパゲッティやマカロニ、ペンネ、ラザニアなどを使って、肉や野菜と一緒に作る料理ができます。野菜は、スライスして焼いたトマトや、マリネしたニンジン、ステーキにしたエビなどが使えます。肉は、豚肉や牛肉のステーキや、小さくカットした鶏肉を使うことができます。

  • ステーキや焼き鳥:肉を主役にした料理です。牛肉や豚肉、鶏肉を使い、ステーキや焼き鳥を作ることができます。サラダや、焼いた野菜(ジャガイモやトマト、ナスなど)と一緒に提供するとよいでしょう。

  • お吸い物やスープ:鍋を使って、お吸い物やスープを作るのも良いでしょう。鶏肉や豚肉、野菜を使ったスープや、魚を使ったお吸い物が人気です。スープは、ラーメンやうどん、そば、その他の中華麺類と一緒に提供することもできます。

  • ベジタリアン料理:肉を使わず、野菜だけで作る料理もあります。野菜を使ったカレーや、野菜のグリルやサラダ、ステーキなどがあります。豆類やナッツ、卵、チーズを使った料理も良いでしょう。

これらはあくまでもアイデアですので、あなた



かなりしっかりした返答でびっくりしました。普通に参考になる。

パスタくらいは茹でるようにしたいです。


AI のべりすと編

Take 1


自炊をしたい。
今日の献立は、
お米と味噌汁に魚だな。
「さて、ちゃっちゃっと作りますか」
まずは、米研ぎからだ。
俺の持っているスキル【農業】を使えば、美味しいお米が作れるはずだ。
『農業』スキルを発動すると、目の前にタブレットが現れた。
このタブレットには、水や肥料の配合データなどが入っているらしい。
「どれどれ……」
タブレットを操作してみると、いくつかの項目があった。
その項目の一つに、【肥料の種類】というものがあった。
「えーっと、何々……【土壌改良剤:1粒】で100分の1ポイントアップ?」
100分の1ってことは、一粒10ポイント?
とりあえず試しに使ってみようと思い、俺は【土壌改良剤:1粒】の項目をタッチした。
すると、画面が切り替わった。
そこには、様々な種類の肥料が表示されていた。
「へぇ~、色んな種類あるんだなぁ……あ!これなんか良さそうだ!」
画面に表示されている肥料を見てみると、その中に気になる物を見つけた。
それは、『有機質堆肥』というものだった。
説明欄を読んでみると、どうやら野菜を育てるのに適したものみたいだ。
「よしっ!これにしよう!」
早速、【土壌改良剤:1粒】をタップする。
すると、画面が切り替わり、肥料の名称と個数を入力するように表示された。俺は肥料の名前を入力していく。
「これでいいかな……」
入力を終えて決定ボタンを押すと、タブレットの画面が変わった。
「うおっ!?」
驚いたことに、先ほど入力した文字が消えて、代わりに数字の羅列が表示されていたのだ。
そして、数字はどんどん減っていく。「これはもしかして……【土壌改良剤:1粒】を使うために必要な数値なのか?」
タブレットの数値を見つめながら考えていると、頭の中に声が聞こえてきた。
《条件を満たしました》
「うわっ!!ビックリした!!」
突然の出来事に驚いていると、また頭に声が流れ込んできた。
《あなたが今使用した【土壌改良剤:1粒】は、畑で使用することができません》
「えっ?どういうことだ?」
俺は不思議に思いながらも、もう一度画面を見た。
すると、いつの間にか【土壌改良剤:1粒】の数字が減っており、0になっていた。
「あれ?無くなってるぞ?なんでだろ……」
そう呟きながら、首を傾げていると……
《使用済みの肥料を削除しますか?Yes/No》 Yesを選択すると、タブレットから肥料の粉末のようなものが出てきた。
それを指先で摘まむと、フワッとした感触が伝わってくる。
「これが肥料の粉か……ちょっと舐めてみるか」
俺は、摘まんでいた肥料の粉を口に入れた。
「うん、美味しくないな」
口の中に広がる苦味を感じながら、タブレットを操作する。
「ん~、他に何か使えそうなものはないか探してみよう」
それからしばらくの間、色々な肥料を使ってみた。その結果分かったことがある。
「なるほどね……このタブレットを使えば、作物に適した肥料を作ることができるのか」
それなら、わざわざ買ったり作ったりする必要が無いな。それにしても、このタブレット便利すぎるな……。
これさえあれば、俺でも農業ができるんじゃないか?
「よし!そうと決まれば、まずは何を作ろうかな♪」
こうして、俺の新しい生活が始まったのだった。………………
「よーし!次は大豆を作ってみ



農家になるといいらしいです。



Take 2


nullクッキングの時間です。
今日の献立は、
《リゲムチャのクリームパスタ》と《オニオンスープ》になります。
まず初めに、《リゲムチャのクリームパスタ》の材料を紹介します。
・リゲムチャ(生):5個
・クリームソースパスタ
:2人前・玉ねぎ
:1個
・オリーブオイル
:大さじ3杯
・白ワインビネガー
:小さじ1/2杯
・塩コショウ
:少々
・パルメザンチーズ
:適量
・黒こしょう
:適量 1、フライパンにオリーブオイルをひいて、弱火で熱し、リゲムチャを炒める。
2、玉ねぎを加え、透き通るまでじっくり炒めたら、クリームソースパスタを加えて絡めるように炒める。
3、器に盛ったら、お好みで黒こしょうを振りかけて完成!****
「…………」
「どう? 簡単でしょう?」
「いや、これは料理じゃないだろ!?」
「何言ってんのよ! 立派な料理じゃん!」
「どこがだよ! リゲムチャってなんだ!? あと玉ねぎもおかしいからな!!」
「あーもううるさいわね!! いいから食べてみなさいよ!!」
「うおっ!?」
俺は無理矢理口にパスタを突っ込まれた。
「――っ!!」
口の中に広がる強烈な酸味。そして、喉の奥へと押し込まれるパス



リゲムチャって何?

あと最後ハルヒとキョンっぽい。ハルヒ見たことないけど


Take 3


お腹が空いた。「さて、そろそろ行くか」
俺は立ち上がり、歩き出した。
俺の頭の中には、すでに先ほどの光景は消えていた。
そして、次に頭によぎるのは……
「さっさと、レベルを上げて【転移】で戻ろう」
という事だけだった――――――――
ここまで読んでいただきありがとうございます! よろしければご感想や評価をいただけますと幸いです。
(本当に励みになります)
モチベーションアップのためにポチッとしてくださると嬉しいです(^ω^)



カスのなろう



自作 AI 編


さすがに Chat GPT と AI のべりすと のコピペだけは適当すぎるので、自分でも何か作ってみることにしました。


とは言ったものの、機械学習の技術などは持ち合わせていないため、なにか作れるとは思えない……


そこで代わりとして、最適な自炊の頻度を線形計画問題(LP)に帰着させて求めてみることにしました。

線形計画問題は、目的関数制約関数がともに変数の線形和で表される最適化問題を指します。
simplex method などを用いてある程度高速に解けることが知られています。


レギュレーションは以下です。


変数

一週間の各曜日の自炊の有無を $${0-1}$$ 変数 $${x_{i,j}}$$ として表します。
$${i}$$ は曜日 ($${i=0}$$ が月曜、$${i=1}$$ が火曜、…、$${i=6}$$ が日曜)、$${j}$$ は昼夜 ($${j=0}$$ が昼、$${j=1}$$ が夜) とします。

朝ご飯は食べないので要りません。


目的関数

一回の外食を $${600}$$ 円、自炊を $${300}$$ 円としたときの食費の最小化を目的とします。
つまり、

$$
\sum_{i=0}^{6} \sum_{j=0}^{1} (600-300x_{i,j})
$$

を最小化します。(自炊を一回するごとに $${300}$$ 円得をするイメージ)
定数項がありますが、適当に $${1}$$ しか取らない変数を導入すればOKです。


 制約関数

最適化問題らしくするために、いくつかの制約を追加してみましょう。


  • 一週間に一回以上は自炊をする

自炊を一回もしないのは意味がないので、最低一回は自炊するものとします。

これは $${\sum_{i=0}^{6} \sum_{j=0}^{1} x_{i,j} \ge 1}$$ と表現できます。


  • 同じ日に二回以上自炊をしない

疲れるので。

これは $${x_{i,0}+x_{i,1} \le 1\ (0\le \forall i \le 6)}$$ と表現できます。


  • 月曜昼、木曜昼、土曜夜、日曜夜は自炊をしない

予定が入っていることが多いので、この日・時間帯は除きます。

$${ x_{0,0}=0,\ x_{3,0}=0,\ x_{5,1}=0,\ x_{6,1}=0 }$$ と表現できます。


  • 連続する $${3}$$ 日間のうち、自炊をするのは $${2}$$ 回まで

これくらいの頻度で十分です。

$${\sum_{i=k}^{k+2} \sum_{j=0}^{1} x_{i\ {\rm mod}\ 7,j} \le 2\ (0\le \forall k \le 6)}$$ と表現できます。



解いてみる

Python の PuLP と呼ばれるモジュールを用いると、線形計画問題を簡単に解くことができます。

コード:

import pulp

problem = pulp.LpProblem("SelfCooking", pulp.LpMinimize)

x = pulp.LpVariable.dicts('x', [(i, j) for i in range(7) for j in range(2)],
                          cat='Binary')
const = pulp.LpVariable('const', 1, 1)

problem += pulp.lpSum(
    [600 * const - 300 * x[i, j] for i in range(7) for j in range(2)])

problem += pulp.lpSum(x[i, j] for i in range(7) for j in range(2)) >= 1
for i in range(7):
    problem += x[i, 0] + x[i, 1] <= 1
problem += x[0, 0] == 0
problem += x[3, 0] == 0
problem += x[5, 1] == 0
problem += x[6, 1] == 0
for k in range(7):
    problem += pulp.lpSum(x[i % 7, j] for i in range(k, k + 3)
                          for j in range(2)) <= 2

print(problem)

status = problem.solve()

for j in range(2):
    for i in range(7):
        print(int(x[i, j].value()), end=' ')
    print()

実行結果:

SelfCooking:
MINIMIZE
8400*const + -300*x_(0,_0) + -300*x_(0,_1) + -300*x_(1,_0) + -300*x_(1,_1) + -300*x_(2,_0) + -300*x_(2,_1) + -300*x_(3,_0) + -300*x_(3,_1) + -300*x_(4,_0) + -300*x_(4,_1) + -300*x_(5,_0) + -300*x_(5,_1) + -300*x_(6,_0) + -300*x_(6,_1) + 0
SUBJECT TO
_C1: x_(0,_0) + x_(0,_1) + x_(1,_0) + x_(1,_1) + x_(2,_0) + x_(2,_1)
 + x_(3,_0) + x_(3,_1) + x_(4,_0) + x_(4,_1) + x_(5,_0) + x_(5,_1) + x_(6,_0)
 + x_(6,_1) >= 1

_C2: x_(0,_0) + x_(0,_1) <= 1

_C3: x_(1,_0) + x_(1,_1) <= 1

_C4: x_(2,_0) + x_(2,_1) <= 1

_C5: x_(3,_0) + x_(3,_1) <= 1

_C6: x_(4,_0) + x_(4,_1) <= 1

_C7: x_(5,_0) + x_(5,_1) <= 1

_C8: x_(6,_0) + x_(6,_1) <= 1

_C9: x_(0,_0) = 0

_C10: x_(3,_0) = 0

_C11: x_(5,_1) = 0

_C12: x_(6,_1) = 0

_C13: x_(0,_0) + x_(0,_1) + x_(1,_0) + x_(1,_1) + x_(2,_0) + x_(2,_1) <= 2

_C14: x_(1,_0) + x_(1,_1) + x_(2,_0) + x_(2,_1) + x_(3,_0) + x_(3,_1) <= 2

_C15: x_(2,_0) + x_(2,_1) + x_(3,_0) + x_(3,_1) + x_(4,_0) + x_(4,_1) <= 2

_C16: x_(3,_0) + x_(3,_1) + x_(4,_0) + x_(4,_1) + x_(5,_0) + x_(5,_1) <= 2

_C17: x_(4,_0) + x_(4,_1) + x_(5,_0) + x_(5,_1) + x_(6,_0) + x_(6,_1) <= 2

_C18: x_(0,_0) + x_(0,_1) + x_(5,_0) + x_(5,_1) + x_(6,_0) + x_(6,_1) <= 2

_C19: x_(0,_0) + x_(0,_1) + x_(1,_0) + x_(1,_1) + x_(6,_0) + x_(6,_1) <= 2

VARIABLES
const = 1 Continuous
0 <= x_(0,_0) <= 1 Integer
0 <= x_(0,_1) <= 1 Integer
0 <= x_(1,_0) <= 1 Integer
0 <= x_(1,_1) <= 1 Integer
0 <= x_(2,_0) <= 1 Integer
0 <= x_(2,_1) <= 1 Integer
0 <= x_(3,_0) <= 1 Integer
0 <= x_(3,_1) <= 1 Integer
0 <= x_(4,_0) <= 1 Integer
0 <= x_(4,_1) <= 1 Integer
0 <= x_(5,_0) <= 1 Integer
0 <= x_(5,_1) <= 1 Integer
0 <= x_(6,_0) <= 1 Integer
0 <= x_(6,_1) <= 1 Integer

Welcome to the CBC MILP Solver 
Version: 2.10.3 
Build Date: Dec 15 2019 

command line - /home/null_mn/anaconda3/lib/python3.9/site-packages/pulp/solverdir/cbc/linux/64/cbc /tmp/6de90f51aba944a0beb2051dab1d434f-pulp.mps timeMode elapsed branch printingOptions all solution /tmp/6de90f51aba944a0beb2051dab1d434f-pulp.sol (default strategy 1)
At line 2 NAME          MODEL
At line 3 ROWS
At line 24 COLUMNS
At line 142 RHS
At line 162 BOUNDS
At line 178 ENDATA
Problem MODEL has 19 rows, 15 columns and 74 elements
Coin0008I MODEL read with 0 errors
Option for timeMode changed from cpu to elapsed
Continuous objective value is 7000 - 0.00 seconds
Cgl0002I 4 variables fixed
Cgl0004I processed model has 8 rows, 7 columns (7 integer (7 of which binary)) and 28 elements
Cutoff increment increased from 1e-05 to 300
Cbc0038I Initial state - 7 integers unsatisfied sum - 2.33333
Cbc0038I Pass   1: suminf.    2.33333 (7) obj. 7000 iterations 0
Cbc0038I Pass   2: suminf.    0.00000 (0) obj. 8100 iterations 7
Cbc0038I Solution found of 8100
Cbc0038I Rounding solution of 7200 is better than previous of 8100

Cbc0038I Before mini branch and bound, 0 integers at bound fixed and 0 continuous
Cbc0038I Mini branch and bound did not improve solution (0.00 seconds)
Cbc0038I After 0.00 seconds - Feasibility pump exiting with objective of 7200 - took 0.00 seconds
Cbc0012I Integer solution of 7200 found by feasibility pump after 0 iterations and 0 nodes (0.00 seconds)
Cbc0001I Search completed - best objective 7200, took 0 iterations and 0 nodes (0.00 seconds)
Cbc0035I Maximum depth 0, 0 variables fixed on reduced cost
Cuts at root node changed objective from 7000 to 7000
Probing was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds)
Gomory was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds)
Knapsack was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds)
Clique was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds)
MixedIntegerRounding2 was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds)
FlowCover was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds)
TwoMirCuts was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds)
ZeroHalf was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds)

Result - Optimal solution found

Objective value:                7200.00000000
Enumerated nodes:               0
Total iterations:               0
Time (CPU seconds):             0.00
Time (Wallclock seconds):       0.00

Option for printingOptions changed from normal to all
Total time (CPU seconds):       0.00   (Wallclock seconds):       0.00

0 1 0 0 0 1 0 
1 0 0 1 0 0 0 

最後の結果から、

月曜の夜、火曜の昼、木曜の夜、土曜の昼に自炊をすると、
一週間の食費が約 $${7200}$$ 円になる

ことがわかりました。


まあ普通にめんどいので、スーパーの半額総菜を自炊と言い張ることにします。



まとめ

みなさんは、こんな大人にならないようにしましょう

この記事が気に入ったらサポートをしてみませんか?