Elegant and functional solution to linear optimization constraint? - excel

Assume you have a linear optimization problem where you are trying to determine which attendees of a corporate event qualify to go through to the VIP event. You are trying to maximize a pre-defined utility, where each attendee has a particular utility, subject to a number of constraints which include:
No more than 4 people from any company at the VIP event
At least 4 companies represented at the VIP event.
Assume you have 400 attendees and only 10 can attend the VIP event, and there are employees from at least 50 different companies to choose from.
I have set up my problem in excel, where I have a row for each attendee, and a binary column for my linear optimization program’s ‘changeable cells’, where 1 is selected if the attendee is chosen for the VIP event and 0 otherwise.
What code can I then write to satisfy the above constraints?
What I have tried so far…
Currently my only solution for dealing with the first constraint listed above is to have 50 additional binary columns (one for each company) where if an attendee is going to the VIP event and they are from the company represented in that particular column, it will list a ‘1’, and ‘0’ otherwise. Then have another 50 cells that sum each column and then set a constraint that says those cells must be less than or equal to 4.
I feel there must be a more elegant and efficient way of doing this however.
I also cannot currently think of a way to write the code to satisfy the second constraint. I have tried having a separate column that displays company names when the changeable cell equals 1, then counting the number of unique values in that column, and then applying a constraint to that cell such that it must be greater than or equal to 3, but apparently that is a “non-linear” constraint.

Related

Creating a UserForm with Variable Number of Inputs

I am looking to create a new UserForm to make it easier for the evaluation team here. Essentially, they must evaluate proposals from a number of firms (anywhere from 2 to 12 or so) against certain factors by ranking the firms in order or preference/suitability. We've had complaints about user errors and confusion when they're just putting the numbers straight onto the spreadsheet itself, so it's been left to me to clean it up and make it more "user-friendly" for them.
I have the set-up part done, where users are asked to input the number of firms to be evaluated, the type of evaluation to carry out (this changes the metrics, but there are always 6 of them), and the names of the firms. The firm names are all put into a Named Range ("evalFirms") on a hidden sheet.
What I'd like is for a new UserForm to then be set up with two columns, the left hand being populated by TextBoxes with the evalFirms the user entered at set up and the right hand being an input to Rank the firms such that each rank is unique (i.e. not having two firms ranking 1st).
Evaluation Metric 1
Firm A | 2
Firm B | 1
: | :
Firm n | n
These ranks will then be passed to a hidden sheet where the relevant calculations are done. That part is also all set up and ready to go, it is just this middle part that's given me headaches. The text box at the top should cycle through each of the 6 evaluation metrics (also a dynamic named range called "evalMetrics") until all firms have been fully evaluated.
I'm not super experienced with UserForms, so I'm having trouble with the varying amount of inputs. I can set up a static form, but rather than set up 12 different forms and have each called depending on the number of firms being evaluated, I'd prefer to have a single dynamic form.
Any help or pointers would be appreciated, thanks.

How do I distribute a value over multiple cells evenly but under a maximum limit?

Example data with desired outcome that I need to calculate
I have 12 items of a certain current value. I have a 'soft' cap of $1,000,000 for these values. Some of the items fall above, and some below this cap level.
I have an amount of money (for this example $900,000) that I want to distribute amongst only the items that fall below the cap (in this example 6 items), with the aim of bringing the value of these items up to but not over the cap value.
If I distribute the $900,000 evenly over these 6 items (each receiving $150,000), you can see that items 2 and 9 would then be over the $1,000,000 cap. So items 2 and 9 should only receive $100,000 to raise their value to the cap, then the remaining 4 items would receive and equal share on the remaining pool of money ($700,000 / 4 = $175,000).
So I need a formula to check every item to see if it needs a distribution (i.e below the cap) and then portion/divide out the money pool as illustrated above in the desired distribution column.
Note: The pool of money to be distributed can change. Also the number of items below the cap can change. The cap value itself can change.
I am hoping to avoid VBA or Solver because the spreadsheet could be used on other people's computers.
Hopefully this makes sense. Thanks.
EDIT:
So far I have been able to get close by adding a helper column and using the following formula:
=IF(SUM($F$6:F14)=$D$23,0,E15*MIN(D15,($D$23-SUM($F$6:F14))/SUM(E15:$E$18)))
Working example when values are sorted.
This seems to work when the values are sorted in descending order, as shown in the example image above. But seems to break when the values are a bit more randomly assorted which is likely to happen (as in the original post).
Just to give you an idea of how the solver can be set up to do a capital budget model here is one, also shows the solver and its settings:

Excel: Matching names based on a matrix of options (Employees provide a list of people they want to meet with)

