Elixirで学び直す高校数学 in Elixir
Mix.install([
{:kino_vega_lite, "~> 0.1.10"},
{:nx, "~> 0.7.0"}
])
Introduction
- https://qiita.com/piacerex/items/6a925db4789feca598c9
- https://qiita.com/piacerex/items/58d80aaf5a8804e90aa7
Plotting graphs
my_data = %{
x: [1, 2, 3, 4, 5, 6, 7],
y: [64.3, 63.8, 63.6, 64.0, 63.5, 63.2, 63.1]
}
VegaLite.new(width: 800, height: 300, title: "my_data")
|> VegaLite.data_from_values(my_data, only: ["x", "y"])
|> VegaLite.mark(:line)
|> VegaLite.encode_field(:x, "x", type: :quantitative)
|> VegaLite.encode_field(:y, "y", type: :quantitative, scale: %{zero: false})
x = 1..11
y =
for i <- x do
3 * i - 24
end
my_data = %{x: x, y: y}
VegaLite.new(width: 800, height: 300, title: "my_data")
|> VegaLite.data_from_values(my_data, only: ["x", "y"])
|> VegaLite.mark(:line)
|> VegaLite.encode_field(:x, "x", type: :quantitative)
|> VegaLite.encode_field(:y, "y", type: :quantitative, scale: %{zero: false})
x-axis step and sample count
np.arange vs np.linspace
- np.arange: 開始/終了/刻み幅
- np.linspace: 開始/終了/要素数
- https://stackoverflow.com/a/62106108/3837223
iota
- 指定した数の 0 からの行列を作成
-
Pythonの
arange
はNxにはないのでNx.iota
をつかって自分で書く
arange = fn start, stop, step ->
how_many = round((stop - start) / step)
Nx.iota({how_many})
|> Nx.multiply(step)
|> Nx.add(start)
end
arange.(1, 3, 0.5)
## y = 3x
start = -1.0
stop = 1.01
step = 0.01
x = arange.(start, stop, step)
y = Nx.multiply(x, 3)
my_data = %{x: Nx.to_list(x), y: Nx.to_list(y)}
## y = 3x
import Nx.Defn
defmodule List33 do
defn triple(x) do
3 * x
end
end
start = -1.0
stop = 1.01
step = 0.01
x = arange.(start, stop, step)
y = List33.triple(x)
my_data = %{x: Nx.to_list(x), y: Nx.to_list(y)}
VegaLite.new(width: 800, height: 300, title: "my_data")
|> VegaLite.data_from_values(my_data, only: ["x", "y"])
|> VegaLite.mark(:line)
|> VegaLite.encode_field(:x, "x", type: :quantitative)
|> VegaLite.encode_field(:y, "y", type: :quantitative)
Solving linear simultaneous equations
a + b = 1
5a + b = 3
Nx.LinAlg.solve(
# 左辺
Nx.tensor([
[1, 1],
[5, 1]
]),
# 右辺
Nx.tensor([
1,
3
])
)
Perpendicular lines
import Nx.Defn
defmodule List35 do
defn perpendicular_lines(x) do
%{
y1: 1 / 2 * x + 1 / 2,
y2: -2 * x + 7
}
end
end
start = -1
stop = 6
step = 1
x = arange.(start, stop, step)
%{y1: y1, y2: y2} = List35.perpendicular_lines(x)
my_data1 = %{x: Nx.to_list(x), y: Nx.to_list(y1)}
my_data2 = %{x: Nx.to_list(x), y: Nx.to_list(y2)}
VegaLite.new(width: 250, height: 500)
|> VegaLite.layers([
VegaLite.new()
|> VegaLite.data_from_values(my_data1, only: ["x", "y"])
|> VegaLite.mark(:line)
|> VegaLite.encode_field(:x, "x", type: :quantitative)
|> VegaLite.encode_field(:y, "y", type: :quantitative),
VegaLite.new()
|> VegaLite.data_from_values(my_data2, only: ["x", "y"])
|> VegaLite.mark(:line)
|> VegaLite.encode_field(:x, "x", type: :quantitative)
|> VegaLite.encode_field(:y, "y", type: :quantitative)
])
Intersection of lines
(-3/2 * x) + (-1 * y) = -6
(1/2 * x) + (-1 * y) = -2
Nx.LinAlg.solve(
# 左辺
Nx.tensor([
[-3 / 2, -1],
[1 / 2, -1]
]),
# 右辺
Nx.tensor([
-6,
-2
])
)
Perpendicular bisector
import Nx.Defn
defmodule List42 do
defn f(x) do
# 基となる線分の傾きと切片
a1 = (5 - 1) / (6 - 0)
b1 = 1
# 線分の中点
cx = (0 + 6) / 2
cy = (1 + 5) / 2
# 線分に直交する直線の傾き
a2 = -1 / a1
# 線分に直交する直線の切片
b2 = cy - a2 * cx
# 直線の式
%{
y1: a1 * x + b1,
y2: a2 * x + b2
}
end
end
x = arange.(0, 8, 1)
y = List42.f(x)
my_data1 = %{x: Nx.to_list(x), y: Nx.to_list(y.y1)}
my_data2 = %{x: Nx.to_list(x), y: Nx.to_list(y.y2)}
VegaLite.new(width: 300, height: 400)
|> VegaLite.layers([
VegaLite.new()
|> VegaLite.data_from_values(my_data1, only: ["x", "y"])
|> VegaLite.mark(:point)
|> VegaLite.encode_field(:x, "x", type: :quantitative)
|> VegaLite.encode_field(:y, "y", type: :quantitative),
VegaLite.new()
|> VegaLite.data_from_values(my_data2, only: ["x", "y"])
|> VegaLite.mark(:line)
|> VegaLite.encode_field(:x, "x", type: :quantitative)
|> VegaLite.encode_field(:y, "y", type: :quantitative)
])
Trigonometric ratios and circles
- Nx.sin や Nx.cos に渡すラジアンを度数から計算する np.radians がNxに無いので、度数法からラジアンに変換する無名関数を作って計算
radians = (degrees / 180) * pi
# 度数をラジアンに変換する関数
radians = fn degrees ->
degrees
|> Nx.divide(180)
|> Nx.multiply(Nx.Constants.pi())
end
# 角度
th = Nx.linspace(0, 360, n: 360)
# 円周上の点Pの座標
x = Nx.sin(radians.(th))
y = Nx.cos(radians.(th))
my_data = %{x: Nx.to_list(x), y: Nx.to_list(y)}
VegaLite.new(width: 500, height: 500)
|> VegaLite.data_from_values(my_data, only: ["x", "y"])
|> VegaLite.mark(:point)
|> VegaLite.encode_field(:x, "x", type: :quantitative)
|> VegaLite.encode_field(:y, "y", type: :quantitative)