2019、七日目の記事です。12月7日じゃない?IQ1なのでよくわかりません。雑多2017年07月06日AWStatsのインターフェースをいじろう(というのはお薦めできない)結果として面倒だったので、「表示を変えた箇所を調べておけばバージョン変わってもなんとかなるかな?」くらいに考えている人は参考にならないとだけ言っておく。AWStatsはログ解析ツールとしては結構有名どころらしく、普通にパッケージ管理ソフトで入るため、単に使いたいと言う場合にはあまり苦労することもなく導入できる。使い方も調べればそれなりにでてくるため、さほど問題は起こらない。(少なくともここに来るような人にはすぐ見つけられるはず)しかし、インターフェースは微妙なところもあり、変更したいと思ったりもする。やってみた感想は「やめた方がいい」なのだけど。変更内容は、一年前の情報も同時に表示すること。自分の所属が大学であるため、webサーバーの負荷などは大体月と曜日に依存している。そのため、何か変化や異常があると、昨年と比較できれば割と簡単に見えるのである。AWStatsのインターフェースはなぜかその年の情報しか出さないので、比較が難しい。起こった問題(怒った問題)を挙げていこうと思う。1)月ごとの情報を表示する箇所は割と簡単に見つけられて、HTMLMainMonthlyという関数になっている。この中に前の年のデータを表示するルーチンを無理矢理書き込めばいいはずなのだが、全く部品化されていないので、今見ている年の処理をコピペするしかない。2)よく見るとところどころにコメントアウトされたあからさまに不要とおぼしきコードが見える。バージョン管理してるだろうが。3)無理矢理表示を追加してるうちに、月ごとの関数から移って日ごとの情報を表示する関数が目に入るが、インデントが少し壊れてる。(もっとも、自分が見たバージョンは現在のバージョンよりさらにひどかったので、少しずつ直しているのだろうか。全部直せよとは思うが。)4)表示させるように変更したので、一年分の情報は読んでいるが全てのログを見ているわけではないということにすぐ気づく。サーバーによってはログがすごい量なのだから当たり前ではあるが、どこで読んでるのか分かりづらい。表示に使っているデータの変更箇所を追うと、どうやら3330行くらいからのRead_History_With_TmpUpdateという関数で読んでるらしい。呼び出し箇所を見ると月ごとに読むようにしている。選択した月とそれ以外で月以外にもう一つ引数が異なっている。意味はさっぱりわからず。中を見れば分かるかと関数の範囲を見ると3800行ある。5)とりあえず選択していない月と同じように読ませればなんとかなるかとやってみたところ、前の年の表示に成功。一安心かと思ったら明らかに「時間毎の通信量」が増加している。何が起こってるのかと調べると昨年の同月分を単純に足している様子(1年後を表示させて気づいた)。変数から当たりを付けてRead_History云々を見ると「選択した月の情報なら計算対象にして、他の月だったら無視する」という状態になっている。月だけ??年のチェックは???6)努力の甲斐あって表示に成功。月」の順になっていてもやもやする。思ったら一箇所だけ「〜年〜月〜」(日付はあるが「日」がない)になっていたりする。何かと思って表示部を見たら順番がハードコーディングされている。一箇所だけ別ファイルからフォーマットを読んで出力している(ただし微妙に不足している)。その中途半端なのをやめろというのに。いうか多言語対応やってるんならハードコーディングするなよ。とまあこんな感じである。全部手で直したので、当然のことながらバージョンアップしたらおじゃん。全体的に思うのは、1)全体のメンテナンスに気を遣っているか若干怪しい。2)細かい引数指定があるのに、普通に出てくるはずの組み合わせを想定していない。3)大域変数だらけで関数毎に想定している状態がさっぱりわからない。4)関数がでかすぎる。全体のテスト以外してないよねこれ、という感じである。雑多2016年12月10日cygwinの依存関係を調べようパッケージ削ると動かなくなるとかヒドすぎる。インストーラが依存関係解析してるんじゃないのか。いう愚痴が出た準備室で新しいお仕事である。「なんかcygwinのインストーラがチェックする依存関係、かなり怪しい」という考えの下、提供されているツールからある程度依存関係を調べられないかということを相談していた。cygcheckとlddという二つのコマンドで対処することにした。パッケージに現れるexeとdllをlddにかけて、依存するライブラリを調べる。そのライブラリが所属するパッケージへの依存関係が発生する。出来ないものじゃないし、とPerlでスクリプトを書いてやってみたのだが、cygcheckがやばいくらい遅い。cygcheckはパッケージ一覧とファイル一覧を持っていて、パッケージ由来は逆引きをやっているっぽいのだ。ボトルネックになってるのは、HDDだからか、ファイルがバカみたいに増えて単に逆引き自体が遅いか(フルインストールなので60GBを越えている)、のどちらかだろう。どちらにせよ解消しないといけない問題なので、別の方法で解決しようと考え中。パッケージ一覧から作れば逆引きできるよねえ、Perlなんだし。この記事は、Coqの標準ライブラリに含まれるMSetsについてです。今回は利用側の視点ではなく、ライブラリ作成側の視点なので、まあ非常にニッチだと思います。名前からピンとくるかもしれませんが、MSetsは集合のライブラリです。集合に入っているかを判定する述語、要素の追加や削除、和集合や共通集合、フィルターをかけるなど、一通りのことができます。単純な集合ではなく、別途利用者が定義した同値関係を与えることで、「同値な要素」が入っているかを判定するようになっています。(同値関係にLogicに定義されているeqを使えばよくある集合になります)MSetsでは、新しい実装を実現する方法として、直接インターフェースを満たすように定義する以外に、RawSetsと呼ばれる「それ自体は集合らしくないこともありうるが、条件を付けると性質が成り立つ」ように記述するインターフェースが提供されています。(実際はWSetsに対してWRawSets、Setsに対してRawSetsがあります。前者が要素に順序関係を必要としない、後者が要素に順序関係を必要とするものです。以下の説明は正しくはWRawSetsのものです。)ちょっと分かりにくい日本語だと思うので、例としてリストを使った実装を考えます。集合を実現するためにリストを用いることは不自然ではありませんが、リストでは要素の重複があったりします。MSetsでは集合の要素全てをリストにして取り出すelementsという関数が定義されており、そのリストに重複はないことが要求されているので、重複を認めるとちょっと面倒です(ちょっとだけですけどね)。そのため、「重複のないリストである」場合にそれを集合とする、と考えることで、リストを使ってRawSetsを構築できます。インターフェース上の性質は全て「重複のないリストであるとする」という条件を課すことになり、それによって初めて証明が可能になったり、また簡単になったりします。「全て」と書いた直後に何ですが、これが本来のRawSetsの考え方のハズなのです。実際のCoqのRawSetsの記述を見てみるとどうでしょう。ほとんどのものはOkという述語を満たすように集合が扱われています。「全て」ではありません。サボったな貴様これは予想なのですが、おそらくMSetsの実装者は、いくつかの集合の実装をした際に、「この性質は条件付けなくても簡単に成り立つからいいや」と抜かしたのです。(実装中に必要になったものだけ追加したのでしょう。)なぜそのような予想を言うかというと、抜けているものがWRawSetsのfilterやpartition、elements、chooseなど、割と実装からならストレートに示せそうな性質ばかりだからです。(RawSetsのmin_elt_spec1から3は2だけある割にどのくらいの影響があるかすぐには説明できませんが)なぜ全部に付けない。こんなことを調べた理由ですが、MSetsでは毎回要素との等価判定をする(または大小関係の比較をする)ので、等価判定が遅い場合、あまり全体のパフォーマンスが上がらないことになります。(もっとも、WSetsはともかくSetsでは大小関係を付けて大体が木探索を行うので要素数の対数のオーダーでしか比較を行わず、あまり影響がない気もします)そこで、等価判定や比較を行う際に「代表的な値」を取ってそれ同士で比較できれば、その「代表的な値」同士で、より高速に比較できるのではないか、と考えたのです。剰余が等しいかで同値関係を定義した場合、剰余の結果を取ればそれが「代表的な値」になるでしょう。集合にある要素を全て剰余にしてしまえば、集合側の要素は毎回剰余を計算しなくてよくなりますから、まあ速くなるのではないでしょうか。これを実装するには、既存の実装を用いて「代表的な値」による集合を構築して、適切にその集合とのやりとりを定義すればよいでしょう。いうわけで実装しようとしたのですが、上の問題で証明できなくなりました。集合に入っている要素は全て「代表的な値」であるはずなのですが、簡単にそうでないものが入ります。filterを始める際に、「代表的な値」以外が入っていると(そして条件がなければ簡単に入り得ます)、filter後の条件を容易には示せません。結果的に、このままではそんな実装はできないわけです。考えてもできるはずなのに!!ちなみに、もう一つ問題があり、MSets中ではfilterやpartitionはある性質を持ったフィルター用関数についてしか言及しません。その結果、目標とするものではfilter後の集合が条件を満たすこと(filter_ok)を示せなくなります。この性質ではfilterに渡す関数に何の仮定も置かれていないからです。裏側で動いている「代表的な値」の集合は、filterがある特定の性質を満たす場合に限りうまく動きます。それじゃ渡しても何も言えません。インターフェースに何もないのですから。Requestを送ろうと思ったのですが、いかんせん古いライブラリ(FSets)との互換性を保つための部分に問題が起こり、もう知るかと投げ出しました。(前者は問題ないのですが、後者がインターフェースに性質を追加するので互換性がなくなります)現状、ほとんどMSetsと同じそれをXSetsという名前で公開しています。Opam使ったライブラリに登録をしたいところですが、あまりにMSetsと同じコードなのでなんとも気が引ける部分ではあります。XSetsの使い方はほぼMSetsと同じです。表面的にはインターフェース上に性質が三つ増えているだけなので。上の問題、MSetsを普通に使っている分には何の問題もないのですが、どうも嫌なところをついてしまったようです。上で述べた「代表的な値」による実装(XSetRepresentative)を作っては見たのですが、なんだかんだと実装に時間がかかった割に多分あまり速度上がりそうもありません。(実はまだ試してません)本当はそれを作ってドヤ顔したかったのですが。最後に、もう一度言いますが、MSetsは普通に使う分には問題なく便利なので、ご心配なく。Studioを共有環境に入れよう!ここでいう共有環境とは、以下のような特徴を持つ七面倒くさい環境を言う。