4

Python と Mayavi2 を使用して粒子群最適化のアニメーションを実行しようとしています。

アニメーションは正常に動作しています。私の問題は、動きをアニメーション化している間はプロットを操作できないことです。具体的には、グラフを回転させてズームしたいと思います。多分誰かがアニメーションをした経験がありますか?

私が行う方法は、最初に粒子の位置を計算してから保存することです。計算が終了したら、point3d() を使用して最初の時点で粒子の位置をプロットし、set() メソッドを使用してデータを更新する時間を繰り返します。

グラフを回転できるようにする方法はありますか? レンダリングを無効にするスレッドに関する何かについて聞いたことがありますが、コードでそれを行う方法がわかりませんでした。他の多くのものに加えて、私は読んだ:

http://code.enthought.com/projects/mayavi//docs/development/html/mayavi/mlab_animation.html

http://code.enthought.com/projects/mayavi//docs/development/html/mayavi/tips.html#acceleration-mayavi-scripts

しかし、それはそれを使用する方法を見ることができません。

助言がありますか?

これが私のコードです:

#!/usr/bin/env python
'''
    @author rt
'''
import pylab as plt
from numpy import *
from mayavi import mlab
from threading import Thread # making plotting faster?
import ackley as ac

class Swarm(Thread, object):
    '''
        constructor for the swarm
        initializes all instance variables
    '''
    def __init__(self,objective_function):
        Thread.__init__(self)
        # optimization options
        self.omega = 0.9 # inertial constant
        self.c1 = 0.06 # cognitive/private constant
        self.c2 = 0.06 # social constant
        self.objective = objective_function # function object

        self.max_iteration = 100 # maximal number of iterations
        # Swarm stuff
        self.number = 0
        self.best = [] # gbest; the global best position
        self.particles = [] # empty list for particles
        # temporary
        self.min = self.objective.min
        self.max = self.objective.max
        self.best_evolution = []
        # self.dimensions = 2 # dimensions NB! 


    '''
        add particles to the swarm
        find the best position of particle in swarm to set global best
    '''
    def add_particles(self, n):
        for i in range(n):
            particle = Particle(self)
            if i == 0: # initialize self.best
                self.best = particle.position
            if particle.eval() < self._eval(): # check if there is a better and if, set it
                self.best = copy(particle.position) 
            self.particles.append(particle) # append the particle to the swarm    

    def _eval(self):
        return self.objective.evaluate(self.best)

    def plot(self):
        for i in range(self.max_iteration):
            pos_x = []
            pos_y = []
            pos_z = []
            #print pos_x
            for particle in self.particles:
                [x,y,z] = particle.trail[i]
                pos_x.append(x)
                pos_y.append(y)
                pos_z.append(z)
            #print pos_x
            if i ==0:
                g = mlab.points3d(pos_x, pos_y,pos_z, scale_factor=0.5)
                ms =g.mlab_source
                ms.anti_aliasing_frames = 0
            ms.set(x=pos_x, y = pos_y, z = pos_z,scale_factor=0.5)     #updating y value
            #print pos_y
            #ms.set(x=pos_x) # update x values
            #ms.set(y=pos_y)     #updating y value
            #ms.set(z=pos_z)     #updating y value

        #for p in self.particles:
            #p.plot()
    def plot_objective(self):
        delta = 0.1
        v = mgrid[self.min:self.max:delta,self.min:self.max:delta]
        z = self.objective.evaluate(v)
        #mlab.mesh(v[0],v[1],z)
        mlab.surf(v[0],v[1],z) # surf creates a more efficient data structure than mesh
        mlab.xlabel('x-axis', object=None)
        mlab.ylabel('y-axis', object=None)
        mlab.zlabel('z-axis', object=None)


    def _info(self):
        self.plot()
        print '----------------------------'
        print 'The best result is:'
        print 'Coordinates:', self.best
        print 'Value: ', self._eval()
        #print 'with ', nreval, 'evaluations'
        print 'nr of particles: ', len(self.particles)
        print '----------------------------'  

    def run(self):
        self.plot_objective()
        self.best = self.particles[0].get_position()  
        iteration = 0
        while iteration < self.max_iteration:
            #if iteration!= 0: obj.scene.disable_render = True
            #disable_render = True
            for particle in self.particles:
                rnd_c1 = array([random.uniform(0,1),random.uniform(0,1)])
                rnd_c2 = array([random.uniform(0,1),random.uniform(0,1)])
                particle.velocity = self.omega * array(particle.velocity) + \
                                    self.c1 * rnd_c1 * (array(particle.best) - array(particle.position)) + \
                                    self.c2 * rnd_c2 * (array(self.best) - array(particle.position)) # TODO: change so independent rnd for components
                particle.position = array(particle.position) + particle.velocity
                if particle.eval() < particle.best_eval():
                    particle.best = copy(particle.position)
                    if particle.eval() < self._eval():
                        self.best = copy(particle.position)
                particle.update() # add the point to the trail
            iteration +=1
            self.best_evolution.append(self._eval())
            #obj.scene.disable_render = False
        print 'finished: ', iteration
        self._info()

