繁体   English   中英

如何使用Theano求解常微分方程?

[英]How do I use Theano to solve an ordinary differential equation?

这是我的Python代码:

import numpy as np


def spread_points_in_cube(n, dimensions=3, rng=None):
    from scipy.integrate import ode
    if rng is None:
        rng = np.random

    size = n * dimensions
    y0 = np.zeros((2 * size))
    y0[:size] = rng.uniform(0, 0.1, size=size)
    t0 = 0.0

    mean = np.zeros(dimensions)
    variance = np.eye(dimensions) * 0

    def decode(y):
        positions = np.remainder(y[:size].reshape((n, dimensions)), 1)
        velocities = y[size:].reshape((n, dimensions))
        return positions, velocities

    def get_forces(positions, velocities):
        delta_positions = positions[:, np.newaxis, :] - positions[np.newaxis, :, :]
        delta_positions = np.remainder(delta_positions + 0.5, 1) - 0.5  # wrapping
        distances = np.linalg.norm(delta_positions, axis=2, ord=2)
        distances += 1e-5
        pairwise_forces = delta_positions * (distances ** -3)[:, :, np.newaxis]
        magnetic_forces = np.sum(pairwise_forces, axis=1) / (n ** 2)

        velocity_mags = np.linalg.norm(velocities, axis=1, ord=2)
        drag_forces = -velocities * velocity_mags[:, np.newaxis]

        forces = magnetic_forces * 0.01 + drag_forces * 10.0
        return forces

    def f(t, y):
        positions, velocities = decode(y)
        forces = get_forces(positions, velocities)
        retval = np.zeros((2 * size))
        retval[:size] = velocities.reshape(size)
        retval[size:] = forces.reshape(size)
        return retval

    r = ode(f).set_integrator('vode', method='bdf')
    r.set_initial_value(y0, t0)
    t_max = 20
    dt = 1
    while r.successful() and r.t < t_max:
        positions, velocities = decode(r.y)
        forces = get_forces(positions, velocities)
        total_speed = np.sum(np.linalg.norm(velocities, axis=1, ord=2))
        total_force = np.sum(np.linalg.norm(forces, axis=1, ord=2))
        #print("\nt", r.t, "\np", positions, "\nv", velocities,
        #      "\nf", forces
        print(total_speed, total_force)
        if total_force < n * 1e-4:
            print("breaking")
            #break
        r.integrate(r.t + dt)
    print("converged after", r.t, total_speed, total_force)
    return positions
spread_points_in_cube(1000, 3)

可以使用Theano解决ODE吗?

这是theano中的一个非常简单的ode求解器:

import numpy
import theano

# the right-hand side
def f(x, t):
    return x*(1-x)

x = theano.tensor.matrix() # why not a matrix
dt = theano.tensor.scalar()
t = theano.tensor.scalar()

x_next = x + f(x, t)*dt # implement your favourite RK method here!

# matrix of random initial values
# store it on the device
x_shared = theano.shared(numpy.random.rand(10, 10))

step = theano.function([t, dt], [],
        givens=[(x, x_shared)],
        updates=[(x_shared, x_next)],
        on_unused_input='warn')

t = 0.0
dt = 0.01

while t < 10:
    step(t, dt)
    t += dt
    # test halt condition here

print(x_shared.get_value()) # read back the result

希望对您有所帮助。 基本上,您必须实现Runge-Kutta方法。

并且请注意theano的优势在于矢量化,因此我不会理会在theano中实现时间循环。 这就是为什么我使用一个简单的python while循环,尽管我可以使用theano scan 无论如何,根据您的目标,优化可能很棘手。 我不是100%相信theano是ODE求解器的理想选择。 无论如何,至少在CPU上,Numpy都会对力和位置矩阵进行矢量化处理。 通过theano实现,您可以利用GPU,但这并不能保证加速。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM