裏 RjpWiki

Julia ときどき R, Python によるコンピュータプログラム,コンピュータ・サイエンス,統計学

groupby で,自作の関数を適用する(Python)

2020年12月27日 | Python

df2 = df.groupby(群)

df2.agg(自作関数の名前)

コメント
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

素数列挙プログラムのスピードアップ

2020年12月27日 | ブログラミング

以下のようなプログラムがあった。

このプログラムだと,10**8 以下の素数を探索するのに 18 日くらいかかる。

import time

primes_list = []
upper_lim   = 10**3
start_time  = time.time()

for integer in range(2, upper_lim + 1, 1):
    if len(primes_list) < 1 :
        primes_list.append(integer)
    else:
        is_divisible = False
        for prime in primes_list:
            if integer % prime == 0:
                is_divisible = True
                break
        if not is_divisible:
            primes_list.append(integer)

#print(primes_list)
print(len(primes_list), "prime numbers foud.")

elapsed_time = time.time() - start_time # 経過時間 = 現在時刻 - 開始時刻
print ("run time: {0}".format(elapsed_time) + " seconds")

偶数の素数は 2 だけ。それ以外は奇数。range(2, upper_lim + 1, 1) でぶん回すのは少なくとも2倍の時間が掛かる。

for ループの中に len(primes_list) < 1 を毎回判定する if ブロックは無駄。

is_divisible という変数を使っているが,後で not is_divisible として使っているのなら,is_prime という変数を作ったほうがわかりやすい。

ある数が,primes_list の中にある素数で割りきれるか primes_list の全体を走査しているが,その数の平方根以下の要素まで調べればよい。そこまでで割り切れなければ素数。

Python の癖であるが,関数にしたほうが速い。

++++++++++

他の人からアドバイスがあって,書き直されたプログラムが3とおりあった。

関数化したこと
2 を特別に扱い,range(3, upper_limit + 1, 2) で探索すること。
all(integer % prime != 0 for prime in primes_list) を使うこと。
しかし,これはあまりよい提案ではないことがわかる。
素数かどうかの走査を早めに終えるためにはこの方法はよくない。

def primes_up_to_(upper_limit):
    if upper_limit < 2:
        return []
    primes_list = [2]
    for integer in range(3, upper_limit + 1, 2):
        if all(integer % prime != 0 for prime in primes_list):
            primes_list.append(integer)
    return primes_list

++++++++++

もう一つのバージョン

for integer in range(2, upper_lim + 1, 1):
    if len(primes_list) < 1 :
        primes_list.append(integer)
    else:
        is_divisible = False
        for prime in primes_list:
            # if prime >= math.sqrt(integer): # このやり方は実によい!!
            if prime > math.sqrt(integer): # 但し,> でないと間違い
                break
            elif integer % prime == 0:
                is_divisible = True
                break
        if not is_divisible:
            primes_list.append(integer)

++++++++++

もう一つのバージョンだが,何をやっているか理解しておらず,処理の重複のため長時間かかることになってしまった。

追加したものは if all() と重複する余分なもの。百害あって一利なし。それに,前のバージョンの prime > math.sqrt(integer) がなくなってしまった。

def primes_up_to_3(upper_limit): # 関数化
    if upper_limit < 2:
        return []
    primes_list = [2]
    for integer in range(3, upper_limit + 1, 2):
        temp_primes_list = []                                       # 追加
        for prime in primes_list:                                   # 追加
            if prime <= math.sqrt(integer):                         # 追加
                temp_primes_list.append(prime)                      # 追加
        if all(integer % prime != 0 for prime in temp_primes_list):
            primes_list.append(integer)
    return primes_list

++++++++++

私が考えていたバージョン。

def gen_primes2(upper_lim = 10000):
    primes_list = [2]
    for integer in range(3, upper_lim + 1, 2):
        is_prime = True
        upper_lim_sqrt = int(integer**0.5)
        for prime in primes_list:
            if prime > upper_lim_sqrt: # 時短にかなり有効
                break
            elif integer % prime == 0:
                is_prime = False
                break
        if is_prime:
            primes_list.append(integer)
    return primes_list

これだと,最初のバージョンでは 10**8 までの検索に 18 日かかっていたであろうものが,10 分で終わる。

++++++++++

しかし,以下の Julia で書いたプログラムだと,さらにその 10 倍速い。

function gen_primes2(upper_lim = 10000)
    primes_list = [2]
    for integer = 3:2:upper_lim
        upper_lim_sqrt = ceil(sqrt(integer))
        is_prime = true
        for prime in primes_list
            if prime >  upper_lim_sqrt
                break
            elseif integer % prime == 0
                is_prime = false
                break
            end
        end
        if is_prime
            append!(primes_list, integer)
        end
    end
    println("$(length(primes_list)) prime numbers foud.")
    # println(primes_list)
end

@time gen_primes2(10^8)
# $ julia gen_primes2.jl
# 5761455 prime numbers foud.
# 54.732656 seconds (35 allocations: 65.001 MiB, 0.00% gc time)

10**8 までの検索が 1分で終わる。

つまり,元のプログラムの2万6千倍速いのだ。

コメント
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

Julia のプログラムを書いてみよう -- 1

2020年12月27日 | ブログラミング

The Julia Language を読み進めているが,1300ページもあるので,モチベーションを維持するために,実際にプログラムも書いてみなくては。

julia> #=
       他の言語と違うところに注目してまとめてみよう。
       複数行の注釈は #= ... =#
       形式としては Java などの /* ... */
       =#

julia> println("我が輩は猫である。\n名前は", "まだない。")
我が輩は猫である。
名前はまだない。

文字列はダブルクオート '"' でなければならない。シングルクオート "'" だとエラーになる。
出力後改行するには print() ではなく println() を使う。これも Java などと同じ。print() で行末に '\n' を付けてもいいけど。
Python の print() とは違い,出力項目の間に自動的に空白は入らない。

julia> print('A', '1', 'π', '\n')
A1π

シングルクオートでくくるのは文字である。'\n' も改行を表す 1 文字。
'π' などのギリシア文字,特殊文字は '\pi[tab]' で入力できる( [tab]はタブキーを押す)。

julia> println("2^5 = $(2^5)")
2^5 = 32

羃乗は '^'。Python が '**' なのは,ちょっと異端なのだ。
"2^5 = $(2^5)" は 文字列中に式の結果を展開する記法。Python の print(f"2^5 = {2^5}") に相当する。 

julia> println("整数除算: div(21, 4) = $(div(21, 4)) または 21 ÷ 4 = $(21 ÷ 4)\n",
       "  ÷ は \\div で入力する。\n",
       "  // は 分数形式(有理数)になる。Python と違うので要注意。\n",
       "  21 // 4 = $(21 // 4), float(21 // 4) = $(float(21 // 4))\n",
       "  240 // 36 = $(240 // 36)")
整数除算: div(21, 4) = 5 または 21 ÷ 4 = 5
  ÷ は \div で入力する。
  // は 分数形式(有理数)になる。Python と違うので要注意。
  21 // 4 = 21//4, float(21 // 4) = 5.25
  240 // 36 = 20//3

整数剰余: mod(21, 4) = 1 または rem(21, 4) = 1 または 21 % 4 = 1
 しかし,除数,被除数に符号が付くと,ややこしいことになる。

整数 a, b に対する除算の結果の「商」と「余り」について「商*b + 剰余 = a」という等式が成り立つことが規定されている。

3 つの関数を定義して,この等式が成り立つかどうかをチェックしてみよう。結果の表示は 「a, b, 商,剰余,等式が成り立つかどうか」の順である。

julia> h(a, b) = println("div() and mod(): $a, $b, $(div(a, b)), $(mod(a, b)), $(div(a, b) * b + mod(a, b) == a)");

julia> g(a, b) = println("div() and rem(): $a, $b, $(div(a, b)), $(rem(a, b)), $(div(a, b) * b + rem(a, b) == a)");

julia> f(a, b) = println("div() and %: $a, $b, $(div(a, b)), $(a % b), $(div(a, b) * b + a % b == a)");

julia> a =  21; b =  4; h(a, b); g(a, b); f(a, b);
div() and mod(): 21, 4, 5, 1, true
div() and rem(): 21, 4, 5, 1, true
div() and %: 21, 4, 5, 1, true

julia> a =  21; b = -4; h(a, b); g(a, b); f(a, b);
div() and mod(): 21, -4, -5, -3, false
div() and rem(): 21, -4, -5, 1, true
div() and %: 21, -4, -5, 1, true

julia> a = -21; b =  4; h(a, b); g(a, b); f(a, b);
div() and mod(): -21, 4, -5, 3, false
div() and rem(): -21, 4, -5, -1, true
div() and %: -21, 4, -5, -1, true

julia> a = -21; b = -4; h(a, b); g(a, b); f(a, b);
div() and mod(): -21, -4, 5, -1, true
div() and rem(): -21, -4, 5, -1, true
div() and %: -21, -4, 5, -1, true

結果は

除数,被除数の符号が同じときには,除数の計算に mod(),rem(), % のどれを使っても,等式は成り立つ。
除数,被除数の符号が違うときには,除数の計算に rem(), % のいずれを使っても,等式は成り立つが,mod() を使った場合は等式は成り立たない。

