From 9f8cfdc63bf9a7772c22774d7b1c7529ce1d3a7b Mon Sep 17 00:00:00 2001 From: Evgeniy L Date: Thu, 24 Dec 2015 13:17:59 +0300 Subject: [PATCH] Convert solution into disks-spaces mapping --- bareon_dynamic_allocator/allocators.py | 51 ++++++++++++++++++++------ bareon_dynamic_allocator/cmd.py | 6 ++- 2 files changed, 44 insertions(+), 13 deletions(-) diff --git a/bareon_dynamic_allocator/allocators.py b/bareon_dynamic_allocator/allocators.py index eca85f6..be3d2c9 100644 --- a/bareon_dynamic_allocator/allocators.py +++ b/bareon_dynamic_allocator/allocators.py @@ -12,6 +12,7 @@ # License for the specific language governing permissions and limitations # under the License. +import itertools import six from scipy.optimize import linprog @@ -19,6 +20,11 @@ from scipy.ndimage.interpolation import shift import numpy as np +from oslo_log import log + + +LOG = log.getLogger(__name__) + def shift(arr, steps, val=0): res_arr = np.roll(arr, steps) @@ -27,6 +33,14 @@ def shift(arr, steps, val=0): return res_arr +def grouper(iterable, n, fillvalue=None): + """Collect data into fixed-length chunks or blocks + Source: https://docs.python.org/2/library/itertools.html#recipes + """ + args = [iter(iterable)] * n + return itertools.izip_longest(fillvalue=fillvalue, *args) + + class Disk(object): def __init__(self, **kwargs): @@ -73,6 +87,8 @@ class DynamicAllocationLinearProgram(object): """ def __init__(self, disks, spaces): + self.disks = disks + self.spaces = spaces # Coefficients of the linear objective minimization function. # During iteration over vertexes the function is used to identify # if current solution (vertex) satisfies the equation more, than @@ -93,7 +109,7 @@ class DynamicAllocationLinearProgram(object): # None for one of min or max when there is no bound. self.bounds = np.array([]) - self._initialize_equation(disks, spaces) + self._init_equation(self.disks, self.spaces) def solve(self): solution = linprog( @@ -101,11 +117,28 @@ class DynamicAllocationLinearProgram(object): A_eq=self.equality_constraint_matrix, b_eq=self.equality_constraint_vector, bounds=self.bounds, - options={"disp": True}) + options={"disp": False}) - return solution.x + LOG.debug("Solution: %s", solution) - def _initialize_equation(self, disks, spaces): + return self._convert_solution(solution) + + def _convert_solution(self, solution): + result = {} + + spaces_grouped_by_disk = list(grouper(solution.x, len(self.spaces))) + for disk_i in range(len(self.disks)): + disk_id = self.disks[disk_i].id + result.setdefault(disk_id, []) + spaces_for_disk = spaces_grouped_by_disk[disk_i] + for space_i, space_size in enumerate(spaces_for_disk): + result[disk_id].append({ + 'space_id': self.spaces[space_i].id, + 'size': space_size}) + + return result + + def _init_equation(self, disks, spaces): for d in disks: # Initialize constraints, each row in the matrix should # be equal to size of the disk @@ -125,10 +158,12 @@ class DynamicAllocationLinearProgram(object): # 0, - x5 multiplier, size of space 1 on 3rd disk, 0 for the first # 0] - x6 multiplier, size of space 2 on 3rd disk, 0 for the first - # For each space x (size of the space) is represented + # For each space, xn (size of the space) is represented # for each disk as separate variable, so for each # disk we have len(spaces) * len(disks) sizes equality_matrix_row = np.zeros(len(spaces) * len(disks)) + + # Amount of coefficients is equal to amount of columns in the matrix self._init_objective_function_coefficient(len(spaces) * len(disks)) # Set first len(spaces) elements to 1 @@ -138,12 +173,6 @@ class DynamicAllocationLinearProgram(object): self.equality_constraint_matrix.append(equality_matrix_row) equality_matrix_row = shift(equality_matrix_row, len(spaces), val=0) - def _add_disk(self): - pass - - def _add_space(self): - pass - def _add_objective_function_coefficient(self): # By default the algorithm tries to minimize the solution # we should invert sign, in order to make it as a maximization diff --git a/bareon_dynamic_allocator/cmd.py b/bareon_dynamic_allocator/cmd.py index c3cb030..3d4f6b1 100644 --- a/bareon_dynamic_allocator/cmd.py +++ b/bareon_dynamic_allocator/cmd.py @@ -12,6 +12,8 @@ # License for the specific language governing permissions and limitations # under the License. +from pprint import pprint + import sys from oslo_config import cfg @@ -62,7 +64,7 @@ def parse_args(conf, args=None): CONF = make_config() parse_args(CONF) -LOG = log.getLogger() +LOG = log.getLogger(__name__) def parse_configs(conf): @@ -73,7 +75,7 @@ def parse_configs(conf): def save_result(data, output_file): - print data + pprint(data) def validate_schema(schema):