検索キーワード「Jupyter」に一致する投稿を日付順に表示しています。 関連性の高い順 すべての投稿を表示
検索キーワード「Jupyter」に一致する投稿を日付順に表示しています。 関連性の高い順 すべての投稿を表示

2026年5月6日水曜日

アレコレたいへん

iCloudもたいへんからの続き


図:アレコレたいへんのイメージ(ChatGPTによる)


今日は今日とて,また一日ややこしい作業に振り回された。それというのも,なまじ生成AI(LLM)が賢いからだ。彼らは簡単にコードを作るだけでなく,ソフトウェアやコンピュータ回りの設定や環境についても,膨大な知識を持って具体的に助言・提案してくれる。

こちらは,エラーメッセージや問題点を丸投げコピペするだけで,解決に近づいていく。まあ,ときどき間違ったこともいうのだが,ほとんど自宅に学生アルバイトのコンサルタントが常駐しているのと同じなのである。これをちゃんと使いこなせれば,老人のIT設定どうしましょう問題も多少改善しそうだが,普通は生成AI(LLM)の設定のところで詰んでしまう。


iCloudの山を越えたことに油断して,MacBookAir M1 の掃除に着手した。自分のホームディレクトリがゴミだらけだったので,そのディレクトリリストを丸投げして助言してもらった。特にhomebrewで次々と実験的にインストールしたソフトウェア断片を何とかしたかったからだ。

アドバイスに従って,作業していくとかなりきれいになったつもりだったが,肝腎のjupyter lab でjuliaやpythonを動かそうとするとこけてしまった。調子に乗ってよけいなものまで捨ててしまったからだ。いや,ChatGPTは注意してくれていたのですよ。それを無視して勝手に暴走した自分が悪い自己責任なのだけど,暴走させたのは彼らだ(それは責任転嫁・・・)。

なんとか復活し,ディスクの使用量が55%からおよそ50%まで削減することができた。まあいっか。

2026年4月21日火曜日

ヒマワリ

ひまわりからの続き


図1:黄金比がつくる向日葵の種のシミュレーション


放送大学の自然科学の授業で,岸根順一郎さんが向日葵の種の配列のシミュレーションを見せていた。自然は黄金比を選んでいるというわけだ。バラメタを少し変えるといろいろな模様が出現する。

自分でも試してみたくて,バイブコーディングに走る。ChatGPT Auto で試したところ,Juliaに慣れていないせいか,なかなかエラーが消えない。しょうがないので,ChatGPT Thinking-5.4 でリセットしてからお願いする。プロンプトは以下のとおり。
Q(koshix):
Jupyter環境で,次のJulia プログラムをつくってください。 向日葵の種(塗りつぶした色つき小円でよい)の分布が 1粒ずつ内側から充足されていくインラインアニメーション。 これで意味が分かりますか? なるべく簡素で高速なものにしてください。

種の大きさや色相,パラメタの変更機能などを注文すると,「Julia で毎回 GIF や mp4 を作るより、Jupyter セル内に HTML/JavaScript の小さな UI を埋め込む 方がずっと軽くて速いです。」ということで,修正版ができた。饅頭の薄皮だけJuliaで中身の餡子はすべてJavascriptというよくわからないけど,よくあるパターンらしい。

最後に,Gemini Pro に投げてコード全体を簡素化してもらったところ,少しスッキリした。黄金比の部分を変えると,様々なパターンが現われる。

この中からJavascriptのコードを含むhtmlを取り出して,独立で動くように修正し,角度係数αを,1.60〜1.83まで0.01刻みで変化させた結果を合成した画像も,ほとんどそのまま出力してくれた。プロンプトを0.1刻みと間違えて入力しても,正しく解釈してくれる。



図2:α = 1.60〜1.83までの向日葵パターンの変化



using UUIDs

