Finding maximal sum of happiness - algorithm

I have a problem to solve, and do not see any optimal solution :/ The problem is:
I have n workers and k jobs. Each job is to be done by specified number of workers, and each worker has his level of happines for each job. I have to to make a work schedule so that workers would be as happy as possible.
So, I have array a1 of int[n,k] (k >= n). k-th column of i-th row contains preference (number from 0 to 10) of i-th worker for k-th job. I also have array a2 of int[k], where i-th element contains number of people who will be doing that job. Each worker is to do the same number of jobs. I have to find maximal possible sum of happines, knowing that n >= max(a2).
My solution is to use recursion. Select first worker for first combination of jobs, add preferences to the sum, check if sum is higher then maximal already found, and if it is, go to the next worker. When back, check the next combination for the first worker etc. This works fine for small amount of workers, but has to high computational complexity to solve bigger problems. Have You got any idea for better solution?
PS. Guy from another site recommended me using Hungarian Algorithm, but it assumes that n == k, and I do not know how to make it working with n <= k
PS2 an exaple:
a1:
job1 job2 job3 job4
wokrer1 1 3 4 2
worker2 9 8 1 2
worker3 6 7 8 9
a2:
job1 job2 job3 job4
count 1 2 2 1
example solution:
worker1: job2, job3 (7)
worker2: job1, job2 (17)
worker3: job3, job4 (17)
sum: 41

