Hungarian Algorithm not giving right result for multiple assignments - algorithm

The problem scenario :
The number of tasks(n) is greater than the number of workers(m).
I need to assign multiple tasks to a single worker.
Here is the cost matrix
I have 6 tasks and 3 workers available.
C (i,j) = 1, for the cell which indicates, worker can be assigned to task.
C (i,j) = 1000, for the cell which indicates, worker can not be assigned to task.
The cost matrix
TASK/WORKER WORKER1 WORKER2 WORKER3
TASK 1 1 1000 1000
TASK 2 1000 1 1000
TASK 3 1000 1000 1000
TASK 4 1 1000 1000
TASK 5 1000 1 1000
TASK 6 1000 1000 1
Here , worker1 can do tasks ( TASK-1, TASK-4)
worker2 can do tasks ( TASK-2, TASK-5)
worker3 can do tasks ( TASK-6)
To create square matrix, I added dummy WORKERS : DWORKER1, DWORKER2 and DWORKER3) as follows and assigned very large value(1000000) to the cell value.
TASK/WORKER WORKER1 WORKER2 WORKER3 DWORKER1 DWORKER2 DWORKER3
TASK 1 1 1000 1000 1000000 100000 1000000
TASK 2 1000 1 1000 1000000 100000 1000000
TASK 3 1000 1000 1000 1000000 100000 1000000
TASK 4 1 1000 1000 1000000 100000 1000000
TASK 5 1000 1 1000 1000000 100000 1000000
TASK 6 1000 1000 1 1000000 100000 1000000
I used the scipy package scipy.optimize.linear_sum_assignment. As follows:
from scipy.optimize import linear_sum_assignment
cost = np.array([[1,1000,1000,1000000,100000,1000000],[1000,1,1000,1000000,1000000,1000000],[1000,1000,
1000,1000000,100000,1000000],[1,1000,1000,1000000,1000000,1000000],[1000,1,1000,1000000,100000, 1000000],[1000,1000,1,1000000,1000000,1000000]])
row_ind, col_ind = linear_sum_assignment(cost)
The output for col_ind is array([5, 3, 4, 0, 1, 2])
The output indicates (If I am not wrong):
- Assign 6th task to worker 1
- Assign 4th task to worker 2
- Assign 5th task to worker 3
- Assign 1st task to Dummy worker 1
- Assign 2nd task to Dummy worker 2
- Assign 3rd task to Dummy worker 3
What I am expecting is, assigning TASK ( 1, 2 and 3) to the real workers not the dummy workers.
Is that possible through this implementation? Or I am missing anything here?

Hungarian algorithm is for solving the assignment problem, where there is exactly one task assigned to each worker. By doing the trick you propose, you will indeed have 1 task assign to each dummy worker also.
If you are interested in only assigning tasks to real workers, and assigning multiple tasks, that is much easier : for each task, select the worker with the smallest cost. In your example, it means that worker 1 will do tasks 1 and 4, worker 2 will do task 2 and 5, worker 3 will do task 6, and task 3 will be done by one of the three workers (depending on how you handle the equality case).

Related

Dax measure- sum of percent of total by group with condition

For simplicity sake, I have the following dummy data:
id val
1 5
1 30
1 50
1 15
2 120
2 60
2 10
2 10
My desired output is the following:
id SUM_GT_10%
1 95%
2 90%
SUM_GT_10% can be obtained by the following steps:
Calculate the sum of val for each id
Divide val by 1
sum of 2 if 2 > 10%
using the example data, the sum of val is 100 for id 1 and 200 for id 2, so we would obtain the following additional columns:
id val 1 2
1 5 100 5%
1 30 100 30%
1 50 100 50%
1 15 100 15%
2 120 200 60%
2 60 200 30%
2 10 200 5%
2 10 200 5%
And our final output (step 3) would be sum of 2 where 2> 10%:
id SUM_GT_10%
1 95%
2 90%
I don't care about the intermediate columns, just the final output, of course.
James, you might want to create a temporary table in your measure and then sum its results:
tbl_SumVAL =
var ThisId = MAX(tbl_VAL[id])
var temp =
FILTER(
SELECTCOLUMNS(tbl_VAL, "id", tbl_VAL[id], "GT%",
tbl_VAL[val] / SUMX(FILTER(tbl_VAL, tbl_VAL[id] = ThisId), tbl_VAL[val])),
[GT%] > 0.1
)
return
SUMX(temp, [GT%])
The temp table is basically recreating two steps that you have described (divide "original" value by the sum of all values for each ID), and then leaving only those values that are greater than 0.1. Note that if your id is not a number, then you'd need to replace MAX(tbl_VAL[id]) with SELECTEDVALUE(tbl_VAL[id]).
The final result looks like that -
Also, make sure to set your id field to "Not Summarize", in case id is a number -

Convert between priority of two systems

I have two "systems" the with some records.
System A has record with priority from 1-4 (lets say minSystemAP = 4, maxSystemAP = 1).
System A Priority:
4 - Low, 3- Medium, 2 - High, 1 - Critical.
System B has record with priority from 1-10 (lets say minSystemBP = 10, maxSystemBP = 1).
System A Priority: 1-Minimum, 5- Medium, 10- High.
I'm trying to create record from System B in System A.
How can i "convert" between the priority of SystemA to SystemB?
Meaning, Record with priority 10 in System B will be record with priority ~ 4 in System A.
and record with priority 5 in System B will be record with priority ~ 2 in System A.
What is the best way to do that?
The mapping must assign multiple priorities in SystemB to one priority in SystemA.
E.g.:
A 1 1 2 2 2 3 3 3 4 4
B 1 2 3 4 5 6 7 8 9 10
This mapping-function would meet your requirements and can simply be implemented as integer-division:
int prioA = prioB / 3 + 1;

Find maximum point out of n tasks

Exact problem statement :
Given N tasks, find the maximal points that can be achieved by finishing them
Problem Constraints:
There are T minutes for completing N tasks
Solutions can be submitted at any time, including exactly T minutes after the start
i-th task submitted t minutes after the start, will get
maxPoints[i] - t * pointsPerMinute[i] points
i-th task takes requiredTime[i] minutes to solve
Input Format
Line 1: T, total minutes available to finish
Line 2: Comma separated list of maxPoints
Line 3: Comma separated list of pointsPerMinute
Line 4: Comma separated list of requiredTime
Sample Input
75
250 500 1000
2 4 8
25 25 25
Sample Output
1200
Explanation
First, solve the third task 25 minutes after the start of the contest. Get 1000 - 8 * 25 = 800 points
Second, solve the second task 50 minutes after the start of the contest. Get 500 - 4 * 50 = 300 points
Third, solve the first task 75 minutes after the start of the contest. Get 250 - 2 * 75 = 100 points
In total, get 800 + 300 + 100 = 1200 points
I was able to get the solution by permuting and the calculating the point for each arrangement. I couldn't figure out optimized solution for this.
I use greedy algorithm to solve this.
I use m for maxPoint, p for pointsPerMinute, r for requiredTime.
Consider finishing A task before B task, you can get:
Point(A, B) = m[A] - p[A] * r[A] + m[B] - p[B] * (r[A] + r[B])
Finishing B task before A task, you can get:
Point(B, A) = m[B] - p[B] * r[B] + m[A] - p[A] * (r[A] + r[B])
If you should finish A task before B task, Point(A, B) need greater than Point(B, A), so Point(A, B) - Point(B, A) >= 0.
For some calculation, we can get:
r[A] / p[A] < r[B] / p[B].
That means, if we need to finish A task before B task, r[A] / p[A] should less than r[B] / p[B]. And we can sort all tasks by this and count the answer.

Hungarian algorithm with multiple assignments

Let's say we're given N jobs and K workers to do those jobs. But for some jobs we need 2 employees, while for some we need just one. Also the employees can't do all jobs. For example worker 1 can do jobs 1,2 and 5, while not jobs 3 and 4. Also if we hire worker 1 to do job 1, then we want him to do jobs 2 and 5, since we've already paid him.
So for example let's say we have 5 jobs and 6 workers. For jobs 1,2 and 4 we need 2 men, while for jobs 3 and 5 we need just one. And here's the list of the jobs every worker can do and the wage he requires.
Worker 1 can do jobs 1,3,5 and he requires 1000 dollars.
Worker 2 can do jobs 1,5 and he requires 2000 dollars.
Worker 3 can do jobs 1,2 and he requires 1500 dollars.
Worker 4 can do jobs 2,4 and he requires 2500 dollars.
Worker 5 can do jobs 4,5 and he requires 1500 dollars.
Worker 6 can do jobs 3,5 and he requires 1000 dollars.
After little calculation and logical thinking we can conclude that we have to hire workers 1,3,4 and 5, which means that the minimum wage we need to pay is: 1000+1500+2500+1500=5500 dollars.
But how we can find an efficient algorithm that will output that amount? This somehow reminds me of the Hungarian Algorithm, but all those additional constrains makes it impossible for me to apply it.
We can represent a state of all jobs as a number in a ternary system(2-two people remaing, 1-one person remaining and 0 if it is already done). Now we can compute f(mask, k) = the smallest cost to hire some workers among the first k in such a way that the state of remaining jobs is mask. Transitions are as follows: we either go to (mask, k + 1)(not hiring the current worker) or we go to (new_mask, k + 1)(in this case we pay this worker his salary and let him do all the jobs he can). The answer is f(0, K).
The time complexity is O(3^N * K * N).
Here is an idea how to optimize it further(and get rid of the N factor). Let's assume that the current mask is mask and the man can do jobs from another mask'. We could actually simply add mask to mask', but there is one problem: the positions where there was 2 in the mask and 1 in mask' will get broken. But we can fix: for each mask, let's precompute a binary mask allowed_mask that contain all position where the digit is not 2. For each man and for each allowed_mask we can precompute that mask' value. Now each transition is just one addition:
for i = 0 ... k - 1
for mask = 0 ... 3^n - 1
allowed_mask = precomputed_allowed_mask[mask]
// make a transition to (i + 1, mask + add_for_allowed_mask[i][allowed_mask])
// make a transition to (i + 1, mask)
Note that there are only 2^n allowed masks. So the time complexity of this solution is O(3^N * N + T * 2^N * K * N + T * 3^N * K)(the first term is for precomputing allowed_masks for all ternary mask, the second one is for precomputing mask' for all allowed_masks and people, and the last is for dp itself).

timetable scheduling using multidimensional priority table

I need a solution to schedule tasks on given dates for timetable scheduling. It is based on each user's vote. I have a table that contains number of votes for the task for the date:
Tasks: {"A","B","C","D","E"},
Dates: {"1 Jan","2 Jan","5 Jan","7 Jan","10 Jan"},
Total users: 16
A B C D E
=============================================
1-Jan | 6 3 1 4 2
2-Jan | 1 3 4 6 2
5-Jan | 2 3 3 1 7
7-Jan | 6 1 2 3 4
10-Jan | 1 6 5 3 1
For example, on 1-Jan, task A has 6 votes, task B has 3 votes, etc.
I need to schedule only one task for one date.
How to schedule tasks? Can anybody help?

Resources