Why is Microsoft Solver Foundation not returning a solution? - linear-programming

I'm trying to solve my linear program with Microsoft Solver Foundation, but it doesn't return a solution. It doesn't give a clear message to what is wrong, so I'm not sure what is going on. I have checked the constraints and I believe they are coded correctly, but maybe the LP model is wrong on itself? I would be glad if you can take a look at it and see what's wrong :)
===Solver Foundation Service Report===
Date: 15/10/2021 16:00:21
Version: Microsoft Solver Foundation 3.0.2.10889 Express Edition
Model Name: DefaultModel
Capabilities Applied: MILP
Solve Time (ms): 51
Total Time (ms): 103
Solve Completion Status: Unknown
Solver Selected: Microsoft.SolverFoundation.Solvers.SimplexSolver
Directives:
Simplex(TimeLimit = -1, MaximumGoalCount = -1, Arithmetic = Default, Pricing = Default, IterationLimit = -1, Algorithm = Default, Basis = Default, GetSensitivity = False)
Algorithm: Primal
Arithmetic: Exact
Variables: 133 -> 133 + 40
Rows: 40 -> 40
Nonzeros: 522
Eliminated Slack Variables: 0
Basis: Slack
Pivot Count: 0
Phase 1 Pivots: 0 + 0
Phase 2 Pivots: 0 + 0
Factorings: 0 + 0
Degenerate Pivots: 0 (0,00 %)
Branches: 0
I'm making this for a practical assignment, so I prefer not to share my code. For information about the assignment: it's a machine assignment problem, where you have to plan two appointments for all patients. There are global parameters:
p1: the duration of the first appointment
p2: the duration of the second appointment
g: the gap between the first and second appointment
Each patient needs two appointments t1 and t2 that need to be planned. Each patient also has personal parameters:
interval I1=[r1, d1], the time interval in which the first appointment can be planned
x: (personal) extra gap between the first and second appointment
length l, the length of the second time interval. I2=[t1 + p1 + g + x, t1 + p1 + g + x + l - 1]

Related

Assign the work for 2 people so that the time is minimum

Question:
There are N works that needs to be assigned for 2 people. Person A can finish work i in a[i] time, person B can finish work i in b[i] time.
Each work can only be assigned to 1 person. After the works are assigned, each person will do their works seperately.
The overall time will be the larger of the total time taken by the 2 people.
Find a way to assign the work so that the Overall Time is minimum.
Example:
N = 6
a[] = 10 100 30 50 50 80
b[] = 100 30 40 40 60 90
Answer: 130
Explaination:
Person A do work 1, 3, 6 -> total time: 120
Person B do work 2, 4, 5 -> total time: 130
Overall time: 130
Constrants:
N <= 100
a[i], b[i] <= 30.000
My take
I tried solving it with dynamic-programming, more specifically: DP[i][p][c]
With i is the number of works done so far, p is total time of person A so far, c is total time of person B so far. For each i, we can try to give the work to either person A or B, then save the best answer in DP[i][p][c] so we dont have to recalculate it.
But p and c can get up to 3.000.000, so I tried to shrink it to DP[i][max(p,c)]
The code below gives the right answer for the example case, and some other case I generated:
int n, firstCost[105], secondCost[105];
int dp[105][300005];
int solve(int i, int p, int c){
if(i > n) return max(p, c);
int &res = dp[i][max(p, c)];
if(res != -1) return res;
res = INT_MAX;
int tmp1 = solve(i+1, p + firstCost[i], c);
int tmp2 = solve(i+1, p, c + secondCost[i]);
res = min(tmp1, tmp2);
return res;
}
int main(){
// input...
cout << solve(1, 0, 0);
}
But when I submited it, it gives the wrong anwer to this case:
20
4034 18449 10427 4752 8197 7698 17402 16164 12306 5249 19076 18560 16584 18969 3548 11260 6752 18052 14684 18113
19685 10028 938 10379 11583 10383 7175 4557 850 5704 14156 18587 2869 16300 15393 14874 18859 9232 6057 3562
My output was 77759 but the answer is suppose to be 80477.
I don't know what I did wrong, is there anyway to imrpove my solution?
P/S:
Here's the original problem, the page is in Vietnamese, you can create an account and submit there
The trick that you're missing is the idea of an optimal fringe.
You are trying to shrink it to max(p,c), but it may well be that you need to send the first half the jobs to person A, and that initially looks like a terrible set of choices. You are right that you could get the right answer with DP[i][p][c], but that quickly gets to be too much data.
But suppose that p0 <= p1 and c0 <= c1. Then there is absolutely no way that looking at a path through (p1, c1) can ever lead to a better answer than (p0, c0). And therefore we can drop (p1, c1) immediately.
I won't give you code, but I'll show you a bit of how this starts with your example.
4034 18449 10427 4752 8197 7698 17402 16164 12306 5249 19076 18560 16584 18969 3548 11260 6752 18052 14684 18113
19685 10028 938 10379 11583 10383 7175 4557 850 5704 14156 18587 2869 16300 15393 14874 18859 9232 6057 3562
At first we start off with DP = [[0,0]].
After we assign the first element, you get [[0,19685], [4034,0]].
After we assign the second we get, [[0,29713], [4034,10028], [18449,19685], [22483,0]]. We can drop [18449,19685] because it isn't as good as [4034,10028], so we get to [[0,29713], [4034,10028], [22483,0]].
The third element gives [[0,30651], [4034,10966], [10427,29713], [14461,10028], [22483,938], [32910,0]] and then we can drop [10427,29713] as being worse than [4034,10966]. And now we are at [[0,30651], [4034,10966], [14461,10028], [22483,938], [32910,0]].
And so on.
As an additional optimization I'd first sort the indexes by c[i]/p[i] and produce a greedy solution where we assign all of the beginning indexes to A and all of the end to B. From the existence of that greedy solution, we never need to look at any solution with p or c worse than that known solution. After we get half-way through the jobs, this should become a useful filter.

