OCamlでニュートン法(2)

さて、前回微分の計算をするところまでで終わっていたんだけど今回は実際に Newton-Raphson で実装してみよう。
\Large \mathbf{x_{n+1}=x_{n}-\frac{f(x_{n})}{f\prime(x_{n})}}

(* small number *)
let dx = 1.0e-10;;

(* threshold *)
let threshold = 1.0e-15;;

(* derivative *)
let deriv f x dx = (f (x +. dx) -. f x) /. dx;;

(* X n+1 *)
let xn_plus_one f x = x -. (f x) /. (deriv f x dx);;

(* newton-raphson *)
let newton_raphson f i =
  let rec newton x =
    let next_num = xn_plus_one f x in
    Printf.printf "%.20f\n" next_num;
    if abs_float (next_num -. x) < threshold then ()
    else newton next_num
  in newton i;;

実行すると

# #use "newton.ml";;
val dx : float = 1e-10
val threshold : float = 1e-15
val deriv : (float -> float) -> float -> float -> float = <fun>
val xn_plus_one : (float -> float) -> float -> float = <fun>
val newton_raphson : (float -> float) -> float -> unit = <fun>
# let f x = x ** 2.0 -. 2.0;;
val f : float -> float = <fun>
# newton_raphson f 2.0;;
1.50000004137018194683
1.41666667356169995173
1.41421568647730544477
1.41421356237427708891
1.41421356237309514547
1.41421356237309492343
- : unit = ()
# newton_raphson f 10.0;;
5.10001781366008355434
2.74608272554679633259
1.73719668537143467901
1.44423846224395591165
1.41452565448231015743
1.41421359644891775353
1.41421356237308581960
1.41421356237309514547
1.41421356237309492343

このように2の平方根が求まるが、見ればわかるとおり二分法と比べて大幅に収束が速くなっている。ただし、誤差の関係上thresholdの値を1.0e-16以下にしてしまうと収束しなくなってしまうという問題もある。

OCamlでニュートン法(1) 微分の計算

さて、ニュートン法とは二分法のとこでもやったy=f(x)x軸との交点を求める場合に関数の接線を用いるという方法。
\Large f\prime(x_{n})= \frac{f(x_{n})-0}{x_{n}-x_{n+1}}
で、x_{n+1}について解いて、
\Large \mathbf{x_{n+1}=x_{n}-\frac{f(x_{n})}{f\prime(x_{n})}}
これを使う。
このうち、今回はf\prime(x_{n})の計算の仕方。

f\prime(x_{n})を求めるのに一番簡単なのは
\lim_{dx\to0} \left(\frac{f(x+dx) - f(x)}{dx}\right)
においてdxを十分小さな値にして計算する方法。

差分法というらしい。

ということでf(x) = x^2を例に実際に試してみる。解析的手法だとf\prime(x)=2xであり、xが1の場合はf\prime(1)=2となる。では数値計算でも同様の結果となるか?

let f x = x ** 2.0;;

let rec recderiv x dx t =
    if t < 500 then
      let deriv x dx = ( f ( x +. dx ) -. f x ) /. dx in
      Printf.printf "dx: %.17f  dy/dx: %.17f  error: %.17f\n" dx (deriv x dx) (abs_float (2.0 -. (deriv x dx)));
      recderiv x (dx /. 10.0) (t + 1)
    else
      ()
;;

としてこれを deriv.ml というファイル名で保存。
で、実行。

# #use "deriv.ml";;
val f : float -> float = <fun>
val recderiv : float -> float -> int -> unit = <fun>
# recderiv 1.0 1.0e-5 0;;
dx: 0.00001000000000000  dy/dx: 2.00001000001392981  error: 0.00001000001392981
dx: 0.00000100000000000  dy/dx: 2.00000099992436686  error: 0.00000099992436686
dx: 0.00000010000000000  dy/dx: 2.00000010108780613  error: 0.00000010108780613
dx: 0.00000001000000000  dy/dx: 1.99999998784505761  error: 0.00000001215494239
dx: 0.00000000100000000  dy/dx: 2.00000016548074155  error: 0.00000016548074155
dx: 0.00000000010000000  dy/dx: 2.00000016548074155  error: 0.00000016548074155
dx: 0.00000000001000000  dy/dx: 2.00000016548074155  error: 0.00000016548074155
dx: 0.00000000000100000  dy/dx: 2.00017780116468158  error: 0.00017780116468158
dx: 0.00000000000010000  dy/dx: 1.99840144432528155  error: 0.00159855567471845
dx: 0.00000000000001000  dy/dx: 1.99840144432528155  error: 0.00159855567471845
dx: 0.00000000000000100  dy/dx: 2.22044604925031308  error: 0.22044604925031308
dx: 0.00000000000000010  dy/dx: 0.00000000000000000  error: 2.00000000000000000
dx: 0.00000000000000001  dy/dx: 0.00000000000000000  error: 2.00000000000000000
dx: 0.00000000000000000  dy/dx: 0.00000000000000000  error: 2.00000000000000000

