ラベル Processing の投稿を表示しています。 すべての投稿を表示
ラベル Processing の投稿を表示しています。 すべての投稿を表示

2018年7月23日月曜日

アルゴリズムパズル 2-4 実装例

1. 概要

『アルゴリズムパズル ―プログラマのための数学パズル入門』という本の問題を解いてる.
初級編なので無限に簡単すぎてあまり面白みを感じられてない.
プログラムも短いのでまとめて問題2-4の実装例を貼っておく.

2. 実装例

この本はパズルの問題文・ヒント・解法が羅列されているという少し特殊な本なので,ブログにパズルの内容について書くのは引用に収まるのか?という疑問があるので問題文は書かないです.

2.1. 手袋選び

最悪のケースだけ考えれば良いということに気づかなかったのは痛いが,手袋が左右違うというのは問題文に書いておくべきではと思った.
ヒントにあるとおり(a)はたまたま同じ側の手袋が出まくるケースを,(b)はたまたまたくさんある色が出まくってて,しかも片方の方の手袋が出まくるケースを考えれば良いですね.
そうするともうただ計算式を書くだけという感じなのでプログラムを書く必要ないな……という感じです.

2.2. 長方形の分割

数字やテキストの処理で済まないのではみたいな問題だったが再帰的に直角三角形を分割するプログラムをProcessingで書いた.
まぁ無限に分割の仕方はあるので本とは異なる実装にはなった(長方形をまず直角三角形に分割して,それぞれの三角形をint(n/2)個とn-int(n/2)個の直角三角形に分割するのを繰り返してる).
見た目は本よりも良さそうではあるが初級編なので著者は再帰関数を使わない手法にしたんだろうなぁと思うなどした.
実装のための計算で,ベクトルを幾何のベクトルとして触ったの何年ぶりだよという感じだった(そしてふつうに計算ミスしたりしてた).

2.3. 兵士の輸送

1人のケースについて考えればあとはそれをn人に適用するだけなのでプログラムを書くほどでもない……

3. 所感

こうやってブログに書くことで継続的にやるモチベーションを作ってるのだけど問題が簡単すぎるとモチベダウンがすごい.上級者向けは多分僕が逆立ちしても解けないんだろうけど.

2017年8月5日土曜日

現代制御勉強メモと倒立振子の制御例

## 概要

現代制御の勉強メモです.実装するまでの過程をトレースしたかったので,それに必要な知識の確認程度に書いたものです.
内容は状態フィードバック則と同一次元状態オブザーバのまとめと,それを使って適当な制御対象を制御してみてみます.
なお授業で扱った内容を思い出すためのものである上,幾つか扱ってない部分があったり間違ってたり省略してたりするので,ちゃんとした説明は教科書見直してください.学部生なんだ許されてくれ.

## 勉強メモ


### メインコンセプト

次のような状態方程式と呼ばれる形で表された微分方程式がある.ただし\(x\)はベクトルで内部状態を表し,\(u\)は入力,\(y\)は出力である.また\(A,B,C,D\)は定数行列である.

\[ \begin{eqnarray} \dot{x}&=&Ax+Bu\\ y&=&Cx+Du \end{eqnarray} \]

メインコンセプトは,この微分方程式の内部状態\(x\)を,0ベクトルにどうやって近づけるかということである.\(x\)が0ベクトルに収束するためには行列「\(A\)の固有値の実部がすべて負」でなければいけない.「\(A\)の固有値の実部がすべて負」の時,\(x\)は指数関数的に減衰していくことが知られているため,\(x\)は0ベクトルに収束する.

さて,実際にモデルを立てた時に「\(A\)の固有値の実部がすべて負」という条件が満たされていなかったとする.その場合,\(x\)は0に収束するどころか発散してしまう場合がある.しかし,このとき入力\(u\)をうまく与えてやることで擬似的に「\(A\)の固有値の実部をすべて負」にできる.その最も単純な方式として状態フィードバックを用いた極配置という方法を取る.

この方法では,入力\(u\)を次のような形で与える.ただし\(K\)は適当な定数行列である.

\[ u=Kx+v \]

これを上式に代入すると次のようになる.

\[ \begin{eqnarray} \dot{x}&=&(A+BK)x+Bv\\ y&=&Cx+Du \end{eqnarray} \]

したがって定数行列\(A\)が,擬似的に\(A+BK\)となった.したがって\(K\)をうまいこと決めてやれば,定数行列\(A\)の固有値を変えられる.固有値の実部が全て負になるような\(K\)にすれば,\(x\)は0ベクトルに収束し目的が達成できる.

さて,現代制御論のメインコンセプトは上に述べたとおりである.しかし上では語弊を承知で具体的な計算などはすべて除いた.そのため実際には安定化させられない条件というのがいくつかある.また,入力\(u\)は\(u=Kx+v\)とすればよいといったが,\(x\)がわからなければ\(u\)を決定できない.そのため\(x\)を推定する必要がある.

以下では制御ができるかできないかを表す指標「可制御性」,状態\(x\)が推定できるかできないかを表す指標「可観測性」について述べる.

### 状態フィードバック則(文献[1]P35)

先程定数行列\(K\)をうまく決めてやれば,定数行列\(A\)の固有値を擬似的に変えられることをのべた.実際には\(K\)はその要素を適当な変数で置いてやって固有値方程式
\[ \det(\lambda I-(A+BK))=0 \]
が,実部が負となる適当な固有値 \(\lambda_1,...,\lambda_n\)を自分で決めてやって,次式のようにその解がその固有値になるようにしてやれば良い.

\[ \det(\lambda I-(A+BK))=\prod_{i=1}^n(\lambda - \lambda_i) \]

ただし\(\lambda_1,...,\lambda_n\)は係数が実数の多項式の解となるような状態(複素平面上においた時に実軸対称)でなければならない.

### 可制御性(文献[1]P35)


さて上記の式を実際に立ててみると連立方程式は\(K\)の要素に関する線形連立方程式になることが保証されているらしい.しかし妥当な解が得られないような場合がある.すなわち,思い通りに制御することができない場合がある.思い通りに制御できないことを不可制御性を持つと良い,逆に思い通りに制御できることを可制御であるという.

可制御であるということの必要十分条件は次の条件が満たされている場合である事が示されている(文献[1]P38).
\[ rank M_c=rank [B \,\, AB\,\,\dots\,\,A^{n-1}B]=n \]

この行列\(M_c\)は可制御性行列とよばれるもので,微分方程式の解析解を求めると出てくる

