一般

KCSで行われた一般的な事柄

情報(工学)科の授業は教養ですらないという話 – 慶應義塾大学編

この記事はKCS Advent Calendar 25日目の記事です。

こんにちは、mt_caretです。最終日です。1お疲れ様でした。

情報科の授業は教養に過ぎないという話 – 東京工業大学附属科学技術高校編 — yosida95

自分がまだ高校生の時にこのブログ記事が大変話題になり、この記事や派生記事が大変印象に残りました。自分もついに学部3年になり、研究室も決まったので、そろそろ自分の大学や情報(工学)科に関する所感を述べます。不満だけ述べても生産的でないので、どうすれば良くなると思うかについても少し言及します。

TL;DR

  • カリキュラムが合わなかった(特に専門講義はかなり期待はずれだった)
  • 体系的な、幅広い範囲の情報科学教育(i.e. 教養)を期待しないほうがよい
  • 独学できる人ならSFCは悪くないのではないか

=> 進学先を間違えた

自分について

まずは軽く自己紹介をしようと思います。慶應義塾大学理工学部情報工学科に所属しています。

中学・高校ではロボコンや情報セキュリティに取り組んでおり、 CombGigを始めとする、CombConfと同じテーマの勉強会を開いたりしていました。その過程で、自分がやっていることはものづくりを趣味でやる範囲を出ていないことを痛感し、興味のない科目を学ぶことを強制されることなく、体系的に情報科学の様々な分野を学びたいと思い、大学に大変期待をしていました。

入学まで

興味のない分野の勉強に上手く打ち込むことができず入試に落ち、慶應義塾大学に進むことに。経済学部・環境情報学部・理工学部の3つに受かったため、情報科学を一番学べそうな理工学部に入ることにしました。

学門制 | 慶應義塾大学理工学部

ようこそ、学びの庭への 入口 [学門]へ! – 慶應義塾大学理工学部

慶應義塾大学には学門という概念があり、理工学部の入試の時点で学門1~5のどれかに入り、学部2年に進むタイミングで成績ベースで学科振り分けがされます。自分は情報工学科の定員が最も多い学門5を選びました。

B1

この学門制度にはいくつな不思議な点があります。

例えば、学門関係なく理工学部生は全員「基礎教育科目」という名目で数学・物理・化学や自然科学実験という物理と化学に関する実験を行う科目を履修することが強いられています。成績が悪いと希望しない学科に配属される可能性があるため、必死に取り組む必要があります。これが自分にとって予想以上に苦痛で、何故やる必要があるのか理解できないまま、情報科学を学ぶ権利を得るために、高校の時と同じように情報科学と一切関係のない分野の勉強や課題に取り組んでいました。

また、学門に関するサイトに

入学後、自分の興味や関心に応じて徐々に学びたい分野を絞っていき、2年進級時に所属する学科を決定します。

とありますが、自分の入学後、自分の興味や関心に応じて徐々に学びたい分野を絞っていった結果進みたい学科の枠が自分の学門に無い場合、「学門越え」が必要になりますが、理工学部全体で1学年1000人居る中許可されのは数人程度なので非常に難しいです

余談ですが、情報科学を学んだりプログラミング言語を学んだりする講義は理工学部の 1年の時は普通の選択科目としては用意されていません。例えば経済学部にはあるようだという話は聞いています。

B2

なんとか情報工学科に配属され、おお喜びです。これでやっと情報科学が学べるぞ!と思いきや、薄々感じていた違和感がより強く現れます。情報技術の話が通じる人が周りにいません。講義でもプログラミングはおろかパソコンを触ったことのない人を想定して進み、いくつかの講義を除き全て紙に鉛筆で進みます。

2年の時はC言語を学びます。2同期の多くはプログラミングをしたことがないため初めて学ぶプログラミング言語となりますが、3 純粋に文法と簡単な演習問題をやるだけなので、例えばポインタを理解していなくてもなんとかなりそうな感じでした。

コンピュータグラフィックスを専門とされている先生がアルゴリズムの講義を教え、4 ところどころテクニカルタームを誤用なさったり、最も実の有る講義と感じたラムダ計算とアルゴリズムのための離散数学の講義はそれぞれ文学部と数理科学科の先生によるものだったりと全体的に教員不足を感じました。アルゴリズムと言語処理系が専門の情報工学科の先生が欲しかったです。

また、講義を受けるための必修科目(prerequisites)、という概念がなくどの講義も事前知識を仮定されてないためか、例えばフーリエ変換やOSI参照モデルを別々の講義で複数回やり、カリキュラムの構成に違和感がありました。

B3

Cを1年かけて学んだ(?)次はJavaを学びます。5

3年の前期の後半は香港の企業でのインターンシップをやっていたため、限られた数の講義しか受けることができていませんが、3年になると4年の講義を履修することができることもあり、履修した範囲では流石に2年の講義と比べてもう少し深い内容になっている気がします。

しかし、米大などでは Captstone course6として位置付けられているコンパイラやOSの講義が後期週1コマに詰め込まれており、例えば計算理論の講義でDFAをゆっくり学ぶのと並列してコンパイラの講義でレキサ・パーサの文脈でDFAを軽く教わるといったような状況になり、やはりカリキュラムの構成が微妙だと感じました。

また、計算理論の講義ではAutomata Theory, Languages, and Computationをテキストとして進めますが、学生には難しいということでチューリングマシンの章まではやりません。なので、チューリングマシンを扱わず情報工学科の学位を得ることができます。余談ですが、同じ理工学部の数理科学科ではチューリングマシンまで含めて学ぶ計算理論の講義があるそうです。

こういったものを経て現在に至ります。研究室配属に関しても様々な話がありますが、話の本筋である情報科学教育から外れますので割愛します。

不満

  • 講義1つ1つが軽く、深いレベルの理解につながるような手を動かす課題を出す講義が非常に少ない
  • カリキュラム全体に統一感が無く、情報科学の中でも通信に偏っている
  • 同期に情報技術に取り組んできた人がとても少ない

良い点

  • G Suite・Google Drive無制限・Office 365あたりの福利厚生

結論

結論としては、

講義を通しては体系的な学習はできず、学部3年間は結構大きい機会損失だった

という風に考えています。カリキュラムについて良く調べ、事前に本質を見抜くべきでした。

申し送り

機会損失を減らす方向で、自分みたいな人に向けて書きます。

慶應義塾大学理工学部の受験を考えている人向け

  • 情報科学を学びたいなら、数理科学科がオススメです
  • 独学ができるなら、情報工学科と比べ必修科目が少なく自由時間が多い7 環境情報学部は悪くない選択肢だと思います

理工学部1年向け

  • 環境情報学部への転学部は比較的簡単らしい
  • KCSやロボット技術研究会といったサークルに入ったりし、探しに行くと大変優秀な人は一定数いる

情報工学科n年向け

  • ご愁傷さまです
  • n = 1くらいなら1年+αは埋没費用としてあきらめて大学の再受験は選択肢の1つだと思います
  • 過去n年は埋没費用として諦めて、残りのの4-n年の学費で学位を購入する気持ちで取り組みましょう。
    • ちゃんと取り組むと機会損失が増えるので講義・課題は最低限の手間を掛けて後は独学をがんばりましょう
  • 外の世界を見ましょう
    • 勉強会での発表は良い経験になります
    • インターンはよい経験になるだけではなく、職にも繋がります

免責

なお、このブログエントリを真に受けた事によって生じた利益や不利益について私はもちろんあなたの周囲の誰も責任を取りません。 自分の進路における決定はすべて自分の責任の下に行なわれるべきです。 しかし、無責任な周囲による無責任な意見を積極的に聞いて自分自身で咀嚼した方がお得です。 あなたは自身が想像している以上に視野狭窄です。 周囲の意見を聞くことで、自分だけでは考えつかなかった選択肢がいくつも出現して裏ステージへ進める可能性が高まります。
私自身がひどい視野狭窄に陥っている可能性が高いので、周囲の意見を聞こうという自戒です。 よろしければ、このエントリや私の考え方についてご意見や反論などをください。
(情報科の授業は教養に過ぎないという話 – 東京工業大学附属科学技術高校編 — yosida95より)

完全にこれです。是非意見・反論をください。

謝辞

