simulated annealing output chooser
parent
c6b648195f
commit
2914c64fda
|
|
@ -3,6 +3,30 @@ import unittest
|
||||||
import writer
|
import writer
|
||||||
|
|
||||||
class TestLineChooser(unittest.TestCase):
|
class TestLineChooser(unittest.TestCase):
|
||||||
|
def test_simulated_annealing(self):
|
||||||
|
chooser = writer.LineChooserSimulatedAnnealing()
|
||||||
|
chooser.now = lambda *args: 100
|
||||||
|
|
||||||
|
for name, c in ({
|
||||||
|
"fresh something": [
|
||||||
|
writer.LineChooserSimulatedAnnealing.initial_health,
|
||||||
|
chooser.now(),
|
||||||
|
],
|
||||||
|
"old something": [
|
||||||
|
writer.LineChooserSimulatedAnnealing.initial_health - writer.LineChooserSimulatedAnnealing.decay_rate * 5,
|
||||||
|
chooser.now() - 5,
|
||||||
|
],
|
||||||
|
"fresh nothing": [
|
||||||
|
writer.LineChooserSimulatedAnnealing.initial_health - writer.LineChooserSimulatedAnnealing.nothing_penalty,
|
||||||
|
chooser.now(),
|
||||||
|
],
|
||||||
|
}).items():
|
||||||
|
self.assertEqual(
|
||||||
|
c[0],
|
||||||
|
chooser.health(self.new_line(True, c[1], not "nothing" in name)),
|
||||||
|
name,
|
||||||
|
)
|
||||||
|
|
||||||
def test_latest_sticky(self):
|
def test_latest_sticky(self):
|
||||||
stale_something = self.new_line(False, 1, 1)
|
stale_something = self.new_line(False, 1, 1)
|
||||||
stale_nothing = self.new_line(False, 1, None)
|
stale_nothing = self.new_line(False, 1, None)
|
||||||
|
|
|
||||||
|
|
@ -2,12 +2,14 @@ import time
|
||||||
import json
|
import json
|
||||||
import pyautogui
|
import pyautogui
|
||||||
import log
|
import log
|
||||||
|
import random
|
||||||
|
|
||||||
class Writer:
|
class Writer:
|
||||||
def __init__(self, writer):
|
def __init__(self, writer):
|
||||||
self.writer = writer
|
self.writer = writer
|
||||||
self.previous = Line([])
|
self.previous = Line([])
|
||||||
self.chooser = LineChooserLatestSticky()
|
self.chooser = LineChooserLatestSticky()
|
||||||
|
self.chooser = LineChooserSimulatedAnnealing()
|
||||||
|
|
||||||
def write(self, v):
|
def write(self, v):
|
||||||
latest = Line(v)
|
latest = Line(v)
|
||||||
|
|
@ -86,12 +88,35 @@ class LineChooser:
|
||||||
return b
|
return b
|
||||||
if not b:
|
if not b:
|
||||||
return a
|
return a
|
||||||
return self._choose(a, b)
|
|
||||||
|
|
||||||
class LineChooserLatestSticky(LineChooser):
|
|
||||||
def _choose(self, a, b):
|
|
||||||
latest = max([a,b], key=lambda x:x.t)
|
latest = max([a,b], key=lambda x:x.t)
|
||||||
oldest = min([a,b], key=lambda x:x.t)
|
oldest = min([a,b], key=lambda x:x.t)
|
||||||
|
return self._choose(latest, oldest)
|
||||||
|
|
||||||
|
def now(self):
|
||||||
|
return time.time()
|
||||||
|
|
||||||
|
class LineChooserLatestSticky(LineChooser):
|
||||||
|
def _choose(self, latest, oldest):
|
||||||
if latest.is_nothing() and oldest.is_recent():
|
if latest.is_nothing() and oldest.is_recent():
|
||||||
return oldest
|
return oldest
|
||||||
return latest
|
return latest
|
||||||
|
|
||||||
|
class LineChooserSimulatedAnnealing(LineChooser):
|
||||||
|
initial_health = 50
|
||||||
|
nothing_penalty = 10
|
||||||
|
decay_rate = 5
|
||||||
|
|
||||||
|
def _choose(self, latest, oldest):
|
||||||
|
oldest_health = self.health(oldest)
|
||||||
|
seed = random.randint(0, 100)
|
||||||
|
if seed < oldest_health:
|
||||||
|
print("LineChooserSimulatedAnnealing retaining old because", seed, "<", oldest_health)
|
||||||
|
return oldest
|
||||||
|
return latest
|
||||||
|
|
||||||
|
def health(self, line):
|
||||||
|
health = LineChooserSimulatedAnnealing.initial_health
|
||||||
|
health = health - LineChooserSimulatedAnnealing.decay_rate * (self.now() - line.t)
|
||||||
|
if line.is_nothing():
|
||||||
|
health -= LineChooserSimulatedAnnealing.nothing_penalty
|
||||||
|
return health
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue