此为老师留的大作业
算法依据: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; }
演示结果