Transforming a logic constraint into python pulp code

I started working on a problem in the past several days...
A company plans its business in a three month period. It can produce
110 units at a cost of 600 each. The minimum amount it must produce
per month is 15 units if active (but of course, it can choose to be closed
during the month, and produce 0 units). Each month it can subcotract the
prodution of 60 units, at a cost of 660 each. Storing a unit for one month
costs 20$ per unit per month. The marketing department has forcasted
sales of 100, 130 and 150 units for the next three months, respectively.
The goal is to meet the demand each month while minimizing the total
cost.
I deduced that we need to have an objective function of form min[Sum(i=0..3) 600*x1+660*x2+20*x3].
We need to add some constrains on x1>=15, and on x2 0<=x2<=60
Also we will also need another constraint for each month...
For the first one i=1 => x1+x2 = 100 - x3last (x3last is an extra variable that should hold the amount existing in deposit from the previous month), and for i=2 and i=3 same constraints.
I don't have any idea how to write this in pulp, and i would appreciate some help. Thx ^_^
I'd tend to agree with #Erwin that you should focus on formulating the problem as a Linear Program. It is then easy to translate this into code in PULP or one of many other PULP libraries/tools/languages.
As an example of this - lets work through this process for the example problem you have written out in your question.
Decision Variables
The first thing to decide is what you can/should decide. This set of information is called the decision variables. Picking the best/easiest decision variables for your problem comes with practice - the important thing is that once you know the values of the variables you have a unique solution to the problem.
Here I would suggest the following. These assume that the forecasts for demand are perfect. For each month i:
Whether the production line should be open - o[i]
How much to produce in that month - p[i]
How much to hold in storage for next month - s[i]
How much to get made externally - e[i]
Objective Function
The objective in your case is obvious - minimise the total cost. So we can just write this down: sum(i=0...2)[p[i]*600 + s[i]*20 + e[i]*660]
Constraints
Let's lift these directly our of your problem description:
"It can produce 110 units at a cost of 600 each. The minimum amount it must produce per month is 15 units if active (but of course, it can choose to be closed during the month, and produce 0 units)."
p[i] >= o[i]*15
p[i] <= o[i]*110
The first constraint forces the minimum production about to be 15 if the production is open that month (o[i] == 1), if the production is not open this constraint has not effect. The second constraint sets a maximum value on p[i] of 110 if the production is open and a maximum production of 0 if the production is closed that month (o[i] == 0).
"Each month it can subcotract the prodution of 60 units, at a cost of 660 each"
e[i] <= 60
"The marketing department has forcasted sales of 100, 130 and 150 units for the next three months, respectively. The goal is to meet the demand each month while minimizing the total cost." If we declare the sales in each mongth to be sales[i], we can define our "flow constraint" as:
p[i] + e[i] + s[i-1] == s[i] + sales[i]
The way to think of this constraint is inputs on the left, and outputs on the right. Inputs of units are production, external production, and stuff taken out of storage from last month. Outputs are units left/put in storage for next month and sales.
Finally in code:
from pulp import *
all_i = [1,2,3]
all_i_with_0 = [0,1,2,3]
sales = {1:100, 2:130, 3:150}
o = LpVariable.dicts('open', all_i, cat='Binary')
p =LpVariable.dicts('production', all_i, cat='Linear')
s =LpVariable.dicts('stored', all_i_with_0, lowBound=0, cat='Linear')
e =LpVariable.dicts('external', all_i, lowBound=0, cat='Linear')
prob = LpProblem("MinCost", LpMinimize)
prob += lpSum([p[i]*600 + s[i]*20 + e[i]*660 for i in all_i]) # Objective
for i in all_i:
prob += p[i] >= o[i]*15
prob += p[i] <= o[i]*110
prob += e[i] <= 60
prob += p[i] + e[i] + s[i-1] == sales[i] + s[i]
prob += s[0] == 0 # No stock inherited from previous monts
prob.solve()
# The status of the solution
print ("Status:", LpStatus [prob.status])
# Dislay the optimums of each var
for v in prob.variables ():
print (v.name, "=", v.varValue)
# Objective fcn
print ("Obj. Fcn: ", value(prob.objective))
Which returns:
Status: Optimal
external_1 = 0.0
external_2 = 10.0
external_3 = 40.0
open_1 = 1.0
open_2 = 1.0
open_3 = 1.0
production_1 = 110.0
production_2 = 110.0
production_3 = 110.0
stored_0 = 0.0
stored_1 = 10.0
stored_2 = 0.0
stored_3 = 0.0
Obj. Fcn: 231200.0

