Traccia la distribuzione gaussiana in 3D


10

Nella teoria della probabilità, la distribuzione normale (o gaussiana) è una distribuzione di probabilità continua molto comune. Le distribuzioni normali sono importanti nelle statistiche e sono spesso utilizzate nelle scienze naturali e sociali per rappresentare variabili casuali con valori reali le cui distribuzioni non sono note.

La sfida

La tua sfida è quella di tracciare la densità di probabilità della distribuzione gaussiana su un piano tridimensionale . Questa funzione è definita come:

Dove:




A = 1, σ x = σ y = σ

Regole

  • Il tuo programma deve prendere un input σ , la deviazione standard.
  • Il programma deve stampare un grafico 3D della distribuzione gaussiana con la massima qualità consentita dalla propria lingua / sistema.
  • Il tuo programma non può utilizzare una distribuzione gaussiana diretta o una densità di probabilità incorporata.
  • Il tuo programma non deve terminare.
  • La trama può essere in bianco e nero o a colori.
  • La trama deve avere le linee della griglia in basso. Le linee della griglia sui lati (come mostrato negli esempi) non sono necessarie.
  • Non è necessario che i grafici presentino numeri di riga accanto alle linee della griglia.

punteggio

Come al solito nel , vince l'invio con il minor numero di byte! Non potrei mai "accettare" una risposta usando il pulsante, a meno che uno non sia incredibilmente piccolo e intuitivo.

Esempio di output

Il tuo output potrebbe assomigliare a questo:

5

O potrebbe apparire così:

6

Più output validi . Uscite non valide .


Ero confuso che hai appena mostrato la funzione per l'asse X. Dobbiamo prendere input / output separati per X e Y sigma e mu's?
Scott Milner,

Quindi dobbiamo supporre che μ sia uguale a 0? E quale scala hai bisogno per xey? Se gli intervalli x e y sono scelti in modo molto piccolo rispetto a σ, il grafico apparirà essenzialmente come una funzione costante.
Greg Martin,

(Per la distribuzione bidimensionale, penso che sia più chiaro se usi | x-μ | ^ 2 nella definizione piuttosto che (x-μ) ^ 2.)
Greg Martin,

@GregMartin Edited.
MD XF,

2
Ancora non chiaro ... cosa sono x_o e y_o e θ?
Greg Martin,

Risposte:


7

Gnuplot 4, 64 62 61 60 47 byte

(Legato con Mathematica ! WooHoo!)

se t pn;se is 80;sp exp(-(x**2+y**2)/(2*$0**2))

Salvare il codice sopra in un file denominato A.gpe richiamarlo con il seguente:

gnuplot -e 'call "A.gp" $1'>GnuPlot3D.png

dove il $1deve essere sostituito con il valore di σ. Ciò salverà un .pngfile denominato GnuPlot3D.pngcontenente l'output desiderato nella directory di lavoro corrente.

Si noti che questo funziona solo con le distribuzioni di Gnuplot 4 poiché in Gnuplot 5 i $nriferimenti agli argomenti sono stati deprecati e sostituiti con sfortunatamente più prolissi ARGn.

Esempio di output con σ = 3:

Uscita campione

Questa uscita va bene secondo OP .


Gnuplot 4, soluzione alternativa, 60 byte

Ecco una soluzione alternativa che è molto più lunga della precedente ma a mio avviso l'output sembra molto migliore.

se t pn;se is 80;se xyp 0;sp exp(-(x**2+y**2)/(2*$0**2))w pm

Ciò richiede ancora Gnuplot 4 per lo stesso motivo della soluzione precedente.

Esempio di output con σ = 3:

Uscita campione n. 2


I am not sure if it molds to the specifications requiredquali specifiche ritieni che non soddisfino?
MD XF,

@MDXF In primo luogo, non sono sicuro che la trasparenza del grafico sia corretta. Sinceramente non mi piace molto, motivo per cui non ero sicuro che sarebbe andato bene qui. In secondo luogo, il grafico inizia un'unità in alto dal basso per impostazione predefinita, e non sono sicuro che vada bene lo stesso. In terzo luogo, poiché il grafico inizia con un'unità alta, non sono sicuro che la sproporzionalità del grafico rispetto ai grafici forniti nel post originale sia corretta. Tuttavia, se per te va bene, ne farò felicemente la risposta principale.
R. Kap,

@MDXF In effetti, stavo per pubblicarlo come risposta originale, ma per questi motivi ho scelto di non farlo e pubblicato invece dalla risposta corrente.
R. Kap,