'''
    Class modeling particle
'''
class Particle():
    def __init__(self, swarm):
        self.swarm = swarm
        x_rand = random.uniform(self.swarm.min,self.swarm.max)
        y_rand = random.uniform(self.swarm.min,self.swarm.max)
        self.position = array([x_rand,y_rand])
        v_x_rand = random.uniform(self.swarm.min,self.swarm.max)
        v_y_rand = random.uniform(self.swarm.min,self.swarm.max)
        self.velocity = array([v_x_rand, v_y_rand])
        self.size = 0.5
        self.best = self.position
        # visualization
        self.trail = []

    def plot(self):
        [x,y] = self.position
        z = self.eval()
        mlab.points3d(x,y,z,scale_factor=self.size)
    def eval(self):
        return self.swarm.objective.evaluate(self.position)
    def best_eval(self):
        return self.swarm.objective.evaluate(self.best)
    def get_position(self):
        return self.position
    def update(self):
        [x,y] = self.position
        z = self.eval()
        #print [x,y,z]
        self.trail.append([x,y,z])
    def plot_trail(self,index):
        [x,y,z] = self.trail[index]
        mlab.points3d(x,y,z,scale_factor=self.size)

# Make the animation
mlab.figure(1, bgcolor=(0, 0, 0), size=(1300, 700)) # create a new figure with black background and size 1300x700

objective = ac.Ackley() # make an objective function

swarm = pso.Swarm(objective) # create a swarm
nr_of_particles = 25 # nr of particles in swarm

swarm.add_particles(nr_of_particles)      
swarm.run()
#swarm.start()
mlab.show()

print '------------------------------------------------------'
print 'Particle Swarm Optimization'
#objective.info()
print 'Objective function to minimize has dimension = ', objective.get_dimension()
print '# of iterations = ', 1000
print '# of particles in swarm = ', nr_of_particles
print '------------------------------------------------------'
4

2 に答える 2

1

私の場合、Brandon Rhodes がモック プログラムに対して提案したことをある程度実行できましたが()、既存のより大きなプログラムを変換することができませんでした。

次に、このリンクを見つけました: http://wiki.wxpython.org/LongRunningTasks

wx.Yield()そのため、ループ内に多くの s をまき散らしました。この方法では、プログラムの構造を変更する必要がなく、ウィンドウを操作できます。より良い方法はリンクで説明されていると思います。

于 2013-06-01T21:18:28.740 に答える
0

あなたの問題はwx、Mayavi GUIウィンドウを実行し、マウスのクリックとドラッグをリッスンし、シーンを移動することで応答するイベントループが、アニメーション中に実行する時間がないことです.それはreturn制御します。

独自のループでプログラムの制御を維持する代わりにwx.Timer、シーンを 1 フレーム更新するクラスを作成し、wx再度スケジュールした後でイベント ループに制御を戻す必要があります。次のようになります。

import wx

...

class Animator(wx.Timer):

    def Notify(self):
        """When a wx.Timer goes off, it calls its Notify() method."""

        if (...the animation is complete...):
            return

        # Otherwise, update all necessary data to advance one step
        # in the animation; you might need to keep a counter or
        # other state as an instance variable on `self`

        # [DATA UPDATE GOES HERE]

        # Schedule ourselves again, giving the wx event loop time to
        # process any pending mouse motion.

        self.Start(0, oneShot=True)  # "in zero milliseconds, call me again!"

1UI を実行するミリ秒数のように、少し高い値で遊んでみましたが、それと、コントロールを選択して「すぐに」返すwxこととの違いを実際には見分けることができませんでした。0

于 2013-01-05T07:35:21.253 に答える