Adding constraints for a known solution causes out of bounds exception

I have a linear optimization goal to Maximize EE+FF, where EE and FF each consist of some C and D.
With code I've written, I can get solver to find:
EE_quantity: 0, FF_quantity: 7
...but I know there to be another solution:
EE_quantity: 1, FF_quantity: 6
In order to validate user input for other valid solutions, I added a constraint for both EE and FF. So I added the EE_quantity == 0, FF_quantity == 7 in the code below, which is a runnable example:
SolverContext c2 = SolverContext.GetContext();
Model m2 = c2.CreateModel();
p.elements = elements_multilevel_productmix();
Decision C_quantity = new Decision(Domain.IntegerNonnegative, "C_quantity");
Decision D_quantity = new Decision(Domain.IntegerNonnegative, "D_quantity");
Decision EE_quantity = new Decision(Domain.IntegerNonnegative, "EE_quantity");
Decision FF_quantity = new Decision(Domain.IntegerNonnegative, "FF_quantity");
m2.AddDecisions(C_quantity, D_quantity, EE_quantity, FF_quantity);
m2.AddConstraints("production",
6 * C_quantity + 4 * D_quantity <= 100,
1 * C_quantity + 2 * D_quantity <= 200,
2 * EE_quantity + 1 * FF_quantity <= C_quantity,
1 * EE_quantity + 2 * FF_quantity <= D_quantity,
EE_quantity == 0,
FF_quantity == 7
);
m2.AddGoal("fixed_EE_FF", GoalKind.Maximize, "EE_quantity + FF_quantity");
Solution sol = c2.Solve(new SimplexDirective());
foreach (var item in sol.Decisions)
{
System.Diagnostics.Debug.WriteLine(
item.Name + ": " + item.GetDouble().ToString()
);
}
It seems that Solver Foundation really doesn't like this specific combination. Using EE_quantity == 1, FF_quantity == 6 is fine, as is using just EE_quantity == 0 or FF_quantity == 7. But using both, AND having one of them being zero, throws an exception:
Index was outside the bounds of the array.
What is going on under the hood, here? And how do I specify that I want to find "all" solutions for a specific problem?
(Note: no new releases of Solver Foundation are forthcoming - it's essentially been dropped by Microsoft.)
The stack trace indicates that this is a bug in the simplex solver's presolve routine. Unfortunately the SimplexDirective does not have a way to disable presolve (unlike InteriorPointDirective). Therefore the way to get around this problem is to specify the fixed variables differently.
Remove the last two constraints that set EE_quantity and FF_quantity, and instead set both the upper and lower bounds to be 0 and 7 respectively when you create the Decision objects. This is equivalent to what you wanted to express, but appears to avoid the MSF bug:
Decision EE_quantity = new Decision(Domain.IntegerRange(0, 0), "EE_quantity");
Decision FF_quantity = new Decision(Domain.IntegerRange(7, 7), "FF_quantity");
The MSF simplex solver, like many mixed integer solvers, only returns the optimal solution. If you want MSF to return all solutions, change to the constraint programming solver (ConstraintProgrammingDirective). If you review the documentation for Solution.GetNext() you should figure out how to do this.
Of course the CP solver is not guaranteed to produce the globally optimal solution immediately. But if you iterate through solutions long enough, you'll get there.

What is rolling sum and how to impliment it in Informatica and my requirement is as follows?

Can someone pl tell me what is rolling sum and how to implement it in Informatica?
My requirement is as below:(Given by client)
ETI_DUR :
SUM(CASE WHEN AGENT_EXPNCD_DIM.EXCEPTION_CD='SYS/BLDG ISSUES ETI' THEN IEX_AGENT_DEXPN.SCD_DURATION ELSE 0 END)
ETI_30_DAY :
ROLLING SUM(CASE WHEN (SYSDATE-IEX_AGENT_DEXPN.ROW_DT)<=30 AND AGENT_EXPNCD_DIM.EXCEPTION_CD = 'SYS/BLDG ISSUES ETI'
THEN IEX_AGENT_DEXPN.SCD_DURATION ELSE 0 END)
ETI_30_DAY_OVRG :
CASE WHEN ETI_DUR > 0 THEN
CASe
WHEN ROLLINGSUM(ETI_DUR_30_DAY FOR LAST 29 DAYS) BETWEEN 0 AND 600 AND ROLLINGSUM(ETI_DUR_30_DAY FOR LAST 29 DAYS) + ETI_DUR > 600 THEN ROLLINGSUM(ETI_DUR_30_DAY FOR LAST 30 DAYS) - 600
WHEN ROLLINGSUM(ETI_DUR_30_DAY FOR LAST 29 DAYS) > 600 THEN ETI_DUR
ELSE 0 END
ELSE 0 END
And i have implemented as below in Informatica.
Expression Transformation:
o_ETI_DUR-- IIF(UPPER(EXCEPTION_CD_AGENT_EXPNDIM)='SYS/BLDG ISSUES ETI',SCD_DURATION,0)
o_ETI_29_DAY-- IIF(DATE_DIFF(TRUNC(SYSDATE),trunc(SCHD_DATE),'DD') <=29 AND UPPER(EXCEPTION_CD_AGENT_EXPNDIM) = 'SYS/BLDG ISSUES ETI' ,SCD_DURATION,0)
o_ETI_30_DAY -- IIF(DATE_DIFF(TRUNC(SYSDATE),trunc(SCHD_DATE),'DD') <=30 AND UPPER(EXCEPTION_CD_AGENT_EXPNDIM) = 'SYS/BLDG ISSUES ETI' ,SCD_DURATION,0)
Aggregator transformation:
o_ETI_30_DAY_OVRG:
IIF(sum(i_ETI_DUR) > 0,
IIF((sum(i_ETI_29_DAY)>=0 and sum(i_ETI_29_DAY)<=600) and (sum(i_ETI_29_DAY)+sum(i_ETI_DUR)) > 600,
sum(i_ETI_30_DAY) - 600,
IIF(sum(i_ETI_29_DAY)>600,sum(i_ETI_DUR),0)),0)
But is not working. Pl help ASAP.
Thanks a lot....!
Rolling sum is just the sum of some amount over a fixed duration of time. For example, everyday you can calculate the sum of expense for last 30 days.
I guess you can use an aggregator to calculate ETI_DUR, ETI_30_DAY and ETI_29_DAY. After that, in an expression you can implement the logic for ETI_30_DAY_OVRG. Note that you cannot write an IIF expression like that in an aggregator. Output ports must use an aggregate function.
Here is a rolling sum example:
count, rolling_sum
1,1
2,3
5,8
1,9
1,10
Basically it is the sum of the values listed previously. To implement it in Informatica use 'local variables' (variable port in expression transformation) as follows:
input port: count
variable port: v_sum_count = v_sum_count + count
output port: rolling_sum = v_sum_count
we have a moving sum function defined in Numerical functions in Expression transformation:
MOVINGSUM(n as numeric, i as integer, [where as expression]).
Please check if it helps.

WEKA : Cost Matrix Interpretation

How do we interpret the cost matrix in WEKA? If I have 2 classes to predict (class 0 and class 1) and want to penalize classfication of class 0 as class 1 more (say double the penalty), what exactly is the matrix format?
Is it :
0 10
20 0
or is it
0 20
10 0
The source of confusion are the following two references:
1) The JavaDoc for Weka CostMatrix says:
The element at position i,j in the matrix is the penalty for classifying an instance of class j as class i.
2) However, the answer in this post seems to indicate otherwise.
http://weka.8497.n7.nabble.com/cost-matrix-td5821.html
Given the first cost matrix, the post says "Misclassifying an instance of class 0 incurs a cost of 10. Misclassifying an instance of class 1 is twice as costly.
Thanks.
I know my answer is coming very late, but it might help somebody so here it is:
To boost the cost of classifying an item of class 0 as class 1, the correct format is the second one.
The evidence:
Cost Matrix I used:
0 1.0
1000.0 0
Confusion matrix (from cross-validation):
a b <-- classified as
565 20 | a = ignored
54 204 | b = not_ignored
Cross-validation output:
...
Total Cost 54020
...
That's a cost of 54 * 10000 + 20 * 1, which matches the confusion matrix above.