ujimushi(@旧sradjp(15364))の日記

旧スラドの日記の引越先です

ここ最近の自分が使っている漢直入力環境について(補足)

blogの管理画面を見てみると,Xdottedしている形跡が。 ということで,言及のあった内容について少し。

最初にアルファベットとか表示されるの使い心地良くなくてKTyping作ったけど、

漢直のユーザーとしてはそれが普通です。

漢字直接入力コミュニティサーベイとか見ても 大体自分で実装している方が多くて,私のような人はむしろ少数派かと。

ちょっと気になったのは、 「mozcの場合は,仮名漢字変換の変換元は平仮名しか登録できない」 と書いてあることで、これは本当なんだろうか。 Google日本語入力は、普通に漢字かな交じりの単語を登録できるんですが。

実際ubuntu 22.04 のMozcは登録はできても変換が効かないので, Mozc 2.26.4220.100時点ではできなかったと考えています。

会社ではubuntu 22.04を使っていますが,ここでのMozcでは辞書登録による交ぜ書き変換は今でもできません。 交せ書きができそうというのはX上の岡さんの記述と家のPCのubuntu 24.04で 最新のバージョンのMozcビルド環境で試してから, その後WindowsGoogle日本語入力で確認して初めて知った感じです。(前回の記事の後)

という訳で,ubuntuでは数年前まではできなかったと考えるのが妥当と思います。 実際大昔に2014年のT-Code's Nightの一連の日記を書いた時に 試した時は出来なかったので元々出来なかったというのが私の認識です。

実際辞書の見出し語に平仮名しか駄目というのは WindowsIMEの仕様に引っぱられたもので, WindowsIMEの仕様がある程度固まった(Windows 8の時あたりかな?)時に 内容を確認して落胆したものです。

一時期Linuxから離れていた時にCannaが無くなっていた(辞書登録がかなり自由だった) り,この20年の間漢直を続けていくのはなかなかハードではありました。

自分でツールを作らない,ただのユーザーというポジションなので。

この方は emacs と mozc で T-Code を使っておられるようです。 tc.el を独自にメンテしながらお使いのようで

独自にtc-ac-completeだけで, tc.elの方は独自にではなくて闇(表に名前が出ていない)の公式メンテナで, 現在活動しているのは naotaさんと私だけで, 後は「Emacs使わんから」と言って現在は名前だけの方々で, 正直 Emacs Lispも全然分からんしtc.elのコードもよく分からんし, 元々EUC-JPのコードがutf-8になってるから色々ごちゃごちゃで うかつに本体には手を出せれへんし, そのくせあんまり感謝されへんし, もううっとうしいわ。

気をとり直して…

まぁ他のメンテナは独自実装の方を頑張ってま(す|した)ね。

実は次の漢直に関する日記には Mozcでの交ぜ書き変換の実現方法のことについて書こうと思っています。

まぁぶっちゃけ手抜きで辞書を作る方法ですが, とりあえずこれから色々試してみようかと思います。 仕事も忙しいし,実現は来年中にできればかな?

なお,Mozcの場合辞書の見出し語は片仮名が効きません。 それが無ければ色々できるのですが…

ただ,Mozcのリリースログを見ると,辞書見出し語1万件→無制限等, 制限を緩める方向なので,これから先にはまだ何かあるかもしれません。 (実際2014年時点でローマ字テーブル1万件の縛りがあった)

まぁもう歳で純粋なプログラマでもないので出来ることをボチボチと。

追記

さっき試したところMozcの平仮名以外の見出し語については,ubuntu24.04の標準のmozcでも登録できなさそうです。ubuntuのmozcのバージョンを確認すると,mozcは 2.28.4715.102なので 公式パッケージを使っている限りubuntuでは交ぜ書き変換を使えないことになります。

mozcのバージョンタグを追っていったところ2022年はまだ無理っぽいので,岡さんが「使える」と言っているのはいったいいつからの認識なんでしょうかね?

Julia言語でマルチプロセスのうち簡単なものを利用してみる

はじめに

