Python:TypeError: hoge() takes 1 positional argument but 2 were given

Context & Probrem

雑多に書いていた関数群をリファクタリングしてクラスとしてまとめていた時にタイトルのようなエラーが出た。

TypeError: hoge() takes 1 positional argument but 2 were given

あれ、おかしいな、と。エラーの内容としてはhogeメソッドが受け取る予定の引数は1つしかないが、2つ渡されているぞ、ということ。コードを見返しても2つも引数指定なんてしていないしどういうこっちゃとなった。

Solution

selfをメソッド引数に生やし忘れてた。言語仕様としてselfを書かないとこうなる。

# 実行時にエラーを吐くコード
class fuga:
   def hoge(xxx):
        pass # なんかしらの処理
# 実行できちゃうコード
class fuga:
   def hoge(self, xxx):
        pass # なんかしらの処理

fuga.hoge()という要領でメソッドの呼び出しを行うと、hogeの第一引数にはfugaが入る仕様になっている。仕様を知らないとなぜエラーが出ているのか表面的にはわからず混乱する事になる。Pythonのこの仕様はプログラマからも評判があまり良くないようで、変更するような提案がなされているらしいが、Pythonの生みの親Guidoによってなぜselfを明記する仕様が重要なことなのかを説明するブログもある。あまり単純な話ではないようで自分もまだ完全に咀嚼しきれていないので言及は避ける。

Reference

大変勉強になった記事

足を踏まれている者の痛みは足を踏まれているものにしかわからない

はじめに

数年前のことですが、親族や友人に辛かった出来事、今辛い思いをしているという話をすると、「そんなものは社会に出ればよくある話だ」「俺(私)だってそのくらいの辛いことはある」「本当に辛かったらうつ病になってて家から出られないから笑」「まぁメンタル鍛えられてるって思えばいいんじゃない」と、自分の気持ちに寄り添うことなく流したり、あるいは辛くて苦しいという僕の気持ちを否定されたように感じる場面があったりしました。今別に辛いかと言われるとゆるゆると、ラフに生きている身なので特に辛いとかはないですが、当時のことを思い出してモヤモヤすることがあったので、言語化して整理しておこう、と思った次第です。

初めての研究室で

今は情報系の大学院に通っているのですが、学部時代は機械系の専攻でした。学部3年生の時くらいに自分は機械じゃなくてソフトウェアの方が向いてるなと感じたので、大学院からは情報系に移ろうと決心しました。とはいえ大学院というのは基本的には研究をするための機関なので、研究をする上で最低限の知識はないと当然ながらダメです。情報系の学部をすっ飛ばして大学院に入学をすることになるので、0から情報工学を学ばなければそもそも大学院の試験をパスできませんし、パスした後も研究をするには多くの知識が要求されます。専門の勉強はほどほどにして足りない知識を補うために毎日必死に勉強したのを覚えています。大学の図書館が閉まった後、知り合いのつてでコッソリ大学のとあるスペースで日が変わるくらいまで勉強してた日々は懐かしいです。この姿勢はB4で研究室配属された後も続きます。

当時の僕の指導教員は専門に身を入れてない僕の態度を快く思わなかったようで、かなり冷たい対応をとられていました。

当時取り組んでいた研究の相談をすると

「しらねーよ、俺の研究じゃねーし」

と言われたり、自分の仮説の筋が悪いと、舌打ちしたり、頭を叩かれたりしながら

「まだそんなこと言ってんのかよ...いい加減学べよお前。」

「お前よりひどいやつ見たことねーよ。何も分かってない。これ以上言うと人格否定になるから言わねーけど、さぁ」

「あ?何がいいてぇんだよ、言ってることが支離滅裂。いい加減にしろよ。」

「半年卒業ずらすか。このままじゃ間に合わないし。」

などの発言を相当高圧的な態度でされました。この年にもなって恥ずかしながら泣きかけました。まじで怖かった。

