diff --git a/case_study.py b/case_study.py new file mode 100644 index 0000000..c603a3e --- /dev/null +++ b/case_study.py @@ -0,0 +1,76 @@ +from quorums import * +import datetime + +def main() -> None: + def seconds(x: int) -> datetime.timedelta: + return datetime.timedelta(seconds=x) + + a = Node('a', write_capacity=2000, read_capacity=4000, latency=seconds(1)) + b = Node('b', write_capacity=1000, read_capacity=2000, latency=seconds(1)) + c = Node('c', write_capacity=2000, read_capacity=4000, latency=seconds(3)) + d = Node('d', write_capacity=1000, read_capacity=2000, latency=seconds(4)) + e = Node('e', write_capacity=2000, read_capacity=4000, latency=seconds(5)) + fr = { + 1.00: 0., + 0.90: 10., + 0.80: 20., + 0.70: 100., + 0.60: 100., + 0.50: 100., + 0.40: 60., + 0.30: 30., + 0.20: 30., + 0.10: 20., + 0.00: 0., + } + + maj = QuorumSystem(reads=majority([a, b, c, d, e])) + grid = QuorumSystem(reads=a*b + c*d*e) + paths = QuorumSystem(reads=a*b + a*c*e + d*e + d*c*b) + + print(maj.capacity(read_fraction=fr)) + print(grid.capacity(read_fraction=fr)) + print(paths.capacity(read_fraction=fr)) + print() + + opt = search(nodes=[a, b, c, d, e], + resilience=1, + read_fraction=fr) + sigma = opt.strategy(read_fraction=fr) + print(opt) + print(sigma) + print(sigma.capacity(read_fraction=fr)) + print() + + print(maj) + print(maj.capacity(read_fraction=fr, f=1)) + print(grid.capacity(read_fraction=fr, f=1)) + print(paths.capacity(read_fraction=fr, f=1)) + print() + + opt = search(nodes=[a, b, c, d, e], resilience=1, read_fraction=fr, f=1) + sigma = opt.strategy(read_fraction=fr, f=1) + print(opt) + print(sigma) + print(sigma.capacity(read_fraction=fr)) + print() + + print(maj.capacity(read_fraction=fr, optimize='latency', load_limit=1/2000), + maj.latency(read_fraction=fr, optimize='latency', load_limit=1/2000)) + print(grid.capacity(read_fraction=fr, optimize='latency', load_limit=1/2000), + grid.latency(read_fraction=fr, optimize='latency', load_limit=1/2000)) + print(paths.capacity(read_fraction=fr, optimize='latency', load_limit=1/2000), + paths.latency(read_fraction=fr, optimize='latency', load_limit=1/2000)) + print() + + opt = search(nodes=[a, b, c, d, e], resilience=1, read_fraction=fr, optimize='latency', load_limit=1/2000) + sigma = opt.strategy(read_fraction=fr, optimize='latency', load_limit=1/2000) + print(opt) + print(sigma) + print(sigma.capacity(read_fraction=fr)) + print(sigma.latency(read_fraction=fr)) + print() + + +if __name__ == '__main__': + main() diff --git a/paper.py b/paper.py new file mode 100644 index 0000000..9317107 --- /dev/null +++ b/paper.py @@ -0,0 +1,90 @@ +from quorums import * +import datetime + + +def main() -> None: + # The basics. + a, b, c = Node('a'), Node('b'), Node('c') + majority = QuorumSystem(reads=a*b + b*c + a*c) + print(majority.resilience()) # 1 + print(majority.capacity(read_fraction=1)) # 1.5 + print() + + # Different capacities + a, b = Node('a', capacity=100), Node('b', capacity=100) + c, d = Node('c', capacity=50), Node('d', capacity=50) + grid = QuorumSystem(reads=a*b + c*d) + print(grid.capacity(read_fraction=1)) # 150 + print() + + # Different read and write capacities. + a = Node('a', write_capacity=100, read_capacity=200) + b = Node('b', write_capacity=100, read_capacity=200) + c = Node('c', write_capacity=50, read_capacity=100) + d = Node('d', write_capacity=50, read_capacity=100) + grid = QuorumSystem(reads=a*b + c*d) + print(grid.capacity(read_fraction=1)) # 300 + print(grid.capacity(read_fraction=0.5)) # 200 + print(grid.capacity(read_fraction=0)) # 100 + print() + + # Workload distribution. + grid = QuorumSystem(reads=a*b + c*d) + print(grid.capacity(read_fraction={0.9: 75, 0.5: 25})) # 229 + print() + + # f-resilient strategies. + grid = QuorumSystem(reads=a*b + c*d) + choose2 = QuorumSystem(reads=choose(2, [a, b, c, d])) + print(grid.capacity(read_fraction=1)) # 300 + print(choose2.capacity(read_fraction=1)) # 300 + print(grid.capacity(read_fraction=1, f=1)) # 100 + print(choose2.capacity(read_fraction=1, f=1)) # 200 + print(choose2.strategy(read_fraction=1, f=1)) # abd: 0.5, abc: 0.5 + print() + + # Network load and latency. + def seconds(n: int) -> datetime.timedelta: + return datetime.timedelta(seconds=n) + + a = Node('a', write_capacity=100, read_capacity=200, latency=seconds(4)) + b = Node('b', write_capacity=100, read_capacity=200, latency=seconds(4)) + c = Node('c', write_capacity=50, read_capacity=100, latency=seconds(1)) + d = Node('d', write_capacity=50, read_capacity=100, latency=seconds(1)) + grid = QuorumSystem(reads=a*b + c*d) + sigma = grid.strategy(read_fraction=1) + print(sigma.capacity(read_fraction=1)) # 300 + print(sigma.network_load(read_fraction=1)) # 2 + print(sigma.latency(read_fraction=1)) # 3 seconds + print(grid.strategy( + read_fraction = 1, + optimize = 'latency', + load_limit = 1 / 150, + network_limit = 2, + )) # ab: 1/3, cd: 2/3 + print() + + # Search. + qs = search( + nodes = [a, b, c, d], + read_fraction = 1, + optimize = 'latency', + load_limit = 1 / 150, + network_limit = 2, + # timeout = seconds(3), + ) + print(qs) # a + b + c + d + sigma = qs.strategy( + read_fraction = 1, + optimize = 'latency', + load_limit = 1 / 150, + network_limit = 2, + ) + print(sigma) # c: 1/3 d: 2/3 + print(sigma.capacity(read_fraction=1)) # 150 + print(sigma.network_load(read_fraction=1)) # 1 + print(sigma.latency(read_fraction=1)) # 1 + + +if __name__ == '__main__': + main()