\[ \begin{eqnarray} x(t)&=&e^{At}x(0)+\int_0^t e^{A(t-\tau)}Bu(\tau)d\tau\\ &=&e^{At}x(0)+\int_0^t (\beta_0 (t-\tau)I+\beta_1(t-\tau)A+\dots+\beta_{n-1}(t-\tau)A^{n-1})Bu(\tau)d\tau \\ &=&e^{At}x(0)+[B \,\, AB\,\,\dots\,\,A^{n-1}B][\int\beta_0udt \dots\int\beta_{n-1}udt ]^T\\ &=&e^{At}x(0)+M_c [\int\beta_0udt \dots\int\beta_{n-1}udt ]^T \end{eqnarray} \]

不可制御の場合はどうやっても不安定であったりするので,そういう場合は制御対象を何かしら変える必要がある.

### 同一次元状態オブザーバ(文献[1]P121)

状態フィードバック則では,入力\(u\)を決定するのに\(u=Kx+v\)としているから,内部状態\(x\)がわかっている必要がある.

普通は内部状態\(x\)を知ることはできず,ここでは出力\(y\)と入力\(u\),および定数行列\(A,B,C\)のみから推定するしか無い.内部状態を推定する方法はいくつかあるらしいが同一次元状態オブザーバというものを紹介する.

まず\(x\)と同じ次元を持ち,次のような微分方程式で表される関数\(z(t)\)について考える.

\[ \dot{z}=Az+Bu+G(y-Cz) \]

この\(z\)が\(x(t)=z(t)\)となってくれれば内部状態\(x\)がわかったことになる.ここで\(x\)と\(z\)の差\(e(t)=x(t)-z(t)\)について考えると,\(\dot{e}=\dot{x}-\dot{z}\)であるから,

\[ \begin{eqnarray} \dot{e(t)}&=&A(x-z)-G(Cx-Cz)\\ &=&A(x-z)-GC(x-z)\\ &=&(A-GC)e(t) \end{eqnarray} \]

となるから,行列\(A-GC\)の固有値の実部が全て負であれば\(e\)は0に収束する,すなわち\(x=z\)となる.したがって\(A-GC\)の固有値の実部が全て負となるように\(G\)を状態フィードバック則と同じように決めてやればよい.

### 可観測性(文献[1]P41)

ただ同一次元状態オブザーバを作れない場合がある.すなわち,内部状態をどれだけ頑張っても出力\(y\)から知ることができない場合がある.そのようなシステムを不可観測であるといい,逆に内部状態を推定できるシステムを可観測であるという.

システムが可観測であるという必要十分条件は次の可観測性行列\(M_o\)が
\[ rank M_o = rank\begin{bmatrix}C\\CA\\\vdots\\CA^{n-1}\end{bmatrix}=n \]

であることである.この可観測性行列は入力が0である場合の\(y\)の解析解

\[ \begin{eqnarray} y&=&C e^{At}x(0)\\ &=&C(\beta_0 (t)I+\beta_1(t)A+\dots+\beta_{n-1}(t)A^{n-1})x(0)\\ &=&[\beta_0\dots \beta_{n-1}]M_o x(0) \end{eqnarray} \]

に出てくる行列である(文献[1]P43).


## 具体例

### 運動方程式の導出

ここでは台車にくっついた倒立振子について考えます.ただし運動方程式の導出は面倒なので参考文献[2]のモデルを用います(というかこの運動方程式の導出がちゃんとできないとだめというか,現代制御ではモデル化ができてしまえば後は勝手に制御則が出てくるので,でもう少し運動方程式の導出を再勉強するべきな気がする).

参考文献[2]より,台車の位置及び振り子の回転角度の運動方程式は次式のようになる.

\[ \begin{bmatrix} M+m&ml\cos(\theta)\\ ml\cos(\theta)&J+ml^2 \end{bmatrix} \begin{bmatrix} \ddot{x}\\\ddot{\theta} \end{bmatrix} + \begin{bmatrix} -ml\dot{\theta}^2\sin\theta\\ -mlg\sin\theta\end{bmatrix} + \begin{bmatrix} B\dot{x}\\C\dot{\theta} \end{bmatrix} =\begin{bmatrix} u\\0 \end{bmatrix} \]

ここで
\[ T=\begin{bmatrix} M+m&ml\cos(\theta)\\ ml\cos(\theta)&J+ml^2 \end{bmatrix} \]
とおけば


\[ \begin{eqnarray} \begin{bmatrix} \ddot{x}\\\ddot{\theta} \end{bmatrix} &=&T^{-1}\left(\begin{bmatrix} ml\dot{\theta}^2\sin\theta\\ mlg\sin\theta\end{bmatrix} +\begin{bmatrix} -B&0\\0&-C \end{bmatrix}\begin{bmatrix} \dot{x}\\\dot{\theta} \end{bmatrix} +\begin{bmatrix} u\\0 \end{bmatrix}\right) \end{eqnarray} \]


となる.数値解析する分にはこの程度の形で書けていればルンゲクッタでシミュレーションできる.

### 線形化

次に,現代制御を適用するために\(\dot{\theta},\theta\)が微小であるという近似をすると
\[ T=\begin{bmatrix} M+m&ml\\ ml&J+ml^2 \end{bmatrix} \]
であり,微分方程式は次のようになる.

\[ \begin{eqnarray} \begin{bmatrix} \ddot{x}\\\ddot{\theta} \end{bmatrix} &=&T^{-1}\left(\begin{bmatrix} 0&0\\ 0&mlg\end{bmatrix}\begin{bmatrix} {x}\\{\theta} \end{bmatrix} +\begin{bmatrix} -B&0\\0&-C \end{bmatrix}\begin{bmatrix} \dot{x}\\\dot{\theta} \end{bmatrix} +\begin{bmatrix} 1\\0 \end{bmatrix}u\right)\\ &=&\frac{1}{\det T}\left( \left[\begin{matrix}0 & - g l^{2} m^{2}\\0 & g l m \left(M + m\right)\end{matrix}\right]\begin{bmatrix} {x}\\{\theta} \end{bmatrix}\\+\left[\begin{matrix}- B \left(J + l^{2} m\right) & C l m\\B l m & - C \left(M + m\right)\end{matrix}\right]\begin{bmatrix} \dot{x}\\\dot{\theta} \end{bmatrix} +\left[\begin{matrix}J + l^{2} m\\- l m\end{matrix}\right]u \right) \end{eqnarray} \]
ここで状態量を(変数名かぶってますが)\(x=\begin{bmatrix}x&\dot{x}&\theta&\dot{\theta}\end{bmatrix}^T\)とすると
\[ \frac{d}{dt}x=\frac{1}{\det T} \begin{bmatrix} 0&\det T&0&0\\ 0&-B(J+ml^2)&-m^2l^2g&Cml\\ 0&0&0&\det T\\ 0&Blm&mgl(M+m)&-C(M+m) \end{bmatrix}x+ \frac{1}{\det T} \begin{bmatrix} 0\\J+ml^2\\0\\-ml \end{bmatrix}u \]
となるから,
\[ \begin{eqnarray} A&=&\frac{1}{\det T} \begin{bmatrix} 0&\det T&0&0\\ 0&-B(J+ml^2)&-m^2l^2g&Cml\\ 0&0&0&\det T\\ 0&Blm&mgl(M+m)&-C(M+m) \end{bmatrix}\\ B&=& \frac{1}{\det T} \begin{bmatrix} 0\\J+ml^2\\0\\-ml \end{bmatrix}\\ C&=& \begin{bmatrix} 1&0&0&0\\ 0&0&1&0\\ \end{bmatrix}\\ \end{eqnarray} \]
とおけば線形化した場合の状態方程式が書ける.