少し前の投稿のように,便利にマルチスレッドを使っていたのですが,基本的にPlots.jl はスレッドセーフではありません。

業務で大量にグラフを描画する必要があるので,やむを得ずマルチプロセスも試してみることにします。

といっても,それぞれ別々のファイルからデータを読み込んでグラフにし,別々の画像ファイルに出力するので, それぞれの処理に依存関係が全くありません。

なので,簡単にマルチプロセスが実現できると思い試してみました。 その試してみたことのノリが分かるような例を作ってみました。

内容

処理の部分を次のfuncs.jlような例を作ってみました。 基本的にダミーで,ただ待つ処理を間に入れているような感じです。

# funcs.jl
using Plots

"""
    read_dummy(filename)

ファイルを読んでいるフリをする関数
"""
function read_dummy(filename::AbstractString)
    @debug "dumy" filename
    sleep(1) # ファイルを読んでるフリ
    rand(Float64, (1000,))
end

"""
    calc_dummy!(data)

`data`を計算して加工するフリをする関数
"""
function calc_dummy!(data::Vector{Float64})
    sleep(2) # いろいろな計算をしているフリ
    data .= 1.0 .- data
    nothing
end

"""
    plot_dummy(data)

プロットをするフリ?をする関数
"""
function plot_dummy(data::Vector{Float64})
    sleep(1) # 時間がかかる小芝居
    plot(data, size=(1024, 512))
end

で先ほどのfuncs.jlの関数を使って順次処理を進めます。 次のようなコードを書きました。

# example_sp.jl
using ProgressMeter

include("./funcs.jl")
datafilenames = "data" .* string.(1:20, pad=3) .* ".csv"
pngfilenames = "output" .* string.(1:20, pad=3) .* ".png"

@showprogress for i in eachindex(datafilenames)
    data = read_dummy(datafilenames[i])
    calc_dummy!(data)
    plt = plot_dummy(data)
    savefig(plt, pngfilenames[i])
end

そして上のコードを実行させます。ProgressMeterの結果表示から ループの部分だけの処理で1分25秒かかっています。

julia> import Pkg; Pkg.activate("/home/ujimushi/blog/test/mp/")
  Activating project at `~/blog/test/mp`

julia> include("example_sp.jl")
Progress: 100%|███████████████████████████████████████| Time: 0:01:25

julia> 

次にマルチプロセス版を実装してみます。先達の記事, Juliaで超単純にマルチプロセスや, マルチプロセスのはまりどころ を参考にしながら実装していきます。

@everywhereをつけると各プロセスで定義することができるようです。また, addprocs(...)の後に@everywhereを実行するのも先達の記事の通りにしました。

@everywhere inlcude(...)とできるのが楽チンです。ただ,定義する量が多いと初期化プロセスに時間がかかります。 今回はPlots.jlのモジュール読み込みに時間かがかっているようでした。また,事前にパッケージモードで モジュールをアップデートしておかないと初期化プロセスのプリコンパイルが長くなってしまうので要注意です。

@distributedマクロは forとの間に2入力引数の関数の引数をとって,それぞれの結果について後処理用の関数として使えますが, 関数の引数を省略すると,ただのfor文のような感じで使えます。 今回は演算結果を利用しないので関数の引数を無しにして利用しています。

# example_mp.jl
using Distributed

addprocs(6, exeflags="--project")
using ProgressMeter
@everywhere include("./funcs.jl")
@everywhere datafilenames = "data" .* string.(1:20, pad=3) .* ".csv"
@everywhere pngfilenames = "output" .* string.(1:20, pad=3) .* ".png"

@showprogress @distributed for i in eachindex(datafilenames)
    data = read_dummy(datafilenames[i])
    calc_dummy!(data)
    plt = plot_dummy(data)
    savefig(plt, pngfilenames[i])
end

そして実行させてみます。ループの部分は20秒です。 全体の処理時間が短くなっています。

julia> import Pkg; Pkg.activate("/home/ujimushi/blog/test/mp/")
  Activating project at `~/blog/test/mp`

