A construction company has 6 projects, for each they need $d_i$ workers. The company has no workers at the beginning of project 1.
Each new worker must take a safety course that costs 300, and 50 more for each worker.
If there is no new worker there is no course.
Firing a worker does not cost any money, and a workers can't be rehired.
Given that the salary of a worker is 100 per project, formulate a linear programming problem that minimizes the workers costs.
What I tried:
Let $x_i$ be the number of new workers for project $i$.
Let $y_i$ be the number of old workers remaining from previous projects until project $i$ (all the workers hired - all the workers that were fired)
Let $z_i$ be an indicator such that $z_i =0 \iff x_i>0$
The function I'm trying to solve is:
$\min(\sum_{i=1}^6 150x_i + 300(1-z_i) + 100y_i)$
s.t:
\begin{align}
x_i,y_i,z_i &\ge 0 \\
z_i &\ge 1-x_i \\
y_i + x_i &\ge d_i \\
y_i &\ge y_{i-1} + x_i
\end{align}
Something feels not right to me. The main reason is that I tried to use matlab to solve this and it failed.
What did I do wrong? How can I solve this question?
When I see this correctly you have two small mistakes in your constraints.
The first appears when you use z_i >= 1-x_i. This allows z_i to take the value 1 all the time, which will never give you the extra cost of 300. You need to upper bound z_i such that z_i will not be 1 when you have x_i>0. For this constraint you need something called big M. For sufficiently large M you would then use z_i <= 1-x_i/M. This way when x_i=0 you can have z_i=1, otherwise the right hand side is smaller than 1 and due to integrality z_i has to be zero. Note that you usually want to choose M as tight as possible. So in your case d_i might be a good choice.
The second small mistake lays in y_i >= y_{i-1} + x_i. This way you can increase y_i over y_{i-1} without having to set any x_i. To force x_i to increase you need to flip the inequality. Additionally by the way you defined y_i this inequality should refer to x_{i-1}. Thus you should end up with y_i <= y_{i-1} + x_{i-1}. Additionally you need to take care of corner cases (i.e. y_1 = 0)
I think with these two changes it should work. Let me know whether it helped you. And if it still doesn't work I might have missed something.
Related
Detailed business problem:
I'm trying to solve a production scheduling business problem as below:
I have two plants producing FG A and B respectively.
Both the products consume the same Raw Material x
I need to create a 30 day production schedule looking at the Raw Material availability.
FG A and B can be produced if there is sufficient raw material available on the day.
After every 6 days of production the plant has to undergo maintenance and the production on that day will be zero.
Objective is to maximize the margin looking at the day level Raw material available and adhere to the production constraint (i.e. shutdown after every 6th day)
I need to build a linear programming to address the below problem:
Variable y: (binary)
variable z: cumulative of y
When z > 6 then y = 0. I also need to reset the cumulation of z after this point.
Desired output:
How can I build the statement to MILP constraint. Are there any techniques for solving this problem. Thank you.
I think you can model your maintenance differently. Just forbid any sequences of 7 ones for y. I.e.
y[t-6]+y[t-5]+y[t-4]+y[t-3]+y[t-2]+y[t-1]+y[t] <= 6 for t=1,..,T
This is easier than using your accumulator. Note that the beginning needs some attention: you can use historic data for this. I.e., at t=1, the values for t=0,-1,-2,.. are known.
Your accumulator approach is not inherently wrong. We often use it to model inventory. An inventory capacity is a restriction on how large the accumulated inventory can be.
I am trying to overcome a machine allocation problem with time horizon of 5 day. Production plan is hard to catch up, so my objective is to minimize total machines working time spent. Machines uses molds to produce and there are molds for each type of product. If a product is produced at the end of the day and if there will be production later day, total setup needed for that machine should be decreased by one. For this reason,
sets
i: mold type
j:jobs
k: days
parameters
x(i,k) ith mold production needed at day k
y(i,j) 1 if ith mold is compatible with jth machine
Decision variable
m(i,j,k) : 1 if ith mold processed in jth machine in day k 0 o/w
b(j,k) setup number of jth machine in day k
While computing the setup number for day 1, b(j,’1’), is simply equal to the sum of m(i,j,k).
For computing other days setup number I tried these but these made problem nonlinear and it takes months to solve.
b(j,'2')=e=sum(i,m(i,j,'2')) - sum(i,m(i,j,'2')*m(i,j,'1'))
By this way, if mold i is produced in both days, there will not be any setup made at second day. In order to restrain multiple setup reduction I put: sum(i,m(i,j,'2')*m(i,j,'1')) =l= 1
So, how can I decrease the setup number for a machine if it has used a mold a day before without making the problem nonlinear.
It is possible to linearize m(i,j,'2')*m(i,j,'1'):
Both(i,j) <= m(i,j,'2')
Both(i,j) <= m(i,j,'1')
Both(i,j) >= m(i,j,'2')+m(i,j,'1')-1
Both(i,j) is a binary variable
This transformation is done automatically by some solvers.
Note that there are alternative ways to model the start of a run, and often there are things to exploit (depending on the details).
I'm new to linear programming and trying to develop an ILP model around a problem I'm trying to solve.
My problem is analogous to a machine resource scheduling problem. I have a set of binary variables to represent paired-combinations of machines with a discrete-time grid. Job A takes 1 hour, Job B takes 1 hr and 15 minutes, so the time grid should be in 15 minute intervals. Therefore Job A would use 4 time units, and Job B would use 5 time units.
I'm having difficulty figuring out how to express a constraint such that when a job is assigned to a machine, the units it occupies are sequential in the time variable. Is there an example of how to model this constraint? I'm using PuLP if it helps.
Thanks!
You want to implement the constraint:
x(t-1) = 0 and x(t) = 1 ==> x(t)+...+x(t+n-1) = n
One way is:
x(t)+...+x(t+n-1) >= n*(x(t)-x(t-1))
Notes:
you need to repeat this constraint for each t.
A slightly better version is:
x(t+1)+...+x(t+n-1) >= (n-1)*(x(t)-x(t-1))
There is also a disaggregated version of this constraint that may help performance (depending on the solver: some solvers can do this disaggregation automatically).
Things can become interesting near the beginning and end of the planning period. E.g. machine started at t=-1.
Update:
A different approach is just to limit the "start" of a job to 1. I.e. allow only the combination
x(j,t-1) = 0 and x(j,t) = 1
for a given job j. This can be handled in a similar way:
start(j,t) >= x(j,t)-x(j,t-1)
sum(t, start(j,t)) <= 1
0 <= start(j,t) <= 1
First let me explain the problem I'm trying to solve. I'm integrating my code with 3rd party library which does quite complicated financial predictions. For the purposes of this question let's just say I have a blackbox which returns y when I pass in x.
Now, what I need to do is find input (x) for a given output (y). Since I know lowest and highest possible input values I wrote the following algorithm:
define starting input range (minimum input value to maximum input value)
divide the range into two equal parts and find output for a middle value
find which half output falls into
repeat steps 2 and 3 until range is too small to divide any further
This algorithm does the job nicely, I don't see any problems with it. However, is there a faster way to solve this problem?
It sounds like x and y are strongly correlated (i.e. as x increases, so does y), as otherwise your divide and conquer algorithm wouldn't work.
Assumuing this is the case, and you could work out a correlation factor, then you might be able to multiply the midpoint by the correlation factor to potentially hone in the expected value quicker.
Please note that I've not tested this idea at all, but it's something to think about. Possible improvements would be to make the correlationFactor a moving average, or precompute it based on, say, the deciles between xLow and xHigh.
Also, this assumes that calling f(x) is relatively inexpensive. If it is expensive, then the increased number of calls to f(x) would dwarf any savings. In fact - I'm starting to think this is a stupid idea...
Hopefully the following pseudo-code illustrates what I mean:
DivideAndConquer(xLow, xHigh, correlationFactor, expectedValue)
xMid = (xHigh - xLow) * correlationFactor
// Add some range checks to make sure that xMid is within xLow and xHigh!!
y = f(xMid)
if (y == expectedValue)
return expectedValue
elseif (y < expectedValue)
correlationFactor = (xMid - xLow) / (f(xMid) - f(xLow))
return DivideAndConquer(xLow, xMid, correlationFactor, expectedValue)
else
correlationFactor = (xHigh - xMid) / (f(xHigh) - f(xMid))
return DivideAndConquer(xMid, xHigh, correlationFactor, expectedValue)
Im wondering if I can optimize my pathfinding code a bit, lets look at this map:
+ - wall, . - free, S - start, F - finish
.S.............
...............
..........+++..
..........+F+..
..........+++..
...............
The human will look at it and say its impossible, becouse finish is surrounded... But A-star MUST check all fields to ascertain, that there isnt possible road. Well, its not a problem with small maps. But when I have 256x265 map, it takes a lot of time to check all points. I think that i can stop searching while there are closed nodes arround the finish, i mean:
+ - wall, . - free, S - start, F - finish, X - closed node
.S.............
.........XXXXX.
.........X+++X.
.........X+F+X.
.........X+++X.
.........XXXXX.
And I want to finish in this situation (There is no entrance to "room" with finish). I thought to check h, and while none of open nodes is getting closer, then to finish... But im not sure if its ok, maybe there is any better way?
Thanx for any replies.
First of all this problem is better solved with breadth-first search, but I will assume you have a good reason to use a-star instead. However I still recommend you first check the connectivity between S and F with some kind of search(Breadth-first or depth-first search). This will solve our issue.
Assuming the map doesn't change, you can preprocess it by dividing it to connected components. It can be done with a fast disjoint set data structure. Then before launching A* you check in constant time that the source and destination belong to the same component. If not—no path exists, otherwie you run A* to find the path.
The downside is that you will need additional n-bits per cell where n = ceil(log C) for C being the number of connected components. If you have enough memory and can afford it then it's OK.
Edit: in case you fix n being small (e.g. one byte) and have more than that number of components (e.g. more than 256 for 8-bit n) then you can assign the same number to multiple components. To achieve best results make sure each component-id has nearly the same number of cells assigned to it.