@MDXF In realtà, posso renderlo ancora più breve se questo va bene. Capisco se non lo sarà, ma non fa male chiedere. È il modo predefinito per Gnuplottracciare la densità di probabilità della distribuzione gaussiana con un Sigma di 2senza alcuna modifica dell'ambiente.
R. Kap,

@MDXF Immagino che avrei potuto chiedere prima di pubblicare la mia risposta originale, ma al momento ero molto ansioso di pubblicare una risposta.
R. Kap,

14

C ++, 3477 3344 byte

Il conteggio dei byte non include le newline non necessarie.
MD XF ha giocato a golf fuori 133 byte.

C ++ non può competere per questo, ma ho pensato che sarebbe stato divertente scrivere un renderer software per la sfida. Ho strappato e giocato a golf alcuni pezzi di GLM per la matematica 3D e ho usato l'algoritmo di linea di Xiaolin Wu per la rasterizzazione. Il programma genera il risultato in un file PGM denominato g.

Produzione

#include<array>
#include<cmath>
#include<vector>
#include<string>
#include<fstream>
#include<algorithm>
#include<functional>
#define L for
#define A auto
#define E swap
#define F float
#define U using
U namespace std;
#define K vector
#define N <<"\n"
#define Z size_t
#define R return
#define B uint8_t
#define I uint32_t
#define P operator
#define W(V)<<V<<' '
#define Y template<Z C>
#define G(O)Y vc<C>P O(vc<C>v,F s){vc<C>o;L(Z i=0;i<C;++i){o\
[i]=v[i]O s;}R o;}Y vc<C>P O(vc<C>l, vc<C>r){vc<C>o;L(Z i=0;i<C;++i){o[i]=l[i]O r[i];}R o;}
Y U vc=array<F,C>;U v2=vc<2>;U v3=vc<3>;U v4=vc<4>;U m4=array<v4,4>;G(+)G(-)G(*)G(/)Y F d(
vc<C>a,vc<C>b){F o=0;L(Z i=0;i<C;++i){o+=a[i]*b[i];}R o;}Y vc<C>n(vc<C>v){R v/sqrt(d(v,v));
}v3 cr(v3 a,v3 b){R v3{a[1]*b[2]-b[1]*a[2],a[2]*b[0]-b[2]*a[0],a[0]*b[1]-b[0]*a[1]};}m4 P*(
m4 l,m4 r){R{l[0]*r[0][0]+l[1]*r[0][1]+l[2]*r[0][2]+l[3]*r[0][3],l[0]*r[1][0]+l[1]*r[1][1]+
l[2]*r[1][2]+l[3]*r[1][3],l[0]*r[2][0]+l[1]*r[2][1]+l[2]*r[2][2]+l[3]*r[2][3],l[0]*r[3][0]+
l[1]*r[3][1]+l[2]*r[3][2]+l[3]*r[3][3]};}v4 P*(m4 m,v4 v){R v4{m[0][0]*v[0]+m[1][0]*v[1]+m[
2][0]*v[2]+m[3][0]*v[3],m[0][1]*v[0]+m[1][1]*v[1]+m[2][1]*v[2]+m[3][1]*v[3],m[0][2]*v[0]+m[
1][2]*v[1]+m[2][2]*v[2]+m[3][2]*v[3],m[0][3]*v[0]+m[1][3]*v[1]+m[2][3]*v[2]+m[3][3]*v[3]};}
m4 at(v3 a,v3 b,v3 c){A f=n(b-a);A s=n(cr(f,c));A u=cr(s,f);A o=m4{1,0,0,0,0,1,0,0,0,0,1,0,
0,0,0,1};o[0][0]=s[0];o[1][0]=s[1];o[2][0]=s[2];o[0][1]=u[0];o[1][1]=u[1];o[2][1]=u[2];o[0]
[2]=-f[0];o[1][2]=-f[1];o[2][2]=-f[2];o[3][0]=-d(s,a);o[3][1]=-d(u,a);o[3][2]=d(f,a);R o;}
m4 pr(F f,F a,F b,F c){F t=tan(f*.5f);m4 o{};o[0][0]=1.f/(t*a);o[1][1]=1.f/t;o[2][3]=-1;o[2
][2]=c/(b-c);o[3][2]=-(c*b)/(c-b);R o;}F lr(F a,F b,F t){R fma(t,b,fma(-t,a,a));}F fp(F f){
R f<0?1-(f-floor(f)):f-floor(f);}F rf(F f){R 1-fp(f);}struct S{I w,h; K<F> f;S(I w,I h):w{w
},h{h},f(w*h){}F&P[](pair<I,I>c){static F z;z=0;Z i=c.first*w+c.second;R i<f.size()?f[i]:z;
}F*b(){R f.data();}Y vc<C>n(vc<C>v){v[0]=lr((F)w*.5f,(F)w,v[0]);v[1]=lr((F)h*.5f,(F)h,-v[1]
);R v;}};I xe(S&f,v2 v,bool s,F g,F c,F*q=0){I p=(I)round(v[0]);A ye=v[1]+g*(p-v[0]);A xd=
rf(v[0]+.5f);A x=p;A y=(I)ye;(s?f[{y,x}]:f[{x,y}])+=(rf(ye)*xd)*c;(s?f[{y+1,x}]:f[{x,y+1}])
+=(fp(ye)*xd)*c;if(q){*q=ye+g;}R x;}K<v4> g(F i,I r,function<v4(F,F)>f){K<v4>g;F p=i*.5f;F
q=1.f/r;L(Z zi=0;zi<r;++zi){F z=lr(-p,p,zi*q);L(Z h=0;h<r;++h){F x=lr(-p,p,h*q);g.push_back
(f(x,z));}}R g;}B xw(S&f,v2 b,v2 e,F c){E(b[0],b[1]);E(e[0],e[1]);A s=abs(e[1]-b[1])>abs
(e[0]-b[0]);if(s){E(b[0],b[1]);E(e[0],e[1]);}if(b[0]>e[0]){E(b[0],e[0]);E(b[1],e[1]);}F yi=
0;A d=e-b;A g=d[0]?d[1]/d[0]:1;A xB=xe(f,b,s,g,c,&yi);A xE=xe(f,e,s,g,c);L(I x=xB+1;x<xE;++
x){(s?f[{(I)yi,x}]:f[{x,(I)yi}])+=rf(yi)*c;(s?f[{(I)yi+1,x}]:f[{x,(I)yi+1}])+=fp(yi)*c;yi+=
g;}}v4 tp(S&s,m4 m,v4 v){v=m*v;R s.n(v/v[3]);}main(){F l=6;Z c=64;A J=g(l,c,[](F x,F z){R
v4{x,exp(-(pow(x,2)+pow(z,2))/(2*pow(0.75f,2))),z,1};});I w=1024;I h=w;S s(w,h);m4 m=pr(
1.0472f,(F)w/(F)h,3.5f,11.4f)*at({4.8f,3,4.8f},{0,0,0},{0,1,0});L(Z j=0;j<c;++j){L(Z i=0;i<
c;++i){Z id=j*c+i;A p=tp(s,m,J[id]);A dp=[&](Z o){A e=tp(s,m,J[id+o]);F v=(p[2]+e[2])*0.5f;
xw(s,{p[0],p[1]},{e[0],e[1]},1.f-v);};if(i<c-1){dp(1);}if(j<c-1){dp(c);}}}K<B> b(w*h);L(Z i
=0;i<b.size();++i){b[i]=(B)round((1-min(max(s.b()[i],0.f),1.f))*255);}ofstream f("g");f 
W("P2")N;f W(w)W(h)N;f W(255)N;L(I y=0;y<h;++y){L(I x=0;x<w;++x)f W((I)b[y*w+x]);f N;}R 0;}
  • l è la lunghezza di un lato della griglia nello spazio mondiale.
  • c è il numero di vertici lungo ciascun bordo della griglia.
  • La funzione che crea la griglia viene chiamata con una funzione che accetta due input, le coordinate dello spazio mondiale xe z(+ y aumenta) del vertice e restituisce la posizione dello spazio mondiale del vertice.
  • w è la larghezza della pgm
  • h è l'altezza della pgm
  • mè la matrice di visualizzazione / proiezione. Gli argomenti utilizzati per creare msono ...
    • campo visivo in radianti
    • proporzioni della pgm
    • vicino al piano della clip
    • piano di clip lontano
    • posizione della telecamera
    • obiettivo della fotocamera
    • sul vettore

