Umstellen der Auswertungslogik
This commit is contained in:
@@ -1,58 +1,53 @@
|
||||
import math
|
||||
import random
|
||||
from utils.literal import Literal
|
||||
from utils.memory_cell import MemoryCell
|
||||
from utils.memory_array import MemoryArray
|
||||
from utils.memory_manager import MemoryManager
|
||||
from utils.algo_context import AlgoContext
|
||||
from utils.algo_int import Int
|
||||
from utils.algo_array import Array
|
||||
from vorlesung.L07_hashtable.hashtable import HashTableOpenAddressing
|
||||
|
||||
#Goldener Schnitt
|
||||
a = Literal((math.sqrt(5) - 1) / 2)
|
||||
# Goldener Schnitt (Konstante, nicht instrumentiert)
|
||||
_A = (math.sqrt(5) - 1) / 2
|
||||
|
||||
# Hashfunktion nach multiplikativer Methode
|
||||
def h(x: MemoryCell, m: Literal) -> Literal:
|
||||
with MemoryCell(int(x * a)) as integer_part, MemoryCell(x * a) as full_product:
|
||||
with MemoryCell(full_product - integer_part) as fractional_part:
|
||||
return Literal(abs(int(fractional_part * m)))
|
||||
|
||||
# Quadratische Sondierung
|
||||
def f(x: MemoryCell, i: Literal, m: Literal) -> Literal:
|
||||
c1 = 1
|
||||
c2 = 5
|
||||
with MemoryCell(h(x, m)) as initial_hash, MemoryCell(c2 * int(i) * int(i)) as quadratic_offset:
|
||||
with MemoryCell(initial_hash + quadratic_offset) as probe_position:
|
||||
probe_position += Literal(c1 * int(i)) # Linear component
|
||||
return probe_position % m
|
||||
def h(x: Int, m: Int) -> Int:
|
||||
"""Hashfunktion nach multiplikativer Methode."""
|
||||
full = x.value * _A
|
||||
return Int(int(abs(full - int(full)) * int(m)), x._ctx)
|
||||
|
||||
# Symmetrische quadratische Sondierung
|
||||
def fs(x: MemoryCell, i: Literal, m: Literal) -> Literal:
|
||||
with MemoryCell(h(x, m)) as base_hash, MemoryCell(int(i) * int(i)) as square:
|
||||
if int(i) % 2 == 0: # gerades i: Vorwärtssondierung
|
||||
with MemoryCell(base_hash + square) as position:
|
||||
return position % m
|
||||
else: # ungerades i: Rückwärtssondierung
|
||||
with MemoryCell(base_hash - square) as position:
|
||||
return position % m
|
||||
|
||||
def f(x: Int, i: Int, m: Int) -> Int:
|
||||
"""Quadratische Sondierung."""
|
||||
c1, c2 = 1, 5
|
||||
base = int(h(x, m))
|
||||
probe = base + c1 * int(i) + c2 * int(i) ** 2
|
||||
return Int(probe % int(m), x._ctx)
|
||||
|
||||
|
||||
def fs(x: Int, i: Int, m: Int) -> Int:
|
||||
"""Symmetrische quadratische Sondierung."""
|
||||
base = int(h(x, m))
|
||||
sq = int(i) ** 2
|
||||
if int(i) % 2 == 0:
|
||||
probe = base + sq
|
||||
else:
|
||||
probe = base - sq
|
||||
return Int(probe % int(m), x._ctx)
|
||||
|
||||
|
||||
def analyze_complexity(sizes):
|
||||
"""
|
||||
Analysiert die Komplexität
|
||||
|
||||
:param sizes: Eine Liste von Eingabegrößen für die Analyse.
|
||||
"""
|
||||
ctx = AlgoContext()
|
||||
for size in sizes:
|
||||
MemoryManager.purge() # Speicher zurücksetzen
|
||||
ht = HashTableOpenAddressing(size, f)
|
||||
random_array = MemoryArray.create_random_array(size, -100, 100)
|
||||
for cell in random_array:
|
||||
ctx.reset()
|
||||
ht = HashTableOpenAddressing(size, f, ctx)
|
||||
z = Array.random(size, -100, 100, ctx)
|
||||
for cell in z:
|
||||
ht.insert(cell)
|
||||
MemoryManager.reset()
|
||||
cell = random.choice(random_array.cells)
|
||||
ht.search(cell)
|
||||
MemoryManager.save_stats(size)
|
||||
ctx.reset()
|
||||
target = z[random.randint(0, size - 1)]
|
||||
ht.search(target)
|
||||
ctx.save_stats(size)
|
||||
|
||||
MemoryManager.plot_stats(["cells", "compares"])
|
||||
ctx.plot_stats(["comparisons"])
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
@@ -1,76 +1,75 @@
|
||||
from collections.abc import Callable
|
||||
from utils.literal import Literal
|
||||
from utils.memory_array import MemoryArray
|
||||
from utils.memory_cell import MemoryCell
|
||||
from utils.memory_range import mrange
|
||||
from utils.algo_context import AlgoContext
|
||||
from utils.algo_array import Array
|
||||
from utils.algo_int import Int
|
||||
from utils.algo_range import irange
|
||||
|
||||
|
||||
UNUSED_MARK = "UNUSED"
|
||||
UNUSED_MARK = "UNUSED"
|
||||
DELETED_MARK = "DELETED"
|
||||
|
||||
|
||||
class HashTableOpenAddressing:
|
||||
def __init__(self, m: Literal, f: Callable[[MemoryCell, Literal, Literal], Literal]):
|
||||
if not isinstance(m, Literal):
|
||||
m = Literal(m)
|
||||
self.m = m
|
||||
"""
|
||||
Hashtabelle mit offener Adressierung.
|
||||
|
||||
f – Sondierungsfunktion f(x: Int, i: Int, m: Int) -> Int
|
||||
Liefert die Tabellenposition für Schlüssel x beim i-ten Versuch.
|
||||
"""
|
||||
|
||||
def __init__(self, m: int, f: Callable[[Int, Int, Int], Int], ctx: AlgoContext):
|
||||
self.ctx = ctx
|
||||
self.m = Int(m, ctx)
|
||||
self.f = f
|
||||
self.table = MemoryArray(m)
|
||||
for i in mrange(m):
|
||||
self.table[i].value = UNUSED_MARK
|
||||
self.table = Array([UNUSED_MARK] * m, ctx)
|
||||
|
||||
def insert(self, x: MemoryCell):
|
||||
with MemoryCell(0) as i:
|
||||
while i < self.m:
|
||||
j = self.f(x, i, self.m)
|
||||
if self.is_free(j):
|
||||
self.table[j].set(x)
|
||||
return True
|
||||
i.set(i.succ())
|
||||
def insert(self, x: Int) -> bool:
|
||||
i = Int(0, self.ctx)
|
||||
while i < self.m:
|
||||
j = self.f(x, i, self.m)
|
||||
if self.is_free(j):
|
||||
self.table[j] = x
|
||||
return True
|
||||
i += 1
|
||||
return False
|
||||
|
||||
def search(self, x: MemoryCell):
|
||||
with MemoryCell(0) as i:
|
||||
while i < self.m:
|
||||
j = self.f(x, i, self.m)
|
||||
if self.is_unused(j):
|
||||
return False
|
||||
if self.table[j] == x:
|
||||
return True
|
||||
i.set(i.succ())
|
||||
def search(self, x: Int) -> bool:
|
||||
i = Int(0, self.ctx)
|
||||
while i < self.m:
|
||||
j = self.f(x, i, self.m)
|
||||
if self.is_unused(j):
|
||||
return False
|
||||
if self.table[j] == x:
|
||||
return True
|
||||
i += 1
|
||||
return False
|
||||
|
||||
def delete(self, x: MemoryCell):
|
||||
with MemoryCell(0) as i:
|
||||
while i < self.m:
|
||||
j = self.f(x, i, self.m)
|
||||
if self.is_unused(j):
|
||||
return False
|
||||
if self.table[j] == x:
|
||||
self.table[j].value = DELETED_MARK
|
||||
return True
|
||||
i.set(i.succ())
|
||||
def delete(self, x: Int) -> bool:
|
||||
i = Int(0, self.ctx)
|
||||
while i < self.m:
|
||||
j = self.f(x, i, self.m)
|
||||
if self.is_unused(j):
|
||||
return False
|
||||
if self.table[j] == x:
|
||||
self.table[j].set(DELETED_MARK) # Tombstone setzen (1 write)
|
||||
return True
|
||||
i += 1
|
||||
return False
|
||||
|
||||
def __str__(self):
|
||||
return str(self.table)
|
||||
|
||||
def alpha(self):
|
||||
with MemoryCell(0) as i:
|
||||
used = 0
|
||||
while i < self.m:
|
||||
used += 0 if self.is_free(i) else 1
|
||||
i.set(i.succ())
|
||||
def alpha(self) -> float:
|
||||
"""Belegungsfaktor der Tabelle."""
|
||||
used = sum(0 if self.is_free(Int(i, self.ctx)) else 1
|
||||
for i in range(int(self.m)))
|
||||
return used / int(self.m)
|
||||
|
||||
def is_unused(self, i: Literal):
|
||||
if self.table[i].value == UNUSED_MARK:
|
||||
return True
|
||||
return False
|
||||
def is_unused(self, i: Int) -> bool:
|
||||
return self.table[i].value == UNUSED_MARK
|
||||
|
||||
def is_deleted(self, i: Literal):
|
||||
if self.table[i].value == DELETED_MARK:
|
||||
return True
|
||||
return False
|
||||
def is_deleted(self, i: Int) -> bool:
|
||||
return self.table[i].value == DELETED_MARK
|
||||
|
||||
def is_free(self, i: Literal):
|
||||
def is_free(self, i: Int) -> bool:
|
||||
return self.is_unused(i) or self.is_deleted(i)
|
||||
|
||||
Reference in New Issue
Block a user