### オブザーバ,フィードバックゲインの決定

オブザーバ,フィードバックゲインは手計算で求めるとめんどくさそうなのでライブラリを使います.python-controlやmatlabにはplace関数というものがあって,それを用いるとフィードバックゲインなどを求めることができます.

なお,place関数は\(A+BK\)の\(K\)を決めてくれる関数です.したがって状態オブザーバのゲイン\(G\)を決める方法については,\(A-GC\)の転置をとった\(A^T-C^TG^T\)の\(G^T\)を求めることをすれば良いです.

コードはこんな感じです.

### シミュレーション

シミュレーションはProcessingで行いました.自分用の行列ライブラリ,ODEライブラリを作っておきたかったので読みにくいかもしれないです.

コードはここに上げてあります.
上が制御対象(RK4でシミュレーションした非線形微分方程式),下がオブザーバの出力を可視化したものです.初期値は0にしてあり,キーボードの矢印キーで外乱(入力)を与えてやれば動きます.
制御していない場合は発散し,制御している場合にはちゃんと倒立していることがわかります.オブザーバの出力もだいたい上のと同じ感じになってます.

## 感想

大変だったけどいい経験になりました.あと先輩に聞くと結構授業では端折っているところがあったりするらしいので,もっと勉強しないとなと思いました.

## 参考文献

[1] 吉川恒夫,井村順一,現代制御論,(2014),コロナ社
[2] http://www.robot.mach.mie-u.ac.jp/~nkato/class/sc/Invpend_eq3.pdf
[3] Python で任意極配置のフィードバックゲインを求める | org-技術, http://org-technology.com/posts/pole-placement.html
[4] python-controlを利用する際に直面したエラー - szmlb.net, http://szmlb.hatenablog.com/entry/2015/09/08/203643

2016年2月24日水曜日

フーリエ級数の可視化プログラムの実装[Processing]

もはや2週間前のネタを真似ただけで新規性に乏しいのですが……(´・ω・`)
一応実装にあたって元ネタを書いておかないと申し訳ないのでツイートを貼らせていただきます……



という経緯です.

今回の実装はProcessingによるものなので上記ツイートのような数式で描くことができませんが,プログラミング言語というだけあって自由度は高いものとなっています.

円の数とか任意に決められますし.関数も自由に決められますし.

追記:鰺坂もっちょ先生がトゥギャってくれました→世はまさに大フーリエ時代 - Togetterまとめ

・ソースコード


例として矩形波を近似しています.関数funcの中身を[0,1)区間で変えてやればその形になりますが,無限大に発散させたりするとダメです.
あと数字が小さすぎる(1.0とか)だと小さすぎて見えませんので気をつけてください.


2016年2月17日水曜日

画像を一筆書きで描くプログラムを実装した[Python,Processing]

1.概要

この動画の最後のやつの,ほぼ完璧なトレースができます.
 

とりあえず順序としては
1.画像を読み込む
2.エッジ部分の座標を取り出す
3.巡回セールスマン問題として一筆書き経路を探索
4.フーリエ級数展開
5.画像を描画
という手順です.

今回サンプルとして画像はこいつを使います.勝手に使ってください.
Processingしかできない人や,Pythonの実行環境ないひとは一筆書きの経路を探索した結果の座標ファイルを置いておきます.こいつをProcessingのソースコードと同一フォルダに入れておけば一応はできます.ちなみにこんな感じ.


プログラムが長過ぎるので注意してください.もっとスマートにかければ良いのだけれど,無駄にクラスを作成して再利用しやすい形にした……(´・3・`)ドウセツカワナイノニ

2.プログラム

まず上記の手順の1-3を行うソースコードです.
蟻コロニー最適化のプログラムなのでこの前書いたやつの書き直しみたいな感じです.
実際はopt2を使って更に最適化してますが,それのコードはネットのやつを丸パクリしたやつなので流石に上げられません(参考URL先に借りたソースコードがあります).


次にProcessingで上記の手順の4,5の描画を行うコード

2016年1月8日金曜日

Processingでライフゲームを実装[Processing]

 プログラマーなら誰しも一度はハマるライフゲーム。知ってる人も知らない人も見てってくださいな。

1.ライフゲームとは


 ライフゲームはよく「最も単純な人工生命」とか言われる。まぁ見方によっては間違っていないけれど,どちらかと言うとパズルみたいなもの。

 基本的には細胞(セル・Cell)の生き死にを,ルールに従って決める。ルールは大まかにいうと,

・寂しいと死んじゃう(周囲に生きているセルが無いと死ぬ)
・暑苦しいと死んじゃう(周囲にセルが多すぎると死ぬ)
・環境が良ければ子供が生まれる(周囲に生きているセルがそこそこあれば生まれる)

 という感じ。もう少し詳しく言うと。

・自分が生きていて,周り8マスに生きているセルが2か3なら生きられる。
・自分が死んでいてい,周り8マスに生きているセルが3つなら生まれる。
・上記以外の場合は死ぬ。

 というもの。実際の例で示す。


 緑色の部分が生きているセル。上の図の赤く囲った部分のセルは,周囲に4つ生きているセルがあるので「暑苦しく」て死ぬ(黒くなる)。

 逆に,生まれるケースはこんな感じ。


 この図では自分が死んでいていて(黒くて),周りに生きているセルが3つなので生まれます(緑になる)。
 とこんな感じになるが,実際に見てみればわかると思います。

