Skip to content

Commit

Permalink
minor perfomance tweaks
Browse files Browse the repository at this point in the history
  • Loading branch information
AIn0n committed Dec 3, 2021
1 parent b872bd5 commit 68f15d4
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 70 deletions.
28 changes: 3 additions & 25 deletions expandingModel/figureTypes.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from dataclasses import dataclass
import dataclasses
from typing import Iterable


Expand All @@ -16,20 +17,6 @@ class Vec:
start: Point
end: Point

def isVertical(self) -> bool:
return self.start.x == self.end.x

def isHorizontal(self) -> bool:
return self.start.y == self.end.y

def isAligned(self, other) -> bool:
if self.isVertical() and other.isHorizontal and other.start.x <= self.start.x <= other.end.x:
return True
elif self.isHorizontal() and other.isVertical and other.start.y <= self.start.y <= other.end.y:
return True
return False


class Rect:

def __init__(self, p: Point, width: int, height: int) -> None:
Expand All @@ -40,9 +27,7 @@ def __init__(self, p: Point, width: int, height: int) -> None:
self.height_u = height // 2
self.height_d = height // 2
self.p = p
self.calcCoords()
self.calcField()
self.calcVecs()
self.calcEverything()

def calcCoords(self) -> None:
''' d-------c
Expand Down Expand Up @@ -87,14 +72,6 @@ def getVerVecs(self) -> Iterable:
def getHorVecs(self) -> Iterable:
return [self.horDown, self.horUp]

def isAlignedHorizontally(self, rect):
return self.horUp.isAligned(rect.verRight) or self.horDown.isAligned(rect.verRight) \
or rect.horUp.isAligned(self.verLeft) or rect.horDown.isAligned(self.verLeft)

def isAlignedVertically(self, rect):
return self.verLeft.isAligned(rect.horDown) or self.verRight.isAligned(rect.horDown) \
or rect.verLeft.isAligned(self.horUp) or rect.verRight.isAligned(self.horUp)

def isToRightOf(self, rect):
return rect.b.x <= self.a.x

Expand Down Expand Up @@ -162,6 +139,7 @@ def expandDown(self, rects, area) -> None:
self.height_d = abs(self.p.y - new_y)
self.calcEverything()

#TODO: move this into unit tests
if __name__ == '__main__':
rB = Rect(Point(50, 50), 100, 100)
r = Rect(Point(5, 5), 4, 4)
Expand Down
70 changes: 25 additions & 45 deletions expandingModel/genAlgorithm.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from typing import Tuple
from figureTypes import *
import random
from random import getrandbits, randint, choice, choices, uniform

class Specimen:
def __init__(self, genes :int, rangeX, rangeY) -> None:
Expand All @@ -12,13 +13,13 @@ def randomizeChrsom(self) -> None:
self.chrsom[n] = [self.getRndPoint(), self.getRndFuncNr()]

def getRndFuncNr(self) -> int:
return [random.randint(0, 1) for n in range(4)]
return [getrandbits(1) for n in range(4)]

def getRndPoint(self):
return Point(random.randint(*self.rangeX), random.randint(*self.rangeY))
return Point(randint(*self.rangeX), randint(*self.rangeY))

def randGenes(self, num) -> int:
return random.choices(range(len(self.chrsom)), k = num)
return choices(range(len(self.chrsom)), k = num)

def newChild(self, chrsom, prob):
child = Specimen(0, self.rangeX, self.rangeY)
Expand All @@ -37,45 +38,39 @@ def inversion(self) -> None:
(min_idx, max_idx) = sorted(self.randGenes(2))
self.chrsom = \
self.chrsom[:min_idx] + \
list(reversed(self.chrsom[min_idx:max_idx])) + \
self.chrsom[min_idx:max_idx][::-1] + \
self.chrsom[max_idx:]

def mutate(self, prob) -> None:
if random.uniform(0, 1) < prob:
random.choice([self.swap, self.replacement, self.inversion])()
if uniform(0, 1) < prob:
choice([self.swap, self.replacement, self.inversion])()

class FitnessClass:
def __init__(self, area: Rect, rooms: tuple) -> None:
self.area = area
self.rooms = rooms

def getRndSpecimen(self):
rX = [self.area.a.x, self.area.b.x]
rY = [self.area.a.y, self.area.d.y]
rX = (self.area.a.x, self.area.b.x)
rY = (self.area.a.y, self.area.d.y)
return Specimen(len(self.rooms), rX, rY)

def countFitness(self, specimen: Specimen) -> None:
totalArea = 0
movedRooms = []
totalArea, rooms = 0, []
for idx, gene in enumerate(specimen.chrsom):
movedRect = self.rooms[idx].cloneOffset(gene[0])
if not self.area.containsRectangle(movedRect):
new = self.rooms[idx].cloneOffset(gene[0])
if not self.area.containsRectangle(new) or\
any(map(lambda room : room.collides(new), rooms)):
specimen.fitness = 0
return
for room in movedRooms:
if movedRect.collides(room):
specimen.fitness = 0
return
movedRooms.append(movedRect)
for n in range(len(self.rooms)):
curr = movedRooms.pop(0)
if gene[1][0]:curr.expandLeft(movedRooms, self.area),
if gene[1][1]:curr.expandRight(movedRooms, self.area),
if gene[1][2]:curr.expandUp(movedRooms, self.area),
if gene[1][3]:curr.expandDown(movedRooms, self.area)
totalArea += curr.field
movedRooms.append(curr)

rooms.append(new)
for _ in range(len(self.rooms)):
r = rooms.pop(0)
for i, func in enumerate([r.expandLeft, r.expandRight, r.expandUp, r.expandDown]):
if gene[1][i]: func(rooms, self.area)
totalArea += r.field
rooms.append(r)

specimen.fitness = totalArea

class GeneticAlgorithm:
Expand Down Expand Up @@ -109,27 +104,12 @@ def buildNewGeneration(self) -> None:
self.generation.sort(key = lambda x : x.fitness, reverse= True)
new = [*self.generation[:int(len(self.generation) * self.elitarism)]]

fitnessArray = [x.fitness for x in self.generation]
fitnessArr = [x.fitness for x in self.generation]
while len(new) < len(self.generation):
parents = random.choices(self.generation, weights=fitnessArray, k=2)
parents = choices(self.generation, weights=fitnessArr, k=2)
new.extend(self.getChildren(*parents))
self.generation = new

def repeat(self, n: int) -> None:
for x in range(n):
self.buildNewGeneration()

if __name__ == '__main__':
squares = tuple([
Rect(Point(0, 0), 2, 4),
Rect(Point(0, 0), 4, 6),
Rect(Point(0, 0), 12, 2),
Rect(Point(0, 0), 8, 4),
Rect(Point(0, 0), 8, 6),
Rect(Point(0, 0), 4, 10)])
fitCls = FitnessClass(Rect(Point(0, 0), 80, 80),squares)
genAlg = GeneticAlgorithm(200, 0.1, 0.2, fitCls)
genAlg.repeat(5000)
bestSpecimen = max(genAlg.generation, key = lambda x : x.fitness)
print(bestSpecimen.chrsom)
print(bestSpecimen.fitness)
self.buildNewGeneration()

0 comments on commit 68f15d4

Please sign in to comment.