julia> include("example_mp.jl")
Progress: 100%|███████████████████████████████████████| Time: 0:00:20

julia> 

ただ,これだけの記事では分かりづらいですが,Plots.jlを各プロセスで読み込むのにかなり時間がかかっています。

しかし,業務では3000件ぐらいの時系列データ(各1件当たり複数のデータ)のグラフを描かせており オーバーヘッドがそれほど気にならないぐらい全体の時間がかかるものだったので,非常に助かりました。

それぞれの処理に依存関係がある時はこう単純ではないのですが,コア数が多いCPUでは 有効に処理時間を削減できそうです。

その他

その他に利用しやすいのはmap関数をマルチプロセス化したpmap関数で,

result_map = @showprogress pmap(src_vectors) do src
    ...
end

のような感じで処理状況を確認しながら演算することができます。

filterっぽい結果を返すなら

flags = @showprogress pmap(src_vectors) do src
    ...
    trueなら残す。falseなら削除する判定文
end
src_filtered = src_vectors[flags]

とかで実現できますね。

なお,マルチスレッドの時もそうですが,for文のところでzip関数を使うとエラーになるとか 色々注意点はありそうなのですが,その辺りは体育系なので体当たりで 学んでいくといったところです。

エラーで学ぶタイプの自分にとっては動的スクリプト言語はありがたいです。 また,引数の型の指定も可能で,エディタからの支援も効きやすいのも嬉しいところです。

Plots.jlのGRバックエンドで横長の図を描いた時に凡例の線が長過ぎるのを調節する方法

仕事柄長い時系列のデータを複数要素表示するグラフをよく描くのですが,少し気になる挙動がありました。 凡例の中のがやや長過ぎる感じなのです。

次のようなコードで横長のグラフを描画してみます。

using Plots

plt = plot(sin; xlims=(0, 100pi), size=(1600, 200),
           legendfontfamily="ipag", label="線が長過ぎる")
savefig(plt, "plots-legend-line-too-long.png")

結果は次の通りです。やや線が長過ぎるような気がします。

で,GRバックエンド実装を見ると,この線の長さは グラフ(subplot)の横幅を基準として3/45の比で設定されているようでした。 なるほど。グラフを横長にすると間延びして見えるはずです。

で,この部分を変更できるように魔改造してみます。

次のコードを実装します。 これは,gr_legend_base_factor_per_ratioという参照型の変数を作って, グラフの横幅とlegendの基準長さとの比を可変にできるようにします。

using Plots