事前に読み、フィードバックを送ってくれた皆さん、ありがとうございました。


  1. 遅刻しました。ごめんなさい。

  2. サンプルコードの文法が間違っているためそのままではコンパイルが通らないことが多々あったことが印象に残っています。また、課題の出力フォーマットが曖昧な上に手動で採点が行われているため、提出されたコードは目視で確認し採点する時がある、といったようなことをTAの方から聞いた記憶があります。既存のオンラインジャッジでもよいので、(可能であればオンラインの)自動的な採点システムが欲しかったです。

  3. C自体情報科学をやる上で必須だと思いますが、初めて学ぶ上でつまづきやすい、本質的でない部分が多いような気がしてなりません。SchemeやPythonあたりでSICPをやるぐらいが丁度よいかなと思いました。

  4. 線形探索に一時間半の講義を丸々掛けていたのが印象に残っています。

  5. E.W.Dijkstra Archive: To the Budget Council (concerning Haskell)
    余談ですが、環境情報学部ではプログラミングの講義として上級者向けにHaskellを学ぶ選択肢があるようです。

  6. こういった講義の存在は日本の大学では聞いたことがありません。東大のCPU実験あたりが該当するのでしょうか?

  7. 諸説あるようです。

Marloコンペ用の強化学習環境をサーバーに立てた話(おまけ:Google ColabでDQN)

はじめに

こんにちは、syuntoku14です。現在カリフォルニアでスマブラしてます。イカちゃん強いね。

 

スマブラのせいで時間がなくなってしまったので、本記事ではDavisで作成した無についてしゃべります。

 

皆さんMarloコンペというのをご存知ですか?OpenAIが主催しているMinecraft環境での強化学習の大会で、入賞するとカナダに行けたりするすごいやつです(もう終わっちゃいましたが、来年もあると思います)。

 

MarloコンペのチームにDavisで参加し、私は環境構築を担当したわけなんですが、この環境構築が鬼めんどくさかったのでスクリプト化しました。

 

一応公式ページにインストール方法などは書いてあるんですが、Minecraft環境非常に不親切で、ウィンドウがある環境でないと動きません。このままではGoogle Cloudなどクラウド上で学習させることが出来ません。困りましたね。

 

 やったこと

 

xvfbを使って仮想ウィンドウを作成し、Marloを走らせました。が、これだけではなぜか動かなかったので(OpenGL周りが原因?)、最終的に公式が配布しているDockerファイルを弄くり、中にあるlaunchClient.shをxvfb付きで実行したら動きました。

 

最終的に出来上がったDocker imageがこれです:

 

以下のコマンドで任意のポートにつなげて実行できます。

 

“`
docker run -it –rm -p [number of port]:10000 syuntoku/marlo_client
“`

 

ここまで自力で頑張ったあとで、これDocker Hubに既に存在していることに気がついてしまいました。圧倒的車輪の再発明だったんですね(悲しいね)。まあDockerについての知識が微妙についたので良いんじゃないでしょうか。

 

あとはこれをdocker-composeと–scaleオプションで並列化させて実行するだけです。(スクリプトにしました)

 

クラウド上で利用するにはDockerやCUDA、Anacondaのインストールもやらないといけないので、これもスクリプトにしました。

 

できたもの

Github:

https://github.com/syuntoku14/marlo_headless

使い方は一応READMEに書いてあります。

 

手順:
1. AWSでもGoogle Cloudでも何でも良いが、Ubuntu18.04環境を立ちあげる。
2. Jupyterの設定も勝手にしするので(ポート5000)、各クラウドのブラウザから5000番ポートを開けとく
2. 中でgit clone https://github.com/syuntoku14/marlo_headless.git
3. . ./marlo_headless/install/gcp/install.bash
4. . ./marlo_headless/docker/launch_multi_client.sh [number of environment]

 

私はVimmerなので、Jupyter-notebookのvim extensionをセットアップするスクリプトなども別でついてます。

 

肝心の学習ですが、まだやっていないです(無能)。学習させたらまた記事を書きます。おちまい。

 

おまけ

 

Courseraの課題でDQNを実装してGoogle Colab上で動かしました。

 

Gist:

 

先ほど紹介したMarlo用のスクリプトはついでにgym環境もインストールするので、上記のgistを参考にして適当にやればGoogle Cloudで簡単にAtariの学習も出来ます。やったね。

 

Algebraic Effects for Rust

Algebraic Effects for Rust

この記事はKCS Advent Calender 18日目の記事です!
Algebraic Effectsが最近話題ですね!自分は普段Rustというプログラミング言語を使っているのですが,残念ながら(?)Algebraic Effectsの言語レベルサポートはありません.無ければ作るとも言いますし,AEをサポートするライブラリを作ってみたので紹介します.

Algebraic Effectsとは?

自分も良く分かりません.教えてください.

「継続がとれる例外」らしいですね.

どうやって実装したの?

びしょ〜じょさんの記事によると,コルーチンを使うとAEの実装ができるようです.ちょうどRustにはasync/awaitサポートのためにコルーチンが今年入ったので,それを使えば実装できそうですね.詳しい実装方法は次のコミケ(30日日曜日です!)の冊子にこれから書く書いたのでそちらを参考にしてください!

はじめてのAlgebraic Effects

以下で登場するコードはhttps://github.com/pandaman64/hello-effからもダウンロードすることができます.

まずはRustを入手します.新しい機能を利用しているので(特にunsized_locals)最新のNightlyビルドが必要です.

$ rustup update
$ rustup toolchain install nightly

それが済んだら新しいプロジェクトを作りましょう.

$ cargo new hello-eff
$ cd hello-eff

Cargo.tomlのdependenciesに次の行を追加します.まだcrates.ioにはアップロードしていないのでGitHubのURLを書いています.

eff = { git = "https://github.com/pandaman64/effective-rust.git" }

それではmain.rsを下のように書いていきましょう.

#![feature(generators)]

use eff::*;

struct Hello;
impl Effect for Hello {
    type Output = String;
}

struct World;
impl Effect for World {
    type Output = String;
}

fn main() {
    let with_effect = eff! {
        let hello = perform!(Hello);
        let world = perform!(World);

        format!("{} {}!", hello, world);
    };

    run(with_effect, |x| println!("{}", x), handler! {
        H @ Hello[_] => {
            resume!("Hello".into());
        },
        W @ World[_] => {
            resume!("World".into());
        }
    });
}

これをcargo runで実行すると

Hello, World!

と表示されることでしょう.

これは一体何が起きているのでしょうか.
コードを一行一行見ていきましょう.

#![feature(generators)]

これは,このモジュールではジェネレータを使うという宣言です.ジェネレータとはコルーチンのRustでの名称です.Rustでは実験的な機能は明示的にオプトインしなければ使うことができません(feature gateと呼びます).このライブラリはジェネレータをフルに活用しているので,この宣言が必要です.

use eff::*;

次の行はライブラリのインポートです.自分が書いたAEライブラリはeffという名前で公開されているので,eff::*と書くことによって後ろのeff!handlehandler!といった関数・マクロをインポートします.

さて,この後に続くのがエフェクトの宣言です.

struct Hello;
impl Effect for Hello {
    type Output = String;
}

ここでは,Helloという名のエフェクトを宣言しています.effではエフェクトの宣言はEffectトレイトを実装することで行います.Effectトレイトの実装にはOutput型を指定する必要があり,Outputはこのエフェクトが解決したときにどの型の値になるかに相当します.

Worldの方も同様にエフェクトの宣言がされています.

それでは,main()の中を見ていきましょう.まずは以下の部分です.

let with_effect = eff! {
    let hello = perform!(Hello);
    let world = perform!(World);

    format!("{} {}!", hello, world);
};

ここでは,eff!マクロを使ってエフェクト付きの計算を定義しています.注意してほしいのは,この時点ではまだeff!内部の計算は実行されていないということです.eff!の中では,perform!を使ってエフェクトを発動することができます.perform!式の結果は上で紹介したEffectトレイトのOutput型となります.
今回の場合はどちらもStringですね.perform!によって取得した値はformatの行のように自由に使うことができます.

eff!で定義したエフェクト付きの計算はrun関数によって実行することができます.

run(with_effect, |x| println!("{}", x), handler! {
    H @ Hello[_] => {
        resume!("Hello".into());
    },
    W @ World[_] => {
        resume!("World".into());
    }
});

run関数は
1. エフェクト付き計算
2. value handler
3. effect handler

の3つを引数にとります.1のエフェクト付き計算は上で紹介したeff!マクロで作った値です.2のvalue handlerはeff!マクロ内の最終的な計算結果を受け取ってあれこれする関数です.今回は|x| println!("{}", x)と標準出力にプリントしてますが,そのままの値が欲しい場合は|x| xとすれば良いでしょう.3のeffect handlerにエフェクトに応じて処理を行うコードを記述します.

effect handlerはhandler!マクロにハンドラを並べることで定義します.一つ一つのハンドラは

ユニークな識別子 @ エフェクトの型 [ パターン ] => 式

という文法で記述します.ハンドラを複数書くときは,カンマで区切って書きます(実装をサボっているので末尾カンマは許容されません).

