Newton fraktalları üret


24

Bir fonksiyonun köklerini belirlemek için Newton yöntemini hepiniz biliyorsunuz, değil mi? Bu görevdeki amacım size bu algoritmanın ilginç bir yönünü tanıtmak.

Newton'un algoritması yalnızca belirli, ancak tüm karmaşık girdi değerlerinin çoğuna yakınsak olur. Karmaşık düzlem üzerindeki tüm girdi değerlerinin yönteminin yakınsamasını resmederseniz, genellikle şöyle güzel bir fraktal elde edersiniz:

F (x) = x ^ 3-1 için Newton fraktal Vikipedi Commons görüntü

Özellikler

Bu görevin amacı, bu tür fraktallar üretmektir. Bu, giriş olarak bir polinom elde edeceğiniz ve ilgili fraktal'ı görüntü olarak çıktı olarak seçtiğiniz bir biçimde yazdırmanız gerektiği anlamına gelir.

Giriş

Giriş, boşluklarla ayrılmış karmaşık sayıların bir listesidir. Onlar tarzda aşağı yazılır <Real part><iImaginary part>bu sayı gibi,: 5.32i3.05. Giriş numarasının 4 ondalık basamaktan daha büyük olmadığını ve 1000'den küçük olduğunu varsayabilirsiniz. Bunlardan ilki sıfır olmamalıdır. Örneğin, bu programınıza bir girdi olabilir:

1 -2i7.5 23.0004i-3.8 i12 0 5.1233i0.1

Sayılar, en yüksek güçle başlayan bir polinomun katsayıları olarak yorumlanır. Bu tarifnamenin geri kalanı boyunca, girdi polinomu P olarak adlandırılır . Yukarıdaki giriş bu polinom eşittir:

f (x) = x 5 + (-2 + 7,5 i ) x 4 + (23,0004 - 3,8 i ) x 3 + 12 i x 2 + 5,1233 + 0,1 i

Girdi, size stdin'den, programa iletilen bir argümandan veya programınıza görüntülenen bir istemden gelebilir. Girişin baştaki veya sondaki boşluk karakterleri içermediğini varsayabilirsiniz.

sıva

Fraktal aşağıdaki şekilde yapılmalıdır:

  • P'nin kökleri kadar fazla renk ve sapma için ekstra bir renk seçin
  • Görünür düzlemdeki her sayı için, yöntemin yakınsak olup olmadığını ve eğer varsa hangi köke doğru olduğunu belirleyin. Noktayı, sonuçlara göre renklendirin.
  • Cetvelleri veya diğer süslü şeyleri yazdırmayın
  • Noktalara, yani oryantasyon için polinomların kökleri olan siyah bir nokta yazdırın. Her kök çevresine dört adede kadar piksel yazdırabilirsiniz.
  • Görünür düzlemi bir şekilde seçmenin, tüm köklerin ayırt edilebildiği ve mümkünse geniş bir alana yayılacağı bir yol bulun. Çıktı çerçevesinin mükemmel bir şekilde yerleştirilmesine gerekmese de, çerçeveyi kabul edilemez bir şekilde seçen bir cevabı kabul etmeyi reddetme hakkını saklı tutarım, örn. her zaman aynı koordinatlarda, tüm kökler bir noktada, vb.
  • Çıktı görüntüsünün boyutu 1024 * 1024 piksel olmalıdır.
  • Render süresi en fazla 10 dakikadır.
  • Tek duyarlıklı kayan nokta değerleri kullanmak yeterlidir

Çıktı

Çıktı, bir marka X işletim sistemi için standart yazılımla okunabilen, seçtiğiniz bir dosya biçiminde raster grafik görüntüsü olmalıdır. Nadir bir format kullanmak istiyorsanız, web sitesine bir görüntüleyici indirebileceğiniz bir link eklemeyi düşünün.