追記
ライフゲームに関する動画で非常に面白い動画があったので貼っておきます。


2.ソースコード


 上の文章を読まずにソースコードコピペするのが割りと賢い判断かもね。

boolean[][] board;      /* 現在の状態を保存する変数 */
boolean[][] temp_board; /* 次の状態を保存する変数 */
int N = 64;            /* 一辺の数 */


void setup() {
  size(512, 512);

  /* ボードの作成 */
  board = new boolean[N][N];
  temp_board = new boolean[N][N];
  for (int i = 0; i < N * N; i++ )
    board[i/N][i%N] = int(random(2)) == 0 ;

  frameRate(10);
}

void draw() {
  background(0);

  /* 四角形の幅を決める */
  int w = width/N;

  /* 生き死にを決める */
  step();
  /* マウスで状態を変える */
  edit_board();

  /* 色を指定 */
  fill(0, 255, 0);
  stroke(0, 255, 0);
  
  for (int i = 0; i < N; i++ ) {
    for (int j = 0; j < N; j++ ) {
      /* board[i][j]がtrueすなわち生きている場合描画 */
      if ( board[i][j] )
        rect(i*w, j*w, w, w);
    }
  }
}

/* 生き死にを決める関数 */
void step() {
  /* temp_boardにとりあえずその後の状態を保存 */
  for (int i = 0; i < N; i++ ) 
    for (int j = 0; j < N; j++ ) 
      temp_board[i][j] = is_alive(i, j);
      
  /* ボードをコピー */
  for (int i = 0; i < N; i++ ) 
    for (int j = 0; j < N; j++ ) 
      board[i][j] = temp_board[i][j];
}

boolean is_alive(int x, int y) {
  int count = 0;
  
  /* 周囲8マスを見る */
  for (int i = -1; i <= 1; i++ ) 
    for (int j = -1; j <= 1; j++ ) 
      if ( in_range(x+i, y+j) )
        if ( i != 0 || j != 0 )
          if ( board[x+i][y+j] )
            count++;

  
  if ( board[x][y] && ( count == 2 || count == 3 ) )
    return true;/* 生きていて周りに友達がいるから生き残れる */
  else if ( board[x][y] == false && count == 3 )
    return true;/* それなりに人がいるから新しい子供が生まれる */
  else 
    return false;/* それ以外は生き残れない */
}

boolean in_range(int x, int y) {
  if ( x < 0 || x >= N || y < 0 || y >= N )
    return false;
  return true;
}

void edit_board() {
  int x = mouseX * N / width;
  int y = mouseY * N / height;

  if ( in_range(x, y) )
    board[x][y] = !board[x][y];
}

2015年10月25日日曜日

ウラムの螺旋を描く[Processing]

 素数っていいですよね。孤高な感じがして。でもなんか覚えにくいイメージがありますね。私の場合は,数字を覚えるときに,数字が小さいとその数字を因数分解して覚えます。そうすると「ああ,2^2+3^3=108なのか。2,2,3,3で覚えやすいな」みたいなことがあるのですが,素数はそういった覚え方ができないのがまた逆に良いですね。

1.ウラムの螺旋とは


 ウラムの螺旋はウラムさんが見つけたものです。とりあえずこんな感じの図形のこと。なんとなくn斜めに線が浮かび上がっているのがわかるでしょうか。
 この図形は素数に当たる数字の場所を緑色に塗ったものです。素数というと,なんだか法則性があるようでないような感じがしますが,このように図にしてみると法則性がありそうだということがわかります。
 この図形の書き方は,数字をある規則によって並べていき,素数を塗ると幾つかの線が現れるというものです。以下にその数字の並べ方を書いておきます。自分の手で一回書いてみると面白いですよ。
素数を青色に塗ってみました。なんとなく線が浮かび上がってくるのがわかるでしょうか。なぜこのような性質があるのかに対して,証明は確かされていなかったはず。しかしこのウラムの螺旋から,素数を多く生産する数式がたくさん発見された。

 ちなみに二次式で素数を大量生産できる式といえばこんな式がある。
n=0なら41(素数),n=1なら43(素数),n=2なら47(素数),n=3なら53(素数)……と,n=39までは全部素数になる。この数式であらわされる素数をオイラー素数と言ったりする。昔この式であらわされる自然数は全部素数になるよ,というデマに騙されたことがある。n=41を入れれば合成数になることは明らかなのにね。

2.ソースコード


 余談はさておき,プログラムはこんな感じ。素数はエラトステネスの篩で計算した。色を塗る場所の計算がちょっと雑で,上の表とは違っているかもしれない。まぁでも見るだけなら問題ない。
 ホントよくこんなこと考えたよね。まず数字を並べたりしないし,素数を縫ったりもしないからなぁ……。

boolean[] Board;

void setup() {
  /* 適当な大きさでウィンドウを開く */
  size(512, 512);

  /* indexが素数ならfalseの配列を作る */
  Board = new boolean[width*height+1];
  Board[0] = Board[1] = true;

  /* 素数かどうかをあらかじめエラトステネスの篩で計算 */
  for (int i = 2; i < sqrt(Board.length) ; i++ ) {
    /* iが素数ならば */
    if ( Board[i] == false ) {
      /* その倍数は合成数 */
      for (int j = 2 * i; j < Board.length; j += i ) {
        Board[j] = true;
      }
    }
  }
}

void draw() {
  /* 背景を黒にする */
  background(0);

  /* 描画する色を緑にする */
  stroke(0, 255, 0);
  fill(0, 255, 0);
  
  /* 原点を中心に持ってくる */
  translate(width/2, height/2);

  /* 描画する座標 */
  int x = 0;
  int y = 0;
  /* 座標をどう動かすかを計算するための変数 */
  int dx = 1;
  int dy = 0;
  int n = 1;
  
  for (int i = 1; i < width * height + 1; i++ ) {
    /* 素数ならば描く */
    if ( Board[i] == false )
      rect(x, y, 1, 1);  

    /* iに応じて次の描画場所を決める */
    if ( n * n + 1 == i ) {
      dy = (n % 2)*2-1;
      dx = 0;
      n++;
    } else if ( n * n - n + 1 == i) {
      dx = (n % 2)*2-1;
      dy = 0;
    }
    x += dx;
    y += dy;
  }
}

2015年10月21日水曜日

黄金比でひまわりの種の配列を描く[Processing]

 現状すべての記事に「プログラミング」タグが付いていることに困惑を隠せない今日この頃です。

 今日は黄金比やフィボナッチ数列の紹介でよく見るこの図形を描きます。


 この図形よく見かけるけれど描き方が今まで全くわからんかったのです。某専門学校に行ってる友人が授業で出されたというソースコードを見て知りました。今日はこれを紹介します。

