見出し画像

ChatGPTのプログラムを読む能力がヤバすぎる

ChatGPTでプログラミングをしたことがあるだろうか?

「ないわ」という人。あなたがもしエンジニアなら、今すぐ試してほしい。これは本当にヤバいテクノロジーだ。エンジニアとして評価される能力がこれから劇的に変わる。筆者はそう確信している。

GPTを使いこなせるかどうか?

これが次世代のエンジニアの生命線になるだろう。GPTを使いこなすエンジニアはとんでもない生産性向上を実現し、GPTを使えないエンジニアは問答無用で仕事がなくなる。もしくはGPTの運用コストより安い給料で搾取される。

「GPT×エンジニアリング」のノウハウをいち早くキャッチアップすることで、このキモすぎるテクノロジーの大波に乗ろうではないか。

ChatGPTにプログラムを書いてもらう方法については、以前こちらのnoteで紹介した。

「二次元の熱伝導方程式」について、あれこれとChatGPTに指示することでプログラムを書かせる方法を具体的なプロンプトとともにまとめたものだ。このnoteに掲載したすべてのコードはChatGPTが書いている。

例えば、
「熱伝導方程式を解いて、温度分布とプロファイルを表示してほしい。熱拡散率を変えてそれを比較したい。」
と伝えればこんなコードを書いてくれる。

import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1 import make_axes_locatable

# Constants
Lx, Ly = 1, 1  # Domain dimensions (m)
Nx, Ny = 100, 100  # Number of grid points
dx, dy = Lx / (Nx - 1), Ly / (Ny - 1)  # Grid spacing (m)
total_time = 12.0  # Total simulation time (s)
thermal_diffusivities = [0.5 * 1e-4, 1e-4, 1.5 * 1e-4]  # Different thermal diffusivities

