基于遗传算法和粒子群算法的混合算法实现小老鼠找奶酪问题

此为老师留的大作业

算法依据:http://wenku.baidu.com/view/4387f569af1ffc4ffe47acc7

算法实现

#ifndef CHEESE_H
#define CHEESE_H

#include <QGraphicsPixmapItem>
#include <QGraphicsItem>
#include <QPixmap>
#include <QPainter>

class Cheese : public QGraphicsPixmapItem
{
//    Q_OBJECT
public:
    Cheese();
    void setSize(int size);
    void paint(QPainter *painter,
                   const QStyleOptionGraphicsItem *option, QWidget *widget);

private:
    QPixmap pixmap;
    
};
#ifndef MAINWINDOWS_H
#define MAINWINDOWS_H

#include <QMainWindow>

#include <QLabel>
#include <QMenu>
#include <QMenuBar>
#include <QToolBar>
#include <QStatusBar>
#include <QMessageBox>
#include <QSlider>
#include <QtGui>
#include <QFileDialog>
#include <QGraphicsScene>
#include <QGraphicsView>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QPushButton>

#include <math.h>

#include "mouse.h"
#include "cheese.h"
#include "particle.h"
#include "MixAlogrithm.h"

struct CheesePoint
{
    int X;
    int Y;
};

class MainWindows : public QMainWindow
{
    Q_OBJECT
public:
    explicit MainWindows(QWidget *parent = 0);


private:
    QGraphicsView *view;
    QGraphicsScene *scene;

    CheesePoint* cheesePos;

    Cheese *cheeses;
    Mouse *mouses;

    double *cheeses_size;

    QLabel *label1;
    QLabel *label2;
    QLabel *label3;
    QLabel *label4;
    QPushButton *initPushButton;
    QPushButton *nextPushButton;

    QHBoxLayout *uplayout;
    QVBoxLayout *mainlayout;

    int steps;

    MixAlogrithm* mymix;

signals:
    
public slots:
    void OPSCheeses();

    void InitProcess();

    double getDensity(int,int);

    void showDensity();
};

#endif // MAINWINDOWS_H

#ifndef MIXALOGRITHM_H
#define MIXALOGRITHM_H

#include <math.h>
#include <QtGlobal>
#include "particle.h"

class MixAlogrithm
{
public:
    MixAlogrithm(int dim, int num);
    void Initialize();

    int SetXup(double* xup);  //设置微粒坐标上界
    int SetXdown(double* dXdown); //设置微粒坐标下界

    //设置微粒最大速度,以数组为参数
    int SetVmax(double* dVMax);

    //设置微粒最大速度,以上下界百分比为参数
    int SetVmax(double dPer);

    //设置权重
    void SetW(double w);
    //设置C1,C2
    void SetC1(double c);
    void SetC2(double c);

    void SetFit(double dFit,int i,int sel);
    void SetFitBest(double dFit,int i);

    double GetFit(int i);

    //微粒飞翔,产生新一代微粒
    void ParticleFly();

    //查找最优粒子
    void FindBestParticle();

    //设置所选粒子的坐标,可以初始化一个已知的粒子,避免太多的随机性
    void SetX(int i, double* dX);

    //返回所选粒子的坐标
    double* GetX(int i, int sel);

    //返回最佳粒子的X和最佳适合度
    double* GetBest();

    //交叉遗传
    void Cross();

    //变异
    void Vary();

    //变异选择
    void VarySelect();

    //遗传选择
    void GeneSelect();

private:
    MyParticle* particles; //微粒群数组
    MyParticle* sonparticles; //子代微粒群
    MyParticle* varyparticles; //变异粒子群
    int PNum; //微粒个数
    int GBestIndex; //最好微粒索引
    double W; //惯性权重
    double C1; //加速度系数1
    double C2; //加速度系数2
    double* Xup; //微粒坐标上界数组
    double* Xdown; //微粒坐标下界数组
    double* Vmax; //微粒最大速度数组
    double* FitBak;
};

#endif // MIXALOGRITHM_H

