Julia 프로그래밍 언어로 프랙탈 만들기
나 자신을 먼저 소개하겠습니다:
평소 수학을 좋아했기 때문에 어떻게 하면 프로그래밍을 재미있게 할 수 있을지, 내가 재미있을 수 있는 일, (기술적인) 내용을 모르는 다른 사람들과 공유할 수 있는 일이 무엇일지 고민했습니다.
선택의 여지가 많지만 시각적 측면이 특히 보람이 있기 때문에 많은 프랙탈을 사용하게 됩니다.
저는 높은 수준의 빠른 프로그래밍 언어인 Julia로 작업합니다. 이것은 Julia 자체에 대한 튜토리얼이 아니며 라이브러리에 대한 약간의 내용입니다. 제가 한 일과 방법을 보여주기 위한 것입니다.
사용한 패키지:
정말 간단하게 시작해 봅시다. 2D는 워밍업으로 스파이럴을 해봅시다. 이를 위해 이 나선의 모든 점을 플로팅하고 연결합니다. 그리고 사용자가 원하는 원의 수를 선택하게 하십시오(실제 프랙탈을 만들려면 무한대가 됩니다).
using GLMakie
function spiral_point(n)
rot = (ℯ^(im*n)) # set up the rotation of the point
point = rot/n
(point.re, point.im) # this point converge to (0, 0) as n grows
end
function spiral(n) # where n is the number of spirals
V = Tuple{Float64, Float64}[]
for i in 1:0.01:2π*n
push!(V, spiral_point(i))
end
V
end
println("How many spirals do you want? (number in N)")
const num = parse(Int, readline())
spiral(num) |> lines |> display
나는 개인적으로 n이 커짐에 따라 세부 사항을 충분히 변경하지 않는 것이 마음에 들지 않습니다. 처음에는 느리고 더 빠르면 더 시원하고 더 많은 세부 사항을 표시합니다. 이를 위해 그래디언트 기능을 수행해 보겠습니다.
using GLMakie
function gradient(n)
f(x) = √(x/n)
end
function spiral_point(n, f)
rot = (ℯ^(im*n))
point = rot/f(n)
(point.re, point.im)
end
function spiral(n, f)
V = Tuple{Float64, Float64}[]
for i in 1:0.01:2π*n
push!(V, spiral_point(i, f))
end
V
end
println("How many spirals do you want? (number in N)")
const num = parse(Int, readline())
spiral(num, gradient(num)) |> lines |> display
훨씬 좋아 보인다. 커스터마이징에 유용한 기술.
재귀는 프랙탈을 생성하는 일반적인 기술입니다. n이 작을 때 정말 멋져 보이고 n이 클 때 정말 친숙해 보이는 예를 보여드리겠습니다 :)
using Luxor
const N = 9 # change that to change the deps
const SIZE = 2700 # change that to resize the image
const NAME = "MyLovelyFractal.png" # change that to change the name of your .png file you'll receive
function points(x, y, size, l=Tuple{Int, Int}[])
0 == size && return x, y, [l; (x, y)]
x, y, l = points(x, y, size-1, l)
y -= 2^(size-1)
x -= 2^(size-1) - 1
x, y, l = points(x, y, size-1, l)
x += 1
y += 2^(size-1)
points(x, y, size-1, l)
end
p(s) = points(0, 0, s)[end]
function main()
v = p(NUM)
Drawing(SIZE, SIZE, NAME)
origin(0, SIZE)
setcolor("blue")
for i in 1:length(v)-1
line(Point(v[i])*5, Point(v[i+1])*5, :stroke)
end
finish()
preview()
end
main()
나는이 작은 것을 자랑스럽게 생각합니다 :)
보시다시피 n이 커질수록 Sierpinski 삼각형처럼 보입니다.
Sierpinski 삼각형에 대해 말하자면, 우리는 라인 섹션에 있으므로 Lindenmayer-System을 사용하여 이를 수행하는 것은 어떻습니까?
using Lindenmayer
Sierpinski = LSystem(Dict("G" => "F+G+F", "F" => "G-F-G"), "F")
drawLSystem(Sierpinski,
forward = 6,
startingorientation = 0,
turn = 60,
iterations = 6,
filename = "Sierpinsky.png")
힐베르트의 경우:
Hilbert = LSystem(Dict("X" => "-YF+XFX+FY-", "Y" => "+XF-YFY-FX+"), "X")
# rotation unit = -90
일부 식물의 경우:
Plant = LSystem(Dict("F" => "FF+[+F-F-F]-[-F+F+F]"), "F")
# rotation uni = 22.5
가능성을 생각해 보세요!✨✨✨
프랙탈을 찾을 때 식물을 그리는 많은 방법을 보게 될 것이므로 또 다른 방법을 만들어 보겠습니다. 이번에는 임의의 숫자를 사용하여 마지막으로 선 대신 점 방향으로 흩어지기 시작합니다(더 많은 유연성을 허용함).
using GLMakie
f1(x, y) = [0 0; 0 0.16] * [x, y]
f2(x, y) = [0.85 0.04; -0.04 0.85] * [x, y] + [0, 1.6]
f3(x, y) = [0.2 -0.26; 0.23 0.22] * [x, y] + [0, 1.6]
f4(x, y) = [-0.15 0.28; 0.26 0.24] * [x, y] + [0, 0.44]
function f(x, y)
r = rand()
r < 0.01 && return f1(x, y)
r < 0.86 && return f2(x, y)
r < 0.93 && return f3(x, y)
f4(x, y)
end
function barnsley_fern(iter)
X = [0.0]
Y = [0.0]
for i in 1:iter
x, y = f(X[end], Y[end])
push!(X, x)
push!(Y, y)
end
scatter(X, Y, color=:green, markersize=1)
end
barnsley_fern(1_000_000)
이제 포인트 기반 프랙탈을 수행하고 있으므로 mandelbrot 및 Julia의 세트를 수행할 수 있습니다!
f(z, c) = z*z + c
function is_stable(iter, z, c)
for _ in 1:iter
if abs(z) > 2
return false
end
z = f(z, c)
end
true
end
function mandel(precision, X, Y, f) # passing this f will be explained just after
Points = Tuple{Float64, Float64}[]
for x in X
for y in Y
z = f(x, y)
if is_stable(precision, z, z)
push!(Points, (x, y))
end
end
end
scatter(Points, markersize=1)
end
function julia(precision, X, Y, c, f)
Points = Tuple{Float64, Float64}[]
for x in X
for y in Y
z = f(x, y)
if is_stable(precision, z, c)
push!(Points, (x, y))
end
end
end
scatter(Points, markersize=4)
end
mandel(80, -2:0.0025:2, -2:0.0025:2, Complex) |> display
sleep(10)
julia(80, -2:0.0005:2, -2:0.0005:2, -0.8im, Complex) |> display
줄리아에서 만든 줄리아 세트, 사랑스러워요.
이제... 왜 내가
f
를 통과했습니까? Welp, 그것이 어떻게 작동하는지 보기 위해 직접 만들기로 결정할 수 있기 때문입니다 :)이 예제는 3D이므로 내가 만든 함수 중 일부를 재사용하지 않았지만 아이디어를 얻을 수 있습니다.
using CliffordAlgebras, GLMakie
const S = CliffordAlgebra(1, 1, 0)
const e1 = S.e1
const e2 = S.e2
# f definition
# is_stable definition
import Base.abs
abs(n::MultiVector) = vector(n) .^ 2 |> sum |> sqrt # type piracy /(o_o)\
function mandel(precision, X, Y, Z, f)
Points = Tuple{Float64, Float64, Float64}[]
for x in X
for y in Y
for z in Z
num = f(x, y, z)
if is_stable(precision, num, num)
push!(Points, (x, y, z))
end
end
end
end
Points
end
const RANGE = -2:0.05:2
fun(a, b, c) = a + b*e1 + c*e2
mandel(50, RANGE, RANGE, RANGE, fun) |> (x -> scatter(x, markersize=4))
이제 Cl(1, 1, 0)에 정의된 만델브로트 세트의 3D 슬라이스가 있습니다.
그리고 이제 마지막 부분, 애니메이션 덕분에 이 전체 세트를 볼 수 있습니다!
fun(a, b, c)
까지 동일한 코드가 있다고 가정해 보겠습니다.n = Observable(0.0)
fn = lift(d -> (a, b, c) -> (a + b*e1 + c*e2 + d*e1*e2), n)
p = lift(f -> mandel(50, RANGE, RANGE, RANGE, f), fn)
fig, axe = scatter(p)
const frames = 1:28
record(fig, "Cl1-1-0_4DMandel.gif", frames; framerate=28) do frame
n[] = -1.5+frame/10
end
보다? 통과
f
의 도움으로 많은 일을 할 수 있습니다!그래서 여기에서 끝입니다. CliffordAlgebra(1, 1, 0)에 정의된 경우 mandelbrot 세트 전체를 본 행운의 사람 중 한 명입니다(모든 누락된 점 제외...)!
흥미로웠기를 바랍니다.
그래서, 왜 줄리아?
모든 컴파일 시간이고 TTFP는 진짜이기 때문에 눈치채지 못할 수도 있지만 Julia는 정말 빠릅니다. 일단 알고리즘이 다운되면 Python에서 할 수 있는 것보다 훨씬 더 많은 반복을 실행할 수 있습니다.
그것은 정말 훌륭한 수학 능력을 가지고 있고 표기법에서 수학에 가깝고 매우 자연스럽게 느껴집니다.
그것은 매우 표현력이 풍부하며, 무언가를 잘 작동시키는 것을 더 쉽게 만듭니다.
멋진 커뮤니티, 저는 Human of Julia(discord) 서버의 일부 사람들을 정말 좋아합니다.
Reference
이 문제에 관하여(Julia 프로그래밍 언어로 프랙탈 만들기), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/juliapbn/building-fractals-with-the-julia-programming-language-22ao텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)