@eval Plots begin
    """
        gr_legend_base_factor_per_ratio

    legend描画時の横方向の基準(グラフの横幅/45)の比
    デフォルトでは45となっている。

    参照型なので, `gr_legend_base_factor_per_ratio[] = 100`
    のような形で変更すること
    """
    const gr_legend_base_factor_per_ratio = Ref(45.0)
    
    function gr_get_legend_geometry(vp, sp)
        vertical = (legend_column = sp[:legend_column]) == 1
        textw = texth = 0.0
        has_title = false
        nseries = 0
        if sp[:legend_position] !== :none
            GR.savestate()
            GR.selntran(0)
            GR.setcharup(0, 1)
            GR.setscale(0)
            ttl = sp[:legend_title]
            if (has_title = ttl !== nothing)
                gr_set_font(legendtitlefont(sp), sp)
                (l, r), (b, t) = extrema.(gr_inqtext(0, 0, string(ttl)))
                texth = t - b
                textw = r - l
            end
            gr_set_font(legendfont(sp), sp)
            for series in series_list(sp)
                should_add_to_legend(series) || continue
                (l, r), (b, t) = extrema.(gr_inqtext(0, 0, string(series[:label])))
                texth = max(texth, t - b)
                textw = max(textw, r - l)  # holds text width right now
                nseries += 1
            end
            GR.setscale(GR.OPTION_X_LOG)
            GR.selntran(1)
            GR.restorestate()
        end
        # deal with layout
        column_layout = if legend_column == -1
            (1, has_title + nseries)
        elseif legend_column > nseries && nseries != 0 # catch plot_title here
            @warn "n° of legend_column=$legend_column is larger than n° of series=$nseries"
            (1 + has_title, nseries)
        elseif legend_column == 0
            @warn "n° of legend_column=$legend_column. Assuming vertical layout."
            vertical = true
            (has_title + nseries, 1)
        else
            (ceil(Int64, nseries / legend_column) + has_title, legend_column)
        end
        #println(column_layout)

        base_factor = width(vp) /
            gr_legend_base_factor_per_ratio[]  # determines legend box base width (arbitrarily based on `width`)

        # legend box conventions ref(1)
        #  ______________________________
        # |<pad><span><space><text> <pad>|
        # |     ---o--       ⋅ y1        |
        # |__________________↑___________|
        #               (xpos,ypos)

        pad = 1base_factor  # legend padding
        span = 3base_factor  # horizontal span of the legend line: line x marker x line = 3base_factor
        space = 0.5base_factor  # white space between text and legend / markers

        # increment between each legend entry
        ekw = sp[:extra_kwargs]
        dy = texth * get(ekw, :legend_hfactor, 1)
        span_hspace = span + pad  # part of the horizontal increment
        dx = (textw + (vertical ? 0 : span_hspace)) * get(ekw, :legend_wfactor, 1)

        # This is to prevent that linestyle is obscured by large markers.
        # We are trying to get markers to not be larger than half the line length.
        # 1 / leg.dy translates base_factor to line length units (important in the context of size kwarg)
        # gr_legend_marker_to_line_factor is an empirical constant to translate between line length unit and marker size unit
        base_markersize = gr_legend_marker_to_line_factor[] * span / dy  # NOTE: arbitrarily based on horizontal measures !

        entries = has_title + nseries  # number of legend entries

        # NOTE: subtract `span_hspace`, since it joins labels in horizontal mode
        w = dx * column_layout[2] - space - !vertical * span_hspace
        h = dy * column_layout[1]

        (
            yoffset = height(vp) / 30, xoffset = width(vp) / 30,
            base_markersize, base_factor, has_title, vertical,
            entries, column_layout, space,
            texth, textw, span, pad, dy, dx, w, h,
        )
    end
end

上のコードを実行してから,次のように実行します。

# 凡例の基準長さをグラフ横幅の1/150にする
Plots.gr_legend_base_factor_per_ratio[] = 150.0

plt = plot(sin; xlims=(0, 100pi), size=(1600, 200),
           legendfontfamily="ipag", label="線を調整")
savefig(plt, "plots-legend-line-short.png")

結果は次の通りです。 凡例の線が短くなっていることが分かると思います。

このように内部の実装を覗いて自分だけの魔改造をするのも楽しいものです。

最近はプルリクで提案するのが普通なんでしょうが,この辺は好みなので 採用されないことも多いので,本体のライブラリを変更せずに 改造できるのは個人的には非常に重宝しています。

注意点

対応しているのはPlots.jlのバージョン1.xです。 いつかリリースされるバージョン2からはPlots.jlモジュールの構造が変わるので上記のコードでは動かないので注意して下さい。

Julia言語雑感(2024年11月)

Juliaユーザー規約が守れないので他のユーザーと交流できない ミーハー系Julia言語ユーザーが感じたJulia言語の2024年11月, 今月も勝手に書いていきまます。

Julia v1.10.7リリース

Julia Discourseの記事によると, 2024年11月27日にバージョン1.10.7がリリースされました。 現在のLTSである1.10.xの最新版になります。

Julia言語のPodcast「Julia Dispatch」スタート

Julia言語界隈で有名な Chris Rackauckas さんと Michael Tiemann さんがホストとして, Julia言語にまつわるゲストを招いて送るポッドキャスト Julia Dispatchがスタートしました。

Julia Dispatch FMから各エピソードへのリンクが辿れます。

クリスさんは講演ではすごく早口だけどPodCastでは比較的ゆっくりめで, 発音がはっきりしていて,すごく聞きとりやすく英語が全然駄目な私でも 単語は分かるのですが,いかんせん私の英語力の無さで内容は今一つ。