/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the examples of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** You may use this file under the terms of the BSD license as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
**   * Redistributions of source code must retain the above copyright
**     notice, this list of conditions and the following disclaimer.
**   * Redistributions in binary form must reproduce the above copyright
**     notice, this list of conditions and the following disclaimer in
**     the documentation and/or other materials provided with the
**     distribution.
**   * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names
**     of its contributors may be used to endorse or promote products derived
**     from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/

#ifndef MOUSE_H
#define MOUSE_H

#include <QGraphicsItem>

//! [0]
class Mouse : public QGraphicsItem
{
public:
    Mouse();

    QRectF boundingRect() const;
    QPainterPath shape() const;
    void paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
               QWidget *widget);

protected:
    void advance(int step);

private:
    qreal angle;
    qreal speed;
    qreal mouseEyeDirection;
    QColor color;
};
//! [0]

#endif

#ifndef PARTICLE_H
#define PARTICLE_H

class MyParticle
{
public:
    MyParticle();
    MyParticle(int d);

    void InitParticle(int d);
    int GetDim();
    void SetDim(int);
    int IsValid();
    double GetFitness();

    void SetFit(double fit);
    void SetFitBest(double fit);


public:
    double *X; //微粒的坐标数组
    double *V; //微粒的速度数组
    double *XBest; //微粒的最好位置数组
    double Fit; //微粒适合度
    double FitBest; //微粒最好位置适合度
    int Dim; //微粒的维数
    int iValid;  //需要先设定粒子的维数,这个粒子类才好用

};


#endif // PARTICLE_H

#include "cheese.h"

Cheese::Cheese()
{
    pixmap.load(":/images/cheese.jpg");
    setPixmap(pixmap);
}


void Cheese::setSize(int size)
{
    pixmap = pixmap.scaled(size,size,Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
    setPixmap(pixmap);
}

void Cheese::paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
           QWidget *widget)
{
    //pixmap = this->pixmap();
    QRect rect = pixmap.rect();

    painter->drawPixmap(rect,pixmap);

}

/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the examples of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** You may use this file under the terms of the BSD license as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
**   * Redistributions of source code must retain the above copyright
**     notice, this list of conditions and the following disclaimer.
**   * Redistributions in binary form must reproduce the above copyright
**     notice, this list of conditions and the following disclaimer in
**     the documentation and/or other materials provided with the
**     distribution.
**   * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names
**     of its contributors may be used to endorse or promote products derived
**     from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include <QtWidgets>

#include "mainwindows.h"

//! [0]
int main(int argc, char **argv)
{
    QApplication app(argc, argv);
    qsrand(QTime(0, 0, 0).secsTo(QTime::currentTime()));

    MainWindows mainWindow;

    mainWindow.show();

    QTimer timer;

    QObject::connect(&timer, SIGNAL(timeout()), &mainWindow, SLOT(OPSCheeses()));

    timer.start(100000/33);

    return app.exec();
}


//! [6]

#include "mainwindows.h"

static const int MouseCount = 10;
static const int CheeseCount = 2;

double xup[2] = {600.0,600.0};
double xdown[2] = {-600.0,-600.0};
double vmax[2] = {5.0,5.0};

MainWindows::MainWindows(QWidget *parent) :
    QMainWindow(parent)
{
    scene = new QGraphicsScene(-600, -600, 1200, 1200);

    scene->setItemIndexMethod(QGraphicsScene::NoIndex);

    cheesePos = new CheesePoint[CheeseCount];
    cheeses = new Cheese[CheeseCount];
    cheeses_size = new double[CheeseCount];

    mouses = new Mouse[MouseCount];

    view = new QGraphicsView();
    view->setScene(scene);

    view->setDragMode(QGraphicsView::ScrollHandDrag);

    view->resize(1400, 1400);


    mainlayout = new QVBoxLayout();

    uplayout = new QHBoxLayout();

    label1 = new QLabel("迭代次数");
    label2 = new QLabel(QString::number(0));
    label3 = new QLabel(QString::number(0));
    label4 = new QLabel(QString::number(0));

    initPushButton = new QPushButton(tr("初始化"));
    nextPushButton = new QPushButton(tr("下一步"));

    uplayout->addWidget(label1);
    uplayout->addWidget(label2);
    uplayout->addWidget(label3);
    uplayout->addWidget(label4);
    uplayout->addWidget(initPushButton);
    uplayout->addWidget(nextPushButton);
    mainlayout->addLayout(uplayout);

    mainlayout->addWidget(view);

    mymix = new MixAlogrithm(2, MouseCount);

    //showDensity();

    mymix->SetXup(xup);
    mymix->SetXdown(xdown);
    mymix->SetVmax(vmax);//设置最大速度为5个像素
    mymix->Initialize();
    mymix->SetC1(2.0);
    mymix->SetC2(2.1);
    mymix->SetW(0.9);

    InitProcess(); //初始化

    QWidget * w = new QWidget(this);
    w->setLayout(mainlayout);

    setCentralWidget(w);

    setWindowTitle(QObject::tr("小老鼠找奶酪"));
}