1.描き方


 描き方は簡単。点を222.5°ずつ回転させながら打っていくだけ。
極座標表示するならこんな感じ。kを整数とし,θ0 = 222.5°としたとき,
という感じになる。この辺りで「黄金比使ってないやんけ!」という突っ込みが来そうだ。だが実は222.5という数字の中に隠されている。ちょっとここで222.5に黄金比φ=1.618...を掛けてみると,

222.5 × 1.618 = 360.005

 360という数字は一周の角度360°のことです。つまり222.5という数字は360÷(黄金比)の値だったのです。 さらにここでラジアン表記してみるとθ0は次のように表されます。
円周率と黄金比のイリュージョンやぁぁぁ!と叫びたくなりますね。非常に美しいですね。それと同時になぜ円周率を2πと定義しなかったのかというあの話を思い出しますね。

2.ソースコード


 Processingではラジアンでsin,cosは定義されているのでラジアンで計算しています。
/* 黄金比 */
float golden_ratio = (sqrt(5)-1.0)/2.0;

void setup() {
  /* 適当な大きさでウィンドウを表示 */
  size(512, 512);
}

void draw() {
  /* 背景を黒くする */
  background(0);
  /* 原点を画面中央へ寄せる */
  translate(width/2, height/2);
  rotate(PI);

  /* 描画の色を緑にする */
  stroke(0, 255, 0);
  fill(0, 255, 0);

  /* 角度は2π/φ[rad]ごとにプロットする */
  /* つまり円一周をを黄金比で割った値 */
  float theta = 2*PI/golden_ratio;
  float x, y;

  for (int i = 0; i < width/2; i++ ) {
    /* iは中心からの距離であり,また点の番号でもある */
    /* 原点からiの距離,角度i*thetaにプロット */
    x = i * cos(i*theta);
    y = i * sin(i*theta);

    ellipse(x, y, 8, 8);
  }
}

2015年10月5日月曜日

マンデルブロ集合を描く[Processing]

 この間フラクタル図形を描いてみたけれど,一番の有名どころを描いてなかったのでやってみることにした。一応述べておくが私はフラクタルが好きというわけではないです。ただなんか無性に綺麗な図形を描きたくなる,いわば「Processingハイ」という状態であるというだけです。

1.マンデルブロ集合について

詳細はググるなり本で調べるなどしてください。ここでは図形を描くための最低限の情報について書き留めておきます。手元にある本も見ていますが,だいたいWikipediaにおんなじこと書いてある(Wikipediaさんすげー).
 まずマンデルブロ集合というのは次の漸化式で表される数列Znが収束するcの集合です。ただしZn,cは複素数。

 このときcを

 とあらわすならば,点(a,b)について打点していけばマンデルブロ集合を描ける。
 しかし,Processingでは複素数は標準ではサポートしていない。自分でComplex型を定義するのも難儀なので複素数を実部と虚部に分けて計算する。
 Znを次のように実部と虚部に分ける。
そうするとXn,Ynは次のように表される。

 以下に示すプログラムでは,このようにして計算していく。ただしZnの大きさの二乗が閾値Lを超えたら計算をやめるようにしてる。そのへんはプログラムを参考にしてほしいです。

2.ソースコード

まぁ長々と説明してきたがつまりこういうこと。
/* Znを何回漸化式で計算するか */
int N = 255;
/* Znの最大値 */
int L = 255;
/* 拡大率 */
float SCALE = 3.0;

void setup() {
  size(512, 512);
}

void draw() {
  /*中心に原点を持ってくる*/
  translate(width/2, height/2);
  background(0);

  for (int a = -width/2; a <= width/2; a++ ) {
    for (int b = -height/2; b <= height/2; b++ ) {
      /* 複素数c=x+yiを定める */
      float x = SCALE * a / width;
      float y = SCALE * b / height;
      /* 漸化式に基づいて計算 */
      int r = calc(x, y);

      /* 収束の速度に応じて色を指定 */
      /* 下のプログラムは適当。stroke(赤成分緑成分,青成分) */
      stroke(r%256, r*4%256, r*16%256);
      /* 点の描画 */
      rect(a, b, 1, 1);
    }
  }
}

/* 漸化式にもとづいてZnが発散するnを計算 */
int calc(float x, float y) {
  float tx, ty;
  float zx = 0.0;
  float zy = 0.0;

  for (int i = 1; i <= N; i++ ) {
    tx = zx;
    ty = zy;

    zx = tx*tx-ty*ty+x;
    zy = 2*tx*ty+y;

    /* 発散した(閾値を超えた)場合はiを返す */
    if ( zx*zx + zy*zy > L )
      return i;
  }
  
  /* 発散しなかった場合は0を返す */
  return 0;
}

 割りといい感じに描けた。

GUIライブラリのcontrolP5を使ってみる[Processing]

 Processingで何か作ろうかと思ったが,何も思いつかない。とりあえずProcessingでボタンやリストボックスなどのGUIのアプリケーションには必須のコントロールと呼ばれるものの使い方を覚えようと思う。

1.controlP5のインストール

ProcessingではcontrolP5というライブラリを使うことでボタンなどを扱う事ができる。Processingを起動し,上のメニューバーから「スケッチ」→「ライブラリのインポート」→「ライブラリの追加」を選択。

 上のテキストボックスにcontrolP5と入力して,選択してinstallをクリック。

2.スライドとボタンを使ってみる

exampleのプログラムを打ってボタンを配置して終わるのもつまらないのでこの間やったフラクタル図形のパラメータをいじるように設定してみる。
import controlP5.*;

/* Hフラクタル用のパラメータ */
int N = 5;
int L = 128;
/* コントロールを扱うControlP5クラス */
ControlP5 cp5;

void setup() {
  size(512, 512);

  /* コントロールの初期化 */
  cp5 = new ControlP5(this);

  /* Nの値を変化させるスライダーを追加 */
  cp5.addSlider("N")
    .setPosition(10, 10)/*位置*/
    .setSize(256, 10)/*大きさ*/
    .setRange(1, 8);/*値の範囲*/

  /* Lの値を変化させるスライダーを追加 */
  cp5.addSlider("L")
    .setPosition(10, 30)/*位置*/
    .setSize(256, 10)/*大きさ*/
    .setRange(10, 1024);/*値の範囲*/

  /* 押されたらbutton1_Clickを実行するボタンを追加 */
  cp5.addButton("button1_Click")
    .setPosition(10, 50)/*位置を設定*/
    .setSize(256, 10);/*大きさを設定*/
}