でもこのポッドキャストの雰囲気が好きで,時々意味も分からないのに かけっ放しにしている今日この頃です。

Julia Advent Calendar(Qiita)

今年もQiitaのAdvent Calendarが開催され, Julia言語のカレンダーもあります。 QiitaのユーザーかつJulia言語ユーザーの方は投稿されてはいかがでしょうか?

私はQiitaユーザーではないですしネタもないので,誰かが投稿をするのを確認するのを楽しみにしています。

Julia in Physics 2024

ネットの情報で知ったのですが,2024年12月14日(土) 13:00 - 19:00 に Julia in Physics 2024が開催されるようです。

個人的にはあまり物理学に詳しくないので参加予定はないですが,オンラインでの参加も可能とのことなので, 興味のある方は参加を検討してはいかがでしょうか。

IDE: alternatives to VS Code?

IDE: alternatives to VS Code?の記事なんですが, 質問者曰く

  • 元々R使っててR StudioみたいなのがいいんだけどVS Code使ってみたら今一つ
  • Emacsvimはノーサンキュー
  • 何かVS Code以外のIDEはない?

ということのようです。回答としては

  • Zedがいいんじゃね?
  • まだJulia言語に対応してないけどPositronが将来的に対応するかも

などなど。

個人的にはそんなにRStudioがいいんだったらRStudioでJulia使えばいいじゃんとか思ってしまいました。

私はEmacs使って20年以上だからなぁ…今更他のを使うのは難しいという感じがします。

EmacsでJuliaを使うのにはjulia-mode + eglot-jl + julia-replという 比較的保守的な環境で利用しています。

他にもjulia-snailとかもあるのですが,julia-replだとcygwinを使って かろうじてwindowsでも動くjuliaのrepl機能が使えないので私はスルーという感じです。

その他

Julia Discouseでは今でもv1.11では~という投稿が多いような感じです。 意外と私はv1.11特有の不具合には出会ったことがないのですが,家であまりJuliaのコードを書かないというだけかもしれません。

さいごに

仕事で大量のデータを分析する必要があって,並列処理について少し調べて使ってみて かなりの恩恵がありました。

この日記でも仕事関係で調べたことを紹介する機会があるかもしれませんし,時間がないので何もしないかもしれません。

個人的には最近久しぶりに漢直の方に興味が移っているということもありますが, そこでもJulia言語を活用できそうな気がしています。

Julia言語のスレッド機能のうち簡単に使えそうなものを使ってみる

はじめに

急に仕事が忙しくなり始め,業務で取り扱うデータ量が大きくなってきました。

今まではあまり実行時間を気にしなかったのですが,あまり手を入れずに処理を短時間で終わらせたいと考えました。

そこで,今まであまり調べてなかったJulia言語の並列処理化に手をつけてみました。ここでは,あまり頭を使わずに実現できる方法をピックアップしてみました。

並列処理化

参考にしたのはスレッド並列の基礎や, 二冊の鈍器1等です。

並列処理化には

  • プロセスによる並列化
  • スレッドによる並列化

の二種類があるのですが,今回はわりと手軽に感じたスレッドによる並列化を試してみます。

スレッドによる並列化を利用する時には,Juliaの環境を実行する前に準備が必要です。

一つは,julia言語を起動する時に julia -t 4 のように引数で最大スレッド数を指定する方法,もう一つはjuliaを起動する前に環境変数JULIA_NUM_THREADSに 最大スレッド数を指定する方法です。

プロセス並列化の場合はjuliaを起動した後にプロセス数の変更が可能ですが,スレッド並列化の場合は起動前に指定する必要があります。

なお,デフォルトではスレッド数は1となっていて, Threads.nthreads()で現在の環境のスレッド数を確認することができます。

並列化に適した処理

並列化に適した処理は 「それぞれ別のファイルのデータにフィルタをかけて,別々のファイル保存する」とかのように,それぞれの処理に依存関係がなく独立しているものです。

  • グローバル変数を利用しない
  • 入力データは関数の引数で入力する
  • 入力データ(入力引数)を不用意に書き換えない
  • 出力先のファイルをそれぞれの処理で共有しない