研究室によっては通ってさえいれば教授がある程度やるべきことや実験の方針などを一緒に相談しながら決めてくれて、スイスイ研究が進んでいくものですが、僕の所属していた研究室は、研究の方針は自分で考えさせる方針だったため(研究の方針を教授が決めると与えられたタスクを消化するだけで教育にならないため)大学に通えばどうにかなるのかというと、そんなことはありませんでした。同期や先輩方に相談に乗ってもらったりしながら研究を進めようとするのですが、なかなか思うように行かず、じゃあ指導教員に相談できるのかと言うと、前述したような対応をとられるので恐怖でアポは取れず、時間がただただ過ぎ去っていきました。

進捗を出さずに相談に行くとキレられるし、かといって相談せずに進捗が出るのかというと、研究はそれほど甘くなく、自分はそれができるほど賢くなく、時間は過ぎて刻限が近づく。他の研究室の友達が卒論執筆に取り掛かろうとするときに、自分はほとんど成果が出せないまま、行く先のわからない暗闇の中を歩き回っているような感覚に陥っていて不安と焦燥と絶望と恐怖で頭がおかしくなりそうでした。というより完全にパニック状態か鬱だったと思います。食が細くなってカロリーメイト一本とかで食事を済ませるようになったり、夜眠れない日々が数ヶ月続いてました。

精神的に相当追い詰められていたため、あまりにも辛くて休学を考えたり、希死念慮にかられて楽な自殺方法を調べたり、腹いせに研究室の資材を全て破壊してやろうかとか色々考えてました。 しかし大学院に合格していたため何がなんでもストレートで卒業しないと、せっかく頑張って舵を切り直そうとしている自分の人生が壊れてしまうため休学等はできず、辛い日々を耐えるしかなかったです。またうつ病診断されると就活に響くんじゃないか、うつ病だったとしても就活前に診断をもらうのはよくないかもしれない、とか思ってたりもして、余計病院には行けなかったです。

卒論発表の二週間前とかになってもまとまった成果が出てなかったので、自宅は風呂に入る時のみ利用して、それ以外の時間は研究室に寝泊まりし、シミュレーションをぶん回しながらロジックがボロボロのプレゼン資料と卒論を作ってました。シミュレーション、卒論執筆、プレゼン資料作成を同時並行的にこなしがら、詰まったところはボコボコにされること覚悟で指導教員に相談、泣きながら形だけの卒論を仕上げて、終わった後は気が抜けて3日くらい家でぼーっとしてました。精神的にも体力的にもめちゃんこしんどかったです。

足を踏まれている者の痛みは足を踏まれているものにしかわからない

大体はこんな感じの話をしながら「いやぁ最近まじで辛くてさぁ」って友人や家族に話してました。僕はぱっと見はメンタルが強いように見えるらしく、後から聞くとまさか希死念慮が沸くほど辛いと思ってなかった、とか言われたりもしましたが、当時は冒頭述べたような反応をされることが多く、SOSのメッセージを誰も受け取ってくれね〜〜無理〜〜〜〜ってなってました。人によっては、ある程度筋立ててパワハラで精神が参ってた時期があると話しても、否定してきて辛かったです。まぁ多分そいつは僕のことを友達だとは思ってなかったからそういう反応だったのかも知んないです。友達は選んだ方がいいかも知んないっすね。

さて、長々と前置きをしたところで本題に入ると、重要なのは当時の僕の経験を、あなたが辛いものだと捉えたか、それとも別にそうでもないと捉えたかは、僕にとってはどうでもいいということです。 日常会話の中で辛い経験を友人や家族に共有することは多くの人がすることだと思いますが、その際に「社会にはその手の辛いことがたくさんある」「僕(私)だってそういうことがあった。別にお前だけじゃない」と社会一般というどこからどう取り出したのかわからないモノサシと、自分の主観というモノサシで、他者の辛さを測ってそんなものは矮小なものだと吐き捨てる。そういう攻撃的な反応をする人がいます。この時、足を踏まれて痛みを感じているのは僕なのに、足を踏まれている僕を観測した第三者が僕の痛みを推し量り、評価しているわけですが、痛みの度合いは僕にしかわからないものです。あなたが痛みを評価するのは誤りです。

