「技術」カテゴリーアーカイブ

RUST勉強中、9/11の積み上げ?

前回はcargo install cargo-generateまで実行したので、その続きです。

taki@DESKTOP-4VF3GEO:~/rust$ cargo generate --git https://github/rustwasm/wasm-pack-template
Error: Please check if the Git user / repository exists.

Caused by:
    failed to resolve address for github: Name or service not known; class=Net (12)
taki@DESKTOP-4VF3GEO:~/rust$ cargo generate --git https://github.com/rustwasm/wasm-pack-template
🤷   Project Name : mandelbrot
🔧   Destination: /home/taki/rust/mandelbrot ...
🔧   Generating template ...
[ 1/12]   Done: .appveyor.yml
[ 2/12]   Done: .gitignore
[ 3/12]   Done: .travis.yml
[ 4/12]   Done: Cargo.toml
[ 5/12]   Done: LICENSE_APACHE
[ 6/12]   Done: LICENSE_MIT
[ 7/12]   Done: README.md
[ 8/12]   Done: src/lib.rs
[ 9/12]   Done: src/utils.rs
[10/12]   Done: src
[11/12]   Done: tests/web.rs
[12/12]   Done: tests
🔧   Moving generated files into: `/home/taki/rust/mandelbrot`...
💡   Initializing a fresh Git repository
✨   Done! New project created /home/taki/rust/mandelbrot
taki@DESKTOP-4VF3GEO:~/rust$ tree mandelbrot/
mandelbrot/
├── Cargo.toml
├── LICENSE_APACHE
├── LICENSE_MIT
├── README.md
├── src
│   ├── lib.rs
│   └── utils.rs
└── tests
    └── web.rs

