在3D中绘制高斯分布


10

在概率论中,正态(或高斯)分布是一种非常常见的连续概率分布。正态分布在统计中很重要,并且在自然科学和社会科学中经常用来表示其分布未知的实值随机变量。

挑战

您面临的挑战是在3维平面上绘制高斯分布的概率密度。该函数定义为:

哪里:




= 1,σ X = σ ÿ = σ

规则

  • 您的程序必须采用一个输入σ,即标准偏差。
  • 您的程序必须在您的语言/系统允许的情况下,以最高质量打印高斯分布的3D图。
  • 您的程序可能未使用直接的高斯分布或内置的概率密度。
  • 您的程序不必终止。
  • 您的情节可能是黑白或彩色的。
  • 您的绘图的底部必须有网格线。侧面的网格线(如示例中所示)是不必要的。
  • 您的绘图不需要在网格线旁边有线号。

计分

像在,最少字节的提交将获胜!我可能永远不会使用按钮来“接受”答案,除非它很小且直观。

输出示例

您的输出可能看起来像这样:

5

或者它可能看起来像这样:

6

有效的 输出无效的 输出


我很困惑您只显示了X轴的功能。我们是否需要为X和Y的sigma和mu分别输入/输出?
Scott Milner's

那么我们是否假设μ等于0?对于x和y,您需要什么比例?如果选择的x和y范围相对于σ非常小,则该图基本上看起来像是常数函数。
格雷格·马丁

(对于二维分布,我认为如果在定义中使用|x-μ| ^ 2而不是(x-μ)^ 2会更清楚。)
Greg Martin

@GregMartin编辑。
MD XF

2
仍然不清楚... x_o和y_o和θ是什么?
格雷格·马丁

Answers:


7

gnuplot的 4,64个 62 61 60 47字节

(与Mathematica捆绑!呜呼!)

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

将上面的代码保存到一个名为的文件中A.gp,并使用以下命令调用它:

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

其中$1是与的值来替换σ。这会将.png名为GnuPlot3D.png包含所需输出的文件保存到当前工作目录中。

请注意,这适用于Gnuplot 4的发行版,因为在Gnuplot 5 $n中已弃用了对参数的引用,并不幸地将其替换为更冗长的引用ARGn

输出示例σ = 3

样本输出

根据OP,此输出很好。


Gnuplot 4,替代解决方案,60字节

这是另一种解决方案,比以前的解决方案要长得多,但我认为输出看起来要好得多。

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

出于与先前解决方案相同的原因,这仍然需要Gnuplot 4。

输出示例σ = 3

样本输出2


I am not sure if it molds to the specifications required您认为不符合什么规格?
MD XF

@MDXF首先,我不确定图表的透明度是否可以。老实说,我真的不喜欢它,这就是为什么我不确定在这里是否可以的原因。其次,默认情况下,图形从底部开始高一个单位,我不确定这是否也可以。第三,由于图形从一个单位高开始,所以我不确定该图形与原始文章中给出的图形相比是否不合理。但是,如果您一切都OK,我将很乐意将其作为主要的答案。
卡普

@MDXF实际上,我打算将其发布为原始答案,但是由于这些原因,我选择不发布并由当前答案发布。
卡普

@MDXF其实,我可以使它更短,如果是好的。我知道是否可以,但问问并没有伤害。这是默认方式,它在没有任何环境修改的情况下Gnuplot绘制Sigma为的高斯分布的概率密度2
卡普

@MDXF我想我可能在发布原始答案之前就曾提出过要求,但是当时我非常渴望发布答案。
卡普

14

C ++ 3477 3344字节

字节数不包括不必要的换行符。
MD XF打了133个字节。

C ++无法竞争这一点,但是我认为编写一个用于应对挑战的软件渲染器会很有趣。我撕裂并打了一些GLM进行3D数学运算,并使用Wu Xiaolin的线算法进行栅格化。程序将结果输出到名为的PGM文件中g

输出量

#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 是世界空间中网格一侧的长度。
  • c 是沿网格每个边缘的顶点数。
  • 创建网格的函数被一个带有两个输入的函数调用,两个输入分别是顶点的xz(+ y向上)世界空间坐标,并返回该顶点的世界空间位置。
  • w 是pgm的宽度
  • h 是pgm的高度
  • m是视图/投影矩阵。用于创建的参数m是...
    • 弧度视场
    • pgm的长宽比
    • 在裁剪平面附近
    • 远夹飞机
    • 相机位置
    • 相机目标
    • 向上矢量

渲染器可以轻松拥有更多功能,更好的性能以及更好的打高尔夫球,但是我很开心!


2
哇,真是不可思议!
MD XF

1
一点也不...去吧!
Patrick Purcell

1
在那里,您可以节省133个字节!
MD XF

1
这太棒了!如果您能告诉我您从哪里学到的所有知识,那就太好了
HatsuPointerKun

1
@HatsuPointerKun很高兴您喜欢它!本教程... opengl-tutorial.org/beginners-tutorials/tutorial-3-matrices ...是一个不错的起点。
Patrick Purcell

9

Mathematica,47个字节

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

以σ为输入

输入值

[2]

输出
在此处输入图片说明

-2个字节,由于LLlAMnYP


1
Mathematica赢了吗?没有惊喜:P
MD XF

3
使用E^(-(x^2+y^2)/2/#^2)
LLlAMnYP

6

R,105 102 87 86个字节

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

从STDIN取得Sigma。创建了一个从载体-66在步骤.1两个xy然后创建一个121x121通过取的外积矩阵xy。这比调用matrix和指定尺寸要短。现在已经填充了矩阵,但是没关系,因为我们正在覆盖它。

for过的值-loop循环x,利用矢量化操作的R,同时创造了密度矩阵一行。

(s)apply再次是用于向量化运算的较短方法。就像英雄一样,它独自处理矩阵的创建,节省了很多字节。

在此处输入图片说明

128个 125 110 109字节,但方式更看中:

该图由plotly包创建。遗憾的是,该规范有些罗word,因此需要大量字节。结果确实很花哨。我强烈建议您自己尝试一下。

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


我的问题是,图并规定没有需要有行号,你的第二次提交的罚款。
MD XF

哦,我一定错过了。我交换了解决方案。我认为该plotly情节花哨的程度足以保证仍包含在此处。
JAD

好吧,两者都比我的要好得多:P
MD XF

由于您只使用s一次,因此可以一开始2*scan()^2将其删除s=scan();吗?它将节省3个字节。
KSmarts

6

Applesoft BASIC,930 783 782 727 719个 702 695 637字节

-72字节和一个工作程序,这要感谢吊顶猫发现我的错误和缩短的算法

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

取消高尔夫版本。

输入时1

输入1

输入时2

输入2


1
这再次显示了BASIC的优越性..

通过将一个或多个变量设置为某个经常使用的值(例如10),可以节省更多字节。此外,建议将其替换EXP(X)/(2*3.14159*S1*S1)EXP(X)*M
ceilingcat
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.