Skip to content

Commit 2d9404f

Browse files
committed
Optimize computeFitness further
1 parent b6173f5 commit 2d9404f

File tree

3 files changed

+46
-15
lines changed

3 files changed

+46
-15
lines changed

main.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,4 +64,27 @@ int main(int argc, char *argv[])
6464
* It's probably faster to use one hueg contiguous array rather than a multidimentional, for each color.
6565
* We'll just use i*width+j with i*width computed out of the inner loop.
6666
*
67+
* Maybe in computeFitness we could convert everything to RGB instead of RGBA, so we'd always have 0xFF for the A
68+
* And then blindly compute our difference of uint8_t, this way we might get vector instructions and unrolling.
69+
*
70+
* Stuff from EvoLisa :
71+
* Can add new polygons at a random zindex instead of always on top
72+
* Insert a new point in the middle of two points (then we could optimize the new point)
73+
* Remove a point
74+
* Can do multiple mutations at the same time. Can do no mutation at all.
75+
* Maybe try to do this too, but we should avoid empty mutation loops if possible.
76+
* Make it likely that we'll always have at least one mutation every loop.
77+
* His probabilities of adding/removing points are per poly, so when you have a lot of polys
78+
* the polys mutation loop is the only thing running, and it almost never adds/removes/moves polys, just mutate.
79+
* And each poly mutated also has a point mutation loop. So it'd end up taking all the damn time with our polys.
80+
* We should make it per mutation loop instead. Since we can have up to 10k polys without problem it seems better.
81+
* He has separate mutation rates for everything.
82+
* He has a min/max poly count and min/max point count.
83+
* When mutating, accept <= changes in fitness. We accept +fitnessThreshold< currently
84+
* Maybe keep the +fitnessThreshold< for adding the initial polys (until we reach minPolys)
85+
* Then start mutating using <=. We shouldn't be able to get stuck doing/undoing in a loop,
86+
* since the mutation process is mostly random, not optimizations.
87+
* When we add a completely new poly, we'll still want to optimize its color/shape.
88+
* But in the normal mutations we don't optimize the shape/color of random polys.
89+
*
6790
*/

widget.cpp

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
unsigned Widget::height;
1717
unsigned Widget::width;
18+
QImage Widget::pic;
1819

1920
using namespace std;
2021

@@ -64,7 +65,7 @@ Widget::~Widget()
6465
exit(0);
6566
}
6667

67-
int Widget::computeFitness(QImage& target, QRect box)
68+
int Widget::computeFitness(const QImage& target, const QRect box)
6869
{
6970
unsigned minx, maxx, miny, maxy;
7071
if (box.isNull())
@@ -81,33 +82,39 @@ int Widget::computeFitness(QImage& target, QRect box)
8182
maxy = miny + box.height();
8283
}
8384

84-
QVector<QRgb*> originalLines;
85-
QVector<QRgb*> targetLines;
85+
static QVector<QRgb*> originalLines;
86+
originalLines.resize(maxy-miny);
8687
for (unsigned i=miny; i<maxy; i++)
87-
originalLines.append((QRgb*)pic.scanLine(i));
88+
originalLines[i] = ((QRgb*)pic.scanLine(i));
89+
static QVector<QRgb*> targetLines;
90+
targetLines.resize(maxy-miny);
8891
for (unsigned i=miny; i<maxy; i++)
89-
targetLines.append((QRgb*)target.scanLine(i));
92+
targetLines[i] = ((QRgb*)target.scanLine(i));
9093

91-
auto computeSlice = [&](unsigned start, unsigned end)
94+
auto computeSlice = [&](const unsigned start, const unsigned end)
9295
{
9396
unsigned partFitness=0;
9497
for (unsigned i=start-miny; i<end-miny; i++)
9598
{
9699
// Sum of the differences of each pixel's color
97100
for (unsigned j=minx; j<maxx; j++)
98101
{
99-
QRgb ocolor = originalLines.at(i)[j];
100-
int oR=qRed(ocolor), oG=qGreen(ocolor), oB=qBlue(ocolor);
101-
QRgb tcolor = targetLines.at(i)[j];
102-
int tR=qRed(tcolor), tG=qGreen(tcolor), tB=qBlue(tcolor);
102+
unsigned ocolor = originalLines.at(i)[j];
103+
int oR=(ocolor>>16), oG=(ocolor>>8)&0xFF, oB=(ocolor&0xFF);
104+
unsigned tcolor = targetLines.at(i)[j];
105+
int tR=(tcolor>>16), tG=(tcolor>>8)&0xFF, tB=(tcolor&0xFF);
103106
partFitness += abs(tR-oR)+abs(tG-oG)+abs(tB-oB);
104107
}
105108
}
106109
return partFitness;
107110
};
108-
QFuture<unsigned> firstSlice = QtConcurrent::run(computeSlice, miny, maxy/2);
109-
unsigned fitness = computeSlice(maxy/2, maxy);
110-
fitness += firstSlice.result();
111+
QFuture<unsigned> slice1 = QtConcurrent::run(computeSlice, miny, maxy/4);
112+
QFuture<unsigned> slice2 = QtConcurrent::run(computeSlice, maxy/4, 2*maxy/4);
113+
QFuture<unsigned> slice3 = QtConcurrent::run(computeSlice, 2*maxy/4, 3*maxy/4);
114+
unsigned fitness = computeSlice(3*maxy/4, maxy);
115+
fitness += slice1.result();
116+
fitness += slice2.result();
117+
fitness += slice3.result();
111118

112119
return fitness;
113120
}

widget.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include <QImage>
66
#include <QVector>
77
#include <QMenuBar>
8+
#include <stdint.h>
89

910
#include "poly.h"
1011

@@ -22,7 +23,7 @@ class Widget : public QWidget
2223
public:
2324
explicit Widget();
2425
~Widget();
25-
int computeFitness(QImage& target, QRect box=QRect());
26+
static int computeFitness(const QImage& target, const QRect box=QRect());
2627
Poly genPoly(); // Creates a new random polygon
2728
static void drawPoly(QImage& target, Poly& poly);
2829
static void drawPoly(QImage& target, Poly& poly, QPainter& painter);
@@ -55,7 +56,7 @@ private slots:
5556
Ui::Widget *ui;
5657
QMenuBar *menuBar;
5758
QAction* startStopAction, *openAction, *cleanAction, *optimizeAction;
58-
QImage pic;
59+
static QImage pic;
5960
QImage generated;
6061
bool running;
6162
QVector<Poly> polys;

0 commit comments

Comments
 (0)