2 directories, 7 files
taki@DESKTOP-4VF3GEO:~/rust$ curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh
sh: 139: [: x86_64: unexpected operator
info: downloading wasm-pack
info: successfully installed wasm-pack to `/home/taki/.cargo/bin/wasm-pack`
taki@DESKTOP-4VF3GEO:~/rust$ cd mandelbrot/
taki@DESKTOP-4VF3GEO:~/rust/mandelbrot$ wasm-pack build
[INFO]: Checking for the Wasm target...
info: downloading component 'rust-std' for 'wasm32-unknown-unknown'
info: installing component 'rust-std' for 'wasm32-unknown-unknown'
[INFO]: Compiling to Wasm...
   Compiling proc-macro2 v1.0.43
   Compiling quote v1.0.21
   Compiling unicode-ident v1.0.3
   Compiling wasm-bindgen-shared v0.2.82
   Compiling log v0.4.17
   Compiling syn v1.0.99
   Compiling cfg-if v1.0.0
   Compiling once_cell v1.14.0
   Compiling bumpalo v3.11.0
   Compiling wasm-bindgen v0.2.82
   Compiling wasm-bindgen-backend v0.2.82
   Compiling wasm-bindgen-macro-support v0.2.82
   Compiling wasm-bindgen-macro v0.2.82
   Compiling console_error_panic_hook v0.1.7
   Compiling mandelbrot v0.1.0 (/home/taki/rust/mandelbrot)
warning: function `set_panic_hook` is never used
 --> src/utils.rs:1:8
  |
1 | pub fn set_panic_hook() {
  |        ^^^^^^^^^^^^^^
  |
  = note: `#[warn(dead_code)]` on by default

warning: `mandelbrot` (lib) generated 1 warning
    Finished release [optimized] target(s) in 4.32s
[INFO]: Installing wasm-bindgen...
[INFO]: Optimizing wasm binaries with `wasm-opt`...
[INFO]: Optional fields missing from Cargo.toml: 'description', 'repository', and 'license'. These are not necessary, but recommended
[INFO]: :-) Done in 10.50s
[INFO]: :-) Your wasm pkg is ready to publish at /home/taki/rust/mandelbrot/pkg.
taki@DESKTOP-4VF3GEO:~/rust/mandelbrot$ npm init wasm-app www
npx: installed 1 in 2.333s
🦀 Rust + 🕸 Wasm = ❤
taki@DESKTOP-4VF3GEO:~/rust/mandelbrot$ cd www
taki@DESKTOP-4VF3GEO:~/rust/mandelbrot/www$ npm install
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@1.2.9 (node_modules/fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@1.2.9: wanted {"os":"darwin","arch":"any"} (current: {"os":"linux","arch":"x64"})

added 587 packages from 362 contributors and audited 655 packages in 5.343s

18 packages are looking for funding
  run `npm fund` for details

found 100 vulnerabilities (3 low, 30 moderate, 53 high, 14 critical)
  run `npm audit fix` to fix them, or `npm audit` for details
taki@DESKTOP-4VF3GEO:~/rust/mandelbrot/www$ npm run start

> create-wasm-app@0.1.0 start /home/taki/rust/mandelbrot/www
> webpack-dev-server

ℹ 「wds」: Project is running at http://localhost:8080/
ℹ 「wds」: webpack output is served from /
ℹ 「wds」: Content not from webpack is served from /home/taki/rust/mandelbrot/www
ℹ 「wdm」: Hash: c3b265e5d69900dfbb35
Version: webpack 4.43.0
Time: 268ms
Built at: 09/11/2022 8:48:14 AM
                           Asset       Size  Chunks                         Chunk Names
                  0.bootstrap.js    3.4 KiB       0  [emitted]
8e8fa9289c240ac706a1.module.wasm  872 bytes       0  [emitted] [immutable]
                    bootstrap.js    369 KiB    main  [emitted]              main
                      index.html  297 bytes          [emitted]
Entrypoint main = bootstrap.js
[0] multi (webpack)-dev-server/client?http://localhost:8080 ./bootstrap.js 40 bytes {main} [built]
[./bootstrap.js] 279 bytes {main} [built]
[./index.js] 56 bytes {0} [built]
[./node_modules/ansi-html/index.js] 4.16 KiB {main} [built]
[./node_modules/ansi-regex/index.js] 135 bytes {main} [built]
[./node_modules/hello-wasm-pack/hello_wasm_pack.js] 698 bytes {0} [built]
[./node_modules/strip-ansi/index.js] 161 bytes {main} [built]
[./node_modules/webpack-dev-server/client/index.js?http://localhost:8080] (webpack)-dev-server/client?http://localhost:8080 4.29 KiB {main} [built]
[./node_modules/webpack-dev-server/client/overlay.js] (webpack)-dev-server/client/overlay.js 3.51 KiB {main} [built]
[./node_modules/webpack-dev-server/client/socket.js] (webpack)-dev-server/client/socket.js 1.53 KiB {main} [built]
[./node_modules/webpack-dev-server/client/utils/createSocketUrl.js] (webpack)-dev-server/client/utils/createSocketUrl.js 2.91 KiB {main} [built]
[./node_modules/webpack-dev-server/client/utils/log.js] (webpack)-dev-server/client/utils/log.js 964 bytes {main} [built]
[./node_modules/webpack-dev-server/client/utils/reloadApp.js] (webpack)-dev-server/client/utils/reloadApp.js 1.59 KiB {main} [built]
[./node_modules/webpack-dev-server/client/utils/sendMessage.js] (webpack)-dev-server/client/utils/sendMessage.js 402 bytes {main} [built]
[./node_modules/webpack/hot sync ^\.\/log$] (webpack)/hot sync nonrecursive ^\.\/log$ 170 bytes {main} [built]
    + 21 hidden modules
ℹ 「wdm」: Compiled successfully.

問題無く完了しました。

【C#】【アルゴリズム】最大公約数を求める(ユークリッドの互除法)

二つの値の最大公約数を求めるアルゴリズムです。

まともに計算すると時間が掛かるので、ユークリッドの互除法というアルゴリズムを使用します。

        /**
         * AとBの最大公約数を求める(ユークリッドの互除法)
         * 
         * @param A 最大公約数を求める対象の値A
         * @param B 最大公約数を求める対象の値B
         * @return AとBの最大公約数
         */
        public long GreatestCommonDivisor(long A, long B)
        {
            while(A >= 1 && B >= 1)
            {
                if(A < B)
                {
                    B = B % A;
                }
                else
                {
                    A = A % B;
                }
            }
            if(A >= 1)
            {
                return A;
            }
            return B;
        }

ポイントは、

・大きい方の数を「大きい方を小さい方で割った余り」に書き換える処理を繰り返す

・片方が0になったら操作を終了する。もう片方の数が最大公約数

というところ。

【数学】【PYTHON】直線と直交する直線を求める

y=a1x+bとy=a2x+b2の直線があった場合、a1 = a2であれば、平行。

a1 × a2 = -1であれば直交するとのこと。

それを確認するためのグラフ作成です。

この例では、y=1/2x+1/2と直交する直線は、y=-2x+7なので、それを描画します。

from ast import increment_lineno
import matplotlib.pyplot as plt
import numpy as np

def function_y(x):
    return 1 / 2 * x + 1 / 2

def function_y2(x):
    return -2 * x + 7

x = np.arange(-1, 6)
y = function_y(x)
y2 = function_y2(x)

plt.plot(x, y)
plt.plot(x, y2)
plt.axis('equal')
plt.grid(color='0.8')
plt.show()

RUST勉強中、8/28の積み上げ?

今回はDockerで前回までのTodoアプリを動作させます。

ということで、Dockerfileの作成。

FROM rust:1.63

WORKDIR /todo

COPY Cargo.toml Cargo.toml
COPY ./src ./src
COPY ./templates ./templates

RUN cargo build --release

RUN cargo install --path .

CMD ["todo"]

これを作成したら、

> docker build -t todo-app .

実はこのビルドに一番時間がかかっていたりする。

まず、Dockerのインストールから始める。

WSL環境なのですが、それでもDockerのサイトからインストーラーを起動してインストールする必要あり。

でも、ビルドにエラーが出てきて、

いろいろ試してみた結果、rustのバージョンを新しくしたら通った、という結果でした。

そして、ビルドが通ったら

> docker run -p 8080:8080 todo-app

で起動します。

今回、(いままで避けてきた)Dockerをやってみたけど、

意外と簡単だなぁ。

【Stable Diffusion】AIに画像を描かせてみた話

ツイッターで公開したこれらの画像。

https://twitter.com/n2_taki/status/1562711879012986882?s=20&t=9Th-qjdEZxvQqltKmGYaXQ
https://twitter.com/n2_taki/status/1562805935919493122?s=20&t=9Th-qjdEZxvQqltKmGYaXQ

これらはオープンソース化されたStable Diffusionで描いて貰いました。

こちらの記事を参考にしました。

https://zenn.dev/koyoarai_/articles/02f3ed864c6127bb2049

環境構築はこちら。

上のページ内のリンクからでも行けます。

https://zenn.dev/opamp/articles/c5e200c6b75912

気をつける点は、anacondaでPyTorchの設定を行うときは、

anacondaフォルダ内のスタートプログラムからコマンドプロンプトを起動させないと、上手く設定できない。

おそらく、Pythonのバージョンの関係かと。

あとは、ldmをアクティベートした状態でイカのコマンドを入力します。

> python optimizedSD/optimized_txt2img.py --prompt "ここにどんな画像を書いてほしいかをAIに指示(英語)" --H 512 --W 512 --seed 2 --n_iter 2 --n_samples 10 --ddim_steps 50

自分の環境では、VRAM8GBありましたが、画像サイズとか、出力枚数を大きくするとVRAMが枯渇するかもです。

VRAMが足りなくなると、プログラムが失敗するので、設定を見直しましょう。

AIで生成した画像の中には失敗作もあります。

むしろ、どんな失敗してくれるのか、を見るのが楽しみ。

もうしばらく、AI画像作成にはまりそうです。

【C#】【アルゴリズム】約数を列挙する

値Nが持つ約数を列挙するアルゴリズムです。

        /**
         * 引数Nの約数をリストで返す
         * 
         * @param N 約数を求める値
         * @return Nの約数のリスト
         */
        public List<long> CalculateIsprimeList(long N)
        {
            List<long> list = new List<long>();
            for (long i = 2; i * i <= N; i++)
            {
                if (N % i != 0)
                {
                    continue;
                }
                list.Add(i);
                if(i != N / i)
                {
                    list.Add(N / i);
                }
            }

            list.Sort();
            return list;
        }

前回の素数判定のコードと似ています。

小さい値から、Nの約数を求めていき、約数だった場合、その値と商も約数として出力します。

【数学】【PYTHON】連立方程式を解く

2点を通る直線のグラフを書く、の前に、連立方程式を解くコードを書いてみます。

from sympy import Symbol, solve

a = Symbol('a')
b = Symbol('b')
ex1 = a + b - 1
ex2 = 5 * a + b - 3

print(solve((ex1, ex2)))
:~/python$ python3 simultaneous_equations.py 
{a: 1/2, b: 1/2}

上のコードは1=a + b、3 = 5a + bの解を求めるコードです。

文字a,bをSymbolとして定義することによって、

ex1,ex2に式を設定し、それをsolve()にタプル式として渡します。

そうすると、解が出力されます。

Pythonすげぇ。

RUST勉強中、8/21の積み上げ

前回の続き

データベースに追加する処理と削除する処理を作成していきます。

まず、フォームのデータを取得するのにserdeクレートを使用します。

[package]
name = "todo"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
actix-web = { version = "4.1" }
actix-rt = { version = "2.7" }
thiserror = { version = "1.0" }
askama = { version = "0.11" }
rusqlite = { version = "0.28", features=["bundled"] }
r2d2 = { version = "0.8" }
r2d2_sqlite = { version = "0.21" }
serde = { version = "1.0", feature = ["derive"] }

次に追加、削除のパスを作成していきます。

まずは追加処理。

#[post("/add")]
async fn add_todo (
    params: web::Form<AddParams>,
    db: web::Data<r2d2::Pool<SqliteConnectionManager>>,
) -> Result<HttpResponse, MyError> {
    let conn = db.get()?;
    conn.execute("INSERT INTO todo (text) VALUES (?)", &[&params.text])?;
    Ok(HttpResponse::SeeOther()
        .header(header::LOCATION, "/")
        .finish())
}

同じように削除処理。

#[post("/delete")]
async fn delete_todo(
    params: web::Form<DeleteParams>,
    db: web::Data<r2d2::Pool<SqliteConnectionManager>>,
) -> Result<HttpResponse, MyError> {
    let conn = db.get()?;
    conn.execute("DELETE FROM todo WHERE id=?", &[&params.id])?;
    Ok(HttpResponse::SeeOther()
        .header(header::LOCATION, "/")
        .finish())
}

そして、追加・削除のパスをサーバに登録。

#[actix_rt::main]
async fn main() -> Result<(), actix_web::Error> {
    let manager = SqliteConnectionManager::file("todo.db");
    let pool = Pool::new(manager).expect("Failed to inithialize the connection pool.");
    let conn = pool.get().expect("Failed to get the connection from the pool.");
    conn.execute(
        "CREATE TABLE IF NOT EXISTS todo (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            text TEXT NOT NULL
        )",
        params![],
    )
    .expect("Failed to create a table 'todo'.");
    HttpServer::new(move || {
        App::new()
        .service(index)
        .service(add_todo)
        .service(delete_todo)
        .data(pool.clone())
        })
        .bind("0.0.0.0:8080")?
        .run()
        .await?;
    Ok(())
}

ソースコードにおけるコメントについて。

プログラマーを悩ませる問題の一つとして、コメントがあると思います。

基本的にコメントには正しいことを書かなければいけないのですが

修正を加えられることによって、コメントと内容が異なってしまうことが多々ありまして

コメントと実装が異なると、のちにコードをメンテナンスするプログラマーは混乱します。

で、コメントはどれくらいの頻度であるべきか?ですが、

これはプロジェクトにもよりまして、

1行1コメントとルールが定められているプロジェクトもあれば、

コメントを残してはいけないというプロジェクトもあります。

まぁ、これは両極端の例ですが。

傾向としては、C言語はコメントを残せというケースが多いように思います。

C言語は関数名、変数名を長くするのは好ましくないという印象があります(偏見

だから意味を極端に省略していった結果、コメントがないとコードが理解できない、という結果になります。

逆にJavaなどのオブジェクト指向言語は比較的コメントが少ないように思います。

こちらは関数名、引数名だけで意味が伝わるように命名しなければならない、という傾向が強いので、

コメントがなくても、関数名、変数名である程度意味が伝わったりします。

そこを突き詰めていった結果、コメントが必要なコードが好ましくない、という考えに行き着いたんでしょうね。

コメントといえば。

昔のプロジェクトはSVNやgitなどのソースコードのバージョン管理の仕組みがなかったので、

ソースコードに修正履歴を残しなさい、というルールが存在していました。

昔のエディターはコメントを色付きで表示する機能も無かったので、

一生懸命解析していたところがコメント化した変更前のコードだった、

ということがよくありました。

現在はこういった修正前のコードは残すのは逆に好ましくないとされています。

そう言うのはgitなどで管理してくれるので。

便利な世の中になったもんだ。