Dosyayı stdout'a gönder. Diliniz stdout'a bir şey koymayı desteklemiyorsa veya bu seçeneği daha az kullanışlı buluyorsanız, başka bir yol bulun. Herhangi bir şekilde, oluşturulan görüntünün kaydedilmesi mümkün olmalıdır.

Kısıtlamalar

  • Görüntü işleme kütüphanesi yok
  • Fraktal üreten kütüphane yok
  • En kısa kod kazanır

Uzantıları

Bu görevi seviyorsanız, noktaları yakınsama hızına veya diğer bazı kriterlere göre renklendirmeyi deneyebilirsiniz. Bazı ilginç sonuçlar görmek istiyorum.


6
Bunun kod golfü olarak uygun olup olmadığından tam olarak emin değilim. Gözlerimde görev çok karmaşık. Yine de yanlış olduğumu kanıtlamış olabilirim.
Joey

5
@Joey: Gerçekten. Bunun kendim için bir kod yarışması olmasını istiyorum.
Joey Adams

2
... veya bu konuda PPM.
Joey

1
@Joey: Niyetim, çoğu insan çok kolay işlerden hoşlanmadığı için oldukça zor bir iş yaratmaktı.
FUZxx

1
Kolayca ayrı işlere bölünür ve eğer diliniz doğal olarak karmaşık kayan nokta sayılarını destekliyorsa, büyük bir yığın tasarruf edebilirsiniz. 1600 karakterde çalışan, 340'ı karmaşık sayı sınıfı olan, tam olarak golf oynamayan bir sürümüm var. Henüz kökleri tanımlamıyor ve renkleri kullanmıyor, ancak NR kodunda bir hata olduğunu varsaydığımı bulmaya çalışıyorum. (-0.5 + 0.866i ile başlayan x ^ 3-1 kökünü bulmak kesinlikle ayrılmamalı!)
Peter Taylor

Yanıtlar:


13

Python, 827 777 karakter

import re,random
N=1024
M=N*N
R=range
P=map(lambda x:eval(re.sub('i','+',x)+'j'if 'i'in x else x),raw_input().split())[::-1]
Q=[i*P[i]for i in R(len(P))][1:]
E=lambda p,x:sum(x**k*p[k]for k in R(len(p)))
def Z(x):
 for j in R(99):
  f=E(P,x);g=E(Q,x)
  if abs(f)<1e-9:return x,1
  if abs(x)>1e5or g==0:break
  x-=f/g
 return x,0
T=[]
a=9e9
b=-a
for i in R(999):
 x,f=Z((random.randrange(-9999,9999)+1j*random.randrange(-9999,9999))/99)
 if f:a=min(a,x.real,x.imag);b=max(b,x.real,x.imag);T+=[x]
s=b-a
a,b=a-s/2,b+s/2
s=b-a
C=[[255]*3]*M
H=lambda x,k:int(x.real*k)+87*int(x.imag*k)&255
for i in R(M):
 x,f=Z(a+i%N*s/N+(a+i/N*s/N)*1j)
 if f:C[i]=H(x,99),H(x,57),H(x,76)
for r in T:C[N*int(N*(r.imag-a)/s)+int(N*(r.real-a)/s)]=0,0,0
print'P3',N,N,255
for c in C:print'%d %d %d'%c

Bir grup rastgele örnek için yakınsama noktaları bularak ekran sınırlarını (ve köklerini) bulur. Daha sonra her bir başlangıç ​​noktası için yakınsama noktalarını hesaplayarak ve her bir yakınsama noktası için rasgele renkler elde etmek için bir karma işlevini kullanarak grafiği çizer. Çok yakından bakınca işaretli kökleri görebilirsiniz.

Örnek polinomun sonucudur.

örneğin polinom sonucu


İyi! Bunu severim.
FUZxxl

14

Java, 1093 1058 1099 1077 karakter