エフェクトの型によってこのハンドラがどのエフェクトをハンドルするのかを指定し,ハンドルした結果がとなります.perform!に渡されたエフェクトはパターンによって束縛されます.今回の例ではHelloWorldといったエフェクトの型が重要で,値自体は不要なので_パターンによって捨てています.ユニークな識別子は実装上の都合(Rustのマクロは識別子を生成できない)で必要です.handler!内でユニークになるよう名前をつけてください.

さて,ハンドル結果のについて見ていきましょう.ここには任意の式を書くことができますが,その中でも特別に扱われるのがresume!マクロです.resume!(式)はエフェクトの発動時点(perform!の時点)から処理を再開します.このとき,perform!の結果はresume!に渡した引数に評価されます.ですので,resume!に渡す式は対応するエフェクトのOutput型の値でなければいけません.これによって,例えば実装の分離ができることでしょう.

ハンドラ内でresume!を行わない場合は,ハンドラの式の結果がrun関数の結果となります.これを使えば,例外のような大域脱出が実装できます.

また,effライブラリはハンドラのexhaustiveness checkを行います.つまり,ハンドラがエフェクト全てを網羅しているかをチェックします.試しに上のコードからWorldのハンドラを削除するとコンパイルエラーとなることでしょう(マクロの内部でエラーが発生するのでエラー自体は読んでも意味が分からないと思います...).

引数をとるエフェクト

エフェクトは引数をとることができます.どうするのかというと,Effectトレイトを実装する型にフィールドを加えるだけです.上のサンプルに下のエフェクト型を追加しましょう.

struct Ask {
    prompt: String
}
impl Effect for Ask {
    type Output = String;
}

次に,eff!部分を下のように置き換えます.Worldエフェクトの代わりにAskエフェクトをperform!するようにしました.

let with_effect = eff! {
    let hello = perform!(Hello);
    let name = perform!(Ask {
        prompt: "What's your name?".into()
    });

    format!("{} {}!", hello, name)
};

さて,扱うエフェクトの型が変わったのでハンドラも書き換えなければいけません.ここでは次のようにしました.

use std::io::{stdin, stdout, Write};
let stdin = stdin();
run(with_effect, |x| println!("{}", x), handler! {
    H @ Hello[_] => {
        resume!("Hello".into());
    },
    A @ Ask[Ask { prompt }] => {
        print!("{} ", prompt);
        stdout().flush().unwrap();

        let mut name = String::new();
        match stdin.read_line(&mut name) {
            Ok(_) => resume!(name.trim().into()),
            Err(_) => eprintln!("failed to read"),
        }
    }
});

Worldのハンドラの代わりにAskのハンドラが追加されています.Askハンドラではpromptをエフェクトから取り出した後(ここで構造体パターンが使われていることに注意),それを表示しユーザからの入力を待ちます.入力が成功した場合には,resume!によって処理を戻します(trimは末尾の改行文字を除くためです).失敗した場合にはfailed to readと標準エラーに出力して終了します.こっそりstdinをハンドラ外の環境から引っ張ってきているのにも注目してください.

error: recursion limit reached while expanding the macro

というエラーが出た場合には#![recursion_limit="128"]という行を先頭に追加してください.

制約

  • ジェネリックなハンドラ.実装上の都合でジェネリックなハンドラが宣言できません.特に不便な点は,ハンドラで参照をとることができません(参照のライフタイムが宣言できないため).
  • その他にもライフタイムの不必要な'static制約がいくつかあります.困ったときはとりあえず参照を使うのをやめてください.
    eff!のネスト.実装のアイデアはあるのでもう少しお待ちください.
  • エフェクトのうち一部だけハンドルするハンドラ.exhaustivenessとこれを両立する実装を考えているところです.型レベル黒魔術が必要かも?

以上,Rust向けAlgebraic Effectsライブラリeffの紹介でした.自分自身良くわからないままやっているので,もっと良くなるところもあると思います.質問・意見等々ある人はhttps://github.com/pandaman64/effective-rustにIssueを立てるかTwitterで@__pandaman64__までぜひメンションを飛ばしてください!

再度の宣伝ですが,KCSはC95の二日目(30日)に同人誌を頒布予定です!
自分もそちらにこのライブラリの仕組みを解説する記事を寄稿しているのでぜひそちらもご覧ください.

ZFSはいいぞ

この記事はKCS Advent Calender 17日目の記事です。

はじめに

初めまして。J科4年の @kumassy_ です。けんきうしつのサーバーの面倒を見ています。

概要

ハードディスクにはたくさんのファイルが保存されているかと思いますが、ハードディスク上にファイルを格納するための仕組みをファイルシステムといいます。世の中にはext4やxfsなどいろいろなファイルシステムがありますが、ZFSというファイルシステムがとてもよさそうだったので紹介します。

ZFSのいいところ

  • ファイルシステムにRAID機能が組み込まれている
  • 使うコマンドが2つで管理が簡単
  • スナップショットがとれる
  • パーティションの容量が動的に拡張されるため、事前にパーティションのサイズを指定しなくてよい

実際に使ってみた

CentOS7.5にハードディスクを4枚さしてRAID-Z1(RAID-5相当)を組んでみました。1枚は/と/boot用で、残りの3枚をZFSで管理します。


# ストレージプールの作成
# LVMでいうVolume Groupのようなもの
$ sudo zpool create tank raidz1 sdb sdc sdd
$ zpool list
NAME SIZE ALLOC FREE EXPANDSZ FRAG CAP DEDUP HEALTH ALTROOT
tank 16.2T 1.55M 16.2T - 0% 0% 1.00x ONLINE -

# データセット(パーティションのようなもの)の作成
# 作成すると自動的にマウントされる
$ sudo zfs create tank/storage
$ sudo zfs create tank/home
$ zfs list
NAME USED AVAIL REFER MOUNTPOINT
tank 730K 10.5T 139K /tank
tank/home 128K 10.5T 128K /tank/home
tank/storage 128K 10.5T 128K /tank/storage

# マウントポイントの変更
$ sudo zfs set mountpoint=/storage tank/storage
$ sudo zfs set mountpoint=/home tank/home

とても簡単!!データセットを作ると自動的にマウントされるので、/etc/fstabの設定すらいらないです!!!!!!

さいごに

ZFSはいいぞ。

他にもスナップショットの作成やsend/receiveによるバックアップなど試したい機能がいろいろありますが、このあたりの資料を参考にしてみてください。

  • https://chibiegg.gitbooks.io/how-to-zfs/content/index.html
  • https://qiita.com/pitekusu/items/d5e9b0e4f5c06f8f76e3
  • https://pthree.org/2012/12/17/zfs-administration-part-x-creating-filesystems/

5次元回転&投影行列

5次元空間上の座標を回転させ、更に2次元平面上に投影するという行列を以前計算しましたのでその結果を掲載致します。

数値計算ソフトに頼めば一瞬で算出してくれそうではありますが、自分は手計算で押し切ったので一種のネタとして見ていただければと思います。

式は『Gamemaker』という日本ではマイナーな2Dゲーム制作に特化した開発ソフトに準拠した(GML言語)記述となっていますが何となく読めると思います。

x,y:最終的な2次元上の座標 / global.rr : 倍率 / a~j : 10個の各回転軸に対応した回転角 / xx,yy,zz,ww,vv : 元の5次元座標 / xxx,yyy : 2次元上の中心座標 / global.p : v軸上の投影視点座標 / global.q : w軸上の投影視点座標 / global.r : z軸上の投影視点座標 (global.p,q,r → ∞ で平行投影)(degtorad() : 度数法→弧度法変換)

