Indexing 如何修复“LoadError:dimensionsmatch(“无法广播数组以减少维度”)”

Indexing 如何修复“LoadError:dimensionsmatch(“无法广播数组以减少维度”)”,indexing,julia,ode,differentialequations.jl,Indexing,Julia,Ode,Differentialequations.jl,我想数值求解以下两个耦合微分方程: d/dt Phi_i = 1 - 1/N * \sum_{j=1}^N( k_{ij} sin(Phi_i - Phi_j + a) d/dt k_{ij} = - epsilon * (sin(Phi_i - Phi_j + b) + k_{ij} 在定义的起始条件下,phi_0 1-dim数组具有N个条目,k_0 2-dim数组具有NxN个条目 我试过这样做:使用differentialsequations.js,构建初始起始条件的矩阵u0=hcatP

我想数值求解以下两个耦合微分方程:

d/dt Phi_i = 1 - 1/N * \sum_{j=1}^N( k_{ij} sin(Phi_i - Phi_j + a) 
d/dt k_{ij} = - epsilon * (sin(Phi_i - Phi_j + b) + k_{ij}
在定义的起始条件下,phi_0 1-dim数组具有N个条目,k_0 2-dim数组具有NxN个条目

我试过这样做:使用differentialsequations.js,构建初始起始条件的矩阵u0=hcatPhi_0,k_0 2-dim数组,NxN+1,并以某种方式定义第一个方程适用于代码[:,1]中的第一列,第二个方程适用于代码[:,2:N+1]中的其他列

using Distributions
using DifferentialEquations

N = 100
phi0 = rand(N)*2*pi
k0 = rand(Uniform(-1,1), N,N)

function dynamics(du, u, p, t)
    a = 0.3*pi 
    b = -0.53*pi 
    epsi = 0.01 

    du[:,1] .= 1 .- 1/N .* sum.([u[i,j+1] * sin(u[i,1] - u[j,1] + a) for i in 1:N, j in 1:N], dims=2)
    du[:,2:N+1] .= .- epsi .* [sin(u[i,1] - u[j,1] + b) + u[i,j+1] for i in 1:N, j in 1:N]
end

u0 = hcat(phi0, k0)
tspan = (0.0, 200.0)
prob = ODEProblem(dynamics, u0, tspan)
sol = solve(prob)

运行这行代码会导致以下错误:

LoadError: DimensionMismatch ("cannot broadcast array to have fewer dimensions")in expression starting at line 47 (which is sol = solve(prob)) 

我是茱莉亚的新手,我不确定我的方向是否正确。请帮帮我

首先,编辑第一个包,它是Distributions而不是Distribution,我花了一段时间才找到错误xD

主要问题是你的第一个等式中的。当你这样做的时候,你不仅仅是给一个数组赋值,你正在创建一个视图。我不能确切地解释什么是视图,但我能告诉你的是,当你进行这种赋值时,左边和右边的类型必须相同

例如:

N = 100
u = rand(N,N+1)
du = rand(N,N+1)

julia> u[:,1] .= du[:,1]
100-element view(::Array{Float64,2}, :, 1) with eltype Float64:
 0.2948248997313967 
 0.2152933893895821 
 0.09114453738716022
 0.35018616658607926
 0.7788869975259098 
 0.2833659299216609 
 0.9093344091412392 
...
结果是一个视图,而不是一个向量。使用这种语法,左侧和右侧必须具有相同的类型,在您的示例中不会出现这种情况。注意,在Julia中,rand5和rand5,1的类型是不同的:第一个是数组{Float64,1},另一个是数组{Float64,2}。在您的代码中,d[:,1]是一个数组{Float64,1},但1.-1/N.*sum.[u[i,j+1]*sinu[i,1]-u[j,1]+a表示1:N中的i,1:N中的j],dims=2是一个数组{Float64,2},这就是它不工作的原因。您有两个选择,请更改等号:

du[:,1] = ...
或:


第一个选项只是一个基本的赋值,第二个选项使用视图方式并匹配双方的类型。

总和中的广播点。[u[i,j+1]*sinu[i,1]-u[j,1]+a代表1:N中的i,j代表1:N],dims=2似乎可疑。它将尝试调用sum::Float64,dims=2,这应该也会出错。对其进行了更改,但错误消息保持不变。尝试另外两行:temp=1.-1/N.*sum[u[i,j+1]*sinu[i,1]-u[j,1]+a表示1:N中的i,j:N中的i,dims=2和printlnsize数组的大小:,sizedu和,在分配给du之前进行尺寸测试,看看打印的是什么。看起来你是对的,但我认为这不是视图的问题。问题是广播本身不喜欢将2D源分配给一维目标。如果要广播赋值,必须确保sum的输出压缩到1D。在这种情况下,dropdims比[:,1]更有效,但最简单的解决方案是在赋值中删除点。不知道dropdims函数,谢谢。发布后,我记得你可以直接使用它,可能也更有效。删除点是最简单的是的,只要把第二个例子,以防OP想要保持代码的美学。不过,我会去掉这两个等式中的点。
du[:,1] .= 1 .- 1/N .* sum.([u[i,j+1] * sin(u[i,1] - u[j,1] + a) for i in 1:N, j in 1:N], dims=2)[:,1]