diff options
| author | Bjoern Brandenburg <bbb@mpi-sws.org> | 2012-02-13 03:04:20 -0500 |
|---|---|---|
| committer | Bjoern Brandenburg <bbb@mpi-sws.org> | 2012-02-13 03:04:20 -0500 |
| commit | 6f1f3ab6fdcb881401ad4d086bbdf1c104c8fb02 (patch) | |
| tree | b13f692f7a2aae5126ff5cb7c7c36d66d245f895 | |
| parent | 532478450c1e0a25ab92b2585a8c3ee61089d02b (diff) | |
Add any_fit and almost_worst_fit binpacking heuristics.
almost_worst_fit: like worst_fit, but uses second-to-worst bin.
any_fit: try each of the implemented heuristics and see if one works.
| -rw-r--r-- | schedcat/mapping/binpack.py | 40 |
1 files changed, 38 insertions, 2 deletions
diff --git a/schedcat/mapping/binpack.py b/schedcat/mapping/binpack.py index 00a2bd9..bbd1224 100644 --- a/schedcat/mapping/binpack.py +++ b/schedcat/mapping/binpack.py | |||
| @@ -103,8 +103,29 @@ def worst_fit(items, bins, capacity=1.0, weight=id, misfit=ignore, | |||
| 103 | c = weight(x) | 103 | c = weight(x) |
| 104 | # pick the bin where the item will leave the most space | 104 | # pick the bin where the item will leave the most space |
| 105 | # after placing it, aka the bin with the least sum | 105 | # after placing it, aka the bin with the least sum |
| 106 | i = sums.index(min(sums)) | 106 | candidates = [s for s in sums if s + c <= capacity] |
| 107 | if sums[i] + c <= capacity: | 107 | if candidates: |
| 108 | # fits somewhere | ||
| 109 | i = sums.index(min(candidates)) | ||
| 110 | sets[i] += [x] | ||
| 111 | sums[i] += c | ||
| 112 | else: | ||
| 113 | misfit(x) | ||
| 114 | return sets | ||
| 115 | |||
| 116 | def almost_worst_fit(items, bins, capacity=1.0, weight=id, misfit=ignore, | ||
| 117 | empty_bin=list): | ||
| 118 | sets = [empty_bin() for _ in xrange(0, bins)] | ||
| 119 | sums = [0.0 for _ in xrange(0, bins)] | ||
| 120 | for x in items: | ||
| 121 | c = weight(x) | ||
| 122 | # pick the bin where the item will leave almost the most space | ||
| 123 | # after placing it, aka the bin with the second to least sum | ||
| 124 | candidates = [s for s in sums if s + c <= capacity] | ||
| 125 | if candidates: | ||
| 126 | # fits somewhere | ||
| 127 | candidates.sort() | ||
| 128 | i = sums.index(candidates[1] if len(candidates) > 1 else candidates[0]) | ||
| 108 | sets[i] += [x] | 129 | sets[i] += [x] |
| 109 | sums[i] += c | 130 | sums[i] += c |
| 110 | else: | 131 | else: |
| @@ -129,6 +150,19 @@ def best_fit(items, bins, capacity=1.0, weight=id, misfit=ignore, | |||
| 129 | misfit(x) | 150 | misfit(x) |
| 130 | return sets | 151 | return sets |
| 131 | 152 | ||
| 153 | def any_fit(items, bins, capacity=1.0, weight=id, misfit=ignore, | ||
| 154 | empty_bin=list): | ||
| 155 | for h in [next_fit, first_fit, worst_fit, almost_worst_fit, best_fit]: | ||
| 156 | try: | ||
| 157 | sets = h(items, bins, capacity, weight, report_failure, empty_bin) | ||
| 158 | return sets | ||
| 159 | except DidNotFit as dnf: | ||
| 160 | pass | ||
| 161 | # if we get here, none of the heuristics worked | ||
| 162 | misfit(dnf.item) | ||
| 163 | # if we get here, misfit did not raise an exception => return something | ||
| 164 | return next_fit(items, bins, capacity, weight, misfit, empty_bin) | ||
| 165 | |||
| 132 | def decreasing(algorithm): | 166 | def decreasing(algorithm): |
| 133 | def alg_decreasing(items, bins, capacity=1.0, weight=id, *args, **kargs): | 167 | def alg_decreasing(items, bins, capacity=1.0, weight=id, *args, **kargs): |
| 134 | # don't clobber original items | 168 | # don't clobber original items |
| @@ -141,4 +175,6 @@ next_fit_decreasing = decreasing(next_fit) | |||
| 141 | first_fit_decreasing = decreasing(first_fit) | 175 | first_fit_decreasing = decreasing(first_fit) |
| 142 | worst_fit_decreasing = decreasing(worst_fit) | 176 | worst_fit_decreasing = decreasing(worst_fit) |
| 143 | best_fit_decreasing = decreasing(best_fit) | 177 | best_fit_decreasing = decreasing(best_fit) |
| 178 | almost_worst_fit_decreasing = decreasing(almost_worst_fit) | ||
| 179 | any_fit_decreasing = decreasing(any_fit) | ||
| 144 | 180 | ||