じゃあどう接するのが正解なのかと言われると難しいですが、辛くて苦しくて死にそうな思いをしている(と言ってる)友人に対してさらに追い込むような言動をとるのは間違ってるんじゃあないかなぁと思うわけです。繰り返しになりますが。気持ちを汲んで、辛いんだね、と話をただ聞くだけで、誰かに承認されるだけで気持ちが軽くなることもあるかもしれないですし、場合によっては一緒に悩んで解決策を考えることなんかもできると思います。僕はその方が建設的だと思うし、優しい対応なんじゃないかなぁと思うっす。

終わり

秋になってポエムを吐きたくなったので僕が辛かった時の記憶を吐いて、ついでにポエム書いてスッキリしようって思ってポエムを書きました。 実はモヤモヤしてることが完全には解消されてなくて、「耳障りのいい言葉を吐くだけが友情ではない」とも思ってるので、ときには厳しめの意見を友人にぶつけることも必要だよなぁとも思ったりしていて、バランス感覚が悩ましいです。コミュニケーションはナマモノなので脳みそ使って適切な対応を考えないとダメっすね。

【書評】A Philosophy of Software Design 1章-2章

はじめに

本記事はソフトウェアの Complexity (複雑さ) について扱っているA Philosophy of Software Designを読んだ際の個人的な備忘録です。170Pほどの洋書で読みやすいので、読みながら学びになったことをまとめていきます。読みやすいとは言え英語なので和書の5倍くらいの時間がかかりますが、頑張って読んでいきます。

www.amazon.co.jp

1章:イントロダクション

ソフトウェアを開発していくとソフトウェアは次第に複雑になっていき、ソースコードの修正や機能追加が難しくなっていく。結果として機能追加にかかる時間が増大したりバグを引き起こすこととなるが、これはソフトウェアの複雑さに起因すると著者は語る。なんらかのツールによって複雑さを抑えることも可能ではあるが、限界はある。従ってソフトウェアデザインにおいて、ソフトウェアの複雑さを最小にすることで、ソフトウェアをシンプルに保つことが重要である。

よりプログラムをシンプルにするにはどうすればいいか、一般的には以下の二つの手法がある。

  • コードをよりシンプルにすることで複雑さを減らすこと
    • 特殊ケースを消す
    • 統一性のある識別子を利用すること
  • 複雑さをカプセル化し、意識すべき複雑さを減らすこと=moduler design

....とだいたい上記のような内容でした。目から鱗の大発見!!とかはまあなくて、ソフトウェアの複雑性を抑えるにはどうすればいいのだろうかを考える本だよってこと、そしてそれがいかに重要であるかを述べています。introなんで、まあ「ソフトウェアの複雑さを最小化すること」が本書の目的だってわかればまあそれでよしって感じで流し読みしました。次!

2章:複雑さの性質

本書の目的は複雑さを最小化するための原則を知ることにあるわけですが、そもそも複雑さとはなんだろう?2章では高いレイヤーから議論を行っており、より低いレイヤーの議論は後続の章で語られている。まずは敵を知ることから。

Complexity defined | 複雑さの定義

自分が直感的に感じていたことを数式モデルで表現しており、割と良いな!って思った定義が以下です。


C = \sum_{p}c_pt_p \\
C...Complexity of System(ソフトウェアの複雑さ)\\

c_p...part(p) weigit(そのpartの複雑さ)\\

t...developerがそこに触れる頻度や時間 \\

ある関数がとても複雑な処理をしていて、中身がもはやブラックボックスになっていたとします。これはあなたの開発しているソフトウェアの中で複雑さに寄与しているでしょうか? 答えはそこに触れる時間による、です。