def init_temperature_field(Nx, Ny):
    T = np.zeros((Ny, Nx))
    T[Ny // 2 - 10 : Ny // 2 + 10, Nx // 2 - 10 : Nx // 2 + 10] = 100
    return T

def update_temperature(T, alpha, dt, dx, dy):
    T_new = T.copy()
    T_new[1:-1, 1:-1] = (
        T[1:-1, 1:-1]
        + alpha * dt * (
            (T[1:-1, 2:] - 2 * T[1:-1, 1:-1] + T[1:-1, :-2]) / dx**2
            + (T[2:, 1:-1] - 2 * T[1:-1, 1:-1] + T[:-2, 1:-1]) / dy**2
        )
    )
    return T_new

fig, axes = plt.subplots(3, 2, figsize=(12, 12), sharex='col', sharey='row')

for i, alpha in enumerate(thermal_diffusivities):
    dt = 0.25 * min(dx, dy)**2 / alpha  # Time step (s)
    T = init_temperature_field(Nx, Ny)
    n_steps = int(total_time / dt)
    
    for step in range(n_steps + 1):
        T = update_temperature(T, alpha, dt, dx, dy)

    # Plot the final temperature distribution in the xy-plane
    im = axes[i, 0].imshow(T, cmap='hot', origin='lower', extent=[0, Nx, 0, Ny])
    axes[i, 0].set_title(f'Temperature Distribution (α = {alpha:.1e})')
    axes[i, 0].set_ylabel('y (m)')

    # Create a custom colorbar axis with the same length as the y-axis
    divider = make_axes_locatable(axes[i, 0])
    cax = divider.append_axes("right", size="5%", pad=0.1)
    fig.colorbar(im, cax=cax, label='Temperature (°C)')

    # Plot the temperature profile along the x-axis through the center
    x = np.linspace(0, Lx, Nx)
    axes[i, 1].plot(x, T[Ny // 2, :], label=f'α = {alpha:.1e}')
    axes[i, 1].set_title(f'Temperature Profile (α = {alpha:.1e})')
    axes[i, 1].set_ylabel('Temperature (°C)')

# Set the x-axis label for the bottom subplots
for ax in axes[-1, :]:
    ax.set_xlabel('x (m)')

plt.suptitle('2D Heat Transfer for Different Thermal Diffusivities')
plt.tight_layout(rect=[0.1, 0.03, 1, 0.95])  # Increase left margin to 0.1
plt.show()
プログラムの実行結果

おそろしいプログラミング能力と言わざるを得ない。この程度のコードであればChatGPTはあっさりと書いてしまうのだ。

これを使いこなせるかどうかで、エンジニアの生産性が天と地ほど違ってくるのは容易に想像できる。ChatGPTはエンジニアの能力格差を拡大するとんでもない装置なのだ。

こんなおそろしいプログラミング能力をもつChatGPTだが、「プログラムを書かせる」以外にも、実はおそろしい使い方がある。「プログラムを読ませる」という使い方だ。

本稿では、ChatGPTがもつ驚異の「プログラムを読む能力」を紹介する。

コードにコメントを書いてもらう

物理シミュレーションや数値計算に限らず、筆者はプログラムにコメントを書く作業がきわめて嫌いである。面倒くさすぎる。大事なのはわかっている。わかっているけど書けない。

これをChatGPTにやらせてみたらどうか?

以下は筆者が書いたCFDのコードである。実行するといわゆる円柱まわりの流体の流れを可視化する。

import numpy as np
import matplotlib.pyplot as plt

def distance(x1, y1, x2, y2):
    return np.sqrt((x2-x1)**2 + (y2-y1)**2)

plot_every = 1000
Nx, Ny = 400, 100
tau = .53
Nt = 10000

NL = 9
cxs = np.array([0, 0, 1, 1, 1, 0,-1,-1,-1])
cys = np.array([0, 1, 1, 0,-1,-1,-1, 0, 1])
weights = np.array([4/9,1/9,1/36,1/9,1/36,1/9,1/36,1/9,1/36])

F = np.ones((Ny,Nx,NL)) + 0.01*np.random.randn(Ny,Nx,NL)
F[:,:,3] = 2.3

cylinder = np.full((Ny, Nx), False)
for y in range(0, Ny):
    for x in range(0, Nx):
        if(distance(Nx//4, Ny//2, x, y)<13):
            cylinder[y][x] = True
            
for it in range(Nt):
    #print(it)
    F[:,-1,[6,7,8]] = F[:,-2,[6,7,8]]
    F[:,0,[2,3,4]] = F[:,1,[2,3,4]]
    
    for i, cx, cy in zip(range(NL), cxs, cys):
        F[:,:,i] = np.roll(F[:,:,i], cx, axis=1)
        F[:,:,i] = np.roll(F[:,:,i], cy, axis=0)
        
    bndryF = F[cylinder,:]
    bndryF = bndryF[:,[0,5,6,7,8,1,2,3,4]]
    
    rho = np.sum(F,2)
    ux  = np.sum(F*cxs,2) / rho
    uy  = np.sum(F*cys,2) / rho
    
    F[cylinder,:] = bndryF
    ux[cylinder] = 0
    uy[cylinder] = 0
    
    
    Feq = np.zeros(F.shape)
    for i, cx, cy, w in zip(range(NL), cxs, cys, weights):
        Feq[:,:,i] = rho*w* (1 + 3*(cx*ux+cy*uy) + 9*(cx*ux+cy*uy)**2/2 - 3*(ux**2+uy**2)/2)
    F += -(1.0/tau) * (F - Feq)
    
    if (it%plot_every == 0):
        plt.imshow(np.sqrt(ux**2+uy**2))
        plt.pause(.01)
        plt.cla()
実行結果

コードを見ての通り、全くコメントがない。そこでChatGPTにコメントを書いてもらおう。プロンプトは以下。

Can you add a comment in Japanese to the following code? Added comments indicate what physical parameter each variable defined in the program represents. It also indicates what the processes and functions defined in the program calculate.

code : 
上記のコードをコピペ

以下のコードに日本語のコメントを追加してください。追加されたコメントは、プログラム内で定義された各変数がどのような物理パラメータを表しているかを示します。また、プログラム内で定義された処理や関数が何を計算するのかも示します。

プロンプト

ChatGPTからの回答は次のようになる。

以下のコメントをコードに追加しました。物理パラメーターや計算されるプロセスと関数を日本語で説明しています。

GPT4
import numpy as np
import matplotlib.pyplot as plt

def distance(x1, y1, x2, y2):
    return np.sqrt((x2-x1)**2 + (y2-y1)**2)

plot_every = 1000  # どれだけの頻度でプロットを更新するか
Nx, Ny = 400, 100  # シミュレーション領域のサイズ
tau = .53  # 緩和時間
Nt = 10000  # シミュレーションの総時間ステップ数

NL = 9  # Lattice-Boltzmannの速度の数
cxs = np.array([0, 0, 1, 1, 1, 0,-1,-1,-1])  # x方向の速度ベクトル成分
cys = np.array([0, 1, 1, 0,-1,-1,-1, 0, 1])  # y方向の速度ベクトル成分
weights = np.array([4/9,1/9,1/36,1/9,1/36,1/9,1/36,1/9,1/36])  # 速度の重み

F = np.ones((Ny,Nx,NL)) + 0.01*np.random.randn(Ny,Nx,NL)  # 分布関数
F[:,:,3] = 2.3

cylinder = np.full((Ny, Nx), False)  # 円柱の配置を表す二次元配列
for y in range(0, Ny):
    for x in range(0, Nx):
        if(distance(Nx//4, Ny//2, x, y)<13):
            cylinder[y][x] = True
            
for it in range(Nt):
    #print(it)
    F[:,-1,[6,7,8]] = F[:,-2,[6,7,8]]
    F[:,0,[2,3,4]] = F[:,1,[2,3,4]]
    
    for i, cx, cy in zip(range(NL), cxs, cys):
        F[:,:,i] = np.roll(F[:,:,i], cx, axis=1)
        F[:,:,i] = np.roll(F[:,:,i], cy, axis=0)
        
    bndryF = F[cylinder,:]
    bndryF = bndryF[:,[0,5,6,7,8,1,2,3,4]]
    
    rho = np.sum(F,2)  # 密度
    ux  = np.sum(F*cxs,2) / rho  # x方向の速度
    uy  = np.sum(F*cys,2) / rho  # y方向の速度
    
    F[cylinder,:] = bndryF
    ux[cylinder] = 0
    uy[cylinder] = 0
   
    Feq = np.zeros(F.shape)  # 平衡分布関数
    for i, cx, cy, w in zip(range(NL), cxs, cys, weights):
        Feq[:,:,i] = rho*w* (1 + 3*(cx*ux+cy*uy) + 9*(cx*ux+cy*uy)**2/2 - 3*(ux2+uy2)/2)
        F += -(1.0/tau) * (F - Feq) # 分布関数の更新
    if (it % plot_every == 0):
        plt.imshow(np.sqrt(ux**2+uy**2))  # 速度の大きさを表示
        plt.pause(.01)
        plt.cla()

どうだろう。
筆者はこれをはじめて見たとき、恐怖を感じずにはいられなかった。

おそろしいのはコメントの内容だ。「プログラムの全体像」を理解しないと明らかに書けないものになっている。

つまりこういうことだ。
ChatGPTはコメントが一切ないコードを見て、なにをやっているかの全体像を一瞬で読み解き、書かれているプログラミング言語と学問的な数式を照らし合わせ、それに使用する物理パラメータがどのような変数で定義されているのかを判断している。

ちょっとシャレになってない。

コードの解説をしてもらう

世の99%のプログラマーは、自分にとって新しい領域のプログラミングにトライするとき、おおよそ以下のようなステップを踏むのではないだろうか?

  • ググって先人のコードを見つける

  • それを実行して結果を見る

  • さらにググりながらコードの内容を理解しつつ、ちょっとづつ修正していく

基本はこのようなことをやるだろう。なにを隠そう、プログラミングとは先人の知恵を少しだけ自分用に修正する仕事である。他人が書いたコードの理解に努める時間がとても長いのだ。

しかしながら、人の書いたコードはとにかく読みづらい。変数が何を意味し、どんな計算に代入され、その先の計算にどのように使われるのかを読み解くのはとても骨が折れる。

これをChatGPTにやらせてみたらどうか?

例として、上記の例、筆者が書いたコメントが一切ないCFDのコードを解説してもらう。

コードを丸投げし、以下のプロンプトを打ち込んでみよう。

Could you give us an overview of this code?
### コードコピペ ###

このコードの概要を教えてくれますか?

プロンプト

ChatGPTからの回答は以下。DeepLによる和訳のみ掲載する。

このコードは、格子ボルツマン法(LBM)を用いて、円柱状の物体の周りの流体の流れをシミュレートします。LBMは、流体力学をシミュレーションするための計算手法で、流体を指定された数の速度(方向)を持つ格子に離散化することで動作します。このコードでは、配列操作と可視化にそれぞれ使用されるNumPyとMatplotlibのライブラリをインポートしています。

以下、コードの概要を説明します:
1. 2次元直交平面上の2点間の距離を計算するための距離関数を定義する。
2. 格子方向の数NL、格子速度cxsとcys、格子重みweightsを含むシミュレーション・パラメータを設定する。
3. 確率分布関数Fを小さなランダムなノイズで初期化する。
4. 各点から円柱の中心までの距離を計算し、その距離が円柱の半径(この場合は13)より小さいかどうかをチェックすることにより、流体中の円柱を表すブール配列cylinderを作成します。
5. 以下のステップを実行しながら、Nt回反復するシミュレーションを行う:
a. シミュレーション領域の端に流体の境界条件を設定する.
b. 確率分布関数をそれぞれの格子速度の方向にシフトさせて流体を流す。
c. 円柱状の物体にぶつかった流体粒子を跳ね返す。
d. 流体密度rho、速度ux、uyを計算する。
e. 平衡分布 Feq と緩和時間 tau に基づいて確率分布関数を更新する。
6. plot_every 反復ごとに流体速度の大きさをプロットし、流体の流れを可視化する。

シミュレーションでは、円柱状の物体の周りの流体の流れを示す一連の画像が表示され、流体速度は異なる色の濃淡で表現されます。シミュレーションはNt回繰り返し実行され、指定された間隔で流体速度が更新され、流れが可視化されます。

GPT4の回答をDeepLで和訳

繰り返そう。
このコードは全くコメントを書いていない。それなのに、ChatGPTは残酷なほど精緻なアウトラインを一瞬で提供してくれるのだ。

「人が書いた初見のコードを読む」という能力において、ほぼすべての人間はChatGPTに負けたと言って差し支えない。筆者はそう考えている。

この概要について、より詳細に掘り下げたいときは以下のプロンプトを使うと良い。

Could you provide detailed descriptions for section 2 of our overview?

概要の2項について詳細に説明してください。

プロンプト

ChatGPTからの回答は以下。

もちろん!概要の第2節では、いくつかのシミュレーション・パラメータと配列が定義されています。ここでは、それぞれについて詳しく説明します:

1. plot_every: この変数は、ビジュアライゼーションの更新頻度を決定するものです。plot_everyの繰り返し(この場合は1000回)ごとに可視化が更新されます。
2. Nx、Ny: これらの変数は、2D格子(シミュレーション領域)の大きさをx方向とy方向にそれぞれ定義します。この場合、Nxは400、Nyは100に設定されています。
3. tau: 緩和時間です。流体が平衡に向かって緩和する速度を制御します。流体の粘性に影響します。ここでは、tauを0.53に設定しています。
4. Nt: この変数は、シミュレーションの総反復回数を表します。ここでは、Ntは10000に設定されています。
5. NL: この変数は、流体粒子の格子方向(速度)の数を表します。このシミュレーションでは、9つの格子方向(休息粒子を含む)を持つD2Q9格子モデルを使用しています。したがって、NL は 9 に設定されています。
6. cxs, cys: これらの配列は、各格子方向の格子速度の x、y 成分を格納します。格子速度は、流体粒子が格子内で移動できる方向を表す。D2Q9モデルでは、以下のような格子速度が設定されています:
    * 0:静止(移動なし)
    * 1、5、6、7:水平・垂直(北、東、南、西)
    * 2、3、4、8:斜め(北東、南東、南西、北西)。
    cxs および cys 配列は、それぞれこれらの速度の対応する x および y 成分      を格納する。
7. 重み: この配列には、D2Q9モデルの各格子方向に関連する重みが格納されています。これらの重みは、平衡分布関数Feqを計算する際に使用されます。D2Q9モデルの重みは以下の通りです:
    * 静止粒子(0)の4/9
    * 水平・垂直方向(1、5、6、7)は1/9。
    * 対角線方向(2、3、4、8)に対して1/36

GPT4の回答をDeepLで和訳

数式が読みづらいときは以下のプロンプト。

Could you display the formula defined as "Feq[:,:,i] = rho*w* (1 + 3*(cx*ux+cy*uy) + 9*(cx*ux+cy*uy)**2/2 - 3*(ux**2+uy**2)/2)" In the form of a rendered LaTex?

## コード##として定義されている数式をLaTeXで示してくれますか?

プロンプト
GPT4回答

ちょっとシャレになってない(2回目)。

最後に

いかがだろうか。ChatGPTのプログラミング能力で注目すべきは「書く」だけではない。初見のコードを読み解き、それを数学的な知識で解説する能力も驚くほど高い。

ChatGPTはエンジニアの能力格差を拡大するおそろしい装置だ。使い方を早期にキャッチアップすることで、このキモいテクノロジーの恩恵に預かろうではないか。

これら以外の使用法についても目下研究中だ。よさげなものは随時ツイッターで紹介していく。

この記事が参加している募集

AIとやってみた

この記事が気に入ったらサポートをしてみませんか?