function sunflower_simulator()
    uid = "sf_" * replace(string(uuid4()), "-" => "")

    html = """
    <div id="$uid" style="font-family: sans-serif; line-height: 1.4;">
      <div style="margin-bottom: 0.6em;">
        <label>角度係数 α (2π/α): <input id="$(uid)_alpha" type="number" value="1.61803398875" step="0.0001" style="width: 8em;"></label>
        <span style="margin-left:1em;"></span>
        <label>粒数 N: <input id="$(uid)_N" type="number" value="500" step="50" style="width: 5em;"></label>
        <span style="margin-left:1em;"></span>
        <label>速度: <input id="$(uid)_step" type="number" value="5" step="1" min="1" style="width: 4em;"></label>
        <span style="margin-left:1em;"></span>
        <button id="$(uid)_run">実行</button>
      </div>

      <div style="margin-bottom: 0.5em; color: #444; font-size: 0.95em;">
        α を黄金比 φ ≈ 1.618 にすると、回転角 2π/α ≈ 222.5° になります。<br>
        ひまわり配列でよく使う黄金角 137.5° とは、向きが逆なだけで本質的に同じです。
      </div>

      <canvas id="$(uid)_canvas" width="520" height="520" style="border:1px solid #ddd; background:white;"></canvas>
      <div id="$(uid)_info" style="margin-top:0.5em; color:#333;"></div>
    </div>

    <script>
    (function() {
      // DOM要素の取得を簡素化
      const get = id => document.getElementById(`$(uid)_\${id}`);
      const [alphaIn, nIn, stepIn, runBtn, canvas, info] = ["alpha", "N", "step", "run", "canvas", "info"].map(get);
      const ctx = canvas.getContext("2d");
      let animId = null;

      function runOnce() {
        if (animId) cancelAnimationFrame(animId);
        
        const alpha = parseFloat(alphaIn.value);
        const N = Math.max(1, parseInt(nIn.value));
        const step = Math.max(1, parseInt(stepIn.value));

        if (!isFinite(alpha) || alpha === 0) {
          info.textContent = "α は 0 でない数を入れてください。";
          return;
        }

        info.textContent = `α = \${alpha.toFixed(6)}, 回転角 = \${(360 / alpha).toFixed(3)}°, 粒数 = \${N}, 速度 = \${step}`;

        // シード配列の生成 (Array.from でスッキリ記述)
        const angle = 2 * Math.PI / alpha;
        const seeds = Array.from({length: N}, (_, i) => {
          const k = i + 1;
          const r = Math.sqrt(k);
          return {
            x: r * Math.cos(k * angle),
            y: r * Math.sin(k * angle),
            color: `hsl(\${25 + 55 * (k / N)}, 90%, 59%)` // HSV(h, 78%, 96%) とほぼ同等のHSL色
          };
        });

        const W = canvas.width, H = canvas.height;
        const scale = 0.48 * Math.min(W, H) / (Math.sqrt(N) + 1);
        const rad = Math.max(0.9, 140 / Math.sqrt(N + 20));

        let k = 0;
        
        // 描画とアニメーションループを統合
        function tick() {
          k = Math.min(k + step, N);
          
          ctx.clearRect(0, 0, W, H);
          ctx.save();
          ctx.translate(W / 2, H / 2);
          
          for (let i = 0; i < k; i++) {
            ctx.beginPath();
            ctx.arc(seeds[i].x * scale, seeds[i].y * scale, rad, 0, 2 * Math.PI);
            ctx.fillStyle = seeds[i].color;
            ctx.fill();
          }
          ctx.restore();

          if (k < N) animId = requestAnimationFrame(tick);
        }
        
        tick();
      }

      runBtn.onclick = runOnce;

      // Enterキーでの実行イベントをまとめる
      [alphaIn, nIn, stepIn].forEach(el => 
        el.addEventListener("keydown", e => e.key === "Enter" && runOnce())
      );
    })();
    </script>
    """

    display("text/html", html)
end

sunflower_simulator()

2026年2月14日土曜日

コンピュータ環境



図:コンピュータ環境整備を支援するAI(ChatGPTによる)

【事例1】
MacBook Air M1を使っているが,1TBのSSDの使用領域は半分ほどだった。ところが先日,気がつくと,残量が100GBを切ったという警告が出てきた。えっ。となって,あれこれ不要アプリなどを消したものの,残量は150GBくらいにしかならない。仕方がないので,ChatGPTに相談してみた。
Q(koshix):
MacBook Air M1 (macOS 26.2)の ~/Library/Application Support/Microsoft/EdgeUpdater が 20 GB 近くもあって,ディスクを占有しているのですが,削除して構いませんか。Excel Word PowerPoint などのMicrosoftアプリはそのまま使い続けたいです。

Q(koshix):
~/Library/Group Containers が 16 GBもあって,消したいのですけれど,どうですか。
du -h -d 1 "$HOME/Library/Containers" | sort -h | tail -n 30 などで次々と問題点が芋蔓的に見つかった。怪しい部分を個別撃破しようとしたが,そのうち,もっと本質的な問題があったことが発覚した。
Q(koshix):
SSD領域 1 TB のうち,システムデータで 400 GB,自分のローカルで350 GBつかっているのですけど,システムデータはこんなものですか?

