3

I have an integer programming problem. I have a pipe, 10m long. I want to cut out as many 1.2meter pieces as I can and then cut the rest of the pipe in 100mm pieces. I have to leave 100mm for the machine to grab. How do I optimize this in mathematica? I can solve it as an equality i guess but if i just want the answer straight out. Basically, as many y's as possible, then x:es.

Maximize[{x*100+y*1200, x*100+y*1200<9900},{x,y},Integers] just gives me an inequality plot. And yes, I have checked instructions at wolfram.

rcollyer
  • 10,475
  • 4
  • 48
  • 75
johnny
  • 31
  • 2

5 Answers5

3

As 9900 and 1200 are both multiples of 100, the algorithm is just

TotLen = 9900;
numberOf1200pieces = IntegerPart[TotLen/1200];
numberOf100pieces  = IntegerPart[(TotLen - 1200 numberOf1200pieces)/100];

Print["Number of 1200mm pieces: ", numberOf1200pieces];
Print["Number of 100mm pieces: ", numberOf100pieces];
Print["Leftover: ", 9900 - numberOf1200pieces 1200 - numberOf100pieces 100,"mm"];

Number of 1200mm pieces: 8
Number of 100mm pieces: 3
Leftover: 0mm

You may also try:

Maximize[{x*100 + y*1200, x*100 + y*1200 == 9900}, {x, y}, Integers]
->{9900, {x -> 3, y -> 8}}
Dr. belisarius
  • 60,527
  • 15
  • 115
  • 190
1

Use assume on x,y etc to be >0 etc and you will finally be able to get a value with //N

Mathematica doesnt assume you are in the Real world!

stefan
  • 2,886
  • 21
  • 27
1

Belisarius's solution is the simplest method via Maximize. However, it requires changing the inequality to an equality, which does not reflect your intent. Instead, using v. 7, I'd add a second condition

Maximize[{x*100 + y*1200, x*100 + y*1200 <= 9900, y > x > 0}, 
         {x, y}, Integers] -> {9900, {y -> 8, x -> 3}} 

The new condition (y > x > 0) reflects your intent that the larger pieces be chosen first better. Also, note that I changed the inequality (<) to <= as your divisions come out to 9900 exactly.

Community
  • 1
  • 1
rcollyer
  • 10,475
  • 4
  • 48
  • 75
1

To answer the simple question at face value, rather than inferring it to be a toy example of optimization, here is one method of "unitizing" a number.

Floor[ FoldList[Mod, #, Most@#2] / #2 ] &[ 9900, {1200, 100} ]

Responding to belisarius' implication that my reply was too naive, I think this may be a valid, albeit inefficient method for more complicated cases. Consider splitting 9950 into lengths 12, 75, and 1200.

i = 9950;

While[x = Quiet@IntegerPartitions[i--, All, {12, 75, 1200}, 1]; x === {}]

x[[1]] // Tally
Mr.Wizard
  • 24,179
  • 5
  • 44
  • 125
  • The usual problem is a little more subtle because you don't want leftovers. Suppose you have [16, {5, 3}] as input. You may give {3,0} or {2,2} as a result. The last one without leftovers. The general case is a very well studied problem, and there are a lot of commercial products for it. Almost every factory has this kind of problem in some production stage. – Dr. belisarius Mar 26 '11 at 21:58
  • @belisarius That is a deeper problem that the OP may be wanting to solve, and I would like to see a solution using Mathematica. Nevertheless, the question says: "I want to cut out as many 1.2meter pieces as I can and then cut the rest of the pipe in 100mm pieces." I think that my naive code does this. Am I wrong? – Mr.Wizard Mar 26 '11 at 23:17
  • ahhh you are too susceptible today :)! I was _just_ trying to state that the problem gets really weird when you add a few simple constraints, not to mention in the real world. Perhaps my insistence comes from years ago, when I was involved in solving this same problem for a big Avery's paper coil cutting site. It was quite a project. Please accept my apologies if I've been offensive in any way, as that wasn't my intention. – Dr. belisarius Mar 27 '11 at 00:07
  • @belisarius I certainly did not take offense. Can you give me a link an example of the more advanced optimization problem you are talking about? – Mr.Wizard Mar 27 '11 at 00:55
  • See for example http://www.math.tu-dresden.de/~belov/publ/downl/1point5-D/sx_nyy.rtf.doc – Dr. belisarius Mar 27 '11 at 01:14
0
decideOrderOfProduction[itemsToProduce_] := 
 Map[#[[1]] &, Sort[itemsToProduce, #1[[2]] > #2[[2]] &]]
minimizeWaste[pipe1_, pipe2_] := {
  Maximize[{pipe1*x + pipe2*y, pipe1*x + pipe2*y <= 4900, 
    y >= x >= 0}, {x, y}, Integers]
  }
minimizeWaste[pipe_] := {
  Maximize[{pipe*x, pipe*x <= 4900, x >= 0}, x, Integers]
  }
planProduction[itemsToProduce_] := {
  productionOrder = decideOrderOfProduction[itemsToProduce];
  strategy = {};
  While[Length[productionOrder] >= 2,
   pipe1 = productionOrder[[1]];
   pipe2 = productionOrder[[2]];
   strategy = 
    Append[strategy, {pipe1, pipe2, minimizeWaste[pipe1, pipe2]}];
   productionOrder = Drop[productionOrder, 2];];
  If[Length[productionOrder] == 1,
   strategy = 
    Append[strategy, {productionOrder[[1]], Null, 
      minimizeWaste[productionOrder[[1]]]}]];
  strategy
  }


items = {{99, 1}, {200, 12}, {1200, 2}, {90, 5}, {70, 1200}};
decideOrderOfProduction[items]
planProduction[items]
{70, 200, 90, 1200, 99}

{{{70, 200, {{4900, {x -> 10, y -> 21}}}}, {90, 
   1200, {{4890, {x -> 1, y -> 4}}}}, {99, 
   Null, {{4851, {x -> 49}}}}}}

Thats a start but it is bad because somehow I need to take into account priority better and I need to finish the amount of each pipe. Somehow I guess amount needs to be taken into account into priority as well.

johnny
  • 3
  • 1