| 654 | |
| 655 | def binpacking(items,maximum=1,k=None): |
| 656 | r""" |
| 657 | Solves the bin packing problem. |
| 658 | |
| 659 | The Bin Packing problem is the following : |
| 660 | |
| 661 | Given a list of items of weights `p_i` and a real value `K`, what is |
| 662 | the least number of bins such that all the items can be put in the |
| 663 | bins, while keeping sure that each bin contains a weight of at most `K` ? |
| 664 | |
| 665 | For more informations : http://en.wikipedia.org/wiki/Bin_packing_problem |
| 666 | |
| 667 | Two version of this problem are solved by this algorithm : |
| 668 | * Is it possible to put the given items in `L` bins ? |
| 669 | * What is the assignment of items using the |
| 670 | least number of bins with the given list of items ? |
| 671 | |
| 672 | INPUT: |
| 673 | |
| 674 | - ``items`` -- A list of real values (the items' weight) |
| 675 | |
| 676 | - ``maximum`` -- The maximal size of a bin |
| 677 | |
| 678 | - ``k`` -- Number of bins |
| 679 | |
| 680 | - When set to an integer value, the function returns a partition |
| 681 | of the items into `k` bins if possible, and raises an |
| 682 | exception otherwise. |
| 683 | |
| 684 | - When set to ``None``, the function returns a partition of the items |
| 685 | using the least number possible of bins. |
| 686 | |
| 687 | OUTPUT: |
| 688 | |
| 689 | A list of lists, each member corresponding to a box and containing |
| 690 | the list of the weights inside it. If there is no solution, an |
| 691 | exception is raised (this can only happen when ``k`` is specified |
| 692 | or if ``maximum`` is less that the size of one item). |
| 693 | |
| 694 | EXAMPLES: |
| 695 | |
| 696 | Trying to find the minimum amount of boxes for 5 items of weights |
| 697 | `1/5, 1/4, 2/3, 3/4, 5/7`:: |
| 698 | |
| 699 | sage: from sage.numerical.optimize import binpacking |
| 700 | sage: print sorted(binpacking([1/5,1/3,2/3,3/4, 5/7])) # optional - requires GLPK CPLEX or CBC |
| 701 | [[1/5, 3/4], [1/3, 2/3], [5/7]] |
| 702 | |
| 703 | One way to use only three boxes (which is best possible) is to put |
| 704 | `1/5 + 3/4` together in a box, `1/3+2/3` in another, and `5/7` |
| 705 | by itself in the third one. |
| 706 | |
| 707 | Of course, we can also check that there is no solution using only two boxes :: |
| 708 | |
| 709 | sage: from sage.numerical.optimize import binpacking |
| 710 | sage: binpacking([0.2,0.3,0.8,0.9], k=2) # optional - requires GLPK CPLEX or CBC |
| 711 | Traceback (most recent call last): |
| 712 | ... |
| 713 | ValueError: This problem has no solution ! |
| 714 | """ |
| 715 | |
| 716 | if max(items) > maximum: |
| 717 | raise ValueError("This problem has no solution !") |
| 718 | |
| 719 | if k==None: |
| 720 | from sage.functions.other import ceil |
| 721 | k=ceil(sum(items)/maximum) |
| 722 | while True: |
| 723 | from sage.numerical.mip import MIPSolverException |
| 724 | try: |
| 725 | return binpacking(items,k=k,maximum=maximum) |
| 726 | except MIPSolverException: |
| 727 | k = k + 1 |
| 728 | |
| 729 | from sage.numerical.mip import MixedIntegerLinearProgram, MIPSolverException |
| 730 | p=MixedIntegerLinearProgram() |
| 731 | |
| 732 | # Boolean variable indicating whether |
| 733 | # the i th element belongs to box b |
| 734 | box=p.new_variable(dim=2) |
| 735 | |
| 736 | # Each bin contains at most max |
| 737 | for b in range(k): |
| 738 | p.add_constraint(sum([items[i]*box[i][b] for i in range(len(items))]),max=maximum) |
| 739 | |
| 740 | # Each item is assigned exactly one bin |
| 741 | for i in range(len(items)): |
| 742 | p.add_constraint(sum([box[i][b] for b in range(k)]),min=1,max=1) |
| 743 | |
| 744 | p.set_objective(None) |
| 745 | p.set_binary(box) |
| 746 | |
| 747 | try: |
| 748 | p.solve() |
| 749 | except MIPSolverException: |
| 750 | raise ValueError("This problem has no solution !") |
| 751 | |
| 752 | box=p.get_values(box) |
| 753 | |
| 754 | boxes=[[] for i in range(k)] |
| 755 | |
| 756 | for b in range(k): |
| 757 | boxes[b].extend([items[i] for i in range(len(items)) if box[i][b]==1]) |
| 758 | |
| 759 | return boxes |
| 760 | |
| 761 | |
| 762 | |