I have a list of 140 people, and each person is giving me 8 names of employees they would like to meet with.
Given time constraints, we'll try to match them with 5 people to meet or so, with the understanding that they might not get all of their choices, but we want to maximize their choices.
As such, I've currently laid out the data as follows:
Column A: The 140 employees (so 140 rows)
Column B: Each employee's option 1 (first name they listed of person they want to meet)
Column C: Option 2...etc.
...
Column I: Option 8
I'm not sure what is the best way to generate matches as we're trying to maximize based on their list.
My initial gut reaction is to do something like --> Look at columns B through I and see if any of those employees have also said they want to meet with the submitting employee (Column A). As such, we can begin filling like that first.
However, I'm having trouble finding an elegant solution to do this?
Anyone have any suggestions? Thanks!
This can be modeled as an integer programming optimization problem. I assume here employee and person is the same. I.e. person a has a wish list as well as person b. If b is on a's list and a on b's list then you get 2 points if matching a with b.
My attempt: use
x(i,j,t) = 1 if person i meets person j in round t
0 otherwise
The constraints are:
In each round meet exactly one person
Persons a and b can meet at most one time
The preferences can be modeled as a score prefs(i,j). Where prefs(i,j)=1 if preferred. We can generalize this to any number: larger numbers means more preference (and a negative number means: I don't want to meet this person).
This leads to a very large, but easy MIP model. We can exploit symmetry to reduce the size of the problem by half. I.e. we always have
x(a,b,t) = x(b,a,t) for persons a and b
So we would like to use binary decision variables x(i,j,t) only where j < i. This makes the otherwise simple model slightly more complicated:
For 140 persons and 5 rounds we get about 48k variables! This looks daunting but the model solves easily. A minute or so.

Spotfire- calculated column with row ratios based on condition

I’m having trouble understanding if Spotfire allows for conditional computations between arbitrary rows containing numerical data repeated over data groups. I could not find anything to cue me onto a right solution.
Context (simplified): I have data from a sensor reporting state of a process and this data is grouped into bursts/groups representing a measurement taking several minutes each.
Within each burst the sensor is measuring a signal and if a predefined feature (signal shape) was detected the sensor outputs some calculated value, V quantifying this feature and also reports a RunTime at which this happened.
So in essence I have three columns: Burst number, a set of RTs within this burst and Values associated with these RTs.
I need to add a calculated column to do a ratio of Values for rows where RT is equal to a specific number, let’s say 1.89 and 2.76.
The high level logic would be:
If a Value exists at 1.89 Run Time and a Value exists at 2.76 Run Time then compute the ratio of these values. Repeat for every Burst.
I understand I can repeat the computation over groups using OVER operator but I’m struggling with logic within each group...
Any tips would be appreciated.
Many thanks!
The first thing you need to do here is apply an order to your dataset. I assume the sample data is complete and encompasses the cases in your real data, thus, we create a calculated column:
RowID() as [ROWID]
Once this is done, we can create a calculated column which will compute your ratio over it's respective groups. Just a note, your B4 example is incorrect compared to the other groups. That is, you have your numerator and denominator reversed.
If(([RT]=1.89) or ([RT]=2.76),[Value] / Max([Value]) OVER (Intersect([Burst],Previous([ROWID]))))
Breaking this down...
If(([RT]=1.89) or ([RT]=2.76), limits the rows to those where the RT = 1.89 or 2.76.
Next comes the evaluation if the above condition is TRUE
[Value] / Max([Value]) OVER (Intersect([Burst],Previous([ROWID])))) This takes the value for the row and divides it by the Max([Value]) over the grouping of [Burst] and AllPrevious([ROWID]). This is noted by the Intersect() function. So, the denominator will always be the previous value for the grouping. Note that Max() was a simple aggregate used, but any should do for this case since we are only expecting a single value. All Over() functions require and aggregate to limit the result set to a single row.
RESULTS

How can I implement 'balanced' error spreading functionality in Excel?

I have a requirement in Excel to spread small; i.e. pennies, monetry rounding errors fairly across the members of my club.
The error arises when I deduct money from members; e.g. £30 divided between 21 members is £1.428571... requiring £1.43 to be deducted from each member, totalling £30.03, in order to hit the £30 target.
The approach that I want to take, continuing the above example, is to deduct £1.42 from each member, totalling £29.82, and then deduct the remaining £0.18 using an error spreading technique to randomly take an extra penny from 18 of the 21 members.
This immediately made me think of Reservoir Sampling, and I used the information here: Random selection,
to construct the test Excel spreadsheet here: https://www.dropbox.com/s/snbkldt6e8qkcco/ErrorSpreading.xls, on Dropbox, for you guys to play with...
The problem I have is that each row of this spreadsheet calculates the error distribution indepentently of every other row, and this causes some members to contribute more than their fair share of extra pennies.
What I am looking for is a modification to the Resevoir Sampling technique, or another balanced / 2 dimensional error spreading methodology that I'm not aware of, that will minimise the overall error between members across many 'error spreading' rows.
I think this is one of those challenging problems that has a huge number of other uses, so I'm hoping you geniuses have some good ideas!
Thanks for any insight you can share :)
Will
I found a solution. Not very elegant, through.
You have to use two matrix. In the first you get completely random number, chosen with =RANDOM() and in the second you choose the n greater value
Say that in F30 you have the first
=RANDOM()
cell.
(I have experimented with your sheet.)
Just copy a column of n (in your sheet 8) in column A)
In cell F52 you put:
=IF(RANK(F30,$F30:$Z30)<=$A52, 1, 0)
Until now, if you drag left and down the formulas, you have the same situation that is in your sheet (only less elegant und efficient).
But starting from the second row of random number you could compensate for the penny esbursed.
In cell F31 you put:
=RANDOM()-SUM(F$52:F52)*0.5
(pay attention to the $, each random number should have a correction basated on penny already spent.)
If the $ are ok you should be OK dragging formulas left and down. You could also parametrize the 0.5 and experiment with other values. With 0,5 I have a error factor (the equivalent of your cell AB24) between 1 and 2

Resources