public class F{double r,i,a,b;F(double R,double I){r=R;i=I;}F a(F c){return
new F(r+c.r,i+c.i);}F m(F c){return new F(r*c.r-i*c.i,r*c.i+i*c.r);}F
r(){a=r*r+i*i;return new F(-r/a,i/a);}double l(F c){a=r-c.r;b=i-c.i;return
Math.sqrt(a*a+b*b);}public static void main(String[]a){int
n=a.length,i=0,j,x,K=1024,r[]=new int[n];String o="P3\n"+K+" "+K+"\n255 ",s[];F z=new
F(0,0),P[]=new F[n],R[]=new F[n],c,d,e,p,q;for(;i<n;)P[i]=new
F((s=a[i++].split("i"))[0].isEmpty()?0:Float.parseFloat(s[0]),s.length==1?0:Float.parseFloat(s[1]));double
B=Math.pow(P[n-1].m(P[0].r()).l(z)/2,1./n),b,S;for(i=1;i<n;){b=Math.pow(P[i].m(P[i-1].r()).l(z),1./i++);B=b>B?b:B;}S=6*B/K;for(x=0;x<K*K;){e=d=c=new
F(x%K*S-3*B,x++/K*S-3*B);for(j=51;j-->1;){p=P[0];q=p.m(new
F(n-1,0));for(i=1;i<n;){if(i<n-1)q=q.m(c).a(P[i].m(new
F(n-1-i,0)));p=p.m(c).a(P[i++]);}c=c.a(d=q.r().m(p));if(d.l(z)<S/2)break;}i=j>0?0:n;for(;i<n;i++){if(R[i]==null)R[i]=c;if(R[i].l(c)<S)break;}i=java.awt.Color.HSBtoRGB(i*1f/n,j<1||e.l(c)<S&&r[i]++<1?0:1,j*.02f);for(j=0;j++<3;){o+=(i&255)+" ";i>>=8;}System.out.println(o);o="";}}}

Girdi, komut satırı argümanlarıdır - örn java F 1 0 0 -1. Çıktı, PPM formatında stdout'tur (ASCII pixmap).

Ölçek, bir polinomun karmaşık köklerinin mutlak değerine bağlı Fujiwara kullanılarak seçilir; Daha sonra sınırlamayı 1,5 ile çarptım. Parlaklığı yakınsama oranına göre ayarlarım, böylece kökler en parlak kısımlarda olur. Bu nedenle, köklerin yaklaşık konumlarını işaretlemek için siyah yerine beyaz kullanmak mantıklıdır (ki bu, "doğru" bile yapılamayan bir şey için bana 41 karaktere mal olmaktadır. o zaman bazı kökler etiketsiz olarak çıkar, eğer 0.6 piksel içinde birleşen tüm noktaları etiketlersem, o zaman bazı kökler birden fazla pikselin üzerinde etiketlenirse, her kök için kendisinin 1 pikseli içine yaklaşmak için karşılaşılan ilk noktayı etiketlerim. ).