等気をつければ,それほど難しくはないでしょうか? よく分かりません。

for文による並列化

例えば,次のような処理を行う時間がかかる処理があったとします。

  1. データファイル読み込み
  2. データを演算
  3. 演算したデータを保存

ここでは仮に次のようなサンプルを用意します。

function myfile_task(filename::AbstractString, outdir::AbstractString)
    read_dummy(x) = (sleep(2); x)
    calc_dummy(_) = (sleep(2); rand())
    save_dummy(_, _) = (sleep(2); nothing)

    dummy_data = read_dummy(filename)     # データ読み込み(なんちゃって)
    dummy_calced = calc_dummy(dummy_data) # データ演算(なんちゃって)
    save_dummy(dummy_calced, outdir)      # データ保存(なんちゃって)
end
julia> filenames = "myfile" .* string.(collect(1:10))
10-element Vector{String}:
 "myfile1"
 "myfile2"
 "myfile3"
 "myfile4"
 "myfile5"
 "myfile6"
 "myfile7"
 "myfile8"
 "myfile9"
 "myfile10"

julia> outdir = "./hogehoge"
"./hogehoge"

julia> @time for k in 1:10
       myfile_task(filenames[k], outdir)
       end
 60.109670 seconds (23.23 k allocations: 1.143 MiB, 0.03% compilation time)

上の例だと60秒かかります。 ここで,スレッド数を7の環境で次のように実行します。

julia> Threads.nthreads()
7

julia> @time Threads.@threads for k in 1:10
       myfile_task(filenames[k], outdir)
       end
 12.067657 seconds (59.38 k allocations: 2.953 MiB, 1.19% compilation time)

約1/5の実行時間になりました。

map関数の並列化

スレッド並列化の基礎のスライドの中に,map関数のマルチスレッド化というものがあります。

次のような実装です。

function threaded_map(fn, array::AbstractArray)
    tasks = [Threads.@spawn(fn(v)) for v in array]
    [fetch(task) for task in tasks]
end

この関数を試してみます。 時間がかかる処理を次のようにしました。

function mytask(k)
    sleep(2) # 時間がかかる処理のつもり
    k * k
end

通常のmap関数と実行時間を比較したものを次に示します。 処理時間が短くなっていることが分かります。

julia> @time hoge = map(mytask, 1:10)
 20.030014 seconds (43 allocations: 1.516 KiB)
10-element Vector{Int64}:
   1
   4
   9
  16
  25
  36
  49
  64
  81
 100

julia> @time hoge = threaded_map(mytask, 1:10)
  2.027161 seconds (26.51 k allocations: 1.315 MiB, 2.86% compilation time)
10-element Vector{Int64}:
   1
   4
   9
  16
  25
  36
  49
  64
  81
 100

filter関数の並列化

上の例を応用して,filter関数で実装してみます。

function threaded_filter(fn, ar::AbstractArray)
    tasks = [Threads.@spawn(fn(v)) for v in ar]
    [a for (task, a) in zip(tasks, ar) if fetch(task)]
end

この関数を試してみます。処理がかかる関数のつもりは次のような感じ。

function myfilter(k)
    sleep(2) # 時間がかかる処理のつもり
    isodd(k)
end
julia> @time hoge = filter(myfilter, 1:10)
 20.030471 seconds (44 allocations: 1.328 KiB)
5-element Vector{Int64}:
 1
 3
 5
 7
 9

julia> @time hoge = threaded_filter(myfilter, 1:10)
  2.008133 seconds (1.56 k allocations: 76.562 KiB, 1.71% compilation time)
5-element Vector{Int64}:
 1
 3
 5
 7
 9

処理時間が短くなっていることが分かります。

まとめ

ここでは,マルチスレッド処理のうち簡単に使えるもののみ紹介しました。 それぞれの依存関係がある処理はマルチスレッド化するのは難しいのですが, それぞれ独立性が高い処理は比較的簡単にマルチスレッド化できるようです。