x = xxx + global.rr((( cos(degtorad(a))cos(degtorad(c))cos(degtorad(e))cos(degtorad(g)) + sin(degtorad(b))sin(degtorad(c))sin(degtorad(e))cos(degtorad(g)) )xx
+ ( -cos(degtorad(a))cos(degtorad(c))cos(degtorad(e))sin(degtorad(g))sin(degtorad(h)) – sin(degtorad(b))sin(degtorad(c))sin(degtorad(e))sin(degtorad(g))sin(degtorad(h)) – sin(degtorad(a))cos(degtorad(d))cos(degtorad(e))cos(degtorad(h)) – cos(degtorad(b))sin(degtorad(d))sin(degtorad(e))cos(degtorad(h)) )yy
+ ( -cos(degtorad(a))
cos(degtorad(c))cos(degtorad(e))sin(degtorad(g))cos(degtorad(h))sin(degtorad(i)) – sin(degtorad(b))sin(degtorad(c))sin(degtorad(e))sin(degtorad(g))cos(degtorad(h))sin(degtorad(i)) + sin(degtorad(a))cos(degtorad(d))cos(degtorad(e))sin(degtorad(h))sin(degtorad(i)) + cos(degtorad(b))sin(degtorad(d))sin(degtorad(e))sin(degtorad(h))sin(degtorad(i)) + sin(degtorad(a))sin(degtorad(d))cos(degtorad(e))cos(degtorad(i)) – cos(degtorad(b))cos(degtorad(d))sin(degtorad(e))cos(degtorad(i)) )zz
+ ( -cos(degtorad(a))cos(degtorad(c))cos(degtorad(e))sin(degtorad(g))cos(degtorad(h))cos(degtorad(i))sin(degtorad(j)) – sin(degtorad(b))sin(degtorad(c))sin(degtorad(e))sin(degtorad(g))cos(degtorad(h))cos(degtorad(i))sin(degtorad(j)) + sin(degtorad(a))cos(degtorad(d))cos(degtorad(e))sin(degtorad(h))cos(degtorad(i))sin(degtorad(j)) + cos(degtorad(b))sin(degtorad(d))sin(degtorad(e))sin(degtorad(h))cos(degtorad(i))sin(degtorad(j)) – sin(degtorad(a))sin(degtorad(d))cos(degtorad(e))sin(degtorad(i))sin(degtorad(j)) + cos(degtorad(b))cos(degtorad(d))sin(degtorad(e))sin(degtorad(i))sin(degtorad(j)) – cos(degtorad(a))sin(degtorad(c))cos(degtorad(e))cos(degtorad(j)) + sin(degtorad(b))cos(degtorad(c))sin(degtorad(e))cos(degtorad(j)) )ww
+ ( -cos(degtorad(a))
cos(degtorad(c))cos(degtorad(e))sin(degtorad(g))cos(degtorad(h))cos(degtorad(i))cos(degtorad(j)) – sin(degtorad(b))sin(degtorad(c))sin(degtorad(e))sin(degtorad(g))cos(degtorad(h))cos(degtorad(i))cos(degtorad(j)) + sin(degtorad(a))cos(degtorad(d))cos(degtorad(e))sin(degtorad(h))cos(degtorad(i))cos(degtorad(j)) + cos(degtorad(b))sin(degtorad(d))sin(degtorad(e))sin(degtorad(h))cos(degtorad(i))cos(degtorad(j)) – sin(degtorad(a))sin(degtorad(d))cos(degtorad(e))sin(degtorad(i))cos(degtorad(j)) + cos(degtorad(b))cos(degtorad(d))sin(degtorad(e))sin(degtorad(i))cos(degtorad(j)) + cos(degtorad(a))sin(degtorad(c))cos(degtorad(e))sin(degtorad(j)) – sin(degtorad(b))cos(degtorad(c))sin(degtorad(e))sin(degtorad(j)) )vv)
/((global.p – (( sin(degtorad(g)) )xx
+ ( cos(degtorad(g))
sin(degtorad(h)) )yy
+ ( cos(degtorad(g))
cos(degtorad(h))sin(degtorad(i)) )zz
+ ( cos(degtorad(g))cos(degtorad(h))cos(degtorad(i))sin(degtorad(j)) )ww
+ ( cos(degtorad(g))cos(degtorad(h))cos(degtorad(i))cos(degtorad(j)) )vv))(global.q – ( (( sin(degtorad(a))cos(degtorad(c))sin(degtorad(f))cos(degtorad(g)) + cos(degtorad(b))sin(degtorad(c))cos(degtorad(f))cos(degtorad(g)) )xx
+ ( -sin(degtorad(a))cos(degtorad(c))sin(degtorad(f))sin(degtorad(g))sin(degtorad(h)) – cos(degtorad(b))sin(degtorad(c))cos(degtorad(f))sin(degtorad(g))sin(degtorad(h)) + cos(degtorad(a))cos(degtorad(d))sin(degtorad(f))cos(degtorad(h)) + sin(degtorad(b))sin(degtorad(d))cos(degtorad(f))cos(degtorad(h)) )yy
+ ( -sin(degtorad(a))
cos(degtorad(c))sin(degtorad(f))sin(degtorad(g))cos(degtorad(h))sin(degtorad(i)) – cos(degtorad(b))sin(degtorad(c))cos(degtorad(f))sin(degtorad(g))cos(degtorad(h))sin(degtorad(i)) – cos(degtorad(a))cos(degtorad(d))sin(degtorad(f))sin(degtorad(h))sin(degtorad(i)) – sin(degtorad(b))sin(degtorad(d))cos(degtorad(f))sin(degtorad(h))sin(degtorad(i)) – cos(degtorad(a))sin(degtorad(d))sin(degtorad(f))cos(degtorad(i)) + sin(degtorad(b))cos(degtorad(d))cos(degtorad(f))cos(degtorad(i)) )zz
+ ( -sin(degtorad(a))cos(degtorad(c))sin(degtorad(f))sin(degtorad(g))cos(degtorad(h))cos(degtorad(i))sin(degtorad(j)) – cos(degtorad(b))sin(degtorad(c))cos(degtorad(f))sin(degtorad(g))cos(degtorad(h))cos(degtorad(i))sin(degtorad(j)) – cos(degtorad(a))cos(degtorad(d))sin(degtorad(f))sin(degtorad(h))cos(degtorad(i))sin(degtorad(j)) – sin(degtorad(b))sin(degtorad(d))cos(degtorad(f))sin(degtorad(h))cos(degtorad(i))sin(degtorad(j)) + cos(degtorad(a))sin(degtorad(d))sin(degtorad(f))sin(degtorad(i))sin(degtorad(j)) – sin(degtorad(b))cos(degtorad(d))cos(degtorad(f))sin(degtorad(i))sin(degtorad(j)) – sin(degtorad(a))sin(degtorad(c))sin(degtorad(f))cos(degtorad(j)) + cos(degtorad(b))cos(degtorad(c))cos(degtorad(f))cos(degtorad(j)) )ww
+ ( -sin(degtorad(a))
cos(degtorad(c))sin(degtorad(f))sin(degtorad(g))cos(degtorad(h))cos(degtorad(i))cos(degtorad(j)) – cos(degtorad(b))sin(degtorad(c))cos(degtorad(f))sin(degtorad(g))cos(degtorad(h))cos(degtorad(i))cos(degtorad(j)) – cos(degtorad(a))cos(degtorad(d))sin(degtorad(f))sin(degtorad(h))cos(degtorad(i))cos(degtorad(j)) – sin(degtorad(b))sin(degtorad(d))cos(degtorad(f))sin(degtorad(h))cos(degtorad(i))cos(degtorad(j)) + cos(degtorad(a))sin(degtorad(d))sin(degtorad(f))sin(degtorad(i))cos(degtorad(j)) – sin(degtorad(b))cos(degtorad(d))cos(degtorad(f))sin(degtorad(i))cos(degtorad(j)) + sin(degtorad(a))sin(degtorad(c))sin(degtorad(f))sin(degtorad(j)) – cos(degtorad(b))cos(degtorad(c))cos(degtorad(f))sin(degtorad(j)) )vv)
/(global.p – (( sin(degtorad(g)) )xx
+ ( cos(degtorad(g))
sin(degtorad(h)) )yy
+ ( cos(degtorad(g))
cos(degtorad(h))sin(degtorad(i)) )zz
+ ( cos(degtorad(g))cos(degtorad(h))cos(degtorad(i))sin(degtorad(j)) )ww
+ ( cos(degtorad(g))cos(degtorad(h))cos(degtorad(i))cos(degtorad(j)) )vv)
)))(global.r-((( cos(degtorad(a))cos(degtorad(c))sin(degtorad(e))cos(degtorad(g)) – sin(degtorad(b))sin(degtorad(c))cos(degtorad(e))cos(degtorad(g)) )xx
+ ( -cos(degtorad(a))cos(degtorad(c))sin(degtorad(e))sin(degtorad(g))sin(degtorad(h)) + sin(degtorad(b))sin(degtorad(c))cos(degtorad(e))sin(degtorad(g))sin(degtorad(h)) – sin(degtorad(a))cos(degtorad(d))sin(degtorad(e))cos(degtorad(h)) + cos(degtorad(b))sin(degtorad(d))cos(degtorad(e))cos(degtorad(h)) )yy
+ ( -cos(degtorad(a))
cos(degtorad(c))sin(degtorad(e))sin(degtorad(g))cos(degtorad(h))sin(degtorad(i)) + sin(degtorad(b))sin(degtorad(c))cos(degtorad(e))sin(degtorad(g))cos(degtorad(h))sin(degtorad(i)) + sin(degtorad(a))cos(degtorad(d))sin(degtorad(e))sin(degtorad(h))sin(degtorad(i)) – cos(degtorad(b))sin(degtorad(d))cos(degtorad(e))sin(degtorad(h))sin(degtorad(i)) + sin(degtorad(a))sin(degtorad(d))sin(degtorad(e))cos(degtorad(i)) + cos(degtorad(b))cos(degtorad(d))cos(degtorad(e))cos(degtorad(i)) )zz
+ ( -cos(degtorad(a))cos(degtorad(c))sin(degtorad(e))sin(degtorad(g))cos(degtorad(h))cos(degtorad(i))sin(degtorad(j)) + sin(degtorad(b))sin(degtorad(c))cos(degtorad(e))sin(degtorad(g))cos(degtorad(h))cos(degtorad(i))sin(degtorad(j)) + sin(degtorad(a))cos(degtorad(d))sin(degtorad(e))sin(degtorad(h))cos(degtorad(i))sin(degtorad(j)) – cos(degtorad(b))sin(degtorad(d))cos(degtorad(e))sin(degtorad(h))cos(degtorad(i))sin(degtorad(j)) – sin(degtorad(a))sin(degtorad(d))sin(degtorad(e))sin(degtorad(i))sin(degtorad(j)) – cos(degtorad(b))cos(degtorad(d))cos(degtorad(e))sin(degtorad(i))sin(degtorad(j)) – cos(degtorad(a))sin(degtorad(c))sin(degtorad(e))cos(degtorad(j)) – sin(degtorad(b))cos(degtorad(c))cos(degtorad(e))cos(degtorad(j)) )ww
+ ( -cos(degtorad(a))
cos(degtorad(c))sin(degtorad(e))sin(degtorad(g))cos(degtorad(h))cos(degtorad(i))cos(degtorad(j)) + sin(degtorad(b))sin(degtorad(c))cos(degtorad(e))sin(degtorad(g))cos(degtorad(h))cos(degtorad(i))cos(degtorad(j)) + sin(degtorad(a))cos(degtorad(d))sin(degtorad(e))sin(degtorad(h))cos(degtorad(i))cos(degtorad(j)) – cos(degtorad(b))sin(degtorad(d))cos(degtorad(e))sin(degtorad(h))cos(degtorad(i))cos(degtorad(j)) – sin(degtorad(a))sin(degtorad(d))sin(degtorad(e))sin(degtorad(i))cos(degtorad(j)) – cos(degtorad(b))cos(degtorad(d))cos(degtorad(e))sin(degtorad(i))cos(degtorad(j)) + cos(degtorad(a))sin(degtorad(c))sin(degtorad(e))sin(degtorad(j)) + sin(degtorad(b))cos(degtorad(c))cos(degtorad(e))sin(degtorad(j)) )vv)
/((global.p – (( sin(degtorad(g)) )xx
+ ( cos(degtorad(g))
sin(degtorad(h)) )yy
+ ( cos(degtorad(g))
cos(degtorad(h))sin(degtorad(i)) )zz
+ ( cos(degtorad(g))cos(degtorad(h))cos(degtorad(i))sin(degtorad(j)) )ww
+ ( cos(degtorad(g))cos(degtorad(h))cos(degtorad(i))cos(degtorad(j)) )vv)
)(global.q – ((( sin(degtorad(a))cos(degtorad(c))sin(degtorad(f))cos(degtorad(g)) + cos(degtorad(b))sin(degtorad(c))cos(degtorad(f))cos(degtorad(g)) )xx
+ ( -sin(degtorad(a))cos(degtorad(c))sin(degtorad(f))sin(degtorad(g))sin(degtorad(h)) – cos(degtorad(b))sin(degtorad(c))cos(degtorad(f))sin(degtorad(g))sin(degtorad(h)) + cos(degtorad(a))cos(degtorad(d))sin(degtorad(f))cos(degtorad(h)) + sin(degtorad(b))sin(degtorad(d))cos(degtorad(f))cos(degtorad(h)) )yy
+ ( -sin(degtorad(a))
cos(degtorad(c))sin(degtorad(f))sin(degtorad(g))cos(degtorad(h))sin(degtorad(i)) – cos(degtorad(b))sin(degtorad(c))cos(degtorad(f))sin(degtorad(g))cos(degtorad(h))sin(degtorad(i)) – cos(degtorad(a))cos(degtorad(d))sin(degtorad(f))sin(degtorad(h))sin(degtorad(i)) – sin(degtorad(b))sin(degtorad(d))cos(degtorad(f))sin(degtorad(h))sin(degtorad(i)) – cos(degtorad(a))sin(degtorad(d))sin(degtorad(f))cos(degtorad(i)) + sin(degtorad(b))cos(degtorad(d))cos(degtorad(f))cos(degtorad(i)) )zz
+ ( -sin(degtorad(a))cos(degtorad(c))sin(degtorad(f))sin(degtorad(g))cos(degtorad(h))cos(degtorad(i))sin(degtorad(j)) – cos(degtorad(b))sin(degtorad(c))cos(degtorad(f))sin(degtorad(g))cos(degtorad(h))cos(degtorad(i))sin(degtorad(j)) – cos(degtorad(a))cos(degtorad(d))sin(degtorad(f))sin(degtorad(h))cos(degtorad(i))sin(degtorad(j)) – sin(degtorad(b))sin(degtorad(d))cos(degtorad(f))sin(degtorad(h))cos(degtorad(i))sin(degtorad(j)) + cos(degtorad(a))sin(degtorad(d))sin(degtorad(f))sin(degtorad(i))sin(degtorad(j)) – sin(degtorad(b))cos(degtorad(d))cos(degtorad(f))sin(degtorad(i))sin(degtorad(j)) – sin(degtorad(a))sin(degtorad(c))sin(degtorad(f))cos(degtorad(j)) + cos(degtorad(b))cos(degtorad(c))cos(degtorad(f))cos(degtorad(j)) )ww
+ ( -sin(degtorad(a))
cos(degtorad(c))sin(degtorad(f))sin(degtorad(g))cos(degtorad(h))cos(degtorad(i))cos(degtorad(j)) – cos(degtorad(b))sin(degtorad(c))cos(degtorad(f))sin(degtorad(g))cos(degtorad(h))cos(degtorad(i))cos(degtorad(j)) – cos(degtorad(a))cos(degtorad(d))sin(degtorad(f))sin(degtorad(h))cos(degtorad(i))cos(degtorad(j)) – sin(degtorad(b))sin(degtorad(d))cos(degtorad(f))sin(degtorad(h))cos(degtorad(i))cos(degtorad(j)) + cos(degtorad(a))sin(degtorad(d))sin(degtorad(f))sin(degtorad(i))cos(degtorad(j)) – sin(degtorad(b))cos(degtorad(d))cos(degtorad(f))sin(degtorad(i))cos(degtorad(j)) + sin(degtorad(a))sin(degtorad(c))sin(degtorad(f))sin(degtorad(j)) – cos(degtorad(b))cos(degtorad(c))cos(degtorad(f))sin(degtorad(j)) )vv)
/(global.p – (( sin(degtorad(g)) )xx
+ ( cos(degtorad(g))
sin(degtorad(h)) )yy
+ ( cos(degtorad(g))
cos(degtorad(h))sin(degtorad(i)) )zz
+ ( cos(degtorad(g))cos(degtorad(h))cos(degtorad(i))sin(degtorad(j)) )ww
+ ( cos(degtorad(g))cos(degtorad(h))cos(degtorad(i))cos(degtorad(j)) )vv)
))))))))