Il renderer potrebbe facilmente avere più funzioni, prestazioni migliori ed essere un golf migliore, ma mi sono divertito!


2
Wow, è incredibile!
MD XF,

1
Niente affatto ... provaci!
Patrick Purcell,

1
Ecco qua, 133 byte di sconto!
MD XF,

1
Questo è fantastico! Se potessi dirmi dove hai imparato tutto ciò, sarebbe fantastico !
HatsuPointerKun

1
@HatsuPointerKun Lieto che ti piaccia! Questo tutorial ... opengl-tutorial.org/beginners-tutorials/tutorial-3-matrices ... è un ottimo punto di partenza.
Patrick Purcell,

9

Mathematica, 47 byte

Plot3D[E^(-(x^2+y^2)/2/#^2),{x,-6,6},{y,-6,6}]&

accetta come input σ

Ingresso

[2]

produzione
inserisci qui la descrizione dell'immagine

-2 byte grazie a LLlAMnYP


1
Mathematica vincente? Nessuna sorpresa lì: P
MD XF,

3
Salvataggio di 2 byte conE^(-(x^2+y^2)/2/#^2)
LLlAMnYP

6

R, 105 102 87 86 byte

s=scan();plot3D::persp3D(z=sapply(x<-seq(-6,6,.1),function(y)exp(-(y^2+x^2)/(2*s^2))))

Prende Sigma da STDIN. Crea un vettore da -6a 6a passi di .1entrambi xe y, quindi crea una 121x121matrice prendendo il prodotto esterno di xe y. È più breve di chiamare matrixe specificare le dimensioni. La matrice ora è già piena, ma va bene, perché lo stiamo sovrascrivendo.

Le foranse -loop oltre i valori x, facendo uso delle operazioni vettorizzati in R, creando una riga matrice densità alla volta.

(s)applyancora una volta è un metodo più breve per operazioni vettoriali. Come l'eroe, gestisce la creazione della matrice da solo, risparmiando parecchi byte.

inserisci qui la descrizione dell'immagine

128 125 110 109 byte, ma molto più elaborato:

Questo diagramma è creato dal plotlypacchetto. Purtroppo la specifica è un po 'prolissa, quindi questo costa molti byte. Il risultato è davvero davvero fantastico. Consiglio vivamente di provarlo tu stesso.

s=scan();plotly::plot_ly(z=sapply(x<-seq(-6,6,.1),function(y)exp(-(y^2+x^2)/(2*s^2))),x=x,y=x,type="surface")

bla


Ho specificato nella domanda che il grafico non ha bisogno di avere numeri di riga, il tuo secondo invio va bene.
MD XF,

Oh, devo averlo perso. Ho scambiato le mie soluzioni. Penso che la plotlytrama sia abbastanza elaborata da giustificare che sia ancora inclusa qui.
JAD,

Bene, entrambi sono molto, molto più fantasiosi dei miei : P
MD XF,

Dal momento che si utilizza solo suna volta, è possibile eseguire 2*scan()^2e rimuovere s=scan();all'inizio? Si risparmierebbe 3 byte.
KSmarts,

6

Applesoft BASIC, 930 783 782 727 719 702 695 637 byte

-72 byte e un programma di lavoro grazie a ceilingcat che individua il mio errore e un algoritmo abbreviato

0TEXT:HOME:INPUTN:HGR:HCOLOR=3:W=279:H=159:L=W-100:Z=L/10:B=H-100:C=H-60:K=0.5:M=1/(2*3.14159265*N*N):FORI=0TO10STEPK:X=10*I+1:Y=10*I+B:HPLOTX,Y:FORJ=0TOL STEP1:O=10*J/L:D=ABS(5-I):E=ABS(5-O):R=(D*D+E*E)/(2*N*N):G=EXP(-R)*M:A=INT((C*G)/M):X=10*I+Z*O+1:Y=10*I+B-A:HPLOTTOX,Y:IF(I=0)GOTO4
1IF(J=L)GOTO3
2V=INT(J/10):IF((J/10)<>V)GOTO5
3D=ABS(5-I+K):E=ABS(5-O):R=(D*D+E*E)/(2*N*N):U=EXP(-R)/(2*3.14159*N*N):S=INT((C*U)/M):P=10*(I-K)+Z*O+1:Q=10*(I-K)+B-S:HPLOT TOP,Q:HPLOTX,Y
4IF(J=0)GOTO7:IF(I<10)GOTO5:IF(J=L)GOTO6:V=INT(J/10):IF((J/10)=V)GOTO6
5HCOLOR=0
6HPLOTTOX,10*I+B:HCOLOR=3:HPLOTX,Y
7NEXTJ:NEXTI:HPLOTW+1,H:HPLOTTO101,H:HPLOTTO0+1,H

Versione non golfata qui.

Quando viene fornito un input 1:

input-1

Quando viene fornito un input 2:

input-2


1
Questo dimostra ancora una volta la superiorità di BASIC ....

Può salvare qualche byte in più impostando una o più variabili su un valore usato di frequente, come 10. Inoltre, suggerisci di sostituirlo EXP(X)/(2*3.14159*S1*S1)conEXP(X)*M
ceilingcat il
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.