mirror of
https://github.com/KrisKennaway/ii-vision.git
synced 2024-12-21 20:29:21 +00:00
Randomize tie-breaker when pages etc have the same weight, so we
don't consistently prefer larger numbers. There still seems to be a bug somewhere causing some screen regions to be consistently not updated, but perhaps I'll find it when working on the logic to penalize persistent diffs.
This commit is contained in:
parent
a6f32886cd
commit
d3522c817f
117
scheduler.py
117
scheduler.py
@ -4,6 +4,7 @@ import collections
|
||||
from typing import Iterator
|
||||
|
||||
import opcodes
|
||||
import random
|
||||
|
||||
|
||||
class OpcodeScheduler:
|
||||
@ -11,6 +12,67 @@ class OpcodeScheduler:
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
def nonce():
|
||||
return random.randint(0, 255)
|
||||
|
||||
|
||||
class HeuristicPageFirstScheduler(OpcodeScheduler):
|
||||
"""Group by page first then content byte.
|
||||
|
||||
Grouping by page (rather than content) means that we'll reduce the window
|
||||
of time during which we have violated a colour invariant due to bits
|
||||
hanging across byte boundaries.
|
||||
"""
|
||||
|
||||
# Median similarity: 0.862798 @ 15 fps, 10M output
|
||||
def schedule(self, changes):
|
||||
data = {}
|
||||
|
||||
page_weights = collections.defaultdict(int)
|
||||
page_content_weights = {}
|
||||
for ch in changes:
|
||||
xor_weight, page, offset, content, run_length = ch
|
||||
data.setdefault((page, content), list()).append(
|
||||
(xor_weight, run_length, offset))
|
||||
page_weights[page] += xor_weight
|
||||
page_content_weights.setdefault(page, collections.defaultdict(
|
||||
int))[content] += xor_weight
|
||||
|
||||
# Weight each page and content within page by total xor weight and
|
||||
# traverse in this order, with a random nonce so that we don't
|
||||
# consistently prefer higher-valued pages etc.
|
||||
|
||||
pages = sorted(
|
||||
list(page_weights.keys()),
|
||||
key=lambda p: (page_weights[p], nonce()), reverse=True)
|
||||
for page in pages:
|
||||
yield opcodes.SetPage(page)
|
||||
|
||||
content_weights = page_content_weights[page]
|
||||
contents = sorted(
|
||||
list(content_weights.keys()),
|
||||
key=lambda c: (content_weights[c], nonce()),
|
||||
reverse=True)
|
||||
|
||||
for content in contents:
|
||||
yield opcodes.SetContent(content)
|
||||
offsets = sorted(
|
||||
data[(page, content)],
|
||||
key=lambda x: (x[0], nonce()),
|
||||
reverse=True)
|
||||
|
||||
# print("page %d content %d offsets %s" % (page, content,
|
||||
# offsets))
|
||||
for (_, run_length, offset) in offsets:
|
||||
if run_length > 1:
|
||||
# print("Offset %d run length %d" % (
|
||||
# offset, run_length))
|
||||
yield opcodes.RLE(offset, run_length)
|
||||
else:
|
||||
yield opcodes.Store(offset)
|
||||
|
||||
|
||||
|
||||
class HeuristicContentFirstScheduler(OpcodeScheduler):
|
||||
"""Group by content first then page.
|
||||
|
||||
@ -63,61 +125,6 @@ class HeuristicContentFirstScheduler(OpcodeScheduler):
|
||||
yield opcodes.Store(offset)
|
||||
|
||||
|
||||
class HeuristicPageFirstScheduler(OpcodeScheduler):
|
||||
"""Group by page first then content byte.
|
||||
|
||||
Grouping by page (rather than content) means that we'll reduce the window
|
||||
of time during which we have violated a colour invariant due to bits
|
||||
hanging across byte boundaries.
|
||||
"""
|
||||
|
||||
# Median similarity: 0.862798 @ 15 fps, 10M output
|
||||
def schedule(self, changes):
|
||||
data = {}
|
||||
|
||||
page_weights = collections.defaultdict(int)
|
||||
page_content_weights = {}
|
||||
for ch in changes:
|
||||
xor_weight, page, offset, content, run_length = ch
|
||||
data.setdefault((page, content), list()).append(
|
||||
(xor_weight, run_length, offset))
|
||||
page_weights[page] += xor_weight
|
||||
page_content_weights.setdefault(page, collections.defaultdict(
|
||||
int))[content] += xor_weight
|
||||
|
||||
# Weight each page and content within page by total xor weight and
|
||||
# traverse in this order
|
||||
|
||||
pages = sorted(
|
||||
list(page_weights.keys()),
|
||||
key=lambda p: page_weights[p], reverse=True)
|
||||
for page in pages:
|
||||
yield opcodes.SetPage(page)
|
||||
|
||||
content_weights = page_content_weights[page]
|
||||
contents = sorted(
|
||||
list(content_weights.keys()),
|
||||
key=lambda c: content_weights[c],
|
||||
reverse=True)
|
||||
|
||||
for content in contents:
|
||||
yield opcodes.SetContent(content)
|
||||
offsets = sorted(
|
||||
data[(page, content)],
|
||||
key=lambda x: x[0],
|
||||
reverse=True)
|
||||
|
||||
# print("page %d content %d offsets %s" % (page, content,
|
||||
# offsets))
|
||||
for (_, run_length, offset) in offsets:
|
||||
if run_length > 1:
|
||||
# print("Offset %d run length %d" % (
|
||||
# offset, run_length))
|
||||
yield opcodes.RLE(offset, run_length)
|
||||
else:
|
||||
yield opcodes.Store(offset)
|
||||
|
||||
|
||||
class OldHeuristicPageFirstScheduler(OpcodeScheduler):
|
||||
"""Group by page first then content byte.
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user