y = yyy + global.rr((( sin(degtorad(a))cos(degtorad(c))cos(degtorad(f))cos(degtorad(g)) – cos(degtorad(b))sin(degtorad(c))sin(degtorad(f))cos(degtorad(g)) )xx /
+ ( -sin(degtorad(a))cos(degtorad(c))cos(degtorad(f))sin(degtorad(g))sin(degtorad(h)) + cos(degtorad(b))sin(degtorad(c))sin(degtorad(f))sin(degtorad(g))sin(degtorad(h)) + cos(degtorad(a))cos(degtorad(d))cos(degtorad(f))cos(degtorad(h)) – sin(degtorad(b))sin(degtorad(d))sin(degtorad(f))cos(degtorad(h)) )yy
+ ( -sin(degtorad(a))
cos(degtorad(c))cos(degtorad(f))sin(degtorad(g))cos(degtorad(h))sin(degtorad(i)) + cos(degtorad(b))sin(degtorad(c))sin(degtorad(f))sin(degtorad(g))cos(degtorad(h))sin(degtorad(i)) – cos(degtorad(a))cos(degtorad(d))cos(degtorad(f))sin(degtorad(h))sin(degtorad(i)) + sin(degtorad(b))sin(degtorad(d))sin(degtorad(f))sin(degtorad(h))sin(degtorad(i)) – cos(degtorad(a))sin(degtorad(d))cos(degtorad(f))cos(degtorad(i)) – sin(degtorad(b))cos(degtorad(d))sin(degtorad(f))cos(degtorad(i)) )zz
+ ( -sin(degtorad(a))cos(degtorad(c))cos(degtorad(f))sin(degtorad(g))cos(degtorad(h))cos(degtorad(i))sin(degtorad(j)) + cos(degtorad(b))sin(degtorad(c))sin(degtorad(f))sin(degtorad(g))cos(degtorad(h))cos(degtorad(i))sin(degtorad(j)) – cos(degtorad(a))cos(degtorad(d))cos(degtorad(f))sin(degtorad(h))cos(degtorad(i))sin(degtorad(j)) + sin(degtorad(b))sin(degtorad(d))sin(degtorad(f))sin(degtorad(h))cos(degtorad(i))sin(degtorad(j)) + cos(degtorad(a))sin(degtorad(d))cos(degtorad(f))sin(degtorad(i))sin(degtorad(j)) + sin(degtorad(b))cos(degtorad(d))sin(degtorad(f))sin(degtorad(i))sin(degtorad(j)) – sin(degtorad(a))sin(degtorad(c))cos(degtorad(f))cos(degtorad(j)) – cos(degtorad(b))cos(degtorad(c))sin(degtorad(f))cos(degtorad(j)) )ww
+ ( -sin(degtorad(a))
cos(degtorad(c))cos(degtorad(f))sin(degtorad(g))cos(degtorad(h))cos(degtorad(i))cos(degtorad(j)) + cos(degtorad(b))sin(degtorad(c))sin(degtorad(f))sin(degtorad(g))cos(degtorad(h))cos(degtorad(i))cos(degtorad(j)) – cos(degtorad(a))cos(degtorad(d))cos(degtorad(f))sin(degtorad(h))cos(degtorad(i))cos(degtorad(j)) + sin(degtorad(b))sin(degtorad(d))sin(degtorad(f))sin(degtorad(h))cos(degtorad(i))cos(degtorad(j)) + cos(degtorad(a))sin(degtorad(d))cos(degtorad(f))sin(degtorad(i))cos(degtorad(j)) + sin(degtorad(b))cos(degtorad(d))sin(degtorad(f))sin(degtorad(i))cos(degtorad(j)) + sin(degtorad(a))sin(degtorad(c))cos(degtorad(f))sin(degtorad(j)) + cos(degtorad(b))cos(degtorad(c))sin(degtorad(f))sin(degtorad(j)) )vv)
/((global.p – (( sin(degtorad(g)) )xx
+ ( cos(degtorad(g))
sin(degtorad(h)) )yy
+ ( cos(degtorad(g))
cos(degtorad(h))sin(degtorad(i)) )zz
+ ( cos(degtorad(g))cos(degtorad(h))cos(degtorad(i))sin(degtorad(j)) )ww
+ ( cos(degtorad(g))cos(degtorad(h))cos(degtorad(i))cos(degtorad(j)) )vv))(global.q – ( (( sin(degtorad(a))cos(degtorad(c))sin(degtorad(f))cos(degtorad(g)) + cos(degtorad(b))sin(degtorad(c))cos(degtorad(f))cos(degtorad(g)) )xx
+ ( -sin(degtorad(a))cos(degtorad(c))sin(degtorad(f))sin(degtorad(g))sin(degtorad(h)) – cos(degtorad(b))sin(degtorad(c))cos(degtorad(f))sin(degtorad(g))sin(degtorad(h)) + cos(degtorad(a))cos(degtorad(d))sin(degtorad(f))cos(degtorad(h)) + sin(degtorad(b))sin(degtorad(d))cos(degtorad(f))cos(degtorad(h)) )yy
+ ( -sin(degtorad(a))
cos(degtorad(c))sin(degtorad(f))sin(degtorad(g))cos(degtorad(h))sin(degtorad(i)) – cos(degtorad(b))sin(degtorad(c))cos(degtorad(f))sin(degtorad(g))cos(degtorad(h))sin(degtorad(i)) – cos(degtorad(a))cos(degtorad(d))sin(degtorad(f))sin(degtorad(h))sin(degtorad(i)) – sin(degtorad(b))sin(degtorad(d))cos(degtorad(f))sin(degtorad(h))sin(degtorad(i)) – cos(degtorad(a))sin(degtorad(d))sin(degtorad(f))cos(degtorad(i)) + sin(degtorad(b))cos(degtorad(d))cos(degtorad(f))cos(degtorad(i)) )zz
+ ( -sin(degtorad(a))cos(degtorad(c))sin(degtorad(f))sin(degtorad(g))cos(degtorad(h))cos(degtorad(i))sin(degtorad(j)) – cos(degtorad(b))sin(degtorad(c))cos(degtorad(f))sin(degtorad(g))cos(degtorad(h))cos(degtorad(i))sin(degtorad(j)) – cos(degtorad(a))cos(degtorad(d))sin(degtorad(f))sin(degtorad(h))cos(degtorad(i))sin(degtorad(j)) – sin(degtorad(b))sin(degtorad(d))cos(degtorad(f))sin(degtorad(h))cos(degtorad(i))sin(degtorad(j)) + cos(degtorad(a))sin(degtorad(d))sin(degtorad(f))sin(degtorad(i))sin(degtorad(j)) – sin(degtorad(b))cos(degtorad(d))cos(degtorad(f))sin(degtorad(i))sin(degtorad(j)) – sin(degtorad(a))sin(degtorad(c))sin(degtorad(f))cos(degtorad(j)) + cos(degtorad(b))cos(degtorad(c))cos(degtorad(f))cos(degtorad(j)) )ww
+ ( -sin(degtorad(a))
cos(degtorad(c))sin(degtorad(f))sin(degtorad(g))cos(degtorad(h))cos(degtorad(i))cos(degtorad(j)) – cos(degtorad(b))sin(degtorad(c))cos(degtorad(f))sin(degtorad(g))cos(degtorad(h))cos(degtorad(i))cos(degtorad(j)) – cos(degtorad(a))cos(degtorad(d))sin(degtorad(f))sin(degtorad(h))cos(degtorad(i))cos(degtorad(j)) – sin(degtorad(b))sin(degtorad(d))cos(degtorad(f))sin(degtorad(h))cos(degtorad(i))cos(degtorad(j)) + cos(degtorad(a))sin(degtorad(d))sin(degtorad(f))sin(degtorad(i))cos(degtorad(j)) – sin(degtorad(b))cos(degtorad(d))cos(degtorad(f))sin(degtorad(i))cos(degtorad(j)) + sin(degtorad(a))sin(degtorad(c))sin(degtorad(f))sin(degtorad(j)) – cos(degtorad(b))cos(degtorad(c))cos(degtorad(f))sin(degtorad(j)) )vv)
/(global.p – (( sin(degtorad(g)) )xx
+ ( cos(degtorad(g))
sin(degtorad(h)) )yy
+ ( cos(degtorad(g))
cos(degtorad(h))sin(degtorad(i)) )zz
+ ( cos(degtorad(g))cos(degtorad(h))cos(degtorad(i))sin(degtorad(j)) )ww
+ ( cos(degtorad(g))cos(degtorad(h))cos(degtorad(i))cos(degtorad(j)) )vv)
)))(global.r-((( cos(degtorad(a))cos(degtorad(c))sin(degtorad(e))cos(degtorad(g)) – sin(degtorad(b))sin(degtorad(c))cos(degtorad(e))cos(degtorad(g)) )xx
+ ( -cos(degtorad(a))cos(degtorad(c))sin(degtorad(e))sin(degtorad(g))sin(degtorad(h)) + sin(degtorad(b))sin(degtorad(c))cos(degtorad(e))sin(degtorad(g))sin(degtorad(h)) – sin(degtorad(a))cos(degtorad(d))sin(degtorad(e))cos(degtorad(h)) + cos(degtorad(b))sin(degtorad(d))cos(degtorad(e))cos(degtorad(h)) )yy
+ ( -cos(degtorad(a))
cos(degtorad(c))sin(degtorad(e))sin(degtorad(g))cos(degtorad(h))sin(degtorad(i)) + sin(degtorad(b))sin(degtorad(c))cos(degtorad(e))sin(degtorad(g))cos(degtorad(h))sin(degtorad(i)) + sin(degtorad(a))cos(degtorad(d))sin(degtorad(e))sin(degtorad(h))sin(degtorad(i)) – cos(degtorad(b))sin(degtorad(d))cos(degtorad(e))sin(degtorad(h))sin(degtorad(i)) + sin(degtorad(a))sin(degtorad(d))sin(degtorad(e))cos(degtorad(i)) + cos(degtorad(b))cos(degtorad(d))cos(degtorad(e))cos(degtorad(i)) )zz
+ ( -cos(degtorad(a))cos(degtorad(c))sin(degtorad(e))sin(degtorad(g))cos(degtorad(h))cos(degtorad(i))sin(degtorad(j)) + sin(degtorad(b))sin(degtorad(c))cos(degtorad(e))sin(degtorad(g))cos(degtorad(h))cos(degtorad(i))sin(degtorad(j)) + sin(degtorad(a))cos(degtorad(d))sin(degtorad(e))sin(degtorad(h))cos(degtorad(i))sin(degtorad(j)) – cos(degtorad(b))sin(degtorad(d))cos(degtorad(e))sin(degtorad(h))cos(degtorad(i))sin(degtorad(j)) – sin(degtorad(a))sin(degtorad(d))sin(degtorad(e))sin(degtorad(i))sin(degtorad(j)) – cos(degtorad(b))cos(degtorad(d))cos(degtorad(e))sin(degtorad(i))sin(degtorad(j)) – cos(degtorad(a))sin(degtorad(c))sin(degtorad(e))cos(degtorad(j)) – sin(degtorad(b))cos(degtorad(c))cos(degtorad(e))cos(degtorad(j)) )ww
+ ( -cos(degtorad(a))
cos(degtorad(c))sin(degtorad(e))sin(degtorad(g))cos(degtorad(h))cos(degtorad(i))cos(degtorad(j)) + sin(degtorad(b))sin(degtorad(c))cos(degtorad(e))sin(degtorad(g))cos(degtorad(h))cos(degtorad(i))cos(degtorad(j)) + sin(degtorad(a))cos(degtorad(d))sin(degtorad(e))sin(degtorad(h))cos(degtorad(i))cos(degtorad(j)) – cos(degtorad(b))sin(degtorad(d))cos(degtorad(e))sin(degtorad(h))cos(degtorad(i))cos(degtorad(j)) – sin(degtorad(a))sin(degtorad(d))sin(degtorad(e))sin(degtorad(i))cos(degtorad(j)) – cos(degtorad(b))cos(degtorad(d))cos(degtorad(e))sin(degtorad(i))cos(degtorad(j)) + cos(degtorad(a))sin(degtorad(c))sin(degtorad(e))sin(degtorad(j)) + sin(degtorad(b))cos(degtorad(c))cos(degtorad(e))sin(degtorad(j)) )vv)
/((global.p – (( sin(degtorad(g)) )xx
+ ( cos(degtorad(g))
sin(degtorad(h)) )yy
+ ( cos(degtorad(g))
cos(degtorad(h))sin(degtorad(i)) )zz
+ ( cos(degtorad(g))cos(degtorad(h))cos(degtorad(i))sin(degtorad(j)) )ww
+ ( cos(degtorad(g))cos(degtorad(h))cos(degtorad(i))cos(degtorad(j)) )vv)
)(global.q – ((( sin(degtorad(a))cos(degtorad(c))sin(degtorad(f))cos(degtorad(g)) + cos(degtorad(b))sin(degtorad(c))cos(degtorad(f))cos(degtorad(g)) )xx
+ ( -sin(degtorad(a))cos(degtorad(c))sin(degtorad(f))sin(degtorad(g))sin(degtorad(h)) – cos(degtorad(b))sin(degtorad(c))cos(degtorad(f))sin(degtorad(g))sin(degtorad(h)) + cos(degtorad(a))cos(degtorad(d))sin(degtorad(f))cos(degtorad(h)) + sin(degtorad(b))sin(degtorad(d))cos(degtorad(f))cos(degtorad(h)) )yy
+ ( -sin(degtorad(a))
cos(degtorad(c))sin(degtorad(f))sin(degtorad(g))cos(degtorad(h))sin(degtorad(i)) – cos(degtorad(b))sin(degtorad(c))cos(degtorad(f))sin(degtorad(g))cos(degtorad(h))sin(degtorad(i)) – cos(degtorad(a))cos(degtorad(d))sin(degtorad(f))sin(degtorad(h))sin(degtorad(i)) – sin(degtorad(b))sin(degtorad(d))cos(degtorad(f))sin(degtorad(h))sin(degtorad(i)) – cos(degtorad(a))sin(degtorad(d))sin(degtorad(f))cos(degtorad(i)) + sin(degtorad(b))cos(degtorad(d))cos(degtorad(f))cos(degtorad(i)) )zz
+ ( -sin(degtorad(a))cos(degtorad(c))sin(degtorad(f))sin(degtorad(g))cos(degtorad(h))cos(degtorad(i))sin(degtorad(j)) – cos(degtorad(b))sin(degtorad(c))cos(degtorad(f))sin(degtorad(g))cos(degtorad(h))cos(degtorad(i))sin(degtorad(j)) – cos(degtorad(a))cos(degtorad(d))sin(degtorad(f))sin(degtorad(h))cos(degtorad(i))sin(degtorad(j)) – sin(degtorad(b))sin(degtorad(d))cos(degtorad(f))sin(degtorad(h))cos(degtorad(i))sin(degtorad(j)) + cos(degtorad(a))sin(degtorad(d))sin(degtorad(f))sin(degtorad(i))sin(degtorad(j)) – sin(degtorad(b))cos(degtorad(d))cos(degtorad(f))sin(degtorad(i))sin(degtorad(j)) – sin(degtorad(a))sin(degtorad(c))sin(degtorad(f))cos(degtorad(j)) + cos(degtorad(b))cos(degtorad(c))cos(degtorad(f))cos(degtorad(j)) )ww
+ ( -sin(degtorad(a))
cos(degtorad(c))sin(degtorad(f))sin(degtorad(g))cos(degtorad(h))cos(degtorad(i))cos(degtorad(j)) – cos(degtorad(b))sin(degtorad(c))cos(degtorad(f))sin(degtorad(g))cos(degtorad(h))cos(degtorad(i))cos(degtorad(j)) – cos(degtorad(a))cos(degtorad(d))sin(degtorad(f))sin(degtorad(h))cos(degtorad(i))cos(degtorad(j)) – sin(degtorad(b))sin(degtorad(d))cos(degtorad(f))sin(degtorad(h))cos(degtorad(i))cos(degtorad(j)) + cos(degtorad(a))sin(degtorad(d))sin(degtorad(f))sin(degtorad(i))cos(degtorad(j)) – sin(degtorad(b))cos(degtorad(d))cos(degtorad(f))sin(degtorad(i))cos(degtorad(j)) + sin(degtorad(a))sin(degtorad(c))sin(degtorad(f))sin(degtorad(j)) – cos(degtorad(b))cos(degtorad(c))cos(degtorad(f))sin(degtorad(j)) )vv)
/(global.p – (( sin(degtorad(g)) )xx
+ ( cos(degtorad(g))
sin(degtorad(h)) )yy
+ ( cos(degtorad(g))
cos(degtorad(h))sin(degtorad(i)) )zz
+ ( cos(degtorad(g))cos(degtorad(h))cos(degtorad(i))sin(degtorad(j)) )ww
+ ( cos(degtorad(g))cos(degtorad(h))cos(degtorad(i))cos(degtorad(j)) )vv)
))))))))