普段我々が利用しているライブラリは、モノによっては色々な最適化が施されていたりして、一見するとなんのこっちゃよくわからん複雑なソフトウェアです。例えば僕はtensorflowが裏側でやってくれていることを事細かに把握はしてないですし、知らんけど多分複雑です。そういうソフトウェアをコンポーネントとして扱って開発を行っているわけですが、我々の開発とは隔離されたものと言えるでしょう。どんだけ複雑でも開発から隔離されているものはソフトウェアの複雑さに勘定として入れなくてもいいよね、我々が意識すべき複雑さは開発の中でより長く触れる複雑なコンポーネントですよね。

従って、あるコンポーネントの複雑さを、developerが費やす時間で重み付けしてsumを取ることでソフトウェアの複雑さを測ろう。そういう意図のモデルです。

Symptoms of complexity | 複雑性の症状

複雑さがもたらす症状には大きく分けて3つの症状があります。

Change amplification | 変化の増大

コードを改変する際により多くの箇所を修正する必要が出てくること。本の中で出てくる具体例としてはwebpageの背景色の例が挙げられています。 以下、二つの例を取ってみましょう。

  1. それぞれのページでbackgroundカラーが定義されている
  2. ある一つの変数を経由してそれぞれのページのbackgroundカラーを定義している(変数は一つだけ)

仮に前者のソフトウェアデザインで背景色を変更しようと思うと、全てのページの背景色を変えにいかなければなりません。ページが数千もあったら溜まったもんじゃないです。反して後者ならば変数に代入するパラメータを変えれば全てのページの背景色が切り替わります。複雑なソフトウェアとは、より多くの変更を要求します。

Cognitive load | 認知的負荷

コードを改変するときに必要な情報を整理するのに多大な時間を要するようになる。これはわかりやすい複雑さですね。例えばC言語は認知的負荷が高いです。C言語を書いたことがない人に説明すると驚かれますが、動的配列とかが他の言語のようには提供されてなくて、malloc/freeを使ってメモリ管理を自分でしなければなりません。仮に確保したメモリをfree(開放)し忘れるとメモリリークが起こってメモリが枯渇したりします。こういう要素に気をつけながらコードを書くのは骨が折れるし認知的負荷が高いです。RubyPythonで同等の処理を記述するよりも多くの時間がかかる、と言って否定する人はあまりいないでしょう。

他にも以下のようなことが認知的負荷を引き起こすと指摘されています。

Unknown unknowns: 何を知らないのか分からない

変更対象が分からなかったり、変更に際して何を考慮しなければならないのかがわからないこと。これが症状の中で最悪のものです。苦し紛れに書いたコードが、結果としてどのような問題をもたらすことになるのかもよくわかっておらず、問題が起きてからそれを知ることとなる...知見の溜まってないOSSなどを利用していると起こったりしますね...

Cause of complexity | 複雑さの原因

これまでは複雑さがもたらす症状について触れてきましたが、そもそもなぜソフトウェアが複雑になるのかについて、最後にまとめます。筆者は複雑さの原因を2つに分類しています。

  • dependency | 依存
  • obscurity | 曖昧であること

dependency | 依存

クラス間の依存が増えて行ったり、いろんなところで変数が共通して利用されだすと、途端にコードを追うのが辛くなります。クラスのレイヤーの話でなくとも、他のソフトウェアと依存していることもあります。例えばnetworkのプロトコル。senderの仕様を変更したら、receiverも同様に変更しなければなりません。他にもあるmethodのパラメータを増やした結果、呼び出しもとも同様に変更をしなければならなかったり、rest APIとかもクライアントサイドが仕様を変更するとバックエンドもそれに合わせて仕様を変えなければならなかったり...など、依存しているものが増えるとソフトウェアは複雑になっていきます。こっちは構造のお話

obscurity | 曖昧であること

こっちはコードの可読性というか命名のお話。名が体を表すコードならいざ知らず、よくわからない変数名を定義していて、他の人にはなんのこっちゃよくわからんソースコードは複雑さの原因になります。ソースコードから曖昧さを排除することでソフトウェアはシンプルになります。

1章2章まとめ