//初始化
void MainWindows::InitProcess()
{
    double p[2];
    double *dTemp;
    for(int i=0;i<CheeseCount;i++)
    {
        cheesePos[i].X = (qrand()%100)*8 -400;  //奶酪都在比较靠中间的位置
        cheesePos[i].Y = (qrand()%100)*8 -400;
        cheeses_size[i] = (qrand() % 100) / 100.0;
        cheeses[i].setSize(cheeses_size[i]*64);
        cheeses[i].setPos(cheesePos[i].X-cheeses_size[i]*32,cheesePos[i].Y-cheeses_size[i]*32);
        scene->addItem(&cheeses[i]);
    }

    steps = 0;

    label2->setText(QString::number(steps));

    //假设老鼠开始的位置是半径为700的一圈
    for (int i = 0; i < MouseCount; ++i)
    {
        p[0] = ::sin((i * 6.28) / MouseCount) * 700;
        p[1] = ::cos((i * 6.28) / MouseCount) * 700;
        mouses[i].setPos(p[0],p[1]);

        mymix->SetX(i,p);

        mymix->SetFit(getDensity(i,0),i,0);
        mymix->SetFitBest(getDensity(i,0),i);

        dTemp = mymix->GetX(i,0);
        label3->setText(QString::number(dTemp[0],'f',6));

        scene->addItem(&mouses[i]);
    }
}

//优化过程
void MainWindows::OPSCheeses()
{
    double *dTemp;
    double value;

    mymix->FindBestParticle();//查找最优的粒子
    dTemp = mymix->GetBest();
    value = dTemp[2];//最优值在第三个值

    label4->setText(QString::number(value,'f',6));
    mymix->ParticleFly(); //粒子飞翔

    steps++;
    label2->setText(QString::number(steps));

    for(int i=0;i<MouseCount;i++)
    {
        dTemp = mymix->GetX(i,0);

        label3->setText(QString::number(dTemp[0],'f',6));

        mouses[i].setPos(dTemp[0],dTemp[1]);

        value = getDensity(i,0);

        mymix->SetFit(value,i,0);
    }

    mymix->Cross();
    for(int i=0;i<MouseCount;i++)
    {
        value = getDensity(i,1);

        mymix->SetFit(value,i,1);
    }
    mymix->Vary();
    for(int i=0;i<2*MouseCount;i++)
    {
        value = getDensity(i,2);

        mymix->SetFit(value,i,2);
    }
    mymix->VarySelect();
    for(int i=0;i<MouseCount;i++)
    {
        value = getDensity(i,0);

        mymix->SetFit(value,i,0);
    }
    mymix->GeneSelect();
    for(int i=0;i<MouseCount;i++)
    {
        value = getDensity(i,0);

        mymix->SetFit(value,i,0);
    }
}

double MainWindows::getDensity(int m, int sel)
{
    double density = 0.0;
    double *dTemp;

    dTemp = mymix->GetX(m,sel); //获得老鼠的坐标

    for(int i=0;i<CheeseCount;i++)
    {
        density = density +
                  cheeses_size[i] *
                  exp(-1*
                      (((dTemp[0]-cheesePos[i].X)/600.0)*((dTemp[0]-cheesePos[i].X)/600.0)+
                      ((dTemp[1]-cheesePos[i].Y)/600.0)*((dTemp[1]-cheesePos[i].Y)/600.0))
                      /0.1);
    }

    return density;
}