自分自身は上記のコードで実装に成功しましたが、急いで整理したので一部ミスが有りましたら申し訳ありません。

RadeonRaysを使ってみた

どうも,チョコです.

最近レイトレーシングをちょっとやってるんですけど,流石に自分でメモリ構造体を作るのが不効率すぎて辛い.昨日Siggraph Asia行った時に見たRenderMan22が速すぎて衝撃を受けました.

そこで,AMDが開発したRadeonRays(以下RR)というオープンソースなライブラリを見つけました.しかもopencl1.2なのでいろんな環境で動きますね.

(ここでレイトレプロのみなさんへの忠告です.この記事を書いた僕はくそレイトレ―シング初心者です.画像を見て吐き気がしたら見るのをやめましょう.)

さて,RRのサンプルを動かしてみよう.ここではVisualStudioを使ってCornellBoxサンプルをコンパイルして見ましょう.

DmqIdRdUwAA2Wmt.jpg large

おう.すごい.

しかし,これだとレイトレっぽくないので,とりあえず反射を入れましょう.

反射とは要するに,レイをdとしたら,表面の法線nに対して

d’=d2(dn)n

を計算すればいいですね.また,この時,最終の色は元の色と乗算します.

DmqWF7MV4AEb7vS.jpg large

レイトレっぽくなりましたね.