後続の章で述べられているDeep Moduleという概念が大変クリアで美しかったため購入した書籍なのですが、この章も個人的には有意義でした。自分が意識していなかったことが述べられているわけではないですが、暗黙知を形式値に昇華してくれたこと、バラバラの知識・経験的直感をまとめ上げて自然言語にしてくれたこと、それだけで大変価値のある文章でした。引き続きのんびり読んでいきます。

OSI参照モデルとRFC1122

はじめに

先日、非CS学部出身のソフトウェアエンジニアの友達にネットワークのプロトコルについて軽く説明してた時に、OSI参照モデルに則って説明をしていました。 機械工学科から頑張って情報系にジョブチェンジする際にマスタリングTCP/IPを読み込んだのを思い出しながら、喋ってて、内容は以下のようなものです。

  • インターネットプロトコルを構成する要素を以下の7層に区切って考えるモデルである
  • 送信側では、パケットは7層で作られて下の層に降りていきながらラップされていき、受信側では下の層からラップを剥がしながら通信の内容を読み取る。

最後、雑ではありますが、大体正しいこと言ってる気がします。ざっくりしたイメージを共有したところで、具体的な層ごとの説明をしようとしたところで違和感を感じます。

あれ...?プレゼンテーション層とセッション層を代表するプロトコルってなんだ...?

HTTPやSMTPなどは一番上位のレイヤーに位置するという認識はありましたが、ぶっちゃけ5層6層と分離して考えられるのか...?あれ...? トランスポート層TCPUDPプロトコルの違いや輻輳制御などを学んだ記憶があるので説明できる。ネットワーク層IPv4/IPv6、ルーティングアルゴリズムについて勉強した。データリンク層物理層は...CSMA/CD、CSMA/CAとかあの辺のパケットの衝突検知や回避、macアドレスEthernet周りが定義されてるはずだが...うん?ここってEthernetとかは1層と2層跨ってるよな?なんて思いながら言葉に詰まりました。

OSI参照モデルは実装されていない

いろんな文献を参照してるとOSI参照モデルは頻繁に登場します。僕が初めてネットワークをしっかり学んだマスタリングTCP/IPでもOSI参照モデルを利用してネットワークを階層化し、説明をしていました。もちろん4層モデルの存在は知っていましたが、捉え方が違うだけだろうとか思っとりました。全然違いました。OSI参照モデルRFCで採用されていません。RFCで採用されているのは4層モデルであり、OSI参照モデルはあくまで学習用くらいで捉えておいた方がいいようです。wikipediaにも冒頭にそんな説明がありますね*1

ややこしいのは、中途半端に基礎知識みたいな形で広まってるのと、L2スイッチやL3スイッチみたいにOSI参照モデルに則った命名してる機器が普通に存在してたりするので面倒ですね。

RFC1122を読む

ネットワークのレイヤの定義ってどこにあんだ??って思ったら、RFC1122がそれでした。めっちゃ長い。全部読めたもんじゃねぇ。 細かい話は置いておいて、RFC1122*2 はネットワークのレイヤを以下の4階層に分けることを定義してます。

これらの層が果たす役割だったり、要件を定義していくのが、図とか使わず自然言語でずーーーーーーっと続いてます*3。凄まじい。RFCはあまりしっかりと読んだことなかったですが*4、Introductionを読んでいると仕様にもいくつか厳しさのレベルがあって、絶対やんなきゃいけないもの、やった方がいいもの、やっても良いものという風に、言葉使いを定義しています。丁寧ですね。

     *    "MUST"
          This word or the adjective "REQUIRED" means that the item
          is an absolute requirement of the specification.
     *    "SHOULD"
          This word or the adjective "RECOMMENDED" means that there
          may exist valid reasons in particular circumstances to
          ignore this item, but the full implications should be
          understood and the case carefully weighed before choosing
          a different course.
     *    "MAY"
          This word or the adjective "OPTIONAL" means that this item
          is truly optional.  One vendor may choose to include the
          item because a particular marketplace requires it or
          because it enhances the product, for example; another
          vendor may omit the same item.