/* ボタンをクリックした際に呼び出される関数 */
public void button1_Click(){
  /* 画面を保存する */
  saveFrame("###.png");
}

void draw() {
  /* 背景を黒で塗りつぶす */
  background(0);
  /* 線の色を緑に指定 */
  stroke(0, 255, 0);

  /* 再帰関数を呼び出す */
  step(width/2, height/2, 0);
}

/* H-フラクタルを描く関数 */
void step(float x, float y, int n) {
  if ( n >= N )
    return;

  float len = L * pow(0.5, n);

  line(x-len, y, x+len, y);
  line(x-len, y-len, x-len, y+len);
  line(x+len, y-len, x+len, y+len);

  step(x-len, y-len, n+1);
  step(x-len, y+len, n+1);
  step(x+len, y-len, n+1);
  step(x+len, y+len, n+1);
}

 これでこの前やったHフラクタルのパラメータをいじれるようになった。

2015年10月3日土曜日

Yahoo天気予報をProcessingで取得する

 Processingのライブラリの追加機能のおかげで簡単にライブラリを追加できるのでちょっとやってみることにした。

1.YahooWeatherライブラリの追加

まずProcessingを起動し,上のメニューバーから「スケッチ」→「ライブラリのインポート」→「ライブラリの追加」を選択。

 そうしたらウィンドウが出てくるので「yahoo」と入力して,出てくるライブラリを選択して「install」をクリック。

 あっという間にライブラリが追加できた。

2.プログラムを書く

 ProcessingのライブラリリファレンスのサイトにYahooWetherライブラリの詳細が書かれているのでそいつを参考にして作れる。
 
 で,とりあえず現在の状態と明日の天気を表示できた。以下ソースコード。説明はコメントに書いたのでそちらを参照のこと。WOEIDは検索すると各地域の番号が得られるのでそちらを参照のこと。
/* ライブラリのインポート */
import com.onformative.yahooweather.*;

/* 情報を受け取るためのクラス */
YahooWeather weather;
/* 更新間隔[ms] */
int updateIntervallMillis = 30000; 

void setup() {
  size(512, 512);

  /* "Where On Earth IDentifier"という地域ごとに決められたIDのこと */
  /* 東京 :1118370 */
  /* 名古屋:1117817 */
  /* 大阪 :15015370 */
  int WOEID = 1118370;

  /* cはセルシウス温度で表示するように指定したもの */
  weather = new YahooWeather(this, WOEID, "c", updateIntervallMillis);
}

void draw() {
  background(0);
  fill(0, 255, 0);
  /* 日本語が表示されない場合はフォントを変えてみてください */
  textFont(createFont("メイリオ", 16));

  /* 更新確認 */
  weather.update();

  /* 情報の表示 */
  
  /* text(文字列,x,y)で(x,y)から文字列を表示できる */
  text("市町村名: "+weather.getCityName(), 20, 16);
  text("国名  : "+weather.getCountryName(), 20, 32);
  text("経度  : "+weather.getLongitude()+" 緯度: "+weather.getLatitude(), 20, 48);
  text("更新日時: "+weather.getLastUpdated(), 20, 64);
  text("日の出 : "+weather.getSunrise(), 20, 80);
  text("日の入り: "+weather.getSunset(), 20, 96);
  text("*****現在の状態*****",20,128);
  text("天気  : "+weather.getWeatherCondition(),20,144);
  text("気温  : "+weather.getTemperature(), 20, 160);
  text("風速  : "+weather.getWindSpeed(), 20, 176);
  text("風の向き: "+weather.getWindDirection(), 20, 192);
  text("湿度  : "+weather.getHumidity(), 20, 208);
  text("気圧  : "+weather.getPressure(), 20, 224);
  text("*****明日の状態*****",20,256);
  text("天気  : "+weather.getWeatherConditionTomorrow(), 20, 272);
  text("最低気温: "+weather.getTemperatureLowTomorrow(), 20, 288);
  text("最高気温: "+weather.getTemperatureHighTomorrow(), 20, 304);
}

 ProcessingをAndroid端末などで動かすこともできるらしいので,それでアプリなどを作る際には結構使えると思う。

2015年10月2日金曜日

フラクタル図形を描いてみる[Processing]

 図書館に『初めてのフラクタル 数学とプログラミング』という本を見つけた。Processingなら描けるかなと思って借りてみました。とりあえず幾つか描いてみます。

※フラクタルの次元などの理論的な小難しい話は割愛します(そもそも理解していない)。

1.Hフラクタルのプログラム

百聞は一見にしかず。とりあえず見てみればわかると思う。

 Hという文字が沢山くっついているのがわかると思う。一部を拡大すればまたHが出てきて,さらにそれを拡大すれば……となっている。

 まぁプログラムはこちら。

/* stepを呼び出す関数 */
int N = 5;

void setup() {
  size(512,512);
}

void draw() {
  /* 背景を黒で塗りつぶす */
  background(0);
  /* 線の色を緑に指定 */
  stroke(0,255,0);
  
  /* 再帰関数を呼び出す */
  step(width/2,height/2,0);
}

/**
 * @fn
 * H-フラクタルを描くプログラム
 * @param (x) 'H'の文字の中心x座標
 * @param (y) 'H'の文字の中心y座標
 * @param (n) 呼び出された回数(深さ)
 */
void step(float x, float y, int n) {
  if ( n >= N )
    return;

  /* Hの各辺の長さの半分の長さ */
  float len = width / 4 * pow(0.5, n);

  /* 中心の横棒を描く */
  line(x-len, y, x+len, y);
  /* 左の縦棒を描く */
  line(x-len, y-len, x-len, y+len);
  /* 右の縦棒を描く */
  line(x+len, y-len, x+len, y+len);

  /* Hの右上・右下・左上・左下の点から新たに'H'を描く */
  step(x-len, y-len, n+1);
  step(x-len, y+len, n+1);
  step(x+len, y-len, n+1);
  step(x+len, y+len, n+1);
}

再帰関数の練習にはなったかな。

2.シェルピンスキーのふるいを描く

シェルピンスキーのギャスケットとも言うらしい。本の絵を見て作ったから間違ってるかもしれ無いけれど。
 図形はこんなの

 プログラムはこんな感じ。
/* stepを呼び出す回数 */
int N = 7;

void setup() {
  size(512, 512);
}