A(ChatGPT):
400GB の「システムデータ」は 普通ではないです。よほど特殊な使い方(巨大な仮想マシン/開発環境/動画編集のキャッシュ/iCloud・写真のローカル保持/Time Machine スナップショットが大量)でない限り、1TB Mac でシステムデータが 400GB は“異常に大きい側”に入ります。
あらら,そうですか。あれこれ,指示された情報をいれていくと,TimeMachineのスナップショットが主犯であることがわかって,無事にスリム化が完了した。

【事例2】
macOS26.2では,Homebrew でフリーソフトパッケージを管理している。毎朝,brew cleanup; brew update; brew upgrade; brew doctor を実行するのが日課だ。いつからか,jupyterlab だけ,追加の brew link jupyterlab という操作を要求されるようになったが,そのままにしていた。これはどうも不可避のようで,いやならpipx でいれなさいということなのだが,自動で更新してくれないので,ここはパスする。

もうひとつは,このjupyter 環境におけるpythonの利用だ。jupyterlabがバージョンアップすると,毎回 cd /opt/homebrew/Cellar/jupyterlab/4.5.4/libexec/bin で移動して,./python3.14 -m pip install --upgrade pip 以下各モジュールの入れ直しが発生していた。これもなんとかならないかとChatGPTに相談したところ(早く聞けば良かった),次の代替案が提案された。

A(ChatGPT 5.2 Thinking):
(前略)
方案A(おすすめ):“固定の venv” を作って、その Python を Jupyter のカーネルにする。
Homebrew で JupyterLab を更新しても、カーネル側の Python 環境は不変にできます。
ポイントは「Cellar の python じゃなく、別場所の venv を使う」こと。

1) venv を作る(例: ~/venvs/jlab)
python3 -m venv ~/venvs/jlab
source ~/venvs/jlab/bin/activate
> python -m pip install -U pip 
> pip install matplotlib japanize_matplotlib pandas reportlab
> pip install cartopy geopandas
> pip install ipykernel

 ということで,こちらのほうは無事に解決できた。

2025年9月21日日曜日

9月20日(2)

Juliaの日時処理からの続き

5年前の国勢調査の記事がないかと調べていたら,それはなくて5年前の自分の誕生日の記事が発掘された。誕生日の曜日を調べるJuliaプログラムの話だ。5年も経っているからもう一度実行してみようと,Jupyterではすぐ動いたが,コマンドラインでどうするのか迷った。

プログラムを実行形式にchmodして,頭に#!/usr/bin/env julia(あるいはjuliaの絶対パス)を書けばいいだけなのだけれど,!に気がつかず,シェルスクリプトのコメントと解釈されてエラーがでた。しかし耄碌しているのですぐに原因に気付けずChatGPT-5にたよることになる。

そんなこんなで,過去の習作コードをChatGPT-5に投げてバイブコーディングして得られたのが次の結果とコードである。プログラミングとはAIとの対話のことだった。

 koshi@mba2020 ~ % ./birth.jl

【基礎情報】

今日                : 2025年9月21日(日曜日)

誕生日              : 1953年9月20日(日曜日)


【差分と年齢】

生誕からの経過日数 : 26299日

満年齢              : 72歳


【年ごとの誕生日一覧】(*は日曜)  ※最終年:2025年

1953年9月20日(日曜日)  0歳  *

1954年9月20日(月曜日)  1歳  

1955年9月20日(火曜日)  2歳  

1956年9月20日(木曜日)  3歳  

1957年9月20日(金曜日)  4歳  

1958年9月20日(土曜日)  5歳  

1959年9月20日(日曜日)  6歳  *

1960年9月20日(火曜日)  7歳  

1961年9月20日(水曜日)  8歳  

1962年9月20日(木曜日)  9歳  

1963年9月20日(金曜日)  10歳  

1964年9月20日(日曜日)  11歳  *

1965年9月20日(月曜日)  12歳  

1966年9月20日(火曜日)  13歳  

1967年9月20日(水曜日)  14歳  

1968年9月20日(金曜日)  15歳  

1969年9月20日(土曜日)  16歳  

1970年9月20日(日曜日)  17歳  *

1971年9月20日(月曜日)  18歳  

1972年9月20日(水曜日)  19歳  

1973年9月20日(木曜日)  20歳  

1974年9月20日(金曜日)  21歳  

1975年9月20日(土曜日)  22歳  

1976年9月20日(月曜日)  23歳  

1977年9月20日(火曜日)  24歳  

1978年9月20日(水曜日)  25歳  

1979年9月20日(木曜日)  26歳  

1980年9月20日(土曜日)  27歳  