This looks like the Transportation Problem to me. It can be solved using the Hungarian Algorithm though. First let's set up the matrix for the Hungarian Algorithm.
The Hungarian Algorithm is used to find the minimum sum. To make it solve a maximum sum problem you would first have to invert all of your happiness values.
J1 J2 J3 J4
W1 1 3 4 2
W2 9 8 1 2
W3 6 7 8 9
Subtract each value by the greatest value in the matrix.
The greatest value in this matrix is 9.
J1 J2 J3 J4
W1 9-1 9-3 9-4 9-2
W2 9-9 9-8 9-1 9-2
W3 9-6 9-7 9-8 9-9
J1 J2 J3 J4
W1 8 6 5 7
W2 0 1 8 7
W3 3 2 1 0
Now, as you noted, the Hungarian Algorithm only works on square matrices. To make it work on a rectangular matrix, we must make it square. We can do this by adding dummy rows or columns filled with zeroes.
J1 J2 J3 J4
W1 8 6 5 7
W2 0 1 8 7
W3 3 2 1 0
WD 0 0 0 0
Now that we have it in a usable form, we can solve for the minimum sum. I'm going to skip to the solution as instructions on how to use the Hungarian Algorithm are readily available elsewhere.
W1 -> J3
W2 -> J1
W3 -> J4
WD -> J2 (Except this is a dummy row so it doesn't count.)
We have now assigned one job to each of our workers. This is where your second array comes into play.
J1 J2 J3 J4
1 2 2 1
We have assigned a worker to jobs 1, 3, and 4, so we will subtract 1 from their respective values.
J1 J2 J3 J4
0 2 1 0
Since we no longer need anyone to do jobs 1 or 4, we can remove their columns from our happiness matrix as well.
J2 J3
W1 6 5
W2 1 8
W3 2 1
We still have jobs to do though, so we go through the process again.
Add dummy columns to make the matrix square.
J2 J3 JD
W1 6 5 0
W2 1 8 0
W3 2 1 0
and solve. Remember that the columns are for jobs 2 and 3, not 1 and 2.
W1 -> JD
W2 -> J2
W3 -> J3
We have now gone through the algorithm twice, and have assigned five jobs.
W1 -> J3
W2 -> J1, J2
W3 -> J4, J3
We would now go through the entire process again. Since there is only one more job to assign, and one person to assign it to (W1 has only been assigned one job, but they must all be assigned the same number.), we can just go to our final solution.
W1 -> J3, J2
W2 -> J1, J2
W3 -> J4, J3
and the happiness values for this are:
W1 -> 4 + 3 = 7
W2 -> 9 + 8 = 17
W3 -> 9 + 8 = 17
for a total of 41.

The way to use the Hungarian algorithm would be to make a2[i] vertices for job i. Hopefully the a2 array sums to n. If k << n, then you're probably better off formulating as a min-cost circulation problem.

Related

Is there are any similar algorithm to Hungarian method but for solving matrix with size n*m?

Is there are any similar algorithm to Hungarian method but for solving matrix with size n*m?
(n - workers, m - tasks, m > n, every worker must has at least 1 task)
The variant with adding dummy worker is incorrect, because in this case, at least 1 task will be without a worker.
Example:
T1
T2
T3
T4
W1
2
9
6
3
W2
2
3
5
7
W3
5
5
7
2
And the result is:
W1 - T2
W2 - T4
W3 - T1, T3
If you want every task to be assigned to a worker even if that means more than one task is assigned to each worker then run the algorithm once using a dummy row
T1
T2
T3
T4
W1
2
9
6
3
W2
2
3
5
7
W3
5
5
7
2
D1
0
0
0
0
This will assign W1 to T1, W2 to T2, W3 to T4, and D1 to T3. Since T3 was assigned to a dummy worker it was essentially not assigned. If you remove all of the tasks that were assigned to a worker and add dummy columns you can run it again with
D1
D2
T3
W1
0
0
6
W2
0
0
5
W3
0
0
7
Which will assign T3 to W2. So the final assignments are:
W1 to T1
W2 to T2 and T3
W3 to T4

PRAM CREW algorithm for counting odd numbers

So I try to solve the following task:
Develop an CREW PRAM algorithm for counting the odd numbers of a sequence of integers x_1,x_2,...x_n.
n is the number of processors - the complexity should be O(log n) and log_2 n is a natural number
My solution so far:
Input: A:={x_1,x_2,...,x_n} Output:=oddCount
begin
1. global_read(A(n),a)
2. if(a mod 2 != 0) then
oddCount += 1
The problem is, due to CREW I am not allowed to use multiple write instructions at the same time oddCount += 1 is reading oddCount and then writes oddCount + 1, so there would be multiple writes.
Do I have to do something like this
Input: A:={x_1,x_2,...,x_n} Output:=oddCount
begin
1. global_read(A(n),a)
2. if(a mod 2 != 0) then
global_write(1, B(n))
3. if(n = A.length - 1) then
for i = 0 to B.length do
oddCount += B(i)
So first each process determines wether it is a odd or even number and the last process calculates the sum? But how would this affect the complexity and is there a better solution?
Thanks to libik I came to this solution: (n starts with 0)
Input: A:={x_1,x_2,...,x_n} Output:=A(0):=number off odd numbers
begin
1. if(A(n) mod 2 != 0) then
A(n) = 1
else
A(n) = 0
2. for i = 1 to log_2(n) do
if (n*(2^i)+2^(i-1) < A.length)
A(n*(2^i)) += A(n*(2^i) + (2^(i-1)))
end
i = 1 --> A(n * 2): 0 2 4 6 8 10 ... A(n*2 + 2^0): 1 3 5 7 ...
i = 2 --> A(n * 4): 0 4 8 12 16 ... A(n*4 + 2^1): 2 6 10 14 18 ...
i = 3 --> A(n * 8): 0 8 16 24 32 ... A(n*8 + 2^2): 4 12 20 28 36 ...
So the first if is the 1st Step and the for is representing log_2(n)-1 steps so over all there are log_2(n) steps. Solution should be in A(0).
Your solution is O(n) as there is for cycle that has to go through all the numbers (which means you dont utilize multiple processors at all)
The CREW means you cannot write into the same cell (in your example cell=processor memory), but you can write into multiple cells at once.
So how to do it as fast as possible?
At initialization all processors start with 1 or 0 (having odd number or not)
In first round just sum the neighbours x_2 with x_1, then x_4 with x_3 etc.
It will be done in O(1) as every second processor "p_x" look to "p_x+1" processor in parallel and add 0 or 1 (is there odd number or not)
Then in processors p1,p3,p5,p7.... you have part of solution. Lets do this again but now with p1 looks to p3, p5 looks to p7 and p_x looks to o_x+2
Then you have part of the solution only in processors p1, p5, p9 etc.
Repeat the process. Every step the number of processors halves, so you need log_2(n) steps.
If this would be real-life example, there is often calculated cost of synchronization. Basically after each step, all processors have to synchronize themselves so they now, they can do the second step (as you run the described code in each processor, but how do you know if you can already add number from processor p_x, because you can do it after p_x finished work).
You need either some kind of "clock" or synchronization.
At this example, the final complexity would be log(n)*k, where k is the complexity of synchronization.
The cost depends on machine, or definition. One way how to notify processors that you have finished is basically the same one as the one described here for counting the odd numbers. Then it would also cost k=log(n) which would result in log^2(n)

Task with graph - looking for advice

I've a task with graph. I'm not looking for code, but only for idea. I don't know even where should I start.. so content of this task is:
in first line we have two number, n and q.
n - number of cities and q - number of days.
next line contain n integer number n1, n2, n3, n4...n_n where n_i means that we can earn n_i money in city with number i.
next n-1 lines desribe connection between city a and b.
each line is form a, b, c which is mean that
a is connected with b (and b with a) and cost of this path is c.
next we have q lines which desribe changes, we have 2 case
in form 1 v d which means that from dawn day i profit from city v will be d
and form 2 a b d which means that from dawn day i cost of path between a and b (and b to a) will be d
our task is print ids of city where we will be sleep after i day.
we start from city which index 1 and when we're in city number 2 then we will sleep in this city.
for example
input:
4 4
10 20 30 50
1 2 5
2 3 7
2 4 57
1 3 28
1 1 25
2 3 2 1
2 2 4 13
output:
3 1 3 4
sorry for my english :/ as I said before I'm not looking for code but for general idea.
#EDIT
maybe it will be some useful info. When we go to city with index B. We spend there night. Question is. Where we will be spend our nights. I mean how our path looks

Generate a Random Flow Network

I am trying to create a flow network for a given graph so that it can be used to test an algorithm. To provide clarity, I want the flow into each vertex to equal the flow out. All flow comes from the source and goes to the sink. Each edge has a maximum capacity and a direction. I would like to generate a flow through this network that equals the maximum flow (found by the min cut) that never exceeds the capacity for each edge.
Below is a graphical example of what I am given and what I am trying to obtain. Of course the "Desired Flow Graph" is not a unique example. I want this generated randomly.
Given Weighted Graph
Desired Flow Graph
I have this graph represented in MatLab with three arrays. The first array s gives the "from" vertex, the second array t gives the "to" vertex, and the third array w1 gives the maximum capacity from s to t. I would like to generate a random array such as w2 that represents the flow. (Note the letters in the pictures are equivalent to their corresponding numbers in the code where "A" = 1.
s = [1 1 1 2 3 3 4 6 5 6];
t = [2 3 4 5 5 6 6 5 7 7];
w1 = [10 15 10 8 5 7 6 5 18 15];
w2 = [8 12 6 8 5 7 6 0 13 13];
Any help with some sort of algorithm that can perform this task would be greatly appreciated. I would love a link to an algorithm, pseudocode, direct code, or even just a description of how such an algorithm may be implemented. Thanks in advance for the help.
Check out the maxflow function in MATLAB:
http://www.mathworks.com/help/matlab/ref/graph.maxflow.html
For the graph you posted, you can construct a directed graph with these commands:
s = [1 1 1 2 3 3 4 6 5 6];
t = [2 3 4 5 5 6 6 5 7 7];
w1 = [10 15 10 8 5 7 6 5 18 15];
g = digraph(s,t,w1);
Then you can use maxflow to calculate the flow values between node 1 and node 7 and return them in a new directed graph gf:
[mf,gf] = maxflow(g,1,7);
The w2 vector you refer to now just includes the edge weights of the gf graph, so you can extract it like this:
w2 = gf.Edges.Weight

Deciphering the key

Alice invents a key (s1, s2, s3, ... , sk). Bob makes a guess (g1, g2, g3, ... , gk).He is awarded one point for each si = gi.
Each s1 is an integer with the range of 0<=si<=11.
Given a q guesses with their scores bi
(g1, g2, g3, ... , gk) b1
(g1, g2, g3, ... , gk) b2
.
.
.
(g1, g2, g3, ... , gk) bq
Can you state if there is a key possible. Given 0<=si<=11, 1<=k<=11, 1<=q<=8.
For Example
2 2 1 1 2
1 1 2 2 1
For the guess 2 2 1 1 the score is 2
For the guess 1 1 2 2 the score is 1
Because there is a key possible let's say 2 1 1 3 which gives the desired scores.Hence the answer is yes
Another Example
1 2 3 4 4
4 3 2 1 1
For the guess 1 2 3 4 the score is 4
For the guess 4 3 2 1 the score is 1
This has no key which gives the desired scores hence answer is NO
I tried the brute force approach generating n^k such keys where n is the range of si.But it gave Time Limit exceeding error.
Its an interview puzzle. I have seen variants of this question but was not able to solve them.Can you tell me what should I read for such type of questions.
I don't know the best solution to this problem, but if you did a recursive search of the possible solution space, pruning branches which could not possibly lead to a solution, it would be much faster than trying all (n^k) keys.
Take your example:
1 2 3 4 4 -> 4
4 3 2 1 1 -> 1
The 3 possible values for g1 which could be significant are: 1, 4, and "neither 1 nor 4". Choose one of them, and then recursively look at the possible values for g2. Choose one, and recursively look at the possible values for g3, etc.
As you search, keep track of a cumulative score for each of the guesses from b1 to bq. Whenever you choose a value for a digit, increment the cumulative scores for all the guesses which have the same number in that position. Keep these cumulative scores on a stack (so you can back up).
When you reach a point where no solution is possible, back up and continue searching a different path. If you back all the way up to g1 and no more paths are left to search, then the answer is NO. If you find a solution, then the answer is YES.
When to stop searching a path and back up:
If the cumulative score of one of the guesses exceeds the given score
If the cumulative score of one of the guesses is less than the given score minus the number of levels left in the search tree (before you hit the bottom)
This approach could still be very slow, especially if "k" was large. But again, it will be far faster than generating (n^k) keys.

Resources