恒星写真探索問題 †晴れた夜に空を見上げるとたくさんの星が見える.星座は,地球から見て近い星をつないだものだが,たとえば同じおうし座に属する星でも,すばる(プレアデス星団)は地球から410 光年,アルデバランは60 光年の距離にあり,実際の距離が近いわけではない. 遠い将来,人類が太陽系外に進出したとき,遠くの惑星から空を見上げたら,やはりたくさんの星が見えるだろうが,見えている星の配置は違い,星座の形もまったく違っているだろう.とすれば,空に見える星の写真を見れば,それがどの星から撮られた写真なのかがわかるはずだ.たとえば,遠い恒星系の惑星に不時着した宇宙船から,星を写した写真が送られてきたら,どの星に救助に向かうべきかがわかるに違いない. 課題 †ある空間内に存在するすべての星の座標が与えられている.それに対して様々な星 から撮影した「全天写真」が数多く与えられる.これらの写真から,その各々が,ど の星からどの方向を向いて撮影されたものかを計算してほしい.多数の写真が出題 されるので,制限時間内に最もたくさんの写真に対して正解を出したチームが優勝 である 用語解説(本課題のためのもの) †
問題例の詳細 †入力データは,すべての星の絶対座標と,全天写真1000 枚分の写真データからなる.1000 枚分のデータはすべて最初に与えられるので,どの順序で解いてもよい.
プログラミングの注意 †
審査 †
課題攻略のヒントと注意 †課題への取り組み方 †写真を撮った方向がわからないので工夫が必要である.同じ星からの写真であっても撮影方向が違えば各点は違う座標で表現される.そこで,ひとつの考え方は,撮影方向によって変化しない量を計算することである.たとえば,写真に写っている特定の二点間の距離は撮影方向によって変化しない.このような「回転に対して不変な量」で比較するのが有効な方法だろう. また,写真に写っているすべての点がどの星であるかを決定するとなると多くの計算量を要するが,問題ではそこまで要求していない.候補となる星から撮影した写真が,問題の写真と完全に一致することを確認しなくても,いくつかの「回転に対して不変な量」で候補を絞り込んで,候補がひとつに決まればよい.いかにして計算をさぼるかが重要である. 精度に関する注意 †通常の数値計算では残念ながら誤差を避けることはできない.この点を忘れないでおこう.具体的には2 つの重要な点がある.一つは誤差を仮定してプログラムを作ることであり,もう一つは大きな誤差を生み出さないという点である. たとえば,星の位置が同じかどうかをチェックする際,変数(x, y, z) に保持されている入力した写真データの座標と,変数(x0, y0, z0) に保持されている計算した座標が一致するかを確かめる必 要が出てくる.その際, if(x == x0 && y == y0 && z == z0) のようなテストはまったく役に立たない可能性がある.計算による誤差のためにキッチリと等しくならない場合があるからだ. もちろん,出題者側が写真データを計算する際にも誤差は生じている.もしも,出題者とまったく同じ計算で(x0, y0, z0) の値を計算したならば,キッチリと等しくなるかもしれない.しかし,式の上では同じでも,加算や乗算の順序で,誤差の出方が微妙に違う場合も少なくないし,その場合にはキッチリ等しくなるとは思えない.したがって, if(|x-x0|<ϵ && |y-y0|<ϵ && |z-z0|<ϵ) のように,ある程度の誤差(ϵ)の範囲内での比較を考えるべきである.では,ϵ をどの程度の値にすればよいか?これはデータの性質によって決まってくる.今回のデータに対する許容誤差範囲については,例題や今後ヒントとして与えられる情報に応じて判断してほしい.また,あくまで一般論だが,今回の課題では安全を見て許容誤差範囲を少し大きくとっておく方がよい.それにより複数の解の候補が出てくる可能性があるが,多数の星が,すべて許容誤差範囲の射影座標を持つ可能性は非常に低いと考えてよいだろう. もう一つは,計算によっては大きな誤差を出さない注意である.計算によっては同じような計算をしても大きな誤差が出てしまう場合がある.例えば,10000.0+0.00001 は正確には10000.00001 であるが,(C言語のfloat 型などのように)精度が6桁程度しかない場合には10000.0+0.00001 = 10000.0となってしまう.このような誤差を「情報落ち」といい,特に,絶対値の大きい値と小さい値の足し算や引き算を多数繰り返す場合には問題となる.情報落ちを避けるためには,多数の足し算や引き算を行う際に,計算の順序を変更して,小さいもの同士,大きいもの同士を先に計算し,絶対値が異なる数の計算の回数を必要最小限に抑えるといった工夫が必要である. また,123.456 − 123.455 = 0.001 のような計算では,6桁の精度が1桁に落ちてしまうが,このような誤差を「桁落ち」という.桁落ちは,値が近い二つの数の引き算を行う場合に起こる.桁落ちを避けるためには,やはり計算の順序を変えるなどして,大きさの近い二つの数の引き算をなるべく避けることが肝要である. 情報落ちや桁落ちは,他の計算誤差(たとえば四捨五入などによる丸め誤差)などと比べて誤差の蓄積が顕著であり,気づかずにプログラムしてしまうことが多いので注意が必要である.もっとも,今回の課題は,わざわざ誤差が蓄積するような計算をしない限り,情報落ちや桁落ちのせいで正解が求まらないということにはしていないので,最初からこれらの誤差の問題に神経質になる必要はないだろう.どうしても解がうまく求まらない場合には,これらの誤差の問題を思い出してみて欲しい. |