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

【数学】【PYTHON】垂直二等分線を求める

これまでやってきたことを使って、二つの点の線分の中間を垂直に交わる直線を求めます。

例として、(0,1)と(6,5)を結ぶ線分の垂直二等分線を求めてみます。

やり方は、

①線分の傾きを求める

②線分の中点を求める

③線分と直交する直線の傾きを求める

④二つの線の切片を求める

で求めることができるみたいです。

import matplotlib.pyplot as plt
import numpy as np

#元の直線の傾きと切片
a1 = (5-1)/(6-0)
b1 = 1

#線分の中点
cx = (0 + 6) / 2
cy = (1 + 5) / 2

#線分に直交する直線の傾き
a2 = -1 / a1

#線分に直交する直線の切片
b2 = cy - a2 * cx

#直線の式
x = np.arange(0, 7)
y1 = a1*x + b1
y2 = a2*x + b2

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

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

マンデルブロ集合の処理を実装していきます。

まぁ、この処理は難解なので、ここはテキストを写経していきます。

目標はテストコードをパスするところまで。

fn get_n_driverged(x0: f64, y0: f64, max_iter: usize) -> u8 {
    let mut xn = 0.0;
    let mut yn = 0.0;
    for i in 1..max_iter {
        let x_next = xn * xn - yn * yn + x0;
        let y_next = 2.0 * xn * yn + y0;
        xn = x_next;
        yn = y_next;
        if yn * yn + xn * xn > 4.0 {
            return i as u8;
        }
    }
    max_iter as u8
}

pub fn generate_mandalbrot_set(
    canvas_w: usize,
    canvas_h: usize,
    x_min: f64,
    x_max: f64,
    y_min: f64,
    y_max: f64,
    max_iter: usize,
) -> Vec<u8> {
    let canvas_w_f64 = canvas_w as f64;
    let canvas_h_f64 = canvas_h as f64;
    let mut data = vec![];
    for i in 0..canvas_h {
        let i_f64 = i as f64;
        let y = y_min + (y_max - y_min) * i_f64 / canvas_h_f64;
        for j in 0..canvas_w {
            let x = x_min + (x_max - x_min) * j as f64 / canvas_w_f64;
            let iter_index = get_n_driverged(x, y, max_iter);
            let v = iter_index % 8 * 32;
            data.push(v);
            data.push(v);
            data.push(v);
            data.push(255);
        }
    }
    data
}

#[cfg(test)]
mod tests {
    use super::*;
    #[test]
    fn test_get_n_diverged() {
        let max_iter = 10;
        assert_eq!(get_n_driverged(1.0, 0.0, max_iter), 3);
        assert_eq!(get_n_driverged(0.0, 0.0, max_iter), max_iter as u8);
        assert_eq!(get_n_driverged(0.0, 1.0, max_iter), max_iter as u8);
    }
    #[test]
    fn test_generate_mandelbrot_set() {
        let canvas_w = 2;
        let canvas_h = 2;
        let x_min = -1.0;
        let x_max = 1.0;
        let y_min = -1.0;
        let y_max = 1.0;
        let max_iter = 8;
        assert_eq!(
            generate_mandalbrot_set(canvas_w, canvas_h, x_min, x_max, y_min, y_max, max_iter),
            vec![96, 96, 96, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255]
        );
    }
}
:~/rust/mandelbrot$ cargo test
   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: function `get_n_driverged` is never used
 --> src/logic.rs:1:4
  |
1 | fn get_n_driverged(x0: f64, y0: f64, max_iter: usize) -> u8 {
  |    ^^^^^^^^^^^^^^^

warning: function `generate_mandalbrot_set` is never used
  --> src/logic.rs:16:8
   |
16 | pub fn generate_mandalbrot_set(
   |        ^^^^^^^^^^^^^^^^^^^^^^^

warning: `mandelbrot` (lib) generated 3 warnings
warning: `mandelbrot` (lib test) generated 1 warning (1 duplicate)
    Finished test [unoptimized + debuginfo] target(s) in 0.46s
     Running unittests src/lib.rs (target/debug/deps/mandelbrot-c2f466aeb790a116)

running 2 tests
test logic::tests::test_generate_mandelbrot_set ... ok
test logic::tests::test_get_n_diverged ... ok

test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

     Running tests/web.rs (target/debug/deps/web-ca9c3937d615c7ed)

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

   Doc-tests mandelbrot

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

【数学】【PYTHON】二つの直線の交点を求める

二つの直線の交点を求めるには、

二つの直線の連立方程式を解けば求めることができます。

連立方程式はこちらでやってますね。

例えば、y = -3/2x + 6とy= 1/2x + 2の交点を求めてみました。

from sympy import Symbol, solve

x = Symbol('x')
y = Symbol('y')
ex1 = -3/2*x + 6 - y
ex2 = 1/2*x + 2 - y

print(solve((ex1, ex2)))
:~/python$ python3 simultaneous_equations.py 
{x: 2.00000000000000, y: 3.00000000000000}

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の約数を求めていき、約数だった場合、その値と商も約数として出力します。