mod() は % とは違うということである。

ううん。こんなことばかりしているから,学習が進まない。

コメント
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

整数除算の商と剰余

2020年12月27日 | ブログラミング

整数同士の割り算の,商と剰余についてまとめておく。

私が今まで使ったことのある言語についてのみであるが。
Prorog とか Pascal とか PL/I とかそのほかにもあるが,今となっては実行環境がないので,確かめることができない。

結果を先に述べておく。

2 つの整数を (a, b) とすると,それぞれの符号で 4 通りある。例として,(21, 4), (21, -4), (-21, 4), (-21, -4) でやってみる。

★★★  (商, 剰余) がそれぞれ (5, 1), (-5, 1), (-5, -1), (5, -1) となる言語

AWK, C, C#, C++, COBOL, D, F#, FORTRAN, Go, Java, JavaScript, PHP, Scala, Swift, VB
Haskel で quot() と rem() を使う場合,
Julia で div() と rem() を使う場合,
Perl でゼロ方向への丸めをするようにプログラムする場合

★★  (商, 剰余) がそれぞれ (5, 1), (-6, -3), (-6, 3), (5, -1) となる言語

Python2, Python3, R, Ruby,
Haskel で dif() と mod() を使う場合,
Julia で剰余の計算を a - div(a, b) * b で計算するようにプログラムする場合,
Perl で -∞ 方向への丸めを行い,剰余の計算を a - div(a, b) * b で計算するようにプログラムする場合

★ 迂闊にやると,(商, 剰余) がそれぞれ (5, 1), (-5, -3), (-5, 3), (5, -1) となる言語

Julia で div() と mod() を使う場合(誤った選択。div() と rem() を使えば ★★★,剰余の計算を自分ですれば ★★)
Perl で int($a / $b), と $a % $b を使う場合(適切にプログラムして ★★★ にするか ★★ にする)
このような場合,「 a = 商 * b + 剰余」が成り立たないので,不適切な解となってしまう。

========= AWK

BEGIN {
    OFS = ", "
    a = 21
    b = 4
    print int(a / b), a % b
}

========= C

#include
#include

int main(int argc, char **argv) {
    int a = 21;
    int b = 4;
    printf("%d, %d\n", a / b, a % b);
    return EXIT_SUCCESS;
}

========= C#

public class Hello{
    public static void Main(){
        int a, b;
        a = 21;
        b = 4;
        System.Console.WriteLine(a / b + ", " + a % b);
    }
}

========= C++

#include

int main(int argc, char **argv) {
    int a = 21;
    int b = 4;
    std::cout <
    return EXIT_SUCCESS;
}

========= COBOL

identification division.
program-id. Hello.
data division.
working-storage section.
01 working-area.
    02 x pic s9.
    02 y pic s9.
procedure division.
divide 21 by 4 giving x remainder y.
display x, ",  ", y.

========= D

import std.stdio;
void main() {
    int a, b;
    a = 21;
    b = 4;
    writeln(a / b, ", ", a % b);
}

========= F#

let a = 21;;
let b = 4;;
printfn "%d, %d" (a / b) (a % b);;

========= Fortran

program main
 implicit none
 integer a, b
 a = -21
 b = -4
 write(*, *) int(a / b), ", ", mod(a, b)
end program main

========= Go

package main
import "fmt"
func main() {
    var a int = 21
    var b int = 4
    fmt.Printf("%d, %d", a / b, a % b)
}

========= Java

import java.util.*;

public class Main {
    public static void main(String[] args) throws Exception {
        int a = 21;
        int b = 4;
        System.out.println(a / b + ", " + a % b);
    }
}

========= JavaScript

var a = 21;
var b = 4;
var x = a / b;
// 一律に Math.floor を紹介するページが多いが,a, b の符号が違うときには誤った答えになるので注意
x = x < 0 ? Math.ceil(x) : Math.floor(x)
console.log(x + ", " + a % b);

========= PHP

$a = 21;
$b = 4;
echo (int)($a / $b), ", ", $a % $b;
?>

========= Scala

object Main extends App {
    var a = 21
    var b = 4
    println(a / b + ", " + a % b)
}

========= Swift

var a:Int = -23
var b:Int = 4
print("\(a / b), \(a % b)")

========= VB VisualBasic

public class compiler
  shared function Main as integer
    Dim a As Integer: a = -23
    Dim b As Integer: b = 4
    ' int() は -∞方向への丸めなので不適切
    Console.WriteLine(fix(a / b) & ", " & a Mod b)
    return 0
  end function
end class

###############################################

========= Julia

a = 21
b = 4
# ハイブリッド(不適切な実装)
println(div(a, b), ", ", mod(a,b))
# ゼロ方向へ丸め(C などと同じ多数派)
println(div(a, b), ", ", rem(a,b))
# -∞方向へ丸め(Python などと同じだが少数派)
x = div(a, b)
println(x, a - x * b)

========= Perl

$a = 21;
$b = 4;
# ハイブリッド(不適切な実装)
print int($a / $b), ', ', $a % $b;
# ゼロ方向へ丸め(C などと同じ多数派)
print int($a / $b), ', ', $a - int($a / $b) * $b;
# -∞方向へ丸め(Python などと同じだが少数派)
$x = $a / $b
$x = int($x) - $x < 0 ? 1 : 0 
print $x, ', ', $a - $x * b;

###############################################

========= Haskell

main = do
    let a = 21
    let b = 4
    -- ゼロ方向へ丸め(C などと同じ多数派)
    putStrLn $ show(a `quot` b) ++ ", " ++ show(a `rem` b)
    -- -∞方向へ丸め(Python などと同じだが少数派)
    putStrLn $ show(a `div` b) ++ ", " ++ show(a `mod` b)

========= Python2