他にも、要件の追加説明にはDISCUSSIONやIMPLEMENTATIONなんてラベルの項目があって、こういうことが起こるとこんな問題が生じるから、実際に実装するにはこうするといいよ、みたいな実装者への提案もあったりしてます。こんな感じなのか。当たり前ですが実装と1対1で対応するほど詳細な定義はされてなくって、ある程度含み持たせてんだなぁとなりました。この定義をメールでやりとりしながら決めて、で、スーパーハッカーみたいな人たちがその実装作って、実際それが動いてThe Internetを支えてるって、めっちゃcoolですな....

ただ自然言語で説明されてもイメージがつきにくいところがたくさんあって、世に出回ってる教科書や資料なんかを見た方が普通に時間効率はいいですね。大学院の授業で使ったComputer Networkingは相当に丁寧でよかった記憶しかないのでリファレンスにええっすよとだけ推しとこ。

終わり

自分はネットワークが専門でもないですし、ネットワーク関連のR&Dプロジェクトに大学院を出た後アサインされる予定も今のところないです。仕事はアプリケーションよりのエンジニアリングがメインなので。実務の中ではRFCを直接参照するよりも他の媒体で情報収集することが多そうですし、APIを叩くインターフェースが綺麗に簡単に使えるように中身をラップしてくれているので、ぶっちゃけRFCで実装されてようがOSIで実装されてようが気になりませんでした。ただ、他人に何かを説明する場面で嘘つきそうになったのに気づけてよかったっす。知識の整理にもなったし。

あと低レイヤーオタクなのでこういうの読んでると、いつかエンジニアとして成長してネットワークのプロトコル実装するお仕事とかできるくらい強くなりたいなって思いました。誰かスカウトしてください。

*1:wikipediaなんて参考にすんなって人が多いですが9割5分くらい正しいこと書いてる(分野による)んで論文書いたり公式な声明書いたりしない限りはかなり参考になると思ってます。

*2:日本語版の方が読みやすい

*3:長い論文だと100P近いものってありますし、見慣れないわけでもないんですが、フォーマットがcssとか知らなそうなアレでアレがアレで長く感じるのかな

*4:このRFCも隅から隅まで読んだりはしてません

GCS上のオブジェクトを一部だけダウンロードする

はじめに

自分用メモ。欲求は以下

  • GCS上にある数GBとかの大きめのデータの中身を確認したい
  • でもローカルに丸ごと引っ張ってくるのは嫌
  • linuxのheadコマンドみたいに一部だけみたい

comand line(gsutil)

catコマンドのオプションを見てみたら2秒で解決した

$ gsutil cat --help
〜〜略〜〜
OPTIONS
  -h          Prints short header for each object. For example:

                gsutil cat -h gs://bucket/meeting_notes/2012_Feb/*.txt

              This would print a header with the object name before the contents
              of each text object that matched the wildcard.

  -r range    Causes gsutil to output just the specified byte range of the
              object. Ranges are can be of these forms:

                start-end (e.g., -r 256-5939)
                start-    (e.g., -r 256-)
                -numbytes (e.g., -r -5)

              where offsets start at 0, start-end means to return bytes start
              through end (inclusive), start- means to return bytes start
              through the end of the object, and -numbytes means to return the
              last numbytes of the object. For example:

                gsutil cat -r 256-939 gs://bucket/object

              returns bytes 256 through 939, while:

                gsutil cat -r -5 gs://bucket/object

              returns the final 5 bytes of the object.

-hでheader(先頭)をよしなにとってきてくれる。  -rでrangeを指定できる。指定はバイトで指定する

Python

from google.cloud import storage

def gcs_head(bucket_name: str, file_path: str, character_code: str) -> None:
    """
    GCS上のcsvの先頭1MBだけをダウンロードして出力する
    
    input
    bucket_name: str
        gcsのbucket
    file_path: str
        オブジェクトへのパス
    character_code: str
        オブジェクトの文字コード
        downloadしたものはバイト型なので標準出力しようと思うとdecodeする必要がある
    """
    gcs_blob = storage.Client().bucket(bucket_name).blob(file_path)
    head: bytes = gcs_blob.download_as_bytes(end=100000)
    print(head.decode(character_code))