void MainWindows::showDensity()
{
    double temp[2];
    double den;

    int width = 1;
    int height = 1;

    for(int x=-600;x<=600;x+=100)
    {
        for(int y=-600;y<=600;y+=100)
        {
            temp[0] = x;
            temp[1] = y;
            mymix->SetX(0,temp);
            den = getDensity(0,0);
            QGraphicsEllipseItem *ellepseitem = new QGraphicsEllipseItem(x,y,width*den, height*den);
            scene->addItem(ellepseitem);
        }
    }

}

#include "MixAlogrithm.h"
#include  <cstdlib>

MixAlogrithm::MixAlogrithm(int dim, int num)
{
    particles = new MyParticle[num];
    sonparticles = new MyParticle[num];
    varyparticles = new MyParticle[2*num];

    for(int i=0; i<num; i++)
    {
        particles[i].InitParticle(dim);
        sonparticles[i].InitParticle(dim);
    }
    for(int i=0; i<2*num; i++)
        varyparticles[i].InitParticle(dim);

    PNum = num;
    GBestIndex = 0;
    Xup = new double[dim];
    Xdown = new double[dim];
    Vmax = new double[dim];
    FitBak = new double[PNum];
    W = 1;
    C1 = 2;
    C2 = 2;
}

void MixAlogrithm::Initialize()
{
    for(int i=0; i<PNum; i++)
    {
        for(int j=0; j<particles[i].Dim; j++)
        {
            particles[i].X[j] = ((qrand()%100)/100.0)*(Xup[j]-Xdown[j])+Xdown[j];//初始化坐标
            particles[i].XBest[j] = particles[i].X[j];
            particles[i].V[j] = ((qrand()%100)/100.0)*Vmax[j]-Vmax[j]/2;//初始化速度
        }
        particles[i].FitBest = particles[i].Fit; //设最优适合度初值
        if(particles[i].Fit > particles[GBestIndex].Fit)
            GBestIndex = i;//查找群体最优微粒
    }
}

int MixAlogrithm::SetXup(double* xup)
{

    //if(sizeof(xup) == particles[0].GetDim())
    //{
        for(int i=0; i<particles[0].GetDim(); i++)
            Xup[i] = xup[i];
        return 0;
    //}
    //else
    //{
        //return -1;
    //}

}

int MixAlogrithm::SetXdown(double* dXdown)
{
    //if(sizeof(dXdown) == particles[0].GetDim())
    //{
        for(int i=0; i<particles[0].GetDim();i++)
            Xdown[i] = dXdown[i];
        return 0;
    //}
    //else
    //{
    //    return -1;
    //}
}


int MixAlogrithm::SetVmax(double* dVMax)
{
    //if(sizeof(dVMax) == particles[0].GetDim())
    //{
        for(int i=0; i<particles[0].GetDim();i++)
            Vmax[i] = dVMax[i];
        return 0;
    //}
    //else
    //{
        //return -1;
    //}
}

int MixAlogrithm::SetVmax(double dPer)
{
    if(particles[0].GetDim() > 0)
    {
        for(int i=0; i<particles[0].GetDim(); i++)
            Vmax[i] = (Xup[i]-Xdown[i])*dPer;
    }
    else
    {
        return -1;
    }
    return 0;
}

void MixAlogrithm::SetW(double w)
{
    W=w;
}


void MixAlogrithm::SetC1(double c)
{
    C1 = c;
}

void MixAlogrithm::SetC2(double c)
{
    C2 = c;
}

void MixAlogrithm::SetFit(double dFit,int i,int sel)
{
    switch(sel)
    {
    case 0:
        particles[i].SetFit(dFit);
        break;
    case 1:
        sonparticles[i].SetFit(dFit);
        break;
    case 2:
        varyparticles[i].SetFit(dFit);
        break;
    default:
        particles[i].SetFit(dFit);
    }
}

void MixAlogrithm::SetFitBest(double dFit, int i)
{
    particles[i].SetFitBest(dFit);
}

double MixAlogrithm::GetFit(int i)
{
    return particles[i].GetFitness();
}