次に,反射をDiffuseにしましょう.ここではLambertを使います.Lambertは簡単にいうと,入射角と法線の内積で明るさが決まりますね.まずは単純に,表面から半球の法線をランダムに決めて内積を取って乗算します.ただし,ここでは光源を円に変え,円に当たらなかったレイは黒にします.

cwe

ノイズ高いですね(適当).

Diffuseの次は当然Specularですね.ここではBeckmannを使います.説明が面倒なのでググって.ただし,普通にランダムに取ると収束まで結構時間がかかりますので,ここではImportance Samplingを行います.

BeckmannのImportance Samplingはここを見てください.

LambertのImportance Samplingはここを見てください.

Specularだけだとこうなります(Beckmann coefficient = 0.2).

s

ピカピカですね.

DiffuseとSpecularの組み合わせはShlick’s Fresnelを使います.とりあえず単純に,このFresnelの値を確率のカットオフとして,ランダム値がこの値より小さかったらSpecular反射を解散して,そうでなかったらDiffuseということにします.こういうことです.

すると結果はこうなります(Specular = 0.4).

wv

ノイズ高いですね(これしかコメント言えん).

箱は見飽きたので,サルを入れてみましょう.サルは金属にしましょう.

Screenshot (381)

ふむ....

サルは可愛くないので,シャロちゃんを入れましょう().CornellBoxも消して,Skyboxを入れましょう.