Örnek polinomun görüntüsü (GIMP ile png'ye dönüştürülür): X ^ 5 + (-2) 7.5i) x ^ 4 + (23.0004-3.8i) x ^ 3 + 12i x ^ 2 + (5.1233 + 0.1i)


@ FUZxxl, görüntü eski versiyonundan. Daha sonra yakınsama oranına sahip bir tane yükleyeceğim. Ancak kökleri işaretlemedeki problem hangi pikselin işaretleneceğini belirlemektir. Kayan nokta ile tam eşitlik testlerini kullanamamanız, bu nedenle bir epsilonla karşılaştırmanız gereken klasik problemdir. Sonuç olarak, kökler için "kanonik" değerlerim yok. Bir adımda birleşen, ancak hiçbir şeyi işaretlemeyi garanti etmeyen ve tek bir kök için 4 piksellik bir blok işaretleyebilen pikselleri işaretleyebilirim.
Peter Taylor

@Peter Taylor: Gördüğünüz gibi, Keith Randall da bu soruna bir çözüm buldu. Bu gereksinimi ekstra bir zorluk olarak ekledim. Bunu yapmak için bir yaklaşım, her kök için en yakın pikseli hesaplamak ve daha sonra her pikseli eşit olarak kontrol etmek olacaktır.
FUZxxl

@ FUZxxl, amacımı anlamadınız. Bir kökün "en yakın pikseli" iyi tanımlanmadı. Ancak, attığınız tüm test vakaları için işe yarayabilecek bir şeyi hackleyebilirim ve sizi mutlu edecek izlenimini edinebilirim. Onu beyaza boyayacağım, siyahı değil çünkü bu daha mantıklı.
Peter Taylor

@Peter Taylor: Tamam.
FUZxxl

6
Profil resmim kısa sürede değişmeli x^6-9x^3+8, kökleri seçerek ve sonra polinomu basitleştirmek için Wolfram Alpha kullanmalı. Tamam, sonradan GIMP'de tonları değiştirerek hile yaptım.
Peter Taylor

3

Python, 633 bayt

import numpy as np
import matplotlib.pyplot as plt
from colorsys import hls_to_rgb
def f(z):
    return (z**4 - 1)
def df(z):
    return (4*z**3) 
def cz(z):
    r = np.abs(z)
    arg = np.angle(z)   
    h = (arg + np.pi)  / (3 * np.pi)
    l = 1.0 - 1.0/(1.0 + r**0.1)
    s = 0.8 
    c = np.vectorize(hls_to_rgb) (h,l,s)
    c = np.array(c)
    c = c.swapaxes(0,2) 
    return c    
x, y = np.ogrid[-1.5:1.5:2001j, -1.5:1.5:2001j]
z = x + 1j*y    
for i in range(10):
    z -= (f(z) / df(z))
zz = z
zz[np.isnan(zz)]=0
zz=cz(zz)
plt.figure()
plt.imshow(zz, interpolation='nearest')
plt.axis('off')
plt.savefig('plots/nf.svg')
plt.close()

Hız Artışı ve Güzelleşmeden Sonra (756 bytes)

import numpy as np
from numba import jit
import matplotlib.pyplot as plt
from colorsys import hls_to_rgb 

@jit(nopython=True, parallel=True, nogil=True)
def f(z):
    return (z**4 - 1)   

@jit(nopython=True, parallel=True, nogil=True)
def df(z):
    return (4*z**3) 

def cz(z):
    r = np.abs(z)
    arg = np.angle(z)   

    h = (arg + np.pi)  / (3 * np.pi)
    l = 1.0 - 1.0/(1.0 + r**0.1)
    s = 0.8 

    c = np.vectorize(hls_to_rgb) (h,l,s)
    c = np.array(c)
    c = c.swapaxes(0,2) 
    return c    

x, y = np.ogrid[-1.5:1.5:2001j, -1.5:1.5:2001j]
z = x + 1j*y    

for i in range(10):
    z -= (f(z) / df(z))

zz = z
zz[np.isnan(zz)]=0
zz=cz(zz)
plt.figure()
plt.imshow(zz, interpolation='nearest')
plt.axis('off')
plt.savefig('plots/nf.svg')
plt.close()

Aşağıdaki çizim log (z) fonksiyonunun Newton Fractal'ı içindir.

Kütüğü için Newton Fractal (z)


Daha kısa (1 karakter) ad kullanabilir ve birden fazla satırı kullanarak birleştirerek boşlukları kaldırabilirsiniz ;. Ayrıca, mümkün olan bütün boşlukları kaldırın.
mbomb007

Bazı düzenli golf oyunları bunu sadece 353 byte'a düşürür ! Test etmedim ( matplotlibburada yok ), bu yüzden hala çalıştığının garantisi yok.
Khuldraeseth na'Barya
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.