2012-05-16 16:35:58 +00:00
|
|
|
#!/usr/bin/env python
|
|
|
|
#
|
|
|
|
# Copyright 2012 Johannes 'josch' Schauer <j.schauer@email.de>
|
|
|
|
#
|
|
|
|
# This file is part of Sisyphus.
|
|
|
|
#
|
|
|
|
# Sisyphus is free software: you can redistribute it and/or modify
|
|
|
|
# it under the terms of the GNU General Public License as published by
|
|
|
|
# the Free Software Foundation, either version 3 of the License, or
|
|
|
|
# (at your option) any later version.
|
|
|
|
#
|
|
|
|
# Sisyphus is distributed in the hope that it will be useful,
|
|
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
# GNU General Public License for more details.
|
|
|
|
#
|
|
|
|
# You should have received a copy of the GNU General Public License
|
|
|
|
# along with Sisyphus. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
2012-05-02 09:12:10 +00:00
|
|
|
import sys
|
|
|
|
import itertools
|
2012-05-16 07:41:27 +00:00
|
|
|
from util import xmlfiletodict, get_pallet, get_articles, product_varlength, starmap
|
2012-05-08 08:01:10 +00:00
|
|
|
from arrange_spread2 import arrange_in_layer, spread_articles
|
2012-05-02 09:12:10 +00:00
|
|
|
import cPickle
|
|
|
|
from binascii import b2a_base64
|
2012-05-02 11:47:38 +00:00
|
|
|
import zlib
|
2012-05-15 10:39:11 +00:00
|
|
|
import os
|
2012-05-16 07:41:27 +00:00
|
|
|
import random
|
2012-05-02 11:47:38 +00:00
|
|
|
|
|
|
|
def rotate(node):
|
|
|
|
if node is None:
|
|
|
|
return
|
|
|
|
|
|
|
|
if node['article']:
|
|
|
|
# exchange x and y coordinate
|
|
|
|
node['article']['PlacePosition']['X'], node['article']['PlacePosition']['Y'] = node['article']['PlacePosition']['Y'], node['article']['PlacePosition']['X']
|
|
|
|
# rotate article
|
|
|
|
node['article']['Orientation'] = node['article']['Orientation']%2+1
|
|
|
|
|
|
|
|
rotate(node['right'])
|
|
|
|
rotate(node['down'])
|
2012-05-02 09:12:10 +00:00
|
|
|
|
|
|
|
def get_layers(bins, pallet, rot_article=False, rot_pallet=False):
|
|
|
|
for abin in bins:
|
|
|
|
bins[abin] = sorted(bins[abin], key=lambda article: article['Article']['Length']*article['Article']['Width'], reverse=True)
|
|
|
|
plength, pwidth = (pallet['Dimensions']['Length'], pallet['Dimensions']['Width'])
|
2012-05-02 11:47:38 +00:00
|
|
|
if rot_pallet:
|
|
|
|
root, layer, rest = arrange_in_layer(bins[abin], pwidth, plength, rot_article=rot_article)
|
|
|
|
else:
|
|
|
|
root, layer, rest = arrange_in_layer(bins[abin], plength, pwidth, rot_article=rot_article)
|
2012-05-02 09:12:10 +00:00
|
|
|
while layer:
|
|
|
|
spread_articles(root)
|
2012-05-02 11:47:38 +00:00
|
|
|
if rot_pallet:
|
|
|
|
rotate(root)
|
2012-05-02 09:12:10 +00:00
|
|
|
|
|
|
|
occupied_area = 0
|
|
|
|
for article in layer:
|
|
|
|
length, width = article['Article']['Length'], article['Article']['Width']
|
|
|
|
occupied_area += length*width
|
|
|
|
|
|
|
|
# print "layer occupation:", occupied_area/float(plength*pwidth)
|
|
|
|
if occupied_area/float(plength*pwidth) <= 0.7:
|
|
|
|
rot_article, rot_pallet = (yield None, layer)
|
|
|
|
else:
|
|
|
|
rot_article, rot_pallet = (yield layer, None)
|
|
|
|
|
2012-05-02 11:47:38 +00:00
|
|
|
if rot_pallet:
|
|
|
|
root, layer, rest = arrange_in_layer(rest, pwidth, plength, rot_article=rot_article)
|
|
|
|
else:
|
|
|
|
root, layer, rest = arrange_in_layer(rest, plength, pwidth, rot_article=rot_article)
|
|
|
|
|
|
|
|
def get_bit(num, pos):
|
|
|
|
return num>>pos&1
|
2012-05-02 09:12:10 +00:00
|
|
|
|
2012-05-14 21:40:48 +00:00
|
|
|
def get_bitmask(num, length):
|
|
|
|
return tuple(( bool(num>>pos&1) for pos in xrange(length-1,-1,-1) ))
|
|
|
|
|
2012-05-02 09:12:10 +00:00
|
|
|
def main():
|
2012-05-08 08:01:10 +00:00
|
|
|
if len(sys.argv) != 2:
|
|
|
|
print "usage:", sys.argv[0], "order.xml"
|
2012-05-02 09:12:10 +00:00
|
|
|
exit(1)
|
|
|
|
|
|
|
|
orderline = xmlfiletodict(sys.argv[1])
|
|
|
|
pallet = get_pallet(orderline)
|
|
|
|
articles = get_articles(orderline)
|
|
|
|
bins = dict()
|
|
|
|
|
|
|
|
for article in articles:
|
|
|
|
abin = bins.get(article['Article']['Height'])
|
|
|
|
if abin:
|
|
|
|
abin.append(article)
|
|
|
|
else:
|
|
|
|
bins[article['Article']['Height']] = [article]
|
|
|
|
|
2012-05-15 10:39:11 +00:00
|
|
|
if os.environ.get("rot_article"):
|
|
|
|
try_rot_article = bool(int(os.environ["rot_article"]))
|
|
|
|
else:
|
|
|
|
try_rot_article = True
|
|
|
|
|
|
|
|
if os.environ.get("rot_pallet"):
|
|
|
|
try_rot_pallet = bool(int(os.environ["rot_pallet"]))
|
|
|
|
else:
|
|
|
|
try_rot_pallet = True
|
|
|
|
|
2012-05-15 21:34:01 +00:00
|
|
|
if os.environ.get("rot_article_default"):
|
|
|
|
rot_article_default = bool(int(os.environ["rot_article_default"]))
|
|
|
|
else:
|
|
|
|
rot_article_default = False
|
|
|
|
|
|
|
|
if os.environ.get("rot_pallet_default"):
|
|
|
|
rot_pallet_default = bool(int(os.environ["rot_pallet_default"]))
|
|
|
|
else:
|
|
|
|
rot_pallet_default = False
|
|
|
|
|
2012-05-16 07:04:42 +00:00
|
|
|
if os.environ.get("iterations"):
|
|
|
|
max_iter = int(os.environ["iterations"])
|
|
|
|
else:
|
|
|
|
max_iter = -1
|
|
|
|
|
2012-05-16 07:41:27 +00:00
|
|
|
if os.environ.get("randomize"):
|
|
|
|
try_random = bool(int(os.environ["randomize"]))
|
|
|
|
else:
|
|
|
|
try_random = False
|
|
|
|
|
2012-05-15 10:39:11 +00:00
|
|
|
if try_rot_article and try_rot_pallet:
|
2012-05-16 07:41:27 +00:00
|
|
|
if try_random:
|
|
|
|
product_it = starmap(random.randint, itertools.repeat((0,3)))
|
|
|
|
else:
|
|
|
|
product_it = product_varlength(4)
|
2012-05-15 10:39:11 +00:00
|
|
|
elif try_rot_article or try_rot_pallet:
|
2012-05-16 07:41:27 +00:00
|
|
|
if try_random:
|
|
|
|
product_it = starmap(random.randint, itertools.repeat((0,1)))
|
|
|
|
else:
|
|
|
|
product_it = product_varlength(2)
|
2012-05-16 07:04:42 +00:00
|
|
|
|
|
|
|
i = 0
|
2012-05-14 21:40:48 +00:00
|
|
|
while True:
|
2012-05-02 09:12:10 +00:00
|
|
|
rests = list()
|
|
|
|
layers = list()
|
2012-05-14 21:40:48 +00:00
|
|
|
try:
|
2012-05-15 10:39:11 +00:00
|
|
|
if try_rot_article and try_rot_pallet:
|
|
|
|
rot_article, rot_pallet = get_bitmask(product_it.send(True), 2)
|
|
|
|
elif try_rot_article and not try_rot_pallet:
|
|
|
|
rot_article = get_bitmask(product_it.send(True), 1)[0]
|
2012-05-15 21:34:01 +00:00
|
|
|
rot_pallet = rot_pallet_default
|
2012-05-15 10:39:11 +00:00
|
|
|
elif not try_rot_article and try_rot_pallet:
|
2012-05-15 21:34:01 +00:00
|
|
|
rot_article = rot_article_default
|
2012-05-15 10:39:11 +00:00
|
|
|
rot_pallet = get_bitmask(product_it.send(True), 1)[0]
|
|
|
|
else:
|
2012-05-15 21:34:01 +00:00
|
|
|
rot_article = rot_article_default
|
|
|
|
rot_pallet = rot_pallet_default
|
2012-05-14 21:40:48 +00:00
|
|
|
except TypeError:
|
2012-05-15 10:39:11 +00:00
|
|
|
if try_rot_article and try_rot_pallet:
|
|
|
|
rot_article, rot_pallet = get_bitmask(product_it.next(), 2)
|
|
|
|
elif try_rot_article and not try_rot_pallet:
|
|
|
|
rot_article = get_bitmask(product_it.next(), 1)[0]
|
2012-05-15 21:34:01 +00:00
|
|
|
rot_pallet = rot_pallet_default
|
2012-05-15 10:39:11 +00:00
|
|
|
elif not try_rot_article and try_rot_pallet:
|
2012-05-15 21:34:01 +00:00
|
|
|
rot_article = rot_article_default
|
2012-05-15 10:39:11 +00:00
|
|
|
rot_pallet = get_bitmask(product_it.next(), 1)[0]
|
|
|
|
else:
|
2012-05-15 21:34:01 +00:00
|
|
|
rot_article = rot_article_default
|
|
|
|
rot_pallet = rot_pallet_default
|
2012-05-14 21:40:48 +00:00
|
|
|
except StopIteration:
|
|
|
|
break # generator empty
|
|
|
|
it = get_layers(bins, pallet, rot_article, rot_pallet)
|
2012-05-02 09:12:10 +00:00
|
|
|
layer, rest = it.next()
|
|
|
|
if layer:
|
|
|
|
layers.append(layer)
|
|
|
|
if rest:
|
|
|
|
rests.append(rest)
|
|
|
|
|
2012-05-14 21:40:48 +00:00
|
|
|
while True:
|
2012-05-02 09:12:10 +00:00
|
|
|
try:
|
2012-05-15 10:39:11 +00:00
|
|
|
if try_rot_article and try_rot_pallet:
|
|
|
|
layer, rest = it.send(get_bitmask(product_it.send(False), 2))
|
|
|
|
elif try_rot_article and not try_rot_pallet:
|
2012-05-15 21:34:01 +00:00
|
|
|
layer, rest = it.send((get_bitmask(product_it.send(False), 1)[0], rot_pallet_default))
|
2012-05-15 10:39:11 +00:00
|
|
|
elif not try_rot_article and try_rot_pallet:
|
2012-05-15 21:34:01 +00:00
|
|
|
layer, rest = it.send((rot_article_default, get_bitmask(product_it.send(False), 1)[0]))
|
2012-05-15 10:39:11 +00:00
|
|
|
else:
|
2012-05-15 21:34:01 +00:00
|
|
|
layer, rest = it.send((rot_article_default, rot_pallet_default))
|
2012-05-02 09:12:10 +00:00
|
|
|
if layer:
|
|
|
|
layers.append(layer)
|
|
|
|
if rest:
|
|
|
|
rests.append(rest)
|
|
|
|
except StopIteration:
|
|
|
|
break
|
2012-05-02 11:47:38 +00:00
|
|
|
print b2a_base64(zlib.compress(cPickle.dumps((layers, rests, pallet)))),
|
2012-05-15 10:39:11 +00:00
|
|
|
if not try_rot_article and not try_rot_pallet:
|
|
|
|
break # only one iteration if both are deactivated
|
2012-05-16 07:04:42 +00:00
|
|
|
i+=1
|
|
|
|
if max_iter != -1 and i >= max_iter:
|
|
|
|
break
|
|
|
|
|
2012-05-02 09:12:10 +00:00
|
|
|
if __name__ == "__main__":
|
|
|
|
main()
|