curryで数論関数
目で見る合同1次方程式の解
1。カリー化で1変数化
このワークシートはMath by Codeの一部です。
前回はzipを使うと、yがxの単純な代数的な数式でなくても関数が作れることがわかったね。
今回はカリー化を使ってみよう。
数学の関数、特に数論で使う関数は2以上の変数の関数が多いけど、
多変数関数はコード化がしにくい。
そこで、高階関数をサポートしている言語で可能なカリー化を使ってみよう。
たとえば、xとyの2変数関数zがあるとしたら、
zを出すにはxとyを同時に入れないといけない。
でも、関数利用の場面では、xを一時的に定数にして、yだけ動かしたり、yを固定してxだけ動かして調べるとか、いろんな使い方がある。
たとえば、xとyの合計を出すadd(x,y)という関数があるとしよう。
これを細切りして、xを入れて、yをあとで入れてadd(x,y)を出すと再定義したcurryAddを作る。
すると、add_ten = curryAdd(10)とすると、x=10を固定した1変数関数add_ten(y)として
扱うことができるね。
#[OUT]julia
#======================
function add(x, y)
return x + y
end
curryAdd = x -> y -> add(x, y)
add_ten = curryAdd(10)
println(add_ten(5))
#======================
[OUT]
15
2.数論関数をカレー化して使おう
一番単純な合同1次方程式はどんな式だろうか?
ax≡b (mod p)
とかけるね。
これを関数とみると、z=f(a,k,p)という3変数関数の値がbと等しくなるのを探すことになる。
問題によって、a,k,p,bの値が変わると、探し方も変わるね。
さあて、落ち着いて考えてみよう。
xの値はmod pの剰余だから、
bが0でないなら、 xは1からp-1を動かして調べることになる。
ということは、z=f(a,k,p)=bを探すのではなくz=f(a,p)=bを探せばよいことがわかる。
探し方はfの中でxを動かした結果としてzをリストで返し、そこにbを探せばよい。
では、juliaで作ってみよう
<juliaで合同1次方程式を解く>
#=====================================
# ax≡b(mod p)の解がx
function multmod(a,p)
k=1:p
return [a*x % p for x in k]
end
crrymmod = p -> a -> multmod(a, p)
# (例1)4x≡3(mod 19)」の解は? x ≡15
p=19;a=4;b=3
mm = crrymmod(p)
x=findfirst(isequal(b),mm(a))
#=====================================[OUT]
15
#===========================================
#(例2)「4x≡16(mod 28)」の解は? x ≡ 4 (mod 7)
p=29;a=4;b=16
mm = crrymmod(p)
x=findfirst(isequal(b),mm(a))
#===========================================
[OUT]
7
#===========================================
#(例3)「18x≡8(mod 14)」の解は? x≡2 ,9 (mod 7)
p=14;a=18;b=8
mm = crrymmod(p)
x=findall(isequal(b),mm(a))
#===========================================
[OUT]
2-element Vector{Int64}:
2
9
3.2次合同方程式を解こう
2次合同方程式もカレー化で、取り組もう。
質問:どのようにして、合同2次方程式が実装できますか。たとえばjuliaで作ってみよう。
#============================================
#x^2+ax≡b(mod p)の解がx
function squaremod(a,p)
k=1:p
return [(x^2+a*x) % p for x in k]
end
crrymmod = p -> a ->squaremod(a,p)
#(例1)x^2+2x≡0(mod 7)の解は? x ≡ 0, 5 (mod 7)
p=7;a=2;b=0
mm = crrymmod(p)
x=findall(isequal(b),mm(a))
#=============================================
[OUT]
2-element Vector{Int64}:
5
7
mod 7なのにx=7がでるのは変だけど、1スタートの7エンドでxを動かしているので仕方ないね。
わかっていれば問題ない。
#============================================
#(例2)x^2+2x-1≡0(mod 7)の解は?x≡ 2, 3 (mod 7)
#左辺-7して因数分解すると、x2+2x-8=(x-2)(x+4)≡0(mod 7)から、x≡2, -4≡2,3(mod 7)
p=7;a=2;b=1
mm = crrymmod(p)
x=findall(isequal(b),mm(a))
#============================================
[OUT]
2-element Vector{Int64}:
2
3
#============================================
#(例3)x^2≡3(mod 10)の解は?なし
p=10;a=0;b=3
mm = crrymmod(p)
x=findall(isequal(b),mm(a))
#============================================
[OUT]
Int64[]
これは解なしということだね。