void draw() {
  /* 背景を黒で塗りつぶす */
  background(0);
  /* 線の色を緑に指定 */
  stroke(0, 255, 0);

  /* 原点を中心に持ってくる */
  translate(width/2, height/2);
  /* 画面を適当な角度だけ回転する */
  rotate(PI/6);

  /* 再帰関数を呼び出す */
  step(0, 0, 0);
}

/**
 * @fn
 * シェルピンスキーのふるいを描くプログラム
 * @param (x) 三角形の中心x座標
 * @param (y) 三角形の中心y座標
 * @param (n) 呼び出された回数(深さ)
 */
void step(float x, float y, int n) {
  if ( n >= N )
    return;

  float len = width / 3 * pow(0.5, n);
  /* 3分の2 * PI [rad]つまり120度 */
  float theta = 2.0/3.0*PI;
  float x0, x1, y0, y1;

  /* 三角形を描く */
  for (int i = 0; i < 3; i++ ) {
    x0 = x+len * cos( i * theta );
    y0 = y+len * sin( i * theta );
    x1 = x+len * cos( (i+1) * theta );
    y1 = y+len * sin( (i+1) * theta );

    line(x0, y0, x1, y1);
  }

  /* もう一つ小さい三角形の中心を指定し呼び出す */
  len = len / 2;
  for (int i = 0; i < 3; i++ ) {
    step(x+len*cos(i*theta), y+len*sin(i*theta), n+1);
  }
}

 まぁsin,cosの勉強にはなったかな。

3.なんかよくわからないもの

なんかいい感じのやつがあったのであげておきます。ただ詳細はよくわからないです。
L,Rの漸化式をランダムで計算するといい感じの図形が得られる。Lは原点中心の1/4回転を,Rは点(1,0)の拡大を行うとのこと。そうするといい感じのやつが描かれるという。
 百聞は一見にしかず,だ。プログラムと画像はこんな感じ。プログラムを実行したらマウスを動かすと上の式のaが変化して図形が変化します。


 
int N = 4096;

void setup() {
  size(512, 512);
}

void draw() {
  /* 背景を黒で塗りつぶす */
  background(0);
  /* 線の色を緑に指定 */
  stroke(0, 255, 0);


  /* 原点を中心に持ってくる */
  translate(width/2, height/2);
  /* 画面を適当な角度だけ回転する */
  rotate(PI);

  float x = 0.0;
  float y = 0.0;  
  float temp, tx, ty;
  /* 定数aを適当に決める */
  float a = 5.0*(mouseX * mouseY ) / ( width*height );

  for (int i = 0; i < N; i++ ) {
    /* x_n,y_nを保存しておく */
    tx = x;
    ty = y;

    /* 漸化式をランダムに変える */
    if ( random(2) < 1 ) {
      x = -ty;
      y = tx;
    } else {
      temp = (tx-1)*(tx-1)+ty*ty+1;
      x = 1 + a * ( x - 1 ) / temp;
      y = a * ty /temp;
    }
    
    /* 点の描画 */
    rect(x*width/2, y*height/2, 1, 1);
  }
}

 何なんだろこれ。でも面白いからいいか.

ツイッターのアイコンをProcessingで作ってみる

 ブログを始めたついでにツイッターを始めることにした。卵アイコンではなんだか物足りないので何かアイコンを作ろうと思う。

 とはいうものの,アイコンって結構悩みどころ。かっこいい画像がいいけれど,オリジナルにしたい。あと理系っぽい雰囲気をかもし出すためにはなんかグラフとかにしたい。

 散々迷った挙句,とりあえずバラ曲線を描いてみることにした。

1.バラ曲線を描く

まぁまずバラ曲線の式はこちら。極方程式であらわされる。
aとnは定数。θはもちろん変数。Processingで描く際にはθを適当な値から少しづつ変化させて,次の(x,y)について点を打つ。
まぁ実際には点ではなく線を引いている。とりあえずプログラムを見てもらえればわかると思う。

/* シータの値 */
float theta = 0.0;
/* この値を変えると形が変化する */
float n = 5.0/7.0; 

void setup() {
  /* 適当な大きさのウィンドウを表示する */
  size(512, 512);
  /* 背景を黒く塗りつぶす */
  background(0);
}

void draw() {

  float x0, x1, y0, y1;
  float r;

  /* Processingでは左上が原点になっているので中心に持ってくる */
  translate(width/2, height/2);
  /* Processingでは上下が逆なので180度(つまりPI[rad])回転する */
  rotate(PI);

  /* 線の色は緑にする */
  stroke(0, 255, 0);
  /* thetaが変化する前の座標 */
  r = width / 2 * sin(n*theta);
  x0 = r * cos(theta);
  y0 = r * sin(theta);

  /* thetaをちょっとだけ動かす */
  theta += 0.01;

  /* thetaが変化した後の座標 */
  r = width / 2 * sin(n*theta);
  x1 = r * cos(theta);
  y1 = r * sin(theta);

  /* (x0,y0)から(x1,y1)に線を引く */
  line(x0, y0, x1, y1);

  //saveFrame("a.png");
}

x0,y0は前回計算したx1,y1を流用すれば計算回数少なくて済むよ!という声が聞こえてきそうだがプログラム的には(たぶん)こっちのほうが見やすいかなと思ってこうした。

 徐々に描かれるのは仕様です。ほんとは範囲決めて一瞬で描きたかったけれど,nが小数の時にどうするかがわからなかった。整数なら0 <= θ < 2πでやれば描けるんだけれどもね。実行結果は以下の通り。


 十分きれいな形だな。でもこの図形は数学Ⅲでならうくらい有名なものです。これじゃつまらん。オリジナリティがないとか言われそう。なのでちょっとアレンジしてみる。

2.バラバラ曲線を描く

なんて名前付けたらいいのかわからないのでこう呼ぶことにした。上のバラ曲線のプログラムを書いてた時に偶然生まれたもの。ごにょごにょやっている間にえらい変な数式になってしまった。
 訳が分からないよ。一応a,c0~c4は定数。この(x0,y0)から(x1,y1)に引いた線分の集合をバラバラ曲線と呼ぶことにした。とりあえずソースコードみて(お察しください)。

/* 各係数を格納する配列 */
int[] c = { 1, 6, -6, 2, -2};
/* 係数の最小値 */
int C_MIN = -8;
/* 係数の最大値 */
int C_MAX = 8;

void setup() {
  /* 適当な大きさのウィンドウを表示する */
  size(512, 512);
  /* 1秒間に1回drawが呼ばれるようにする */
  frameRate(1);
}