//微粒飞翔,产生新一代微粒
void MixAlogrithm::ParticleFly()
{
    //整个群体飞向新的位置
    for(int i=0; i<PNum; i++)
    {
        for(int j=0; j<particles[i].Dim; j++)
        {
            //修改速度
            particles[i].V[j] = W*particles[i].V[j]+
                    ((qrand()%100)/100.0)*C1*(particles[i].XBest[j]-particles[i].X[j])+
                    ((qrand()%100)/100.0)*C2*(particles[GBestIndex].XBest[j]-particles[i].X[j]);
        }
        for(int j=0; j<particles[i].Dim; j++) //检查速度最大值
        {
            if(particles[i].V[j]>Vmax[j]) particles[i].V[j] = Vmax[j];//速度保护
            if(particles[i].V[j]<-Vmax[j]) particles[i].V[j] = -Vmax[j];//速度保护
        }
        for(int j=0; j<particles[i].Dim; j++)
        {
            particles[i].X[j] += particles[i].V[j]; //修改坐标
            if(particles[i].X[j]>Xup[j]) particles[i].X[j]=Xup[j];//位置保护
            if(particles[i].X[j]<Xdown[j]) particles[i].X[j]=Xdown[j];//位置保护
        }
    }
    //记录上一次的Fit值
    for(int i=0; i<PNum; i++)
        FitBak[i] = particles[i].Fit;
}

//找到最优的粒子
void MixAlogrithm::FindBestParticle()
{
    //设置新的个体最好位置
    for(int i=0; i<PNum; i++)
    {
        if(particles[i].Fit>=particles[i].FitBest)
        {
            particles[i].FitBest = particles[i].Fit;
            for(int j=0; j<particles[i].Dim; j++)
                particles[i].XBest[j] = particles[i].X[j];
        }
    }
    //设置新的最优个体
    for(int i=0; i<PNum; i++)
        if(particles[i].FitBest>=particles[GBestIndex].FitBest && i!=GBestIndex) GBestIndex = i;
}

//设置所选粒子的坐标,可以初始化一个已知的粒子,避免太多的随机性
void MixAlogrithm::SetX(int i, double* dX)
{
    //if(sizeof(dX) == particles[i].Dim)
    //{
        for(int j=0; j<particles[i].Dim;j++)
            particles[i].X[j] = dX[j];
    //}
}

//返回所选粒子的坐标
double* MixAlogrithm::GetX(int i, int sel)
{
    switch(sel)
    {
    case 0:
        return particles[i].X;
        break;
    case 1:
        return sonparticles[i].X;
        break;
    case 2:
        return varyparticles[i].X;
        break;
    default:
        return particles[i].X;
    }
}

//返回最佳粒子的X和最佳适合度
double* MixAlogrithm::GetBest()
{
    double* dret = new double[particles[GBestIndex].Dim +1];
    for(int i=0; i<particles[GBestIndex].Dim; i++)
        dret[i] = particles[GBestIndex].XBest[i];
    dret[particles[GBestIndex].Dim] = particles[GBestIndex].FitBest;
    return dret;
}

//选择、交叉
void MixAlogrithm::Cross()
{
    int Dad[10];
    int SelSign = 0x000003ff , Select;
    int i,j=0;
    //随机两两配对
    while(SelSign != 0)
    {
        Select = qrand()%10;
        i = (0x00000001<<Select);
        if(SelSign & i)
        {
            Dad[j] = Select;
            j++;
            SelSign &= (~i);
        }
    }
    //交叉
    for(i=0;i<(PNum/2);i++)
    {
        double r = (qrand()%100)/100.0;
        int id1,id2;
        id1 = 2*i;
        id2 = id1+1;
        for(j=0;j<particles[0].Dim;j++)
        {
            sonparticles[Dad[id1]].X[j] = r*particles[Dad[id1]].X[j] + (1.0-r)*particles[Dad[id2]].X[j];
            sonparticles[Dad[id2]].X[j] = r*particles[Dad[id2]].X[j] + (1.0-r)*particles[Dad[id1]].X[j];

            sonparticles[Dad[id1]].V[j] = r*particles[Dad[id1]].V[j] + (1.0-r)*particles[Dad[id2]].V[j];
            sonparticles[Dad[id2]].V[j] = r*particles[Dad[id2]].V[j] + (1.0-r)*particles[Dad[id1]].V[j];
        }
    }
}