gcs_head(bucket_name="proj_hoge", file_path="sample.txt", character_code="shift-jis")

Blobsのドキュメントを見てると、ダウンロード系のメソッドにはstartとendの引数があって、読み込みの開始位置と終端をバイトで指定可能。

しっかり学ぶ数理最適化・第2章3.1節 - 双対問題

双対問題

線形計画問題において、最適値を求めるのが困難な際に重要となるのが、最適値の上界と下界を求めることです。最大化問題において、ある実行可能解が得られた時、それは必ず最適値以下であるはずです。つまり得られた実行可能解を下界として捉えることができます。では上界を求めるにはどうすれば良いのでしょうか?上界を求める一つの手段として2.3.1節で述べられる双対問題による手法があります。双対問題を考えることで最大化問題を最小化問題に置き換えることができ、最適値の上界を求めることができるというなんとも不思議な求め方です。賢いですね。まあただ実行可能解を1つ得ることが容易でない問題もあるということで、世の中そんな甘くはなさそうですが...

本節では、やや天下り的な具体例から手法の流れを把握し、その後に一般化を行うことで双対問題を用いた最適値の上界・下界を求める手法に関してみていきます。

数式が非常に多くアレルギーが出そうになりましたがよくよく見てみると別に大した式じゃありません。数式ばかりに目がいきがちですが、著者の梅谷先生はこの節で行っていることを簡潔にまとめてくださってます。まとめると以下です。

制約条件の1次結合を用いて線形計画問題の最適値の良い上界を求めた

理解する前にこの文言を見ても「?」だったでしょうが、理解した後に聞くとなんとも簡潔な表現に聞こえます。後の2.3.2節では緩和問題に触れており、双対問題の導出にはこちらを利用することの方が多いようです。気が向いたらまとめます(多分向かない)

しっかり学ぶ数理最適化輪読回・第2章

数理最適化勉強会も始めました

僕は数学があまり得意ではないので、こういう勉強には気が乗らないのですが、数学から逃げずに少しずつでも工学をやる上で必要な素地を身につけていかなければならないな、と最近ひしひしと感じています。同期もみんなひしひしと感じているようで、数学ゼミを開講する運びになりました。

集合と位相、圏論あたりのマジの基礎からやっていた時期もあったのですが、M2になったしより実用的な分野の勉強会をしたいねってことで数理最適化を学ぶことになりました。個人的には、MLPシリーズの機械学習のための連続最適化をやりたかったりしたのですが、多数決の結果ラボの勉強会で扱う書籍は「しっかり学ぶ数理最適化」に決定しました。カバーしてる範囲がどのくらい違うのかもあまり把握してないですが、とても重厚で名著感が凄まじいため、どうせいつか読む本だと思ってます。なので気合入れて読みたいですね。

「気合入れて読みたいですね」と言ったそばから「最後の生産計画問題サボっとるやんけ」とツッコまれそうですが、疲れたので仕方ないっす。人間限界あるんで。

線形計画問題

目的関数も、制約条件も線形な関数で表現できるものを線形計画問題と呼ぶようです。この章では定式化を行っているだけに留まっていて、それをどのように解くのかまでは議論していません。線形計画問題を解く手法は線形計画法と呼ばれており、後の章で述べられる単体法などに代表される手法を用いることで多くの場合効率的に大域的な最適解を得られるようです。 僕は担当ではなかったので資料を作ってないですが、2.1.2節以降では線形でない問題も近似を行うことで線形計画問題に落とし込めるよ、という話をしており(全てではない)、実用上、様々な問題を線形計画で解けちゃうようです。

この章は読んでいて、確かに、まぁ、そうなるな、みたいな感想をもった章で特別難しい概念や理解に苦しむ定式化なんかはありませんでした。ですがよくよく問題を見てみると「この問題も線形関数だけで表現できるのか!」みたいな発見があって楽しかったです。次回は緩和問題と双対定理に関して発表するのでがんばります。