自分がやっている業務では,上記のように比較的簡単にマルチスレッド化できる処理が多く, もう少し早く真剣に検討すれば良かったと思う今日この頃です。

ただ,メモリの使用量がかなり大きくなるので,たくさんメモリを積んだ環境が必要となるのは言わずもがなです。

How to access mingw64 files pluto notebook?[勝手に回答]

どうでもいい誰も答えなそうな質問を独断で曲解して回答していくこのシリーズ,今回は How to access mingw64 files in pluto notebook?Julia Discourseからの質問です。

I want to read files with mingw64 in pluto notebooks とかも同じ質問者でほぼ同じ質問ですね。

とりあえず自分もWindows上でPlutoをインストールしてやってみます。 私の場合は、

  • mingw64ではなくmsys2ucrt64でお試し
  • fortranではなくgccでお試し

です。

最初のセルは次の通りに入力します。

ENV["PATH"] = "F:\\msys64\\ucrt64\\bin;" * ENV["PATH"]

次のセルに

println(read(`gcc --help`, String))

画面は次のような感じ。

gccはうまくアクセスできているような気がします。 ポイントはmingwとかの環境の場合,binフォルダにあるdllとリンクしていることが多いので, 該当するbinフォルダを環境変数PATHの先頭に追加するとトラブルが少ないです。

次のセルではHello Worldのソースファイルを作成してビルドして実行させ,その出力を文字列として取得します。 Plutoの場合,一セルに複数文を書くと警告が出たりするので,begin~endで囲って一文にします。

hello_string = begin
    cd("F:\\msys64\\home\\ujimushi")
    open("F:\\msys64\\home\\ujimushi\\hello.c", "w") do io
        println(io,
            """
          #include <stdio.h>

          int main() {
              printf("Hello World!!");
              return 0;
          }
          """)
    end
    run(`gcc -o my_hello hello.c`)
    sleep(1)
    read(`.\\my_hello.exe`, String)
end

実行結果のセルは次のような感じ。

何となくアクセスできているような気がします。

cd("mydir")とかでカレントディレクトのが変更できたりもしますし, 実行環境側のフォルダ構造が把握できていれば,特に問題なくアクセスできるような感じです。

ということはPlutoの実行環境をローカルのPCではなく他のPCからアクセスできるようにすると,セキュリティリスクが高そうという感じもしますね。

四国で2024年11月9日 20時過ぎに広域停電発生というニュースに対する妄想

私の実家が四国にあるので,少し興味探くニュースを見ている。

まだ何の情報もないまま,独段と偏見で原因を予想してみる。

これぐらいの広域でまばらに停電しているのは 一つは過負荷リレーが動作した可能性が考えられる。

これは,東日本大震災で発生した,原子力発電所のような容量が大きな 電源が一斉に解列(電力系統から切り離されること)し, 電力の需要の方が大きくなって周波数が低下したため, あるルールに従って停電を発生させて電力を使っている全体量を減らし, 発電と消費の需給バランスを取るものである。

もし,過負荷リレーが動作していたとすると,この時に 停電した地域は相当的に重要度が低いとみなされた地域と推定される。 ご愁傷様である。

では,何がきっかけで過負過リレーが動いたか?

  • 不意の発電所の停止・解列
  • 瀬戸大橋を通る送電線が片回線停止 ぐらいかな?

もう一つは,どこかの電気事故がきっかけで電圧低下が発生した時, 四国の電力系統の端や送電線の細いところの電圧も一緒に下がり, 電圧を維持するために,停電を発生させたか?

香川県は瀬戸大橋で本州側とつながっているから,電圧低下が発生しても 比較的影響が少ない。しかし,高知の西側とかは愛媛県経由の66kV送電線 でしか連系してないからこの辺りは系統が弱く, 後でゆっくり停電範囲を確認した時にその辺りや,根元(愛媛県側)で たくさん停地発生が確認されるようなら, 系統安定度(定態? 過渡?)とかも確認した方がいいかもしれない。

と,以上のように知ったかぶりで発言してみるテスト。本当は全然分かってないんだけどね。