void MixAlogrithm::Vary()
{
    for(int i=0; i<2*PNum; i++)
    {
        for(int j=0; j<varyparticles[i].Dim; j++)
        {
            varyparticles[i].X[j] = ((qrand()%100)/100.0)*(Xup[j]-Xdown[j])+Xdown[j];
        }
    }
}

void MixAlogrithm::VarySelect()
{
    for(int i=0;i<PNum;i++)
    {
        if(particles[i].Fit < varyparticles[i].Fit)
        {
            for(int j=0;j<particles[i].Dim;j++)
            {
                if((varyparticles[i].X[j]-particles[i].X[j])>Vmax[j])//坐标保护
                    particles[i].X[j] += Vmax[j];
                else if((varyparticles[i].X[j]-particles[i].X[j])<-Vmax[j])
                    particles[i].X[j] += -Vmax[j];
                else
                    particles[i].X[j] = varyparticles[i].X[j];
            }
        }

        if(sonparticles[i].Fit < varyparticles[PNum+i].Fit)
        {
            sonparticles[i].Fit = varyparticles[PNum+i].Fit;
            for(int j=0;j<sonparticles[i].Dim;j++)
                sonparticles[i].X[j] = varyparticles[PNum+i].X[j];
        }
    }
}

void MixAlogrithm::GeneSelect()
{
    for(int i=0;i<PNum;i++)
    {
        if(particles[i].Fit < sonparticles[i].Fit)
        {
            for(int j=0;j<particles[i].Dim;j++)
            {
                if((sonparticles[i].X[j]-particles[i].X[j])>Vmax[j])//坐标保护
                    particles[i].X[j] += Vmax[j];
                else if((sonparticles[i].X[j]-particles[i].X[j])<-Vmax[j])
                    particles[i].X[j] += -Vmax[j];
                else
                    particles[i].X[j] = sonparticles[i].X[j];
                particles[i].V[j] = sonparticles[i].V[j];
            }
        }
    }
}

/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the examples of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** You may use this file under the terms of the BSD license as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
**   * Redistributions of source code must retain the above copyright
**     notice, this list of conditions and the following disclaimer.
**   * Redistributions in binary form must reproduce the above copyright
**     notice, this list of conditions and the following disclaimer in
**     the documentation and/or other materials provided with the
**     distribution.
**   * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names
**     of its contributors may be used to endorse or promote products derived
**     from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "mouse.h"

#include <QGraphicsScene>
#include <QPainter>
#include <QStyleOption>

#include <math.h>

static const double Pi = 3.14159265358979323846264338327950288419717;
static double TwoPi = 2.0 * Pi;

static qreal normalizeAngle(qreal angle)
{
    while (angle < 0)
        angle += TwoPi;
    while (angle > TwoPi)
        angle -= TwoPi;
    return angle;
}

//! [0]
Mouse::Mouse()
    : angle(0), speed(0), mouseEyeDirection(0),
      color(qrand() % 256, qrand() % 256, qrand() % 256)
{
    setRotation(qrand() % (360 * 16));
}
//! [0]

//! [1]
QRectF Mouse::boundingRect() const
{
    qreal adjust = 0.5;
    return QRectF(-18 - adjust, -22 - adjust,
                  36 + adjust, 60 + adjust);
}
//! [1]

//! [2]
QPainterPath Mouse::shape() const
{
    QPainterPath path;
    path.addRect(-10, -20, 20, 40);
    return path;
}
//! [2]

//! [3]  //draw the mouse
void Mouse::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
{
    // Body
    painter->setBrush(color);
    painter->drawEllipse(-10, -20, 20, 40);

    // Eyes
    painter->setBrush(Qt::white);
    painter->drawEllipse(-10, -17, 8, 8);
    painter->drawEllipse(2, -17, 8, 8);

    // Nose
    painter->setBrush(Qt::black);
    painter->drawEllipse(QRectF(-2, -22, 4, 4));

    // Pupils
    painter->drawEllipse(QRectF(-8.0 + mouseEyeDirection, -17, 4, 4));
    painter->drawEllipse(QRectF(4.0 + mouseEyeDirection, -17, 4, 4));

    // Ears
    painter->setBrush(scene()->collidingItems(this).isEmpty() ? Qt::darkYellow : Qt::red);
    painter->drawEllipse(-17, -12, 16, 16);
    painter->drawEllipse(1, -12, 16, 16);

    // Tail
    QPainterPath path(QPointF(0, 20));
    path.cubicTo(-5, 22, -5, 22, 0, 25);
    path.cubicTo(5, 27, 5, 32, 0, 30);
    path.cubicTo(-5, 32, -5, 42, 0, 35);
    painter->setBrush(Qt::NoBrush);
    painter->drawPath(path);
}
//! [3]