結果を見るに dx が小さすぎると誤差が大きくなる傾向にある。これは打ち切り誤差や丸め誤差といった問題のためのようだ。次に任意精度を使って解いてみる。OCamlではNumというモジュールが相当するようなのでこのモジュールを使って試してみよう。

#load "nums.cma";;
open Num;;

let f x = x **/ Int 2;;

let rec recnumderiv a b t =
  if t < 500 then
    let deriv x dx = ( f ( x +/ dx ) -/ f x ) // dx in
    let ans = deriv a b in
        Printf.printf "%s\n" (approx_num_fix 180 ans);
    recnumderiv a ( b // (Int 10 ) ) (t + 1)
  else
    ()
;;

これをnumderiv.mlというファイル名として実行。

# #use "numderiv.ml";;
val f : Num.num -> Num.num = <fun>
val recnumderiv : Num.num -> Num.num -> int -> unit = <fun>
# recnumderiv (Int 1) (Int 1 // Int (-5)) 0;;

結果は実行してもらえばわかるが見事に 2 に収束していく。
ただこの Num モジュール、任意精度を扱えるのはいいがすごく扱いにくいのだった。

Ocamlで二分法(2) 平方根を求める&二分法の汎用部品化

昨日に続いて二分法を使い、今度は平方根を求めてみる。

二分法を使う場合に
対象となる関数が連続関数であり、f(a) < 0 かつ f(b) > 0 の場合、f(x) = 0 となる根 x区間 (a,b)に存在する

ということなので \sqrt{a} を求めるにあたり、f(x) = x^2 - a という式においてf(x) = 0 を満たす x が解となる。(ちなみにこの式がピンとくるまでに結構時間がかかったw)
このように y = 0 となる点が解となるように関数を作るのが二分法のキモらしい
ちなみに、二分法における解の精度は \frac{x2 - x1 }{2 ^ n} ということである。

では2の平方根を求めるプログラムを実装してみよう。

f(x) = x^2 - 2

type sign = Positive | Negative ;;

let f x = x ** 2.0 -. 2.0 ;;

let g x =
  if x >= 0.0 then
    Positive
  else
    Negative
;;

let rec bis ( x1, x2, x3, x4 ) =
  if x3 >= x4 then
    (x1, x2, x3, x4)
  else
    let xm = ( x1 +. x2 ) /. 2.0 in
        if g ( f xm ) = g ( f x1 ) then
          bis ( xm, x2, x3 + 1, x4 )
    else
      bis ( x1, xm, x3 + 1, x4 )
;;

実行してみる。

# bis (1.0, 2.0, 0, 30);;
- : float * float * int * int =
(1.41421356145292521, 1.41421356238424778, 30, 30)

今回はサクッと行った!
さてお気づきの通り、前のと比べると関数 f の定義しか変わっていない。
なので次は高階関数を使って関数 f を引数に指定できるようにしてみよう。

type sign = Positive | Negative ;;

let g x =
  if x >= 0.0 then
    Positive
  else
    Negative
;;

let rec bis ( f, x1, x2, x3, x4 ) =
  if x3 >= x4 then
    (x1, x2, x3, x4)
  else
    let xm = ( x1 +. x2 ) /. 2.0 in
        if g ( f xm ) = g ( f x1 ) then
          bis ( xm, x2, x3 + 1, x4 )
    else
      bis ( x1, xm, x3 + 1, x4 )
;;

と、これだけ。
実際にテストしてみる。

# let f x = x ** 2.0 -. 3.0;;
val f : float -> float = <fun>
# bis (f, 1.0, 2.0, 0, 30);;
- : float * float * int * int =
(1.73205080721527338, 1.73205080814659595, 30, 30)
# let f x = x ** 2.0 -. 4.0;;
val f : float -> float = <fun>
# bis (f, 1.0, 3.0, 0, 30);;
- : float * float * int * int = (1.99999999813735485, 2., 30, 30)

できた。
これまでは試行回数を指定してきたわけだけど、次に最小誤差に到達したらその時点でプログラムを終了させるようにしてみる。ここで最小誤差は 1.0e-15 とする。

type sign = Positive | Negative ;;
let min_f = 1.0e-15;;

let g x =
  if x >= 0.0 then
    Positive
  else
    Negative
;;

let rec bis ( f, x1, x2, x3 ) =
  let xm = ( x1 +. x2 ) /. 2.0 in
  if ( x2 -. x1) < min_f then
    (x1, x2, x3 + 1)
  else
    if g ( f xm ) = g ( f x1 ) then
      bis ( f, xm, x2, x3 + 1 )
    else
      bis ( f, x1, xm, x3 + 1 )
;;

さらにグラフを書けるように中点の変遷をテキストに出力するようにする。

type sign = Positive | Negative ;;
let min_f = 1.0e-15;;
let out_file = "out.txt";;

let g x =
  if x >= 0.0 then
    Positive
  else
    Negative
;;

let rec bis ( oc, f, x1, x2, x3 ) =
  let xm = ( x1 +. x2 ) /. 2.0 in
  Printf.fprintf oc "%.17f\n" xm;
  if ( x2 -. x1) < min_f then
    Printf.printf "x1: %.17f x2: %.17f xm: %.17f try: %d\n" x1 x2 xm ( x3 + 1 )
  else
    if g ( f xm ) = g ( f x1 ) then
      bis ( oc, f, xm, x2, x3 + 1 )
    else
      bis ( oc, f, x1, xm, x3 + 1 )
;;

let fbis ( f, x1, x2, x3 ) =
  let oc = open_out out_file in
    bis ( oc, f, x1, x2, x3 );
  close_out oc;
;;

で、結果が

# let f x = cos ( x /. 2.0 );;
val f : float -> float = <fun>
# fbis ( f, 0.0, 6.0, 0);;
x1: 3.14159265358979312 x2: 3.14159265358979356 xm: 3.14159265358979312 try: 54
- : unit = ()

out.txtにも中点の値が書きこまれている。ちなみにこのプログラムを書いている途中、またもや盛大にハマっていた。Printf.printf の行の最後にあるセミコロンの必要性の有無が未だにさっぱりわかっていないのだ。まだまだヘタレである。
で、Excelでグラフおこしながら思ったんだけど、収束が速いってどのくらいからを速いというのだろうか?

Ocaml で二分法

最近、Ocaml数値計算をセットで勉強することにしている。

さてこの二分法とは、解を含む区間の中点を求める操作を繰り返すことによって方程式を解く求根アルゴリズムだそうな・・・。詳しくはWikipediaの二分法を参照のこと。

で、円周率を二分法で求める例、全然たいしたことないコードなんだけど Ocaml で書くのに一時間以上もかかってしまった。でも再帰関数が身に染み込んだ気がするので良し。
アルゴリズムとしては \cos \frac{\pi}{2}が円周率になることを利用し、その近似値を二分法で求めるというもの。なので \sin \piでも同様だと思う。

type sign = Positive | Negative ;;

let f x = cos ( x /. 2.0 );;

let g x =
  if x >= 0.0 then
    Positive
  else
    Negative
;;

let rec bis ( x1, x2, x3, x4 ) =
  if x3 >= x4 then
    (x1, x2, x3, x4)
  else
    let xm = ( x1 +. x2 ) /. 2.0 in
    if g ( f xm ) = g ( f x1 ) then
      bis ( xm, x2, x3 + 1, x4 )
    else
      bis ( x1, xm, x3 + 1, x4 )
;;

実行してみる。

# bis (0.0, 6.0, 0, 50);;
- : float * float * int * int =
(3.14159265358978956, 3.14159265358979489, 50, 50)

収束するのに50回ちょっとかかるみたい。


文系であればこの二分法、意味は全く違う「二分法の罠」というほうが有名かもしれない。例えば
・クリスマスのプレゼントを子供に買ってあげなければいけない
・プレゼント代は自分の少ない小遣いから出さなければいけない
・なるべく出費を抑えたい
という場合において子供はPS3が欲しいものとしよう。

PS3は約3万円、でもできれば1万円以上節約したい。ここで親が繰り出すのが「二分法の罠」なのだ。親がクリスマス前あたりに子供に向かって
Nintendo DSiPSP Go だったらどっちをサンタさんに頼みたい?」
とあらかじめ聞いてしまう。
周りの子供達における DS の普及率が高ければ子供が DS を選ぶという期待値は予め高いものと予想できる。かつ DSi LL でも 18,000 円程度で1万円以上の節約になる。
ということでめでたくクリスマスに子供は DSi をゲットできて、親も PS3 を買わずに済んで見かけ上は win-win となる。

ここではセコい親の例をあげたけど、交渉が仕事のような人であれば知らず知らずのうちにもこの「二分法の罠」を使っていると思われる。キモは相手が許容できるギリギリのところにターゲットを合わせて「(こちら側に都合の良い)正解」となる選択肢を用意し、他の捨て駒となる選択肢もいくつか用意しておくこと。
ただし、将来的な展望を考えた上で使わないと仕事の依頼自体がなくなることもあるのは自明なので、できれば使わない方が良いのは当然である。

「プログラミングの基礎」

前回書いた通り、「最新コンパイラ構成技法」を読む途中で ML 習得の必要性を感じて OCaml を始めたわけだけど、今やすっかりハマっている。
「最新コンパイラ構成技法」については第二部をある程度読み終えて(いやこの二部は実際すごくイカしてる)、Ocaml をある程度使いこなせるようになったらまた第一部の続きから自分でもコンパイラの実装に挑戦しようと思っているところだ。

ということで、「プログラミングの基礎」という本を購入し、Ocaml の単純な記法とアルゴリズムの組み合わせの素晴らしさや難しさに一喜一憂しているのが現状。
ところでこの「プログラミングの基礎」という本はホントに非の付け所がないほど素晴らしい。プログラムを組む際の指針として必要なことはだいたいこの本から学べるんじゃないだろうか。

プログラミングの基礎 ((Computer Science Library))

プログラミングの基礎 ((Computer Science Library))

いわゆる文系プログラマにもオススメ。
今まで必要性を感じずにすっ飛ばしてきたアルゴリズムという部分がこの本のテーマの一つ。一般企業向けのSIをやっていると高度なアルゴリズムが重要になる局面って少ないんだよね。もちろんBIなんかが絡んでくると途端にその重要性はアップするんだけど、どっちかというとデータを入力し、集計してどっかに出力するっていう単純なロジックを組み上げていくほうが多い。もちろん技術的に難しいところもあるけど、たいていは余裕をもってクリアできる範疇だったりする。だからSI企業の募集要項ではどの言語、どのDBを扱えるか、フレームワーク使ってWEBアプリ作れるかっていう程度しか指標にならない・・・。

でもホントはそういう、きっとどこかで誰かが全く同じものを作ってるんだろうなっていうような部分を超えて、新しい価値を生み出していくっていうのが重要なんじゃないか。例えば Google の検索技術みたいなね。確かに最初はアイデア勝負というのは認めるし、アイデアって実際ものすごく大切なんだけどそれが高度な技術の延長上にないのであればそれは実は資本勝負にすぎず、後発の資金力のある企業に飲み込まれてしまうだろう。

その高度な技術を伴った新しい価値を生み出す重要な基礎力の一つがコンピューターサイエンス。
コンピューターサイエンスとはプログラミングと様々な「学」が合流する部分にあると自分では捉えている。その「学」とプログラミングをくっつける糊の役割をしてくれるのが数学(これも学なわけだけど)で、だからこそ自分は数学を今必死にやっている。
数学を学んでいくためにはかなりの労力を要する。小説と違って数学の本を読んでいくのにはかなりの時間がかかって、たとえばたった半ページを理解するのに丸一日、もしくはそれ以上かかったりというのがザラだ。
たびたび、自分の頭の悪さに思いっきり辟易しながらもゆっくりとその歩を進めている途中である。

訳あってOCaml

まさか自分が OCaml を勉強するとは全くもって思っていなかったんだけど、訳あって只今 OCaml 勉強中。

というのも「最新コンパイラ構成技法」を読んでいて、その原著が「Modern Compiler Implementation in ML」。「Modern Compiler Implementation in C」でもないし、ましてや「Modern Compiler Implementation in Java」でもない。MLなの。ML。
で、その本の二章に ML-Lex という ML 向けの字句解析器が登場し、あーやっぱりML書けないとダメかと思うに至り、幸い Ubuntu なら ml-lex や ml-yacc、smlnj(Standard ML of New Jersey) のパッケージはあるんだけど、でもどうせならもっと実用的なのがいいなと思って OCaml に行き着いたと。いろいろ特殊に感じるところはあるけれど、独特な関数の書き方なんかもそんなに苦にならない。前に Erlang やったからかな。おかげでようやく関数型プログラミング言語像がイメージとして捉えられるようになってきたっぽい。

最新コンパイラ構成技法

最新コンパイラ構成技法

最新コンパイラ構成技法

原著のModern Compiler Implementation in ML
Modern Compiler Implement in ML

Modern Compiler Implement in ML

Cバージョン
Modern Compiler Implement in C

Modern Compiler Implement in C

Javaバージョン
Modern Compiler Implementation in Java

Modern Compiler Implementation in Java

それとは別に字句解析器と構文解析器の使い方を勉強。
Lex & Yacc

Lex & Yacc (A Nutshell Handbook)

Lex & Yacc (A Nutshell Handbook)

Flex & Bison
flex & bison: Text Processing Tools

flex & bison: Text Processing Tools

Building Parsers With Java などを参考にしつつ。
Building Parsers With Java™

Building Parsers With Java™

あとは Lua のレクサとパーサのソース読んでみたり。
前途多難だけど、こういういかにもCSっぽい勉強ってしたことがなかったのでそれなりに楽しめる。

autoconf 2.66 にハマる。というか使っちゃいけない。

事の発端は ruby の 1.9.2 を rc1 ではなくブランチリポジトリから直接持ってきて configure && make してインストールしようとしたら configure スクリプトがなかったので autoconf を走らせた時。
開発機が CentOS5 でデフォルトパッケージの Autoconf は 2.59、この状態で ruby のソースディレクトリにおいて autoconf を走らせるとバージョン 2.60 以上が必要というエラーメッセージが出たので GNU のサイトから autoconf の 2.66 をダウンロードしてインストール。で、autoconf実行。

$ autoconf
configure.in:497: error: AC_CHECK_SIZEOF: requires literal arguments
autoconf/types.m4:783: AC_CHECK_SIZEOF is expanded from...
configure.in:489: RUBY_CHECK_SIZEOF is expanded from...
configure.in:497: the top level
autom4te: /usr/bin/m4 failed with exit status: 1

というエラーが発生してしまい、先に進めなくなってしまった。
autoconf のサイトに行ってみると m4 の 1.4.6 以降が最低限必要って書いてある。

$ m4 --version
GNU M4 1.4.5
Written by Rene' Seindal.

Copyright (C) 2006 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

このせいかなーと思って m4 もソースからインストールしなおし。

$ m4 --version
m4 (GNU M4) 1.4.14
Copyright (C) 2010 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later http://gnu.org/licenses/gpl.html.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

さらに autoconf ももう一回 configure &コンパイル&インストール。
もう大丈夫だろうと autoconf を再び走らせると

$ autoconf
configure.in:497: error: AC_CHECK_SIZEOF: requires literal arguments
../../lib/autoconf/types.m4:765: AC_CHECK_SIZEOF is expanded from...
configure.in:408: RUBY_CHECK_SIZEOF is expanded from...
configure.in:497: the top level
autom4te: /usr/local/bin/m4 failed with exit status: 1

またも同様な結果になってしまったのでググってみたらすぐに原因が見つかった・・・。
Don't try autoconf 2.66 at home just yet!
こちらに書かれていることを ruby の configure.in に当てはめて調べてみると、

RUBY_CHECK_SIZEOF(void*, [int long "long long"], [ILP LP LLP])

の部分で void* を渡していて RUBY_CHECK_SIZEOF 定義内の AC_CHECK_SIZEOF([$1], 0, [$4]) でコケてしまうって寸法。
結果的には autoconf 2.66 のリグレッションバグのようで、
http://osdir.com/ml/autoconf-gnu/2010-07/msg00007.html
こちらに修正パッチがあがってる。

これを適用した autoconf でようやく configure スクリプトの作成が可能になり、喜び勇んで configure スクリプトを走らせ、make。
でもそうは問屋が卸さない。

# make
gcc -O3 -ggdb -Wextra -Wno-unused-parameter -Wno-parentheses -Wpointer-arith -Wwrite-strings -Wno-missing-field-initializers -Wno-long-long -I. -I.ext/include/i686-linux -I./include -I. -DRUBY_EXPORT   -o main.o -c main.c
gcc -O3 -ggdb -Wextra -Wno-unused-parameter -Wno-parentheses -Wpointer-arith -Wwrite-strings -Wno-missing-field-initializers -Wno-long-long -I. -I.ext/include/i686-linux -I./include -I. -DRUBY_EXPORT   -o dln.o -c dln.c
gcc -O3 -ggdb -Wextra -Wno-unused-parameter -Wno-parentheses -Wpointer-arith -Wwrite-strings -Wno-missing-field-initializers -Wno-long-long -I. -I.ext/include/i686-linux -I./include -I. -DRUBY_EXPORT   -o dmydln.o -c dmydln.c
gcc -O3 -ggdb -Wextra -Wno-unused-parameter -Wno-parentheses -Wpointer-arith -Wwrite-strings -Wno-missing-field-initializers -Wno-long-long -I. -I.ext/include/i686-linux -I./include -I. -DRUBY_EXPORT   -o dmyencoding.o -c dmyencoding.c
gcc -O3 -ggdb -Wextra -Wno-unused-parameter -Wno-parentheses -Wpointer-arith -Wwrite-strings -Wno-missing-field-initializers -Wno-long-long -I. -I.ext/include/i686-linux -I./include -I. -DRUBY_EXPORT   -o version.o -c version.c
gcc -O3 -ggdb -Wextra -Wno-unused-parameter -Wno-parentheses -Wpointer-arith -Wwrite-strings -Wno-missing-field-initializers -Wno-long-long -I. -I.ext/include/i686-linux -I./include -I. -DRUBY_EXPORT   -o dmyversion.o -c dmyversion.c
/usr/local/ruby_1_9_1/bin/ruby -I. ./tool/compile_prelude.rb ./prelude.rb miniprelude.c
bison -d  -o y.tab.c parse.y
make: *** [parse.c] パイプが切断されました

ぐばー。
bisonよ、お前もか・・・。

# bison --version
bison (GNU Bison) 2.3
Written by Robert Corbett and Richard Stallman.

# rpm -e bison --nodeps

再び GNU のサイトから bison の 2.4.2 を引っ張ってきてインストール。

# bison --version
bison (GNU Bison) 2.4.2
Written by Robert Corbett and Richard Stallman.

これでようやく make が通った。

# /usr/local/ruby_1_9_2/bin/ruby --version
ruby 1.9.2dev (2010-07-06 revision 28549) [i686-linux]

ちなみに 1.9.2 の RC1 だったり、もしくは OS が新しめの ubuntu なんかであれば苦労レスで configure && make がするりと通る。

で、結論。
新しいものを試すって場合、CentOS5 の賞味期限はもう切れているってこと。RHEL6 がすでに beta2 に入り、それほど遠くない時期に正式版がリリースされることを考えると新規プロジェクト向けのサーバ構築で CentOS5 にこだわる理由はないし、そもそも何でそれ使うんだって話になるんだろう。ちなみに現在個人的に契約している VPS は CentOS5 なのだけれども、利用しているソフトウェアは殆どソースからコンパイルしたもので、パッケージは uninstall されゆく一方。ディストリビューションの恩恵を受けることがほぼ出来ない状態になってしまっている。
枯れたパッケージを乗っけて運用するのであれば CentOS5 でぜーんぜん問題ないんだけどなー。