116 lines
4.3 KiB
Python

import logging
logger = logging.getLogger(__name__)
# logging.basicConfig(level=logging.DEBUG)
from utils.memory_array import MemoryArray
from utils.memory_cell import MemoryCell
from utils.literal import Literal
from utils.constants import MIN_VALUE
from utils.memory_manager import MemoryManager
from utils.memory_range import mrange
def example():
initial = [6, 5, 3, 8, 1, 7, 2, 4]
# initial = [-6, -5, -3, -8, 1, 7, 2, 4]
toSort = MemoryArray(initial)
# init_from_size not accessible?
sorted = MemoryArray([-1] * len(initial))
mergeSort(toSort, sorted)
logger.debug(f"sorted {sorted} vs initial {initial}")
assert all(sorted[Literal(i)] == Literal(i+1) for i in range(len(initial))), "Array not sorted correctly"
analyze_complexity(mergeSort, [10, 20, 30, 40, 50, 60, 70, 80, 90, 100])
def merge(left: MemoryArray, right: MemoryArray, sort: MemoryArray):
pointerLeft = MemoryCell(0)
pointerRight = MemoryCell(0)
pointerSort = MemoryCell(0)
compare = lambda x, y: x <= y
logger.debug(f"Merging left {left} with right {right} in sort {sort}")
while pointerLeft < left.length() and pointerRight < right.length():
if compare(left[pointerLeft], right[pointerRight]):
sort[pointerSort] = left[pointerLeft]
pointerLeft += Literal(1)
else:
sort[pointerSort] = right[pointerRight]
pointerRight += Literal(1)
logger.debug(f"Now are at sort {sort} with {pointerLeft} (l) and {pointerRight} (r)")
pointerSort += Literal(1)
# Consume remaining elements
while pointerLeft < left.length():
logger.debug(f"Consuming left {left} from {pointerSort} at {pointerLeft}")
sort[pointerSort] = left[pointerLeft]
pointerLeft += Literal(1)
pointerSort += Literal(1)
while pointerRight < right.length():
logger.debug(f"Consuming right {right} from {pointerSort} at {pointerRight}")
sort[pointerSort] = right[pointerRight]
pointerRight += Literal(1)
pointerSort += Literal(1)
# Sort the array passed as "toSort" and place the result in array "sort"
# Does not change the original Array
def mergeSort(toSort: MemoryArray, sort: MemoryArray):
logger.debug(toSort)
toSortLength = MemoryCell(toSort.length())
# Splitting
# Rec-Term -> Reached single Element. Single Element is already sorted so we place it!
if toSortLength <= Literal(1):
# still working for empty array
if toSortLength == Literal(1):
sort[Literal(0)] = toSort[Literal(0)]
return
# TODO - Use a global var or a reference to an array passed as argument for this
# TODO - Tried non-temp-array approach with alternating Work-Arrays passed to the function, but made code really unreadable. Decided not worth it for now
# Temporary Arrays to hold the split arrays
mid : Literal = toSortLength // Literal(2)
left : MemoryArray = MemoryArray([toSort[i] for i in mrange(mid)])
right : MemoryArray = MemoryArray([toSort[i] for i in mrange(mid, toSortLength)])
# Temporary arrays for sorted halves
leftSort = MemoryArray([-1] * mid.get())
rightSort = MemoryArray([-1] * (toSortLength - mid).get())
# Split further
mergeSort(left, leftSort)
mergeSort(right, rightSort)
# Recreate the array from the seperated parts
merge(leftSort, rightSort, sort)
def analyze_complexity(fn, sizes):
"""
Analysiert die Komplexität einer maximalen Teilfolgenfunktion.
:param max_sequence_func: Die Funktion, die analysiert wird.
:param sizes: Eine Liste von Eingabegrößen für die Analyse.
"""
for size in sizes:
MemoryManager.purge() # Speicher zurücksetzen
random_array = MemoryArray.create_random_array(size, -100, 100)
other_array = MemoryArray([-1] * size)
fn(random_array, other_array)
MemoryManager.save_stats(size)
MemoryManager.plot_stats(["cells", "adds", "compares"])
if __name__ == '__main__':
# For debug, assert if working and complexity-analysis
# example()
for filename in ["data/seq0.txt", "data/seq1.txt", "data/seq2.txt", "data/seq3.txt"]:
print(filename)
toSort = MemoryArray.create_array_from_file(filename)
sorted = MemoryArray([-1] * toSort.length().get())
mergeSort(toSort, sorted)
print(sorted)