| HOME | 目次 | | 2009 (C) H.Ishikawa |
10.1 | ギャンブル必勝法 | ||
10.2 | 在庫管理問題 | ||
10.3 | 欠番 | ||
10.4 | 強磁性体の相転移のシミュレーション | ||
10.5 | ジェネティック・アルゴリズム | ||
演習 |
本書の最後は、「何でもシミュレーションしてみよう」と題し、ギャンブルから、最近注目されている、ジェネティックアルゴリズムまで、乱数を用いた、さまざまな、確率実験を、試みます。
10.1 ギャンブル必勝法
クラップスという名のゲーム文献(8)(13)
カジノで行われているダイス(サイコロ)を使った、クラップスというゲームをとりあげます。このクラップスに限らず、カジノで行われるゲームは、すべて胴元が有利となるようなルールが定められています。したがって長時間平均すれば、必ず胴元が勝つ仕組みとなっているわけですが、必勝法はないものでしょうか。
まず、クラップスのルールを説明します。クラップスは2個のサイコロを用いておこないます。2個のサイコロの目の合計は2から12までの値をとります。(3.5節で示したとおり、7の出る確率が最も大きい。)プレーヤは2個のサイコロを振って、その和が7または、11の時(これをナチュラルといいます)は勝ちで,2、3あるいは12の時(これをクラップスといいます)は負けです。もしそれ以外のとき、すなわち、4、5、6、8、9または、10がでたときは、その値をポイントといい、ひきつづき同じポイントまたは7が出るまで、サイコロを振ります。そして同じポイントがでれば、プレーヤの勝ち、それ以前に7が出れば、負けとなります。もしプレーヤが勝てば、自分の賭け金の2倍の払い戻しを受けます。
このゲームは、たいへんよくできて、ごく僅かな確率の差で、胴元が勝つようにできています。
必勝法
このゲームで必ずプレーヤが勝つ方法はあるでしょうか。もしそれがあれば、ぜひカジノに行って見たいものです。倍増法という必勝法が知られています。倍増法というのは、まず1ドルの賭け金からスタートし、もし勝てば、次も1ドルを賭けますが、負けた場合は2ドルを、さらに負ければ前回の賭け金の2倍の額を次々に賭けていく方法です。この方法では、負けた金額をとりもどせるので、必勝法となりそうです。はたして、これがほんとうに必勝法となるのでしょうか。クラップスにおいて、倍増法をシミュレーションしてみましょう。
シミュレーション・プログラム
ではクラップスのシミュレーションプログラムS1010.javaの説明を行ないます。まず、(1)サイコロの関数を作ります。
int dice();
により、整数1〜6の一様分布の乱数を発生させます。次に、(2)のとおりクラップスのルールどおりに記述して、関数
int craps(void);
を作ります。1回目のサイコロの目の和を sum1 , 2回目以後のサイコロの目の和を sum2 としています。この関数は、勝ちの場合1、負けの場合0の値を返します。
次にメインプログラムですが、1回の賭け金を k ドル、現在の持ち金を q ドルとします。(3)が倍増法による賭けで、もし勝った場合、次の賭け金を1とし、負けた場合前回の2倍を賭けることとします。プログラムでは、賭けを何回も繰り返し、横軸賭けの回数 t 、縦軸持ち金 q をグラフに表示するようにしています。
シミュレーションの結果
プログラムを実行すると、図10.1.1のように時間とともに、着実に持ち金は増加していきますが、時々負けが続くと賭け金が急増し、赤字に転落するときがあります。もしその時、もち金がなくなれば破産ですが、なお余裕があって倍々と賭けることができれば、必ずプラスになります。しかしながら、通常は胴元のほうが資金は豊富で、負けが続いても持ちこたえられるのに対し、客のほうが先に底をついてしまいます。もし十分な資金を用意することができれば、ぜひカジノへ行って、ひと儲けして下さい。
図10.1.1 倍増法による必勝法 |
S1010.java ギャンブル必勝法 | Download | 実行 | |
/* S1010.java * ギャンブル必勝法 * (C) H.Ishikawa 2008 */ package simulation; import java.applet.*; import java.awt.*; import java.awt.event.*; import window.Window; public class S1010 extends Applet implements ActionListener { Button button0; public void init() { button0 = new Button(" 再実行 "); add(button0); button0.addActionListener(this); } public void actionPerformed(ActionEvent e) { String label = e.getActionCommand(); repaint(); } public void paint(Graphics g) { Window w ; w = new Window(); int SPACE = 30; int HIGHT = 400; int WIDTH = 640; long t; /* 賭の回数 */ long q = 100; /* 持ち金 はじめは100ドル */ long k = 1; /* 1回の賭金1ドル */ long T_END = 500; /* 終りの回数 */ /*グラフィックの準備*/ w.setWindow(0, 0.0,0.0,(double)T_END,500.0, SPACE,HIGHT-SPACE,WIDTH-SPACE,SPACE); w.axis(0, "t", T_END/10, "q", 100, g); w.moveTo(0, 0.0, q, g); g.setColor(Color.blue); /*メイン*/ for (t = 1; t <= T_END; t ++) { q = q - k; if (craps() == 1) { /* (3)勝った場合 */ q = q + 2 * k; k = 1; /* 1ドル賭ける */ } else { /* 負けた場合 */ k = k * 2; /* 2倍賭ける */ } w.lineTo(0, (double)(t), (double)(q), g); } } public static int dice(){ /* (1)サイコロ */ return((int)(Math.random() * 6.0 + 1)); } public static int craps(){ /* (2)クラプスのルール */ int r; /* 1:勝ち 0:負け */ int sum1; /* 和1 */ int sum2; /* 和2 */ sum1 = dice() + dice(); if (sum1 == 7 || sum1 == 11) { /* ナチュラル */ r = 1; } else if(sum1 == 2 || sum1 == 3 || sum1 == 12) { /* クラップス */ r = 0; } else { sum2 = 0; r = 0; while (sum2 != 7) { /* 7が出るまで */ sum2 = dice() + dice(); if (sum2 == sum1) { /* ポイント */ r = 1; break; } } } return(r); } } |
| この章始め |
10.2 在庫管理問題(文献(2)(8))
在庫管理問題とは
企業や産業システムでは、原料や製品が供給から需要ひ向かって流れていく過程において、それらを貯蔵する機能が必要です。この貯蔵容量と、それを運用管理する最適の方法を決定するのが、在庫管理問題です。
例えば、ある商店が商品を問屋から仕入れて、客に販売する場合を考えてみましょう。商品を一度に多量仕入れると、在庫をたくさんかかえ、そのための費用がかさみます。逆に少量の在庫では、大きな需要があった場合に品切れの危険が生じ、得べかりし利益をそこない、ひいてはその店の信用を失います。しからば、@ 在庫に要する費用、A 問屋への発注のための費用、B 品切れが発生した場合にこうむる損失の合計を最小にして、利益を最大にするには、いつどれだけ問屋に発注すべきでしょうか。
販売店の在庫 q は、図10.2.1のように毎日の売上げ k 個ずつ減少していきます。基準発注点 q1 をわったら、 a 個の発注をしますが、すぐには入荷せず、 lt 日の遅れがあります。図10.2.2のように、在庫量は変化するでしょう。売上げ個数と入荷おくれが確率的である場合を考え、
q1 の最適値を求めるためのシミュレーション・プログラムを作ってみましょう。
図10.2.1 在庫モデル |
図10.2.2 在庫 q の変化と lt |
lt > 0 :すでに発注ずみであり、あと lt 日で納品される。
lt = 0 :本日納品される。
lt < 0 :発注していない。
(2)で1日平均 k 個ポアソン分布の売上げがあったとします。(3)で発注点 q1 を割り、まだ発注していなければ発注します。(4)で q が負になれば、在庫なしで販売しそこなった数 ls を数えます。(5)では、本日納品されたので、在庫に A を加えます。(6)で在庫費用の累計を計算します。 T_END 日分のシミュレーションを終わったあと、発注費用の累計 sc2 、品切れ損失の累計 sc3 、売上個数の累計 yk を計算し、総売上げ rr を求めます。そしてグラフをプロットし、発注点 q1 をかえ、シミュレーションを続けます。
アウトプット
10000日分のシミュレーションを q1 を0から100まで変化させ、繰り返し行います。 出力されたグラフ図10.2.3を見ると、q1=45 の時に、利益が最大となることがわかります。
図10.2.3 在庫管理の問題 シミュレーション結果 |
S1020.java 在庫管理の問題 | Download | 実行 | |
/* S1020.java * 在庫管理の問題 * (C) H.Ishikawa 2008 */ package simulation; import java.applet.*; import java.awt.*; import java.awt.event.*; import java.text.DecimalFormat; import window.Window; public class S1020 extends Applet implements ActionListener { Button button0; public void init() { button0 = new Button(" 再実行 "); add(button0); button0.addActionListener(this); } public void actionPerformed(ActionEvent e) { String label = e.getActionCommand(); repaint(); } public void paint(Graphics g) { Window w ; w = new Window(); int SPACE = 30; int HIGHT = 400; int WIDTH = 640; long A = 100; /* 1回の入荷量 */ long AL = 5; /* 1日の平均売上個数 */ long ET = 6; /* 納品するまでの平均日数 */ long ST = 2; /* 納品するまでの日数の標準偏差 */ double SP = 7000.0; /* 売値 */ double PC = 5000.0; /* 仕入れ単価 */ double C1 = 20.0; /* 1日1個当たりの在庫費用 */ double C2 = 10000.0; /* 1回の発注にともなう費用 */ double C3 = 500.0; /* 品切れ1個あたりの損失 */ long T_END = 10000; /* 終りの時刻 */ long Q1_MAX = 100; /* q1の最大値 */ long tt; /* シミュレーション日数 */ long q; /* 現在在庫量 */ long q1; /* 発注点 */ long k; /* 1日の売上個数 */ long zk; /* kの累計 */ long yk; /* 売上個数の累計 */ long ls; /* 在庫割れのため売り損なった個数 */ long nn; /* 発注回数 */ long lt; /* (1)入荷遅れ日数 */ double sc1; /* 在庫費用の累計 */ double sc2; /* 発注費用の累計 */ double sc3; /* 品切れ損失の累計 */ double rr; /* 総売上 */ int l = SPACE; /* 表示行 */ DecimalFormat exFormat1 = new DecimalFormat("0"); /*グラフィックの準備*/ w.setWindow(0, 0.0,0.0,Q1_MAX,1.0e08, 5*SPACE,HIGHT-SPACE,WIDTH-SPACE,SPACE); w.axis(0, "q1", 10, "rr", 1e07, g); w.moveTo(0, 0.0, 0.0, g); g.drawString(" q1 rr" ,10 ,l);l = l + 12; /*メイン*/ for (q1 = 0; q1 <= Q1_MAX; q1 = q1 + 5) { /* q1を0からQ1_MAXまで変化させ シミュレーションを行う */ /* 初期設定 */ tt = 0; q = A; zk = 0; ls = 0; nn = 0; lt = -1; sc1 = 0.0; sc2 = 0.0; sc3 = 0.0; /* 1日分のシミュレーション */ while (tt <= T_END) { k = poisson(AL); /* (2)k個売れた */ q = q - k; zk = zk + k; if (q < q1 && lt < 0) { /* (3)発注点を割ったので発注する */ lt = (long)normal(ET, ST); nn = nn + 1; } if (q < 0) { /* (4)在庫割れのため売り損ない */ ls = ls - q; q = 0; } if (lt == 0) { /* (5)入荷 */ q = q + A; } sc1 = q * C1 + sc1; /* (6)在庫費用の累計を計算 */ lt = lt - 1; tt = tt + 1; } sc2 = nn * C2; sc3 = ls * C3; yk = zk - ls; rr = (SP - PC) * yk - sc1 - sc2 - sc3; /* 総売上の計算 */ /* 出力 */ g.drawString(" " + q1 + " " + exFormat1.format(rr) , 10, l); l = l + 12; if (q1 == 0) { w.moveTo(0, q1, rr, g); } else { w.lineTo(0, q1, rr, g); } } } long poisson(double lambda) { /* ポアソン乱数発生 */ double xp = Math.random(); long k = 0; while (xp >= Math.exp(-lambda)) { xp = xp * Math.random(); k = k + 1; } return (k); } double normal(double ex, double sd) { /* 正規乱数発生 */ double xw = 0.0; double x; long n; for (n = 1;n <= 12; n ++) { xw = xw + Math.random(); } x = sd * (xw - 6.0) + ex; return (x); } } |
| この章始め |
10.4 強磁性体の相転移のシミュレーション (文献(15))
図10.4.1 原子の模型 |
図10.4.2 絶対零度の場合とある温度の場合のスピン磁気モーメント |
・・・・・ | 式10.4.1 |
・・・ | 式10.4.2 |
・・・・・ | 式10.4.3 |
図10.4.3 |
・・・・・ | 式10.4.4 |
図10.4.4 イジングモデル シミュレーション結果 |
S1040.java イジングモデル | Download | 実行(長時間CPU占有) | |
/* S1040.java * イジングモデル * (C) H.Ishikawa 2008 */ package simulation; import java.applet.*; import java.awt.*; import java.awt.event.*; import window.Window; public class S1040 extends Applet implements ActionListener { Button button0; Button button1; boolean sw =false; TextField text; double w0; /* 正規化温度 */ public void init() { add(new Label("正規化温度(2.27を中心に試す)=")); text = new TextField("2.27"); add(text); button0 = new Button(" 実行 "); button1 = new Button("クリア"); add(button0); add(button1); button0.addActionListener(this); button1.addActionListener(this); } public void actionPerformed(ActionEvent evt) { String label = evt.getActionCommand(); if (label.equals(" 実行 ")) { sw = true; w0 = Double.parseDouble(text.getText()); } else { sw = false; } repaint(); } public void paint(Graphics g) { Window w ; w = new Window(); int SPACE = 30; int HIGHT = 480; int WIDTH = 640; int MAX = 250; /* 配列の大きさ */ long T_END = 1000; /* シミュレーションを終わる時刻 */ int s[][] = new int[MAX+2][MAX+2]; /* (1)磁気モーメントの値 s[i][j]=1あるいはs[i][j]=-1 */ int i,j; /* 着目している原子の番号 */ int e0; /* 相互作用の値 */ int m; /* s[i][j]=1である原子の数 */ int n; /* forのカウンタ */ int tt = 0; /* シミュレーションの時刻 */ double p; /* 反転の確率 */ double gika; /* 磁化率 */ /* 準備 */ w.setWindow(0, 0,0,MAX, MAX, SPACE,MAX+SPACE,MAX+SPACE,SPACE); w.axis(0, "", MAX, "", MAX, g); w.setWindow(1, 0,0.0,T_END,1.0, SPACE,HIGHT-SPACE,WIDTH-SPACE,MAX+2*SPACE); w.axis(1, "時間", T_END / 10.0, "磁化率", 0.1, g); w.moveTo(1, 0, 1.0, g); m = MAX * MAX; /* (2)初期状態 */ for (j = 0; j <= MAX + 1; j ++) { for (i = 0; i <= MAX + 1; i ++) { s[i][j] = 1; } } /* メイン */ if (sw) { /*"実行"が押されたとき*/ while (tt < T_END) { for (n = 1; n <= MAX * MAX; n ++) { i = (int)(MAX * Math.random()) + 1; /* (3)1からMAXまでの乱数 */ j = (int)(MAX * Math.random()) + 1; /* (4)1からMAXまでの乱数 */ e0 = -s[i][j] * (s[i][j - 1] + s[i][j + 1] + s[i - 1][j] + s[i + 1][j]); /* (5)相互作用エネルギーの計算 */ p = Math.exp(((double)(e0) - 4.0) / w0); /* (6)反転確率 */ if ( p > Math.random()) { /* (7) */ s[i][j] = -s[i][j]; /* (8)反転 */ m = m + s[i][j]; } if (s[i][j] == 1) { g.setColor(Color.blue); w.putPixel(0, (double)(i), (double)(j), g); } else { g.setColor(Color.red); w.putPixel(0, (double)(i), (double)(j), g); } } tt = tt + 1; gika = (double)(2 * m) / (double)(MAX * MAX) - 1.0; /* (9)磁化率 */ g.setColor(Color.green); w.lineTo(1, tt, gika, g); } stop(); } } } |
| この章始め |
10.5 ジェネティック・アルゴリズム
ジェネティック・アルゴリズムとは
ジェネティック・アルゴリズム(GA)は遺伝的アルゴリズムともよばれ、生物の進化過程をシミュレーションすることによって、たくさんの組み合せのなかから最適な解を見つけ出す手法のことをいいます。ダーウィンの自然淘汰理論というのがありますが、これを基礎に、生物の進化過程を工学的モデルにおきかえたものです。
進化過程の概要は、おおよそ次のようにあらわされるでしょう。まず、0と1の値をもつ遺伝子(Gene)からなる染色体(Chromosome)を考えます。この染色体のあつまりを集団(Population)といいます。それに対し図10.5.1ように(1)、(2)、(3)の操作をほどこします。
(1) 交叉
集団内の2つの染色体の組(ペア)において、交叉(crossover)という遺伝子の一部の入れ替えがおこなわれること。
(2) 突然変異
各染色体において、ある確率で、遺伝子の一部が0から1あるいは、1から0に返転すること。
(3) 選択
(1)、(2)をへた遺伝子をもった染色体のうち環境へのより高い適応性をもつものが、選択されること。
(1)、(2)、(3)の遺伝子的操作を1世代とよび、この操作をくりかえしていくと、その集団はより環境に順応する方向に進化します。
ジェネティック・アルゴリズムでは、さまざまな組み合わせを遺伝子からなる染色体で表現し、その組み合わせごとの目的関数を計算します。そして、その値の高いものを選択し、それを残すよう生存競争を何世代にもわたり行わせれば、最終的には、目的関数の値が最大となるようにすることができます。
ジェネティック・アルゴリズムの原理は、驚くほど単純ですが、その探索能力は非常に高く、通常の方法では解を見つけにくい場合でも、比較的容易に正確に近づくことができるといわれています。
図10.5.1 組み替え(交叉と突然変異) |
図10.5.2 ナップザックの問題 |
図10.5.3 遺伝子の組み換え |
結果の出力
2つのウインドウに横軸世代、縦軸それぞれ重量の合計、価値の合計をグラフ表示します。また、もっとも目的関数の大きい k = 0 の染色体の構造、またそのときの重量の合計、価値の合計を表示します。
このプログラムを走らせると、図10.5.4のように、100世代ほどで、最適に近い値が得られていますが、1000世代くりかえし実行する必要があります。
図10.5.4 ナップザック問題 シミュレーション結果 |
S01050.java ナップザック問題 | Download | 実行 | |
/* S1050.java * ナップザック問題 * (C) H.Ishikawa 2008 */ package simulation; import java.applet.*; import java.awt.*; import java.awt.event.*; import java.text.DecimalFormat; import window.Window; public class S1050 extends Applet implements ActionListener { Button button0; public void init() { button0 = new Button(" 再実行 "); add(button0); button0.addActionListener(this); } public void actionPerformed(ActionEvent e) { String label = e.getActionCommand(); repaint(); } public void paint(Graphics g){ Window w ; w = new Window(); int SPACE = 40; int HIGHT = 400; int WIDTH = 640; int LENGTH = 40; /* 染色体の長さ */ int SIZE = 10; /* 集団の大きさ */ double MAX_WEIGHT = 10.0; /* 品物の重量の最大値 */ double MAX_VALUE = 10.0; /* 品物の価値の最大値 */ double LIMIT = 100.0; /* ナップザックに入る重量の限界値 */ int G_END = 2000; /* 繰り返し数 */ double PROB = 0.01; /* 突然変異の確率 */ double PROB2 = 0.5; /* 初期化の確率 */ int gene[][] = new int[2*SIZE][LENGTH]; /* (1)染色体 */ int next_gene[][] = new int[2*SIZE][LENGTH]; /* (2)新世代の染色体 */ double weight[] = new double[LENGTH]; /* 品物の重量 */ double value[] = new double[LENGTH]; /* 品物の価値 */ double total_weight[] = new double[2*SIZE]; /* 重量の合計 */ double total_value[] = new double[2*SIZE]; /* 価値の合計 */ int v_sort[] = new int[2*SIZE]; /* 順番 */ long generation; /* 世代を表すforのカウンタ */ int k,l; /* gene[k][l]のためのforのカウンタ */ int l_rand; /* 交叉位置 */ int k_sort; /* ソート用のforのカウンタ */ int i_swap; /* スワップ用変数 */ double swap; /* スワップ用変数 */ int line = HIGHT; /* 表示行 */ DecimalFormat exFormat1 = new DecimalFormat("0"); /* グラフィックの準備 */ w.setWindow(0, 0.0,0.0,G_END,120, SPACE,HIGHT/2-SPACE/2,WIDTH-SPACE,SPACE); w.axis(0, "generation", G_END / 10, "weight", 20, g); w.moveTo(0, 0.0, 0.0, g); w.setWindow(1, 0.0,0.0,G_END,250, SPACE,HIGHT-SPACE,WIDTH-SPACE,HIGHT/2+SPACE/2); w.axis(1, "generation", G_END / 10, "value", 50, g); w.moveTo(1, 0.0, 0.0, g); /* (3)染色体のイニシャライズ */ for (k = 0 ; k < SIZE; k ++) { for (l = 0; l < LENGTH; l ++) { if (Math.random() < PROB2){ gene[k][l] = 1; } } } /* (4)品物の重さと価値の設定 */ for (l = 0; l < LENGTH; l ++) { weight[l] = MAX_WEIGHT * Math.random(); value[l] = MAX_VALUE * Math.random(); } /* (5)メイン始まり */ for (generation = 1; generation <= G_END; generation ++) { /* 交叉 */ for (k = 0; k < SIZE; k = k + 2) { l_rand=(int)(Math.random() * LENGTH); /* (6)交叉位置 */ for (l = 0; l < l_rand; l ++) { gene[k+SIZE][l] = gene[k][l]; } for (l = l_rand; l < LENGTH; l ++) { gene[k+SIZE][l] = gene[k+1][l]; } for (l = 0; l < l_rand; l ++) { gene[k+1+SIZE][l] = gene[k+1][l]; } for (l = l_rand; l < LENGTH; l ++) { gene[k+1+SIZE][l] = gene[k][l]; } } /* (7)突然変異 */ for (k = SIZE ; k < 2 * SIZE; k ++) { for (l = 0; l < LENGTH; l ++) { if (Math.random() < PROB) { gene[k][l] = 1 - gene[k][l]; } } } /* (8)目的関数の計算 */ for (k = 0; k < 2 * SIZE; k ++) { total_weight[k] = 0.0; total_value[k] = 0.0; for (l = 0; l < LENGTH; l ++) { total_weight[k] = total_weight[k] + gene[k][l] * weight[l]; /* (9) */ total_value[k] = total_value[k] + gene[k][l] * value[l]; /* (10) */ } if (total_weight[k] > LIMIT) { total_value[k] = 0.0; /* (11) */ } } /* (12)ソート */ for (k = 0; k < 2 * SIZE; k ++) { v_sort[k] = k; } for (k = 0; k < 2 * SIZE; k ++) { for (k_sort = k + 1; k_sort < 2 * SIZE; k_sort ++) { if (total_value[k] < total_value[k_sort]) { swap = total_value[k_sort]; total_value[k_sort] = total_value[k]; total_value[k] = swap; i_swap = v_sort[k_sort]; v_sort[k_sort] = v_sort[k]; v_sort[k] = i_swap; } } } /* 新世代におきかえ */ for (k = 0; k < 2 * SIZE; k ++) { for (l = 0 ;l < LENGTH; l ++) { next_gene[k][l] = gene[v_sort[k]][l]; /* (13) */ } } for (k = 0; k < 2 * SIZE; k ++) { for (l = 0; l < LENGTH; l ++) { gene[k][l] = next_gene[k][l]; /* (14) */ } } /* 表示 */ w.lineTo(0, generation, total_weight[v_sort[0]], g); w.lineTo(1, generation, total_value[0], g); } g.drawString("gene = " , 10, line); for (l = 0; l < LENGTH; l ++) { g.drawString("" + gene[0][l], 80 + l* 10, line); } line = line + 12; g.drawString("total_weight =" + exFormat1.format(total_weight[v_sort[0]]) + " total_value =" + exFormat1.format(total_value[0]), 10, line); } } |
| この章始め |
演習
1.10.1節のクラップスは胴元が有利なゲームです。勝っても負けても、毎回1ドルずつ賭け続けた場合、どのくらいの回数でプレーヤが破産するか確かめなさい。
(解答) A1010.java | 実行 |
2. 10.2節の在庫管理問題では、発注点をわった時に発注していたが、毎週1回定時に入荷があるとして、その入荷量を前々日の在庫量により決定し、それにより発注する方法について、シミュレーションし、最適入荷量 を求めなさい。
(解答) A1020.java | 実行 |
3.プログラムs1040.cで w を wc を中心に変えて実行してみなさい。 w が wc より小さい場合、磁化率が0とならず磁石のままであることをたしかめなさい。また
w が wc より大きい場合、磁化率が0となる速度が早いことをたしかめなさい。
(解答省略)
| この章始め |
| HOME | 目次 | | 2009 (C) H.Ishikawa |