void draw() {
  /* 背景を黒く塗りつぶす */
  background(0);

  float x0, x1, y0, y1;
  float r;

  /* Processingでは左上が原点になっているので中心に持ってくる */
  translate(width/2, height/2);
  /* Processingでは上下が逆なので180度(つまりPI[rad])回転する */
  rotate(PI);

  for (float theta = 0.0; theta < 2 * PI; theta += 0.01 ) {
    /* この辺はバラ曲線と似たイメージ */
    r = width / 2 * sin(c[0]*theta);
    x0 = r * cos(c[1]*theta);
    y0 = r * sin(c[2]*theta);
    x1 = r * cos(c[3]*theta);
    y1 = r * sin(c[4]*theta);

    /* 色をそれっぽい感じに変化させる */
    stroke(255*abs(sin(theta)));

    /* (x0,y0)から(x1,y1)に線を引く */
    line(x0, y0, x1, y1);
  }
  
  /* 係数をランダムに変える */
  for (int i = 0; i < c.length; i++ ) {
    c[i] = int(random(C_MIN, C_MAX));
  }
}

/* キーボードが押されたときに呼び出される関数 */
void keyPressed() { 
  /* 保存する */
  saveFrame("######.png");
}
 1秒に1回ランダムにパラメータを決めて表示している。何かしらキーボードを押せば保存される。実行結果の例としてはこんなのが出てきた。

 まぁまぁいいんじゃない?オリジナリティもあるし。まぁ変なのばかりだけれど。しばらくツイッターのアイコンはこれにしておこうと思います。


2015年10月1日木曜日

Processingで音を出してみる

 グラフィックスに特化したProcessingというプログラミング言語があります。今までちまちま使ってきたが音も出せると聞いたのでやってみることにした。果たして,音楽の成績が5段階のうち3だった俺は使いこなせるのでしょうか。

1.ライブラリのインストール

 Processingで音をだすためにはminimというライブラリを使うようだが,Processingのバージョンが3になり,自分でライブラリを追加しなければならないようです。Processingのバージョンが2の人は読み飛ばしてもらって問題ないと思います。
 まずProcessingを起動し,メニューバーの「スケッチ」をクリックすると「ライブラリのインポート」という項目があります。
 
 右側に出てきた項目の中にminimがあれば良いのですが,なければ「ライブラリの追加」をクリック。
 
 そうするとウィンドウが出てくるので上の「Filter」というテキストボックス内に「minim」と入力し,検索結果の中の「Minim」という項目をクリック。そんで「install」を押せばライブラリのインストールは終了。

2.音を鳴らしてみる

 次に音を鳴らしてみる。今回は「ラ」の音を出してみます。しかしそのためには「ラ」の音の周波数を調べる必要があるのですが,次の表を見れば大丈夫。これExcelで計算したの。計算で音階の周波数を求められるって,なんかロマンがあるというか美しさを感じるよね。


 音が一つ高くなると周波数が1.059463倍になる。ちなみにこの数字は2の12乗根で,こうすることで低いドと高いドの音(つまり1オクターブ異なる音)の周波数がちょうど2倍になる。こんなところで数学が出てくるとは思わんかった。昔の人は感覚でこの周波数を区別していたのだろうか。

 まぁそれは置いておくとして,「ラ」の音が440Hzであることが分かったので早速プログラムを作ってみる。
/**
 * ラの音を出力する
 * 2015/09/30
 */

import ddf.minim.*;
import ddf.minim.signals.*;

/* 音声出力用のオブジェクト */
Minim minim;
AudioOutput aout;
SineWave wave;

void setup() {
  /* 適当な大きさにウィンドウを表示する */
  size(256, 256);

  /* 初期設定 */
  minim = new Minim(this);
  aout = minim.getLineOut(Minim.STEREO);
  /* サイン波をとりあえず440[Hz](ラの音),大きさ80%を指定した */
  wave = new SineWave(440, 0.8, aout.sampleRate());
  aout.addSignal(wave);
  
}

void draw(){
  /* ウィンドウの背景を黒く塗っておく */
  background(0);
}

 このプログラムのsetup関数の中のwave = ……のところの440を別の周波数に変えれば別の音が出せます。

3.自動作曲するプログラム

 自動作曲というとなんか大げさじゃないかと思うかもしれないです。そのとおりでございます。ランダムに音を決めて音を鳴らしてみるだけです。ごめんなさい。

/**
 * ランダムに音を鳴らす
 * 2015/10/01
 */

import ddf.minim.*;
import ddf.minim.signals.*;

/* 音声出力用のオブジェクト */
Minim minim;
AudioOutput aout;
SineWave wave;

/* 2の12乗根 */
float FREQ_RATE = 1.0594631;
/* 「ラ」の音の周波数 */
float FREQ_BASE = 440.0;
/* 休止になる確率 */
float PAUSE_PERCENTAGE = 0.25;
/* 演奏する音階の範囲 */
int TONE_RANGE = 4;

void setup() {
  /* 適当な大きさにウィンドウを表示する */
  size(256, 256);

  /* 初期設定 */
  minim = new Minim(this);
  aout = minim.getLineOut(Minim.STEREO);
  /* サイン波をとりあえず440[Hz](ラの音),大きさ80%を指定した */
  wave = new SineWave(440, 0.8, aout.sampleRate());
  aout.addSignal(wave);

  /* 一秒間に8回draw関数が呼び出されるようにする */
  frameRate(8);
}

void draw() {
  float freq;
  int temp;

  if ( random(1) < PAUSE_PERCENTAGE ) {
    /* 休止では周波数を0にする */
    freq = 0;
  } else {
    /* -TONE_RAGEからTONE_RAGEの乱数を生成 */
    temp = (int)(random(-TONE_RANGE, TONE_RANGE));

    /* ラの周波数に(2の12乗根)のtemp乗を掛ける */
    /* こうすることでtempだけ違う音階を出力できる */
    freq = FREQ_BASE * pow(FREQ_RATE, temp);
  }
  /* 周波数freqの音を出す */
  wave.setFreq(freq);

  /* ウィンドウの背景を黒く塗っておく */
  background(0);
}

wave.setFreq([周波数(float型)])で任意の周波数の音が出せる。ランダムに周波数を決め,それを1秒間に8回出力している。それっぽくなってるように思えなくもないが,小学生が適当に鍵盤叩いてるようなもので,まるで音楽ではないですが大目に見てください.
 まぁまた時間があったら自動作曲プログラムとか作ってみます。マルコフ連鎖とか使えばそれっぽくなりそうだし。