レイが表面にぶつからなかった時,方向を使ってSkyboxから色をこのように取ります.ただし,レイがまだ反射していないものなら黒にします.

するとこのようになります(適当).

Screenshot (385)

かわいい...


まだまだダメですが満足したのでやめます.最後にコメントです.

RRのGeneratePerspectiveRaysは視野を気にしないので,表示の縦横比を帰ると変になります.そのため,GLMの行列を使って書き換えます.

Importance Samplingが入っているLambertとBeckmannのコードです.ただし,乱数生成器はXorshiftを使います.

では.

アドベントカレンダー、やります!

こんにちは。mo-takusanです。

だんだんと寒くなってきましたがいかがお過ごしでしょうか。
今回は題名にもあるようにアドベントカレンダーをやるよっていうお知らせです。本当は結構前からSlackの方で呼びかけていたのですが、「記事にもしなくては!」と思い立ったので今回の投稿をしていきます。

経緯

見出しを付けるほど大した動機ではないのですが、最近のKCSの投稿記事を見ると、、

2018-11-23_18h29_11

 

同じ人ばかりの投稿なのです!
しかも、私以外は2人とも4年生なので最悪の場合、このままでは来年の投稿は私だけになってしまうかもしれないのです。これは由々しき事態だ…

ということで時期的にもいい感じだったのでアドベントカレンダーを通して投稿するハードルを下げられればなぁと思った次第です。

アドベントカレンダーとは

 

インターネット上などで、アドベントカレンダーに見立てて12月に一人、または複数人で毎日記事を投稿していくという企画がある。 特にプログラミングに関連するアドベントカレンダーの企画が近年多数行われている。(Wikipediaより)

12月1日から12月25日までの間、KCSのみんなで記事を投稿していこうと思います。投稿する記事の内容については、技術記事からネタ記事、作品紹介でも何でも構いません!

KCS皆様の参加をお待ちしております

今回はADVENTERさんの方で、カレンダーを作成しましたので登録お願いします。

登録はこちらからお願いします!!(それにしてももう一週間くらいしかないのに集まりきってないって大丈夫か…?)

投稿の仕方などはカレンダーが埋まったときにSlackでお知らせしますね。

第三回技術交流会

こんにちは。mo-takusanです。

今年の夏は非常に暑いですが皆さんはいかがお過ごしでしょうか?

KCSでは先日技術交流会を開催いたしました!
KCSの他に参加いただいた団体は以下の通りです。

  • ロボット技術研究会
  • 慶應義塾志木高等学校電子工学研究会
  • 慶應義塾高等学校電子工学研究会
  • 慶應女子高校Keio Computer Girls(KCG)

忙しい中参加いただきありがとうございました!

開催概要

日時:

2018年8月22日(水)14:00~18:00

場所:

矢上キャンパス 34棟 407

参加者:

約30名

プログラム:

14:00-挨拶
14:10-各団体紹介
14:40-研究発表(前半)
15:00-休憩
15:10-研究発表(後半)
15:00-休憩
16:10-ワークショップ
18:00解散

研究発表の様子

今回も各団体から発表者を募ってもらい、各自の研究成果をプレゼン形式で発表してもらいました。
今年はプログラミングの話題に偏らず、DTMやデザイン、ロボティクス等多様なお話を聞くことができました。

以下は発表の様子です。

2018_08_23_12 2018_08_23_5 2018_08_23_7 2018_08_23_8

 
今年はTwitterのハッシュタグを設けて実況なんかもしました!
#慶應技術交流会2018

頂けた資料はココに載せますので気になった方は是非どうぞ!(追加で頂けたら随時更新します)

 

ワークショップ

今回はせっかく集まったのでしっかり交流すべく研究発表の他にワークショップを開催しました。内容は以下のスライドの通りです。

このワークショップは今年の3月にDeNAさんがいらしたときに教えていただいたもので、学びながらも超盛り上がるので持ちネタにしてしまいたくなるほどです笑
簡単に工程をまとめるとこんな感じです。

  1. 4人程度でグループを作る
  2. 各グループにイベントを記すための付箋を配布する
  3. 基本ルールを基にして、イベントマスを作成してもらい、実際に遊んでもらう

  4. 基本ルール
    (1)スタート地点からさいころを振り、出た目の数だけ進む
    (2)一周してスタート地点を通過するたびに1点獲得
    (3)3点獲得した人が勝利

  5. みんなに、どのマスがよかったか、悪かったかを考えてもらう
  6. バランスブレイカーについての解説を行う
  7. それをもとにもう一度マスを作成して遊ぶ

それぞれの班でユニークなマスがいくつもできました!
今回のワークショップで簡単なパーティゲームにおいては、マイナスマスはあまり面白くならないこと、適切な運要素とバランスブレイカーが必要であることが分かっていただけたと思います。

2018_08_23_1
すごろくの様子です。

おわりに

ロボット技術研究会さん、慶應義塾志木高等学校電子工学研究会さん、慶應義塾高等学校電子工学研究会さん、慶應女子高校Keio Computer Girls(KCG)さん、そして当日参加された皆さんのおかげで大変素晴らしい交流会となりました。
こうしたサークルの枠を超えた交流はこれからも是非行いたいと考えていますので、今後ともよろしくお願いします。

ブルースカイ・カタストロフィ

ブルースカイ・カタストロフィ(つよそう)

スクリーンショット 2018-05-05 17.10.41

↑は参考にあった Blue sky orbit in the Gavrilov-A. Shilnikov model でパラメータも同じもの.

以下は, \(\varepsilon\) をそのまま固定しながら, \(\mu\) を \([0.1, 1.1]\) の範囲で動かしたもの(0.02 間隔で 80000 回のルンゲクッタ.最初の 1000 回は捨てている).

wpa_supplicantを使ってkeiomobile2に接続する

この記事について

最近NixOSを使っていて,wpa_supplicantというCLIソフトウェアで無線接続を管理しています.
普通のWi-Fi(PSK方式)ならwpa_passphraseを使えば接続用の設定を自動生成してくれるのですが,大学の無線はWPA2-PEAPなのでこれではいけません.
そこで,設定方法を調べてみました.

結論

以下の設定を/etc/wpa_supplicant.confに追記します.

# for keiomobile2
network={
    ssid="keiomobile2"
    key_mgmt=WPA-EAP
    eap=PEAP
    identity="YOUR ID HERE"
    password="YOUR PASS HERE"
    phase2="auth=MSCHAPV2"
    priority=2
}
# for eduroam
network={
    ssid="eduroam"
    key_mgmt=WPA-EAP
    eap=PEAP
    identity="YOUR ID HERE"
    password="YOUR PASS HERE"
    phase2="auth=MSCHAPV2"
    priority=1
}

YOUR ID HEREYOUR PASS HEREはkeio.jpメールアドレスとkeiomobile2接続用のパスワードを入力します.
keiomobile2の方をeduroamよりも優先的に使ってほしいのでpriorityを高く設定しています.
これをテストするには,一旦wpa_supplicantサービスを止めたあと,wpa_supplicant -i <無線インターフェイス名> -c /etc/wpa_supplicant.confを実行してください.
eduroamの方をテストしたい場合はeduroamのpriorityを上げた後,もう一度上のコマンドを実行します.