//! [4]
void Mouse::advance(int step)
{
    if (!step)
        return;
//! [4]
    // Don't move too far away
//! [5]
    QLineF lineToCenter(QPointF(0, 0), mapFromScene(0, 0));
    if (lineToCenter.length() > 150) {
        qreal angleToCenter = ::acos(lineToCenter.dx() / lineToCenter.length());
        if (lineToCenter.dy() < 0)
            angleToCenter = TwoPi - angleToCenter;
        angleToCenter = normalizeAngle((Pi - angleToCenter) + Pi / 2);

        if (angleToCenter < Pi && angleToCenter > Pi / 4) {
            // Rotate left
            angle += (angle < -Pi / 2) ? 0.25 : -0.25;
        } else if (angleToCenter >= Pi && angleToCenter < (Pi + Pi / 2 + Pi / 4)) {
            // Rotate right
            angle += (angle < Pi / 2) ? 0.25 : -0.25;
        }
    } else if (::sin(angle) < 0) {
        angle += 0.25;
    } else if (::sin(angle) > 0) {
        angle -= 0.25;
//! [5] //! [6]
    }
//! [6]

    // Try not to crash with any other mice
//! [7]
    QList<QGraphicsItem *> dangerMice = scene()->items(QPolygonF()
                                                       << mapToScene(0, 0)
                                                       << mapToScene(-30, -50)
                                                       << mapToScene(30, -50));
    foreach (QGraphicsItem *item, dangerMice) {
        if (item == this)
            continue;

        QLineF lineToMouse(QPointF(0, 0), mapFromItem(item, 0, 0));
        qreal angleToMouse = ::acos(lineToMouse.dx() / lineToMouse.length());
        if (lineToMouse.dy() < 0)
            angleToMouse = TwoPi - angleToMouse;
        angleToMouse = normalizeAngle((Pi - angleToMouse) + Pi / 2);

        if (angleToMouse >= 0 && angleToMouse < Pi / 2) {
            // Rotate right
            angle += 0.5;
        } else if (angleToMouse <= TwoPi && angleToMouse > (TwoPi - Pi / 2)) {
            // Rotate left
            angle -= 0.5;
//! [7] //! [8]
        }
//! [8] //! [9]
    }
//! [9]

    // Add some random movement
//! [10]
    if (dangerMice.size() > 1 && (qrand() % 10) == 0) {
        if (qrand() % 1)
            angle += (qrand() % 100) / 500.0;
        else
            angle -= (qrand() % 100) / 500.0;
    }
//! [10]

//! [11]
    speed += (-50 + qrand() % 100) / 100.0;

    qreal dx = ::sin(angle) * 10;
    mouseEyeDirection = (qAbs(dx / 5) < 1) ? 0 : dx / 5;

    setRotation(rotation() + dx);
    setPos(mapToParent(0, -(3 + sin(speed) * 3)));
}
//! [11]

#include "particle.h"

MyParticle::MyParticle()
{
    iValid = 0;
    Dim = 0;
}

MyParticle::MyParticle(int d)
{
    iValid = 1;
    Dim = d;
    X = new double[Dim];
    V = new double[Dim];
    XBest = new double[Dim];
}


void MyParticle::InitParticle(int d)
{
    iValid = 1;
    Dim = d;
    X = new double[Dim];
    V = new double[Dim];
    XBest = new double[Dim];
}

int MyParticle::GetDim()
{
    return Dim;
}

void MyParticle::SetDim(int dim)
{
    Dim = dim ;
}

int MyParticle::IsValid()
{
    return iValid;
}

double MyParticle::GetFitness()
{
    return Fit;
}

void MyParticle::SetFit(double fit)
{
    Fit = fit;
}

void MyParticle::SetFitBest(double fit)
{
    FitBest = fit;
}


演示结果



  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值