1981年9月20日(日曜日)  28歳  *

1982年9月20日(月曜日)  29歳  

1983年9月20日(火曜日)  30歳  

1984年9月20日(木曜日)  31歳  

1985年9月20日(金曜日)  32歳  

1986年9月20日(土曜日)  33歳  

1987年9月20日(日曜日)  34歳  *

1988年9月20日(火曜日)  35歳  

1989年9月20日(水曜日)  36歳  

1990年9月20日(木曜日)  37歳  

1991年9月20日(金曜日)  38歳  

1992年9月20日(日曜日)  39歳  *

1993年9月20日(月曜日)  40歳  

1994年9月20日(火曜日)  41歳  

1995年9月20日(水曜日)  42歳  

1996年9月20日(金曜日)  43歳  

1997年9月20日(土曜日)  44歳  

1998年9月20日(日曜日)  45歳  *

1999年9月20日(月曜日)  46歳  

2000年9月20日(水曜日)  47歳  

2001年9月20日(木曜日)  48歳  

2002年9月20日(金曜日)  49歳  

2003年9月20日(土曜日)  50歳  

2004年9月20日(月曜日)  51歳  

2005年9月20日(火曜日)  52歳  

2006年9月20日(水曜日)  53歳  

2007年9月20日(木曜日)  54歳  

2008年9月20日(土曜日)  55歳  

2009年9月20日(日曜日)  56歳  *

2010年9月20日(月曜日)  57歳  

2011年9月20日(火曜日)  58歳  

2012年9月20日(木曜日)  59歳  

2013年9月20日(金曜日)  60歳  

2014年9月20日(土曜日)  61歳  

2015年9月20日(日曜日)  62歳  *

2016年9月20日(火曜日)  63歳  

2017年9月20日(水曜日)  64歳  

2018年9月20日(木曜日)  65歳  

2019年9月20日(金曜日)  66歳  

2020年9月20日(日曜日)  67歳  *

2021年9月20日(月曜日)  68歳  

2022年9月20日(火曜日)  69歳  

2023年9月20日(水曜日)  70歳  

2024年9月20日(金曜日)  71歳  

2025年9月20日(土曜日)  72歳    

ChatGPT-5 Thinking が提案してきたコードは以下のとおりである。かなり修正してもらった。

#!/usr/bin/env julia

# birth.jl


using Dates


# --- ヘルパ ---

const WDAY_SHORT = ["月","火","水","木","金","土","日"]

const WDAY_LONG  = ["月曜日","火曜日","水曜日","木曜日","金曜日","土曜日","日曜日"]


fmt_date_ja(d::Date; long_wday::Bool=true) = string(

    Dates.format(d, dateformat"yyyy年m月d日"), "(",

    (long_wday ? WDAY_LONG : WDAY_SHORT)[dayofweek(d)], ")"

)


# 引数: [YYYY MM DD [ENDYEAR]]

function parse_args()

    if length(ARGS) == 0

        return Date(1953, 9, 20), year(Dates.today())

    elseif length(ARGS) == 3 || length(ARGS) == 4

        b = Date(parse(Int, ARGS[1]), parse(Int, ARGS[2]), parse(Int, ARGS[3]))

        lasty = (length(ARGS) == 4) ? parse(Int, ARGS[4]) : year(Dates.today())

        return b, lasty

    else

        error("使い方: ./birth.jl  または  ./birth.jl YYYY M D  [ENDYEAR]")

    end

end


function list_birthdays(birth::Date, last_year::Int)

    last_year = max(last_year, year(birth))  # 下限は誕生年

    for y in year(birth):last_year

        d = Date(y, month(birth), day(birth))

        age = y - year(birth)

        star = (dayofweek(d) == 7) ? "*" : ""   # 7 = 日曜

        println(fmt_date_ja(d; long_wday=true), "  ", age, "歳  ", star)

    end

end


# --- 本体 ---

birthday, list_until = parse_args()

today = Dates.today()


println("【基礎情報】")

println("今日                : ", fmt_date_ja(today; long_wday=true))

println("誕生日              : ", fmt_date_ja(birthday; long_wday=true))


println("\n【差分と年齢】")

days_elapsed = Dates.value(today - birthday)

age_years = year(today) - year(birthday) - (Date(year(today), month(birthday), day(birthday)) > today ? 1 : 0)

println("生誕からの経過日数 : ", days_elapsed, "日")

println("満年齢              : ", age_years, "歳")


println("\n【年ごとの誕生日一覧】(*は日曜)  ※最終年:", list_until, "年")

list_birthdays(birthday, list_until)