a = 21
b = 4
# -∞方向へ丸め(少数派)
print "%d, %d" % (a // b, a % b)

========= Python3

a = 21
b = 4
# -∞方向へ丸め(少数派)
print("%d, %d" % (a // b, a % b))

========= R

a = 21
b = 4
# -∞方向へ丸め(少数派)
cat(sprintf("%d, %d\n", a %/% b, a %% b))

========= Ruby

$a = 21
$b = 4
# -∞方向へ丸め(少数派)
print $a / $b, ', ', $a % $b

 

コメント
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

Python だからって...,numpy も使えば?

2020年12月26日 | Python

文字列中に,どのような文字が幾つあったか知りたいって...

>>> import numpy as np
>>> str = 'あいうえおあおaiueoao999112'
>>> index, count = np.unique(list(str), return_counts=True)
>>> index
array(['1', '2', '9', 'a', 'e', 'i', 'o', 'u', 'あ', 'い', 'う', 'え', 'お'],
      dtype='<U1')
>>> count
array([2, 1, 3, 2, 1, 1, 2, 1, 2, 1, 1, 1, 2])
>>> 
>>> list(index)
['1', '2', '9', 'a', 'e', 'i', 'o', 'u', 'あ', 'い', 'う', 'え', 'お']
>>> list(count)
[2, 1, 3, 2, 1, 1, 2, 1, 2, 1, 1, 1, 2]

コメント
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

Julia -- 10-7(配列)

2020年12月25日 | ブログラミング

組み合わせ

b の逆順列を作る  invperm(v)

julia> v = [2; 4; 3; 1];

一番小さいものが何番目,二番目に小さいものが何番目,... というリストをつくる。

julia> invperm(v)
4-element Array{Int64,1}:
 4
 1
 3
 2

julia> A = ['a','b','c','d'];

julia> B = A[v]
4-element Array{Char,1}:
 'b': ASCII/Unicode U+0062 (category Ll: Letter, lowercase)
 'd': ASCII/Unicode U+0064 (category Ll: Letter, lowercase)
 'c': ASCII/Unicode U+0063 (category Ll: Letter, lowercase)
 'a': ASCII/Unicode U+0061 (category Ll: Letter, lowercase)
 
julia> B[invperm(v)]
4-element Array{Char,1}:
 'a': ASCII/Unicode U+0061 (category Ll: Letter, lowercase)
 'b': ASCII/Unicode U+0062 (category Ll: Letter, lowercase)
 'c': ASCII/Unicode U+0063 (category Ll: Letter, lowercase)
 'd': ASCII/Unicode U+0064 (category Ll: Letter, lowercase)

v が正しい順列ならば true を返す  isperm(v)

julia> isperm([1; 2])
true

julia> isperm([1; 3])
false

インプレースで順列を作る  permute!(v, p)

A を B の順番で取り出して並べる。

julia> A = [1, 1, 3, 4];

julia> perm = [2, 4, 3, 1];

julia> permute!(A, perm);

julia> A
4-element Array{Int64,1}:
 1
 4
 3
 1

インプレースで順列を作る  invpermute!(v, p)

julia> A = [1, 1, 3, 4];

julia> perm = [2, 4, 3, 1];

julia> invpermute!(A, perm);

julia> A
4-element Array{Int64,1}:
 4
 1
 3
 1

逆順に並べたコピーを返す  reverse(v [, start=1 [, stop=length(v) ]] )

julia> A = Vector(1:5)
5-element Array{Int64,1}:
 1
 2
 3
 4
 5

julia> reverse(A)
5-element Array{Int64,1}:
 5
 4
 3
 2
 1

julia> reverse(A, 1, 4)
5-element Array{Int64,1}:
 4
 3
 2
 1
 5

julia> reverse(A, 3, 5)
5-element Array{Int64,1}:
 1
 2
 5
 4
 3

インプレースで逆順  reverse!(v [, start=1 [, stop=length(v) ]]) -> v

julia> A = Vector(1:5)
5-element Array{Int64,1}:
 1
 2
 3
 4
 5

julia> reverse!(A);

julia> A
5-element Array{Int64,1}:
 5
 4
 3
 2
 1

dims で指定した次元について逆順にする  reverse(A; dims::Integer)

julia> b = [1 2; 3 4]
2×2 Array{Int64,2}:
 1  2
 3  4

julia> reverse(b, dims=2)
2×2 Array{Int64,2}:
 2  1
 4  3

 

コメント
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

さて,ここで問題です Challenge0001 (Python)

2020年12月25日 | Python

a, b, c, d の4個の数字を入力とする

もしどれかが 0 なら,それぞれに 0.5 を加える

x = a * d / (b * c)

としたとき,x か  1 / x の大きい方を返す関数を定義せよ

言語は問わない。合計文字数が少ない方がいいぞ!

 

解答例は,ずっとスクロールダウンして...

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

import numpy as np

def func(a, b, c, d):
  if a * b * c * d == 0:
  a, b, c, d = np.array([a, b, c, d])+0.5
  OR = a * d / (b * c)
  return max(OR, 1 / OR)

func(1,2,3,4) # 1.5
func(0,2,3,4) # 3.8888888888888893

コメント
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

Julia -- 10-6(配列)

2020年12月25日 | ブログラミング

配列関数

累積的な演算  accumulate(op, A; dims::Integer, [init])

累和

julia> accumulate(+, [1,2,3])
3-element Array{Int64,1}:
 1
 3
 6

累積

julia> accumulate(*, [1,2,3])
3-element Array{Int64,1}:
 1
 2
 6

julia> accumulate(+, [1,2,3]; init=100)
3-element Array{Int64,1}:
 101
 103
 106

julia> accumulate(min, [1,2,-1]; init=0)
3-element Array{Int64,1}:
  0
  0
 -1

julia> accumulate(+, fill(1, 3, 3), dims=1)
3×3 Array{Int64,2}:
 1  1  1
 2  2  2
 3  3  3

julia> accumulate(+, fill(1, 3, 3), dims=2)
3×3 Array{Int64,2}:
 1  2  3
 1  2  3
 1  2  3

累積的な演算。結果を B に保存  accumulate!(op, B, A; [dims], [init])

julia> x = [1, 0, 2, 0, 3];

julia> y = [0, 0, 0, 0, 0];

julia> accumulate!(+, y, x);

julia> y
5-element Array{Int64,1}:
 1
 1
 3
 3
 6

julia> A = [1 2; 3 4];

julia> B = [0 0; 0 0];

julia> accumulate!(-, B, A, dims=1);

julia> B
2×2 Array{Int64,2}:
  1   2
 -2  -2

julia> accumulate!(-, B, A, dims=2);

julia> B
2×2 Array{Int64,2}:
 1  -1
 3  -1

指定された次元について累積  cumprod(A; dims::Integer)

julia> a = [1 2 3; 4 5 6]
2×3 Array{Int64,2}:
 1  2  3
 4  5  6

julia> cumprod(a, dims=1)
2×3 Array{Int64,2}:
 1   2   3
 4  10  18

julia> cumprod(a, dims=2)
2×3 Array{Int64,2}:
 1   2    6
 4  20  120

イテレーターの累積  cumprod(itr)

julia> cumprod(fill(1//2, 3))
3-element Array{Rational{Int64},1}:
 1//2
 1//4
 1//8

julia> cumprod([fill(1//3, 2, 2) for i in 1:3])
3-element Array{Array{Rational{Int64},2},1}:
 [1//3 1//3; 1//3 1//3]
 [2//9 2//9; 2//9 2//9]
 [4//27 4//27; 4//27 4//27]

julia> cumprod((1, 2, 1))
(1, 2, 2)

julia> cumprod(x^2 for x in 1:3)
3-element Array{Int64,1}:
  1
  4
 36

累積結果を B に保存する  cumprod!(B, A; dims::Integer)

累和  cumsum(A; dims::Integer)

julia> a = [1 2 3; 4 5 6]
2×3 Array{Int64,2}:
 1  2  3
 4  5  6

julia> cumsum(a, dims=1)
2×3 Array{Int64,2}:
 1  2  3
 5  7  9

julia> cumsum(a, dims=2)
2×3 Array{Int64,2}:
 1  3   6
 4  9  15

イテレータの累和  cumsum(itr)

julia> cumsum([1, 1, 1])
3-element Array{Int64,1}:
 1
 2
 3

julia> cumsum([fill(1, 2) for i in 1:3])
3-element Array{Array{Int64,1},1}:
 [1, 1]
 [2, 2]
 [3, 3]

julia> cumsum((1, 1, 1))
(1, 2, 3)

julia> cumsum(x^2 for x in 1:3)
3-element Array{Int64,1}:
  1
  5
 14

累和の結果を B に保存  cumsum!(B, A; dims::Integer)

差分  diff(A::AbstractVector),diff(A::AbstractArray; dims::Integer)

julia> a = [2 4; 6 16]
2×2 Array{Int64,2}:
 2   4
 6  16

julia> diff(a, dims=2)
2×1 Array{Int64,2}:
  2
 10

julia> diff(vec(a))
3-element Array{Int64,1}:
  4
 -2
 12

配列を繰り返して配列を作る  repeat(A::AbstractArray, counts::Integer...)

julia> repeat([1, 2, 3], 2)
6-element Array{Int64,1}:
 1
 2
 3
 1
 2
 3

julia> repeat([1, 2, 3], 2, 3)
6×3 Array{Int64,2}:
 1  1  1
 2  2  2
 3  3  3
 1  1  1
 2  2  2
 3  3  3

文字列を繰り返して文字列を作る  repeat(s::AbstractString, r::Integer)

julia> repeat("ha", 3)
"hahaha"

julia> repeat('A', 3)
"AAA"

行列を 180度回転する  rot180(A)

julia> a = [1 2; 3 4]
2×2 Array{Int64,2}:
 1  2
 3  4

julia> rot180(a)
2×2 Array{Int64,2}:
 4  3
 2  1

行列を k 回,180度回転する  rot180(A, k)

k が偶数なら,copy と同じである。

julia> a = [1 2; 3 4]
2×2 Array{Int64,2}:
 1  2
 3  4

julia> rot180(a,1)
2×2 Array{Int64,2}:
 4  3
 2  1

julia> rot180(a,2)
2×2 Array{Int64,2}:
 1  2
 3  4

行列を左に 90 度回転する  rotl90(A)

julia> a = [1 2; 3 4]
2×2 Array{Int64,2}:
 1  2
 3  4

julia> rotl90(a)
2×2 Array{Int64,2}:
 2  4
 1  3

行列を左に 90 度,k 回回転する  rotl90(A, k)

k が 4 の倍数ならば,コピーと同じである。

julia> a = [1 2; 3 4]
2×2 Array{Int64,2}:
 1  2
 3  4

julia> rotl90(a,1)
2×2 Array{Int64,2}:
 2  4
 1  3

julia> rotl90(a,2)
2×2 Array{Int64,2}:
 4  3
 2  1

julia> rotl90(a,3)
2×2 Array{Int64,2}:
 3  1
 4  2

julia> rotl90(a,4)
2×2 Array{Int64,2}:
 1  2
 3  4
 
行列を右に 90 度回転する  rotr90(A)
 
 julia> a = [1 2; 3 4]
2×2 Array{Int64,2}:
 1  2
 3  4

julia> rotr90(a)
2×2 Array{Int64,2}:
 3  1
 4  2
 
行列を右に 90 度回転する  rotr90(A,k)

julia> a = [1 2; 3 4]
2×2 Array{Int64,2}:
 1  2
 3  4

julia> rotr90(a,1)
2×2 Array{Int64,2}:
 3  1
 4  2

julia> rotr90(a,2)
2×2 Array{Int64,2}:
 4  3
 2  1

julia> rotr90(a,3)
2×2 Array{Int64,2}:
 2  4
 1  3

julia> rotr90(a,4)
2×2 Array{Int64,2}:
 1  2
 3  4

配列の指定された次元について関数で変換する  mapslices(f, A; dims)

julia> a = reshape(Vector(1:16),(2,2,2,2))
2×2×2×2 Array{Int64,4}:
[:, :, 1, 1] =
 1  3
 2  4

[:, :, 2, 1] =
 5  7
 6  8

[:, :, 1, 2] =
  9  11
 10  12

[:, :, 2, 2] =
 13  15
 14  16

julia> mapslices(sum, a, dims = [1,2])
1×1×2×2 Array{Int64,4}:
[:, :, 1, 1] =
 10

[:, :, 2, 1] =
 26

[:, :, 1, 2] =
 42

[:, :, 2, 2] =
 58

行列の最初の次元をイテレートするジェネレータを作る  eachrow(A::AbstractVecOrMat)

julia> a = [1 2; 3 4]
2×2 Array{Int64,2}:
 1  2
 3  4

julia> first(eachrow(a))
2-element view(::Array{Int64,2}, 1, :) with eltype Int64:
 1
 2

julia> collect(eachrow(a))
2-element Array{SubArray{Int64,1,Array{Int64,2},Tuple{Int64,Base.Slice{Base.OneTo{Int64}}},true},1}:
 [1, 2]
 [3, 4]

行列の2番目の次元をイテレートするジェネレータを作る  eachcol(A::AbstractVecOrMat)

julia> a = [1 2; 3 4]
2×2 Array{Int64,2}:
 1  2
 3  4

julia> first(eachcol(a))
2-element view(::Array{Int64,2}, :, 1) with eltype Int64:
 1
 3

julia> collect(eachcol(a))
2-element Array{SubArray{Int64,1,Array{Int64,2},Tuple{Base.Slice{Base.OneTo{Int64}},Int64},true},1}:
 [1, 3]
 [2, 4]

両方の次元をイテレートするジェネレータを作る  eachslice(A::AbstractArray; dims)

 

コメント
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

Julia -- 10-4(配列)

2020年12月25日 | ブログラミング

配列の連接  cat(), vcat(), hcat()

vcat() は第 1 次元で cat()

julia> a = [1 2 3 4 5]
1×5 Array{Int64,2}:
 1  2  3  4  5

julia> b = [6 7 8 9 10; 11 12 13 14 15]
2×5 Array{Int64,2}:
  6   7   8   9  10
 11  12  13  14  15

julia> vcat(a,b)
3×5 Array{Int64,2}:
  1   2   3   4   5
  6   7   8   9  10
 11  12  13  14  15

julia> c = ([1 2 3], [4 5 6])
([1 2 3], [4 5 6])

julia> vcat(c...)
2×3 Array{Int64,2}:
 1  2  3
 4  5  6

hcat() は第 2 次元で cat()

julia> a = [1; 2; 3; 4; 5]
5-element Array{Int64,1}:
 1
 2
 3
 4
 5

julia> b = [6 7; 8 9; 10 11; 12 13; 14 15]
5×2 Array{Int64,2}:
  6   7
  8   9
 10  11
 12  13
 14  15

julia> hcat(a,b)
5×3 Array{Int64,2}:
 1   6   7
 2   8   9
 3  10  11
 4  12  13
 5  14  15

julia> c = ([1; 2; 3], [4; 5; 6])
([1, 2, 3], [4, 5, 6])

julia> hcat(c...)
3×2 Array{Int64,2}:
 1  4
 2  5
 3  6

julia> x = Matrix(undef, 3, 0)  # x = [] would have created an Array{Any, 1}, but need an Array{Any, 2}
3×0 Array{Any,2}

julia> hcat(x, [1; 2; 3])
3×1 Array{Any,2}:
 1
 2
 3

hvcat() は hcat() と vcat() を 1 回のコールで行う。

julia> a, b, c, d, e, f = 1, 2, 3, 4, 5, 6
(1, 2, 3, 4, 5, 6)

julia> [a b c; d e f]
2×3 Array{Int64,2}:
 1  2  3
 4  5  6

julia> hvcat((3,3), a,b,c,d,e,f)
2×3 Array{Int64,2}:
 1  2  3
 4  5  6

julia> [a b;c d; e f]
3×2 Array{Int64,2}:
 1  2
 3  4
 5  6

julia> hvcat((2,2,2), a,b,c,d,e,f)
3×2 Array{Int64,2}:
 1  2
 3  4
 5  6

ベクトルを作る  vect(X...)

julia> a = Base.vect(UInt8(1), 2.5, 1//2)
3-element Array{Float64,1}:
 1.0
 2.5
 0.5
 
ローテート  circshift(A, shift),circshift!(dest, src, shifts)

shift はタプルまたはベクトル。それぞれの次元でどれだけシフトするかの量を表す。正・負・ゼロの値を取る。
circshift! は結果を dest に格納する。

julia> b = reshape(Vector(1:16), (4,4))
4×4 Array{Int64,2}:
 1  5   9  13
 2  6  10  14
 3  7  11  15
 4  8  12  16

julia> circshift(b, (0,2))
4×4 Array{Int64,2}:
  9  13  1  5
 10  14  2  6
 11  15  3  7
 12  16  4  8

julia> circshift(b, (-1,0))
4×4 Array{Int64,2}:
 2  6  10  14
 3  7  11  15
 4  8  12  16
 1  5   9  13

julia> a = BitArray([true, true, false, false, true])
5-element BitArray{1}:
 1
 1
 0
 0
 1

julia> circshift(a, 1)
5-element BitArray{1}:
 1
 1
 1
 0
 0

julia> circshift(a, -1)
5-element BitArray{1}:
 1
 0
 0
 1
 1

julia> src = reshape(Vector(1:16), (4,4))
4×4 Array{Int64,2}:
 1  5   9  13
 2  6  10  14
 3  7  11  15
 4  8  12  16

julia> dest = OffsetArray{Int}(undef, (0:3,2:5))

julia> circcopy!(dest, src)
OffsetArrays.OffsetArray{Int64,2,Array{Int64,2}} with indices 0:3×2:5:
 8  12  16  4
 5   9  13  1
 6  10  14  2
 7  11  15  3

julia> dest[1:3,2:4] == src[1:3,2:4]
true

コメント
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

Julia -- 10-5(配列)

2020年12月25日 | ブログラミング

配列の要素が true のもののインデックスを取り出す  findall(), findall(f::Function, A)

julia> A = [true, false, false, true]
4-element Array{Bool,1}:
 1
 0
 0
 1

julia> findall(A)
2-element Array{Int64,1}:
 1
 4

julia> A = [true false; false true]
2×2 Array{Bool,2}:
 1  0
 0  1

julia> findall(A)
2-element Array{CartesianIndex{2},1}:
 CartesianIndex(1, 1)
 CartesianIndex(2, 2)

julia> findall(falses(3))
Int64[]

julia> x = [1, 3, 4]
3-element Array{Int64,1}:
 1
 3
 4

julia> findall(isodd, x)
2-element Array{Int64,1}:
 1
 2

julia> A = [1 2 0; 3 4 0]
2×3 Array{Int64,2}:
 1  2  0
 3  4  0
julia> findall(isodd, A)
2-element Array{CartesianIndex{2},1}:
 CartesianIndex(1, 1)
 CartesianIndex(2, 1)

julia> findall(!iszero, A)
4-element Array{CartesianIndex{2},1}:
 CartesianIndex(1, 1)
 CartesianIndex(2, 1)
 CartesianIndex(1, 2)
 CartesianIndex(2, 2)

julia> d = Dict(:A => 10, :B => -1, :C => 0)
Dict{Symbol,Int64} with 3 entries:
  :A => 10
  :B => -1
  :C => 0

julia> findall(x -> x >= 0, d)
2-element Array{Symbol,1}:
 :A
 :C

最初に見つかる true のインデックスを返す  findfirst(A), findfirst(predicate::Funciton, A)

julia> A = [false, false, true, false]
4-element Array{Bool,1}:
 0
 0
 1
 0

julia> findfirst(A)
3

julia> findfirst(falses(3)) # returns nothing, but not printed in the REPL

julia> A = [false false; true false]
2×2 Array{Bool,2}:
 0  0
 1  0

julia> findfirst(A)
CartesianIndex(2, 1)

julia> A = [1, 4, 2, 2]
4-element Array{Int64,1}:
 1
 4
 2
 2

julia> findfirst(iseven, A)
2

julia> findfirst(x -> x>10, A) # returns nothing, but not printed in the REPL

julia> findfirst(isequal(4), A)
2

julia> A = [1 4; 2 2]
2×2 Array{Int64,2}:
 1  4
 2  2

julia> findfirst(iseven, A)
CartesianIndex(2, 1)

最後に見つかる true のインデックスを返す  findlast(A), findlast(predicate::Function, A)

julia> A = [true, false, true, false]
4-element Array{Bool,1}:
 1
 0
 1
 0

julia> findlast(A)
3

julia> A = falses(2,2);

julia> findlast(A) # returns nothing, but not printed in the REPL

julia> A = [true false; true false]
2×2 Array{Bool,2}:
 1  0
 1  0

julia> findlast(A)
CartesianIndex(2, 1)

julia> A = [1, 2, 3, 4]
4-element Array{Int64,1}:
 1
 2
 3
 4

julia> findlast(isodd, A)
3

julia> findlast(x -> x > 5, A) # returns nothing, but not printed in the REPL

julia> A = [1 2; 3 4]
2×2 Array{Int64,2}:
 1  2
 3  4

julia> findlast(isodd, A)
CartesianIndex(2, 1)

i 以後の次の true インデックスを返す  findnext(A, i),findnext(predicate::Function, A, i)

julia> A = [false, false, true, false]
4-element Array{Bool,1}:
 0
 0
 1
 0

julia> findnext(A, 1)
3

julia> findnext(A, 4) # returns nothing, but not printed in the REPL

julia> A = [false false; true false]
2×2 Array{Bool,2}:
 0  0
 1  0

julia> findnext(A, CartesianIndex(1, 1))
CartesianIndex(2, 1)

julia> A = [1, 4, 2, 2];

julia> findnext(isodd, A, 1)
1

julia> findnext(isodd, A, 2) # returns nothing, but not printed in the REPL

julia> A = [1 4; 2 2];

julia> findnext(isodd, A, CartesianIndex(1, 1))
CartesianIndex(1, 1)

i 以前の true インデックスを返す  findprev(A, i),findprev(predicate::Function A, i)

julia> A = [false, false, true, true]
4-element Array{Bool,1}:
 0
 0
 1
 1

julia> findprev(A, 3)
3

julia> findprev(A, 1) # returns nothing, but not printed in the REPL

julia> A = [false false; true true]
2×2 Array{Bool,2}:
 0  0
 1  1

julia> findprev(A, CartesianIndex(2, 1))
CartesianIndex(2, 1)

julia> A = [4, 6, 1, 2]
4-element Array{Int64,1}:
 4
 6
 1
 2

julia> findprev(isodd, A, 1) # returns nothing, but not printed in the REPL

julia> findprev(isodd, A, 3)
3

julia> A = [4 6; 1 2]
2×2 Array{Int64,2}:
 4  6
 1  2

julia> findprev(isodd, A, CartesianIndex(1, 2))
CartesianIndex(2, 1)

対角要素を中心に右上と左下を入れ替える  permutedims(m)

転置 transpose とは異なる。

julia> a = [1 2; 3 4];

julia> b = [5 6; 7 8];

julia> c = [9 10; 11 12];

julia> d = [13 14; 15 16];

julia> X = [[a] [b]; [c] [d]]
2×2 Array{Array{Int64,2},2}:
 [1 2; 3 4]     [5 6; 7 8]
 [9 10; 11 12]  [13 14; 15 16]

julia> permutedims(X)
2×2 Array{Array{Int64,2},2}:
 [1 2; 3 4]  [9 10; 11 12]
 [5 6; 7 8]  [13 14; 15 16]

julia> transpose(X)
2×2 Transpose{Transpose{Int64,Array{Int64,2}},Array{Array{Int64,2},2}}:
 [1 3; 2 4]  [9 11; 10 12]
 [5 7; 6 8]  [13 15; 14 16]

julia> permutedims([1, 2, 3, 4])
1×4 Array{Int64,2}:
 1  2  3  4

julia> V = [[[1 2; 3 4]]; [[5 6; 7 8]]]
2-element Array{Array{Int64,2},1}:
 [1 2; 3 4]
 [5 6; 7 8]

julia> permutedims(V)
1×2 Array{Array{Int64,2},2}:
 [1 2; 3 4]  [5 6; 7 8]

julia> transpose(V)
1×2 Transpose{Transpose{Int64,Array{Int64,2}},Array{Array{Int64,2},1}}:
 [1 3; 2 4]  [5 7; 6 8]

コピーを伴わない permutedims  PermuteDimsArray(A, perm) -> B

julia> A = rand(3,5,4);

julia> B = PermutedDimsArray(A, (3,1,2));

julia> size(B)
(4, 3, 5)

julia> B[3,1,2] == A[1,2,3]
true

次元属性が一致するかどうか  promote_shape(s1, s2)

julia> a = fill(1, (3,4,1,1,1));

julia> b = fill(1, (3,4));

julia> promote_shape(a,b)
(Base.OneTo(3), Base.OneTo(4), Base.OneTo(1), Base.OneTo(1), Base.OneTo(1))

julia> promote_shape((2,3,1,4), (2, 3, 1, 4, 1))
(2, 3, 1, 4, 1)

 

コメント
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

Julia -- 10-3(配列)

2020年12月25日 | ブログラミング

参照(indexing)と代入(assignment)
getindex(), setindex()

列優先である。

julia> A = [1 2; 3 4]
2×2 Array{Int64,2}:
 1  2
 3  4

julia> getindex(A, 1)
1

julia> getindex(A, [2, 1])
2-element Array{Int64,1}:
 3
 1

julia> getindex(A, 2:4)
3-element Array{Int64,1}:
 3
 2
 4

setindex!(A, X, inds...) と A[inds...] は同じである。

julia> A = zeros(2,2);

julia> setindex!(A, [10, 20], [1, 2]); # A のインデックス 1,2 に 10, 20 を代入

julia> A[[3, 4]] = [30, 40]; # A のインデックス 3,4 に 30, 40 を代入

julia> A
2×2 Array{Float64,2}:
 10.0  30.0
 20.0  40.0

配列がインデックスを持つか  isassigned()

julia> isassigned(rand(3, 3), 5) # 配列は 1 ~ 9 のインデックスを持ちうる
true

julia> isassigned(rand(3, 3), 3 * 3 + 1) # 従って 3 * 3 + 1 = 10 というインデックスは持たない
false

julia> mutable struct Foo end

julia> v = similar(rand(3), Foo)
3-element Array{Foo,1}:
 #undef
 #undef
 #undef

julia> isassigned(v, 1)
false

コロン ':'

julia> A = reshape(Vector(1:16), (2, 2, 2, 2))
2×2×2×2 Array{Int64,4}:
[:, :, 1, 1] =
 1  3
 2  4

[:, :, 2, 1] =
 5  7
 6  8

[:, :, 1, 2] =
  9  11
 10  12

[:, :, 2, 2] =
 13  15
 14  16

julia> A[CartesianIndex((1, 1, 1, 1))]
1

julia> A[CartesianIndex((1, 1, 1, 2))]
9

julia> A[CartesianIndex((1, 1, 2, 1))]
5

LinearIndices()

julia> A = reshape(Vector(1:16), (2, 2, 2, 2))
2×2×2×2 Array{Int64,4}:
[:, :, 1, 1] =
 1  3
 2  4

[:, :, 2, 1] =
 5  7
 6  8

[:, :, 1, 2] =
  9  11
 10  12

[:, :, 2, 2] =
 13  15
 14  16

julia> A[CartesianIndex((1, 1, 1, 1))]
1

julia> A[CartesianIndex((1, 1, 1, 2))]
9

julia> A[CartesianIndex((1, 1, 2, 1))]
5

julia> A = fill(1, (5,6,7));

julia> b = LinearIndices(A);

julia> extrema(b)
(1, 210)


1からはじまる整数列を要素に持つ配列  LinearIndices()

julia> linear = LinearIndices((1:3, 1:2))
3×2 LinearIndices{2,Tuple{UnitRange{Int64},UnitRange{Int64}}}:
 1  4
 2  5
 3  6

julia> linear[1,2]
4

julia> LinearIndices((1:2,1:3, 2:5))
2×3×4 LinearIndices{3,Tuple{UnitRange{Int64},UnitRange{Int64},UnitRange{Int64}}}:
[:, :, 1] =
 1  3  5
 2  4  6

[:, :, 2] =
 7   9  11
 8  10  12

[:, :, 3] =
 13  15  17
 14  16  18

[:, :, 4] =
 19  21  23
 20  22  24

インデックス I が A の範囲内にあるか  checkbounds(Bool, A, I...)

julia> A = rand(3, 3);

julia> checkbounds(Bool, A, 2)
true

julia> checkbounds(Bool, A, 3, 4)
false

julia> checkbounds(Bool, A, 1:3)
true

julia> checkbounds(Bool, A, 1:3, 2:4)
false

インデックス I が A の範囲内になければエラーにする  checkbounds(A, I...)

julia> checkindex(Bool, 1:20, 8)
true

julia> checkindex(Bool, 1:20, 21)
false

配列を参照する  view(A, inds...)

julia> A = [1 2; 3 4]
2×2 Array{Int64,2}:
 1  2
 3  4

julia> b = view(A, :, 1)
2-element view(::Array{Int64,2}, :, 1) with eltype Int64:
 1
 3

julia> fill!(b, 0)
2-element view(::Array{Int64,2}, :, 1) with eltype Int64:
 0
 0

julia> A # Note A has changed even though we modified b
2×2 Array{Int64,2}:
 0  2
 0  4

配列の次元サイズの変更 reshape()

julia> A = Vector(1:16)
16-element Array{Int64,1}:
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16

julia> reshape(A, (4, 4))
4×4 Array{Int64,2}:
 1  5   9  13
 2  6  10  14
 3  7  11  15
 4  8  12  16

julia> reshape(A, 2, :)
2×8 Array{Int64,2}:
 1  3  5  7   9  11  13  15
 2  4  6  8  10  12  14  16

julia> reshape(1:6, 2, 3)
2×3 reshape(::UnitRange{Int64}, 2, 3) with eltype Int64:
 1  3  5
 2  4  6

配列の次元を削除する  drop(A; dims)

julia> a = reshape(Vector(1:4),(2,2,1,1))
2×2×1×1 Array{Int64,4}:
[:, :, 1, 1] =
 1  3
 2  4

julia> dropdims(a; dims=3)
2×2×1 Array{Int64,3}:
[:, :, 1] =
 1  3
 2  4

配列をベクトルにする  vec()

julia> a = [1 2 3; 4 5 6]
2×3 Array{Int64,2}:
 1  2  3
 4  5  6

julia> vec(a)
6-element Array{Int64,1}:
 1
 4
 2
 5
 3
 6

julia> vec(1:3)
1:3

コメント
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

Julia -- 10-2(配列)

2020年12月25日 | ブログラミング

ベクトルの作成と初期化

Vector{T}(undef, n)

初期化されていない,要素数 n の 型 T のベクトルを作る
 
julia> Vector{Float64}(undef, 3)
3-element Array{Float64,1}:
 2.2910037355e-314
 2.2881675853e-314
 2.2881675853e-314

julia> Vector{Union{Nothing, String}}(nothing, 2)
2-element Array{Union{Nothing, String},1}:
 nothing
 nothing

julia> Vector{Union{Missing, String}}(missing, 2)
2-element Array{Union{Missing, String},1}:
 missing
 missing

二次元行列の作成

型 T の二次元配列  Matrix{T} <: AbstractMatrix{T}

julia> Matrix{Float64}(undef, 2, 3)
2×3 Array{Float64,2}:
 0.0       2.36894e-314  1.0e-323
 5.0e-324  6.0e-323      2.36894e-314

julia> Matrix{Union{Nothing, String}}(nothing, 2, 3)
2×3 Array{Union{Nothing, String},2}:
 nothing  nothing  nothing
 nothing  nothing  nothing

julia> Matrix{Union{Missing, String}}(missing, 2, 3)
2×3 Array{Union{Missing, String},2}:
 missing  missing  missing
 missing  missing  missing

[] によるベクトル

julia> Int8[1, 2, 3]
3-element Array{Int8,1}:
 1
 2
 3

getindex() によるベクトル

julia> A = [1 2; 3 4]
2×2 Array{Int64,2}:
 1  2
 3  4
  
julia> getindex(A, 1)
1
  
julia> getindex(A, [2, 1])
2-element Array{Int64,1}:
 3
 1
  
julia> getindex(A, 2:4)
3-element Array{Int64,1}:
 3
 2
 4

zeros() による配列

zeros([T=Float64,] dims::Tuple)
zeros([T=Float64,] dims...)

 julia> zeros(5)
5-element Array{Float64,1}:
 0.0
 0.0
 0.0
 0.0
 0.0

julia> zeros(Int8, 2, 3)
2×3 Array{Int8,2}:
 0  0  0
 0  0  0

ones() による配列

ones([T=Float64,] dims::Tuple)
ones([T=Float64,] dims...)

julia> ones(1,5)
1×5 Array{Float64,2}:
 1.0  1.0  1.0  1.0  1.0

julia> ones(ComplexF64, 2, 3)
2×3 Array{Complex{Float64},2}:
 1.0+0.0im  1.0+0.0im  1.0+0.0im
 1.0+0.0im  1.0+0.0im  1.0+0.0im

BitArray

BitArray(undef, dims::Integer...)
BitArray{N}(undef, dims::NTuple{N,Int})

julia> BitArray(undef, 2, 2)
2×2 BitArray{2}:
 0  0
 0  0

julia> BitArray(undef, (3, 1))
3×1 BitArray{2}:
 0
 0
 0

イテラブル・オブジェクトで BitArray を作る  BitArray(itr)

julia> BitArray([1 0; 0 1])
2×2 BitArray{2}:
 1  0
 0  1

julia> BitArray(x+y == 3 for x = 1:2, y = 1:3)
2×3 BitArray{2}:
 0  1  0
 1  0  0

julia> BitArray(x+y == 3 for x = 1:2 for y = 1:3)
6-element BitArray{1}:
 0
 1
 0
 1
 0
 0

trues() で BitArray を作る  trues(dims)

julia> trues(2,3)
2×3 BitArray{2}:
 1  1  1
 1  1  1

falses() で BitArray を作る  falses(dims)

julia> falses(2,3)
2×3 BitArray{2}:
 0  0  0
 0  0  0
 
fill() で 配列を作る  fill(x, dims::Tuple),fill(x, dims...)

全ての要素が x である,次元 dim の配列を作る

julia> fill(1.0, (2,3))
2×3 Array{Float64,2}:
 1.0  1.0  1.0
 1.0  1.0  1.0

julia> fill(42)
0-dimensional Array{Int64,0}:
42

x がオブジェクトの参照ならば,全ての要素は同じオブジェクトを参照する。

julia> A = fill(zeros(2), 2);

julia> A[1][1] = 42; # modifies both A[1][1] and A[2][1]

julia> A
2-element Array{Array{Float64,1},1}:
 [42.0, 0.0]
 [42.0, 0.0]

fill!() で配列を作る

fill!(A, Foo()) は, Foo() を 1 回だけ評価した値で満たされた A を返す。

julia> A = zeros(2,3)
2×3 Array{Float64,2}:
 0.0  0.0  0.0
 0.0  0.0  0.0

julia> fill!(A, 2.)
2×3 Array{Float64,2}:
 2.0  2.0  2.0
 2.0  2.0  2.0

julia> a = [1, 1, 1]; A = fill!(Vector{Vector{Int}}(undef, 3), a); a[1] = 2; A
3-element Array{Array{Int64,1},1}:
 [2, 1, 1]
 [2, 1, 1]
 [2, 1, 1]

julia> x = 0; f() = (global x += 1; x); fill!(Vector{Int}(undef, 3), f())
3-element Array{Int64,1}:
 1
 1
 1

similar() で配列を作る
similar(array, [element_type=eltype(array)], [dims=size(array)])

julia> similar(1:10, 1, 4)
1×4 Array{Int64,2}:
 4419743872  4374413872  4419743888  0

julia> similar(trues(10,10), 2)
2-element BitArray{1}:
 0
 0

julia> similar(falses(10), Float64, 2, 4)
2×4 Array{Float64,2}:
 2.18425e-314  2.18425e-314  2.18425e-314  2.18425e-314
 2.18425e-314  2.18425e-314  2.18425e-314  2.18425e-314

ブロードキャストとベクトル化  broadcast()

julia> A = [1, 2, 3, 4, 5]
5-element Array{Int64,1}:
 1
 2
 3
 4
 5

julia> B = [1 2; 3 4; 5 6; 7 8; 9 10]
5×2 Array{Int64,2}:
 1   2
 3   4
 5   6
 7   8
 9  10

julia> broadcast(+, A, B)
5×2 Array{Int64,2}:
  2   3
  5   6
  8   9
 11  12
 14  15

julia> parse.(Int, ["1", "2"])
2-element Array{Int64,1}:
 1
 2

julia> abs.((1, -2))
(1, 2)

julia> broadcast(+, 1.0, (0, -2.0))
(1.0, -1.0)

julia> (+).([[0,2], [1,3]], Ref{Vector{Int}}([1,-1]))
2-element Array{Array{Int64,1},1}:
 [1, 1]
 [2, 2]

julia> string.(("one","two","three","four"), ": ", 1:4)
4-element Array{String,1}:
 "one: 1"
 "two: 2"
 "three: 3"
 "four: 4"

broadcast!()

julia> A = [1.0; 0.0]; B = [0.0; 0.0];

julia> broadcast!(+, B, A, (0, -2.0));

julia> B
2-element Array{Float64,1}:
  1.0
 -2.0

julia> A
2-element Array{Float64,1}:
 1.0
 0.0

julia> broadcast!(+, A, A, (0, -2.0));

julia> A
2-element Array{Float64,1}:
  1.0
 -2.0

ベクトル化演算  @. expr

julia> x = 1.0:3.0; y = similar(x);

julia> @. y = x + 3 * sin(x)
3-element Array{Float64,1}:
 3.5244129544236893
 4.727892280477045
 3.4233600241796016

 

コメント
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

Julia -- 10-1(配列)

2020年12月25日 | ブログラミング

基本的な関数

要素の型  eltype(A)

julia> A = [1 2 3;4 5 6]
2×3 Array{Int64,2}:
 1  2  3
 4  5  6

julia> eltype(A)
Int64

julia> B = [1.0 2.0; 3.0 4.0]
2×2 Array{Float64,2}:
 1.0  2.0
 3.0  4.0

julia> eltype(B)
Float64

総要素数  length(A)

julia> length(A)
6

julia> length(B)
4

次元数  ndims(A)

julia> ndims(A)
2

julia> B = [1 2 3 4 5 6 7 8 9 10] # 1行10列の配列
1×10 Array{Int64,2}:
 1  2  3  4  5  6  7  8  9  10

julia> ndims(B)
2

julia> C = 1:10
1:10

julia> ndims(C) # 1次元の配列(ベクトル)
1

各次元の大きさ  size(A)

julia> size(A)
(2, 3)

julia> size(C)
(10,)

指定した次元の大きさ  size(A, n)

julia> size(A, 1)
2

julia> size(A, 2)
3

julia> size(C, 1)
10

有効な添え字範囲  axes(A)

julia> axes(A)
(Base.OneTo(2), Base.OneTo(3))

julia> axes(C)
(Base.OneTo(10),)

指定した次元の有効な添え字範囲  axes(A, n)

julia> axes(A, 1)
Base.OneTo(2)

julia> axes(A, 2)
Base.OneTo(3)

julia> axes(C, 1)
Base.OneTo(10)

全要素を網羅する効率のよいイテレータ  eachindex(A)

julia> eachindex(A)
Base.OneTo(6)

julia> eachindex(B)
Base.OneTo(4)

julia> eachindex(C)
Base.OneTo(10)

julia> A = [1 2; 3 4];

julia> for i in eachindex(A) # linear indexing
           println(i)
       end
1
2
3
4

julia> for i in eachindex(view(A, 1:2, 1:1)) # Cartesian indexing
           println(i)
       end
CartesianIndex(1, 1)
CartesianIndex(2, 1)

各次元ごとの隣接する要素のメモリ上の距離  strides(A)

julia> D = [1 2 3;4 5 6;7 8 9;10 11 12]
4×3 Array{Int64,2}:
  1   2   3
  4   5   6
  7   8   9
 10  11  12

julia> stride(D)
(1, 4)

指定した次元での隣接する要素のメモリ上の距離  stride(A, n)

julia> stride(D, 1)
1

julia> stride(D, 2)
4

配列の作成と初期化

Array{T}(undef dims)
Array{T, N}(undef dims)

初期化しない(undef),型 T の,N 次元配列(それぞれの次元サイズは dim)を作る。
dim は タプルか,複数の整数。N が明示されないときは dim の長さを使う。
型は,Float64, Int64, Union{Nothing, String} などのように指定する。

Float64 の,2次元配列を作る。初期化しない(undef)。それぞれの次元サイズは 3, 4。

julia> A = Array{Float64,2}(undef, 3, 4)
3×4 Array{Float64,2}:
 2.38811e-314  2.38811e-314  2.38811e-314  2.38838e-314
 2.38811e-314  2.38811e-314  2.38838e-314  2.38841e-314
 2.38811e-314  2.38811e-314  2.38838e-314  2.54817e-314

Int64 の,二次元配列を作る。初期化しない。それぞれの次元サイズは 2, 3。

julia> B = Array{Int64}(undef, 2, 3)
2×3 Array{Int64,2}:
 4529053184  74           0
 4529478432  30  4632025920

Union{Missing, String} 型の配列。初期化は missing(missing value)。

julia> Array{Union{Missing, String}}(missing, 2)
2-element Array{Union{Missing, String},1}:
 missing
 missing

julia> Array{Union{Missing, Int}}(missing, 2, 3)
2×3 Array{Union{Missing, Int64},2}:
 missing  missing  missing
 missing  missing  missing

UndefInitializer() は undef と同じもの。

julia> Array{Float64,1}(UndefInitializer(), 3)
3-element Array{Float64,1}:
 2.2883369826e-314
 2.368470051e-314
 2.3656390153e-314

コメント
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

Julia -- 9(制御構文)

2020年12月25日 | ブログラミング

制御構文

複合式  begin, ;

begin と end で囲まれた式を,順に実行する。最後の式の評価値が返される。

julia> z = begin
               x = 1
               y = 2
               x + y
           end
3

1 行に 1 つの式しか書けないということではない。一行にまとめて書くこともできる。それぞれの式は ';' で区切ればよい。

julia> begin x = 1; y = 2; x + y end
3

'begin''end' で囲む代わりに '( )' で囲んでもよい。

julia> z = (x = 1; y = 2; x + y)
3

もちろん,この場合も行を分けてもよい。

julia> (x = 1;
        y = 2;
        x + y)
3

条件評価 if-elseif-else, 三項演算子 ?:

julia> function test(x, y)
           if x < y
               println("x is less than y")
           elseif x > y
               println("x is greater than y")
           else
               println("x is equal to y")
           end
       end
test (generic function with 2 methods)

julia> test(1, 2)
x is less than y

julia> test(2, 1)
x is greater than y

julia> test(1, 1)
x is equal to y

他のプログラム言語とは違うかもしれないが,Julia の if ブロックはローカルスコープを作らないので,if ブロック内で定義された変数はその外でも使える(筆者注:多くの言語経験者は,「当たり前だろう」と思うかも知れないが)。

Julia の if ブロックは,最後に実行された文(式)の値を戻り値とする。

julia> x = 3;

julia> if x > 0
           "positive!"
       else
           "negative..."
       end
"positive!"

他の多くのプログラミング言語とは異なり,条件式は true か false いずれかの評価値を持つものでなければならない。

julia> if 1 println("true") end
ERROR: TypeError: non-boolean (Int64) used in boolean context

julia> if true println("true") end
true

2 つ上の例は,三項演算子を用いて書くことができる。

julia> x = 10; x > 0 ? "positive!" : "negative..."
"positive!"

julia> x = -10; x > 0 ? "positive!" : "negative..."
"negative..."

複雑にすることも出来る。

julia> test(x, y) = println(x < y ? "x is less than y"    :
                            x > y ? "x is greater than y" : "x is equal to y")
test (generic function with 2 methods)

julia> test(1, 2)
x is less than y

julia> test(2, 1)
x is greater than y

julia> test(1, 1)
x is equal to y

ショート・サーキット評価 &&, ||, チェイン比較

a && b という論理式で,a が true  のときのみ b が評価される。
a || b という論理式で,a が false のときのみ b が評価される。

if   end は, && と同じである。
if ! end は, || と同じである。

これにより,if ブロックを書かずに式を記述できる。

julia> function fact(n::Int)
           n >= 0 || error("n must be non-negative")
           n == 0 && return 1
       end
fact (generic function with 1 method)

julia> fact(-3)
ERROR: n must be non-negative

julia> fact(0)
1

julia> fact(5)
120

&&,|| のオペランドは最後のものは何でもよいが,それ以外は true, false を返すものでなくてはならない。

julia> 1 && true
ERROR: TypeError: non-boolean (Int64) used in boolean context

julia> true && (1, 2, 3)
(1, 2, 3)

julia> false && (1, 2, 3)
falseビット論理演算子  &, |

&&, || と違い,ショート・サーキット評価は行われない。全てのビットが評価される。

julia> 0b0101 & 0b1110 
0x04

julia> 0b0101 | 0b1110
0x0f


繰り返し評価  while, for

while

julia> i = 1;

julia> while i <= 5
           println(i)
           global i += 1 # global って,何だろう?
       end
1
2
3
4
5

for

for ループの外(後)では i は未定義になる。つまり,i のスコープは for ループ内だけである。

julia> for i = 1:5
           println(i)
       end
1
2
3
4
5

julia> for i in 1:4
           println(i)
       end
1
2
3
4

in と ∈

julia> for i in [1, 4, 0]
           println(i)
       end
1
4
0

julia> for s ∈ ["foo","bar","baz"]
           println(s)
       end
foo
bar
baz

break によるループからの脱出

julia> i = 1;

julia> while true
           println(i)
           if i >= 5
               break
           end
           global i += 1
       end
1
2
3
4
5

julia> for j = 1:1000
           println(j)
           if j >= 5
               break
           end
       end
1
2
3
4
5

continue によるループの一部分スキップ

julia> for i = 1:10
           if i % 3 != 0
               continue
           end
           println(i)
       end
3
6
9

複数の for ループの組み合わせ

julia> for i = 1:2, j = 3:4
           println((i, j))
       end
(1, 3)
(1, 4)
(2, 3)
(2, 4)

例外処理

ArgumentError

BoundsError

CompositeException

DimensionMismatch

DividError

DomainError

julia> sqrt(-1)
ERROR: DomainError with -1.0:

EOFError

ErrorException

InexactError

InitError

InterruptException

InvalidStateException

KeyError

LoadError

OutOfMemoryError

ReadOnlyMemoryError

RemoteException

MethodError

OverflowError

Meta.ParseError

SystemError

TypeError

UndefRefError

UndefVarError

StringIndexError

ユーザが定義できる例外

julia> struct MyCustomException <: Exception end

throw 関数

throw により,明示的に例外を作ることができる。

julia> f(x) = x>=0 ? exp(-x) : throw(DomainError(x, "argument must be nonnegative"))
f (generic function with 2 methods)

julia> f(1)
0.36787944117144233

julia> f(-1)
ERROR: DomainError with -1:
argument must be nonnegative

julia> typeof(DomainError(nothing)) <: Exception
true

julia> typeof(DomainError) <: Exception
false

julia> throw(UndefVarError(:x))
ERROR: UndefVarError: x not defined

julia> struct MyUndefVarError <: Exception
           var::Symbol
       end

julia> Base.showerror(io::IO, e::MyUndefVarError) = print(io, e.var, " not defined")

error 関数

error 関数は,正常な制御の流れを遮る ErrorException を生成するために使われる。

julia> fussy_sqrt(x) = x >= 0 ? sqrt(x) : error("negative x not allowed")
fussy_sqrt (generic function with 1 method)

julia> fussy_sqrt(2)
1.4142135623730951

julia> fussy_sqrt(-1)
ERROR: negative x not allowed

try/catch 文

julia> try
           sqrt("ten")
       catch e
           println("You should have entered a numeric value")
       end
You should have entered a numeric value

julia> sqrt_second(x) = try
           sqrt(x[2])
       catch y
           if isa(y, DomainError)
               sqrt(complex(x[2], 0))
           elseif isa(y, BoundsError)
               sqrt(x)
           end
       end
sqrt_second (generic function with 1 method)

julia> sqrt_second([1 4])
2.0

julia> sqrt_second([1 -4])
0.0 + 2.0im

julia> sqrt_second(9)
3.0

julia> sqrt_second(-9)
ERROR: DomainError with -9.0:

finally 句

finally 句には例外処理の後始末を書く。

f = open("file")
try
    # operate on file f
finally
    close(f)
end

タスク(共同関数) yieldto

コメント
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

Julia -- 5(関数)

2020年12月25日 | ブログラミング

関数定義 -- 伝統的形式

'function' で始まり,関数名,仮引数のタプルが続く。
2 行目から関数の内容を記述する。
一番最後に評価された式の値が戻り値になる。
'return 戻り値' で任意の時点で呼出元へ復帰することもできる。
戻り値がない場合は 'return nothing' とする。
最後の行は 'end'

julia> function f(x, y)
           x + y
       end
f (generic function with 1 method)

関数の引用

julia> f(1, 3)
4

関数定義 -- 代入文形式

julia> f(x, y) = x + y
f (generic function with 1 method)

右辺は 1 つの式でなければならないが,(begin - end で囲まれた)複合式でもよい。

julia> g(n) = begin # 階乗の計算
                 ans = 1
                 for i = 1:n
                    ans*= i
                 end
                 ans
              end
g (generic function with 1 method)

無名関数の定義

名前なしの関数を定義し,変数に代入し,変数を関数名のように使うことができる。
よくある使い方は,後に出てくる map 関数で使う方法。

julia> h = x -> x^2 + 2x - 1;

julia> h(3)
14

julia> i = function (x)
           x^2 +2x - 1
       end
#13 (generic function with 1 method)

julia> i(3)
14

2 個以上の引数を持つ無名関数の定義

julia> (x,y,z)->2x+y-z
#17 (generic function with 1 method)

引数を持たない無名関数の定義

julia> () -> 3
#19 (generic function with 1 method)

関数の戻り値のタイプ指定

julia> function g(x, y)::Int8
          return x * y
       end;

julia> typeof(g(2, 4))
Int8

関数の引用

julia> f(1, 3)
4

julia> g(5)
120

高階関数  map()

julia> map(round, [1.2, 3.5, 1.7])
3-element Array{Float64,1}:
 1.0
 4.0
 2.0

julia> map(sqrt, [1.2 3.5 1.7])
1×3 Array{Float64,2}:
 1.09545  1.87083  1.30384

julia> map(x -> x^2 + 2x - 1, [1.2 3.5 1.7])
1×3 Array{Float64,2}:
 2.84  18.25  5.29

タプル

丸括弧 ( ) とカンマ , で構成され,インデックスでアクセスできる。

julia> (1, 1+2)
(1, 3)

julia> (1,) # 要素数が 1 の場合は , が必要
(1,)

julia> () # 空のタプル
()

julia> x = (0.3, "Hello", 6*7)

(0.3, "Hello", 42)

julia> x[1]
0.3

名前付きのタプル

julia> x = (a=2, b=4+6, c="aaa")
(a = 2, b = 10, c = "aaa")

julia> x[1] # インデックスで参照
2

julia> x.b # 名前で参照
10

複数の結果をタプルで返す関数

julia> function foo(a, b)
           a+b, a*b # 2 個の値を返す return (a+b, a*b) と書いてもよい
       end
foo (generic function with 1 method)

julia> foo(2, 3) # 結果がタプルで戻る
(5, 6)

julia> x, y = foo(2, 3) # タプルを分解して代入する
(5, 6)

julia> x # 1 番目の結果
5

julia> y # 2 番目の結果
6

関数の引数にタプルを使う

julia> minmax(x, y) = (y < x) ? (y, x) : (x, y) # 三項演算子
minmax (generic function with 1 method)

julia> gap((min, max)) = max - min
gap (generic function with 1 method)

julia> gap(minmax(10, 2))
8

引数可変関数

引数の個数が固定ではない関数の定義

julia> bar(a,b,x...) = (a,b,x)
bar (generic function with 1 method)

julia> bar(1, 2)
(1, 2, ())

julia> bar(1, 2, 3)
(1, 2, (3,))

julia> bar(1, 2, 3, 4, 5, 6)
(1, 2, (3, 4, 5, 6))

デフォルト値を持つ引数(オプショナルな引数)

たとえば,以下の関数は x, y の 2 つの引数を持つが,y が与えられなかったときは,それぞれ y = 1 であると解釈される。

julia> function test(x, y=3)
           return x * y
       end
test (generic function with 2 methods)

julia> test(4, 8) # 4 * 8
32

julia> test(5) # 5 * 3
15

キーワード引数

キーワード引数はセミコロン ';' の後にまとめて定義される。

julia> function test2(x; y=3)
           return x + y
       end
test2 (generic function with 1 method)

関数を呼び出すときに,キーワード引数を区切るセミコロン ';' はオプショナルである。

julia> test2(2; y=3)
5

以下のように書くのが普通である。

julia> test2(1, y=10)
11

キーワード引数が省略されたときは,デフォルト値が使われる。

julia> test2(3) # test2(3, y=3) と同じ
6

しかし,定義するときにはキーワード名を省略することはできない。

julia> test2(2, 3)
ERROR: MethodError: no method matching 

デフォルト値を持たないキーワード引数を定義できるが,使用する場合には実引数を指定しないとエラーになる。

julia> function test3(x; y)
           return x^y
       end
test3 (generic function with 1 method)

julia> test3(2, y=4)
16

関数の引数のための DO-ブロック構文

julia> A = 1; B = 2; C = 3
3

以下のように書くところを,

julia> map(x->begin
                  if x < 0 && iseven(x)
                      return 0
                  elseif x == 0
                      return 1
                  else
                      return x
                  end
              end,
           [A, B, C])
3-element Array{Int64,1}:
 1
 2
 3

以下のように書くことができる。

julia> map([A, B, C]) do x
           if x < 0 && iseven(x)
               return 0
           elseif x == 0
               return 1
           else
               return x
           end
       end
3-element Array{Int64,1}:
 1
 2
 3

関数の組み立てとパイプ

f, g が関数のとき,(f ∘ g)(引数...) は f(g(引数...)) と同じことを意味する。

対話モードのとき,'∘' は '\circ' で入力できる。

 julia> (sqrt ∘ +)(3, 6)
3.0

julia> sqrt(+(3, 6)) # +(3, 6) は 3 + 6 と同じ
3.0

関数の評価結果を次の関数に渡す(パイプする)ことができる。

julia> 1:10 |> sum |> sqrt
7.416198487095663

1:10 は 1 から 10 までの整数ベクトル。それを sum 関数に渡して sum(1:10) = 55が求められる。さらにそれを sqrt 関数に渡して sqrt(55) = 7.416198487095663 が求められる。

今の場合,以下と同じことになる。

julia> (sqrt ∘ sum)(1:10)
7.416198487095663

ブロードキャスティング

'.|>' とパイプ,ドット・ベクトル化構文を合わせると以下のようなこともできる。

julia> ["a", "list", "of", "strings"] .|> [uppercase, reverse, titlecase, length]
4-element Array{Any,1}:
  "A"
  "tsil"
  "Of"
 7

ドット・ベクトル化構文  .(ベクトル)

ベクトルの各要素に対して働く関数がある。

julia> A = [1.0, 2.0, 3.0];

julia> sin.(A)
3-element Array{Float64,1}:
 0.8414709848078965
 0.9092974268256817
 0.1411200080598672

julia> f(x, y) = 3x + 4y
f (generic function with 1 method)

julia> f.(pi, A)
3-element Array{Float64,1}:
 13.42477796076938
 17.42477796076938
 21.42477796076938

julia> 3pi + 4 * 1
13.42477796076938

julia> B = [4.0, 5.0, 6.0]
3-element Array{Float64,1}:
 4.0
 5.0
 6.0

julia> f.(A, B)
3-element Array{Float64,1}:
 19.0
 26.0
 33.0

julia> 3 * 1 + 4 * 4
19

ネストされた関数は 1 重のブロードキャスト・ループに融合される。

以下の 3 通りの書き方は,全て同じことである。

julia> X = [1, 2, 3];

julia> sin.(cos.(X))
3-element Array{Float64,1}:
  0.5143952585235492
 -0.4042391538522658
 -0.8360218615377305

julia> broadcast(x -> sin(cos(x)), X)
3-element Array{Float64,1}:
  0.5143952585235492
 -0.4042391538522658
 -0.8360218615377305

julia> [sin(cos(x)) for x in X]
3-element Array{Float64,1}:
  0.5143952585235492
 -0.4042391538522658
 -0.8360218615377305

 'ドット・バージョン' に変換  '@.' 

'@.' は,式の中にある,全ての関数呼び出し,演算,代入を 'ドット・バージョン' に変換する。

julia> Y = [1.0, 2.0, 3.0, 4.0];

julia> X = similar(Y); # 事前に結果を格納するためのベクトルを用意する

julia> @. X = sin(cos(Y)) #  X .= sin.(cos.(Y)) と同じ
4-element Array{Float64,1}:
  0.5143952585235492
 -0.4042391538522658
 -0.8360218615377305
 -0.6080830096407656

ドット演算と,関数チェイン '.|>'

ドット演算と,関数チェイン '.|>' を組み合わせると,以下のようなこともできる。

julia> [1:5;] .|> [x->x^2, inv, x->2*x, -, isodd]
5-element Array{Real,1}:
    1
    0.5
    6
   -4
 true

 

 

コメント
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

PVアクセスランキング にほんブログ村

PVアクセスランキング にほんブログ村