Pulp - LP Objective function formulation - linear-programming

I am working on solving a set covering problem for electric vehicle charging stations. My objective is to maximize the demand covered by the radius of a charging station.
I have two variables to make up the objective function.
Yij denotes the demand location i is covered by the radius of charging station j.
Similarly, Xj denotes if charging station j is open.
I am looking to create an objective function such as the following:
Maximize OF = ((Y11 + Y21+ Y31 + .... Yn1) * X1) + ((Y12 + Y22+ Y32 + .... Yn2) * X2) + ....
I tried the following, but am running into issues:
OptModel += lpSum(((Y[i,j] for i in range (I)) * X[j]) for j in range(J))
Any idea on how to formulate this?

It isn't clear from your description why Y is a variable? It sounds like it should be a parameter (known value) if the demand location is within the radius of some source.... There must be some other nuance as to why this isn't known. (If it can be calculated, do it and make it a parameter and your problem is solved.)
The statement you propose is illegal because you are multiplying variables together and that makes the statement non-linear. You need to reformulate....
You have an implicit "and" condition in there in that you only want to receive credit if both Y and X are true, so you will need an additional variable or be clever in how you relate X and Y because you can't multiply them.
Why don't you just add this constraint:
Y[i, j] <= X[j] for each j
that would essentially change the meaning of Y to "in range of an operating charger".
Also realize if you sum up all of these Y vars (or as you appear to try to do in your objective) you will get double counting of any demand that can be charged from multiple stations--not sure if that is intent or not.

Related

Confusion about formula for Linear regression with gradient descent, (Pseudocode)

I'm made a program that calculates the line of best fit of a set of data points using gradient descent. I generate a 1000 random points and then it calculates the line of best fit training on these 1000 points. My confusion lies in the theory of my code.
In the part of my code where the training function is, by using the current m and b values for y= mx +b, the function makes a guess of the y values when it goes through the training points x values. This is supervised learning, so I know what the actual y value is, the function calculates the error and using that error adjusts the m and b values. <-- What is happening in the program when adjusting the line of best fit
I get everything above ^. what I'm confused about is the part of the code that calculates how to adjust these m and b values. Here it is:
guess = m * x + b;
error = y - guess;
m = m + (error * x) * learningrate;
b = b + error * learningrate;
Im confused about why we add instead of subtract that delta m (the (error * x) *learningrate)) part. Ignoring the learningrate, the error * x part is the partial derivative of the error with respect to m. But if we took the partial derivative of something with respect to something, wouldn't it give us the direction of the steepest ascent? Shouldn't we go the opposite direction (subtract the delta m) to get the proper m value? Isn't our goal to reduce the error?
Surprisingly to me, the above code works, if you add the delta m, it adjusts the m and b values in the right direction. So basically my question is: Why aren't we subtracting the delta m part (error *x) as it is pointing in the direction of steepest ascent, and we want to get the opposite of that?
Thanks!

Simulation of two spheres colliding through classical mechanics

I am trying to simulate the collision of two spheres on Fortran 90 by using the equations of classical mechanics.
Firstly, I'm doing this on one dimension: I am fixing a sphere on the ground and putting the other one at a certain height (both are at rest at t=0), and both of them have the same radius and mass.
Being so, the forces acting at the moving particle is the gravitational force and the elastic force (when the spheres start to collide). So, at first, the moving sphere is only subjected to gravitational force, that is, Fg = -g.m. I'm considering only one dimension, so since the particle falling will give me lower values than the height it was in the beginning, it is negative. Now, when the moving particle hits the fixed one, the latter will cause a force of Fe = -k.dx.n, where k is the elastic constant, dx is the overlap and n is the direction of that force (its norm is 1). The elastic force is restitutive, so it should be negative also. To be clear, dx = r1 + r2 - |x1 - x2| and n = (x1-x2)/|x1 -x2|, where r1, r2 are the radii and x1, x2 are the positions of the particles at given time.
The code compiles ok, the only problem is when I go check the positions for the moving particle - sometimes, it keeps getting lower (as it should at first) and then it continues to decrease to negative values - something that should not happen. Or, when the moving sphere does bounce back where it should, it goes back to a height HIGHER than the initial condition (it bounces higher, violating conservation of energy).
The thing is that, the best situation that it seems to be working (that last one, in which it bounces higher), the formula for the elastic force is actually not right (I put dx = r1 + r2 - |x1 + x2|, instead of a minus sign). I've tried correcting the higher bounce by changing some parameters (lowering and increasing elastic constant and lowering the time step), but with no success. Also, the higher bouncing I mentioned is about four times higher, so it is not some problem of error of calculations.
Here are the important parts of the code: where the forces are calculated, and the time integration:
coef1 = abs(1.0d0*x1 - 1.0d0*x2)
coef2 = (1.0d0*x1 - 1.0d0*x2)/coef1
Fx_elasticaparcial(m) = -1.0d0*k*((1.0d0*a1+1.0d0*a2) + 1.0d0*coef1)*coef2
Fx_elasticatotal(l) = 1.0d0*Fx_elasticatotal(l) +1.0d0*Fx_elasticaparcial(m)
forcax(l) = 1.0d0*flagx(l)*(1.0d0*gravidade(massadummy)+1.0d0*Fx_elasticatotal(l))
m is the partial elastic force and l is the total elastic force exerted ON a particle (I've done it thinking of adding more particles further down the road)
function gravidade(massa)
use parametros, only: g
implicit none
real*8 :: gravidade, massa
gravidade = -1.0d0*g*massa
end function gravidade
This one is a function for gravitational force
subroutine integracaoEuler (xo, xn, vxo, vxn, fx, mass)
use parametros, only: N, dt
implicit none
real*8 :: xo, xn, vxo, vxn, fx, mass
xn = 1.0d0*xo + 1.0d0*dt*vxo
xo = 1.0d0*xn
vxn = 1.0d0*vxo + 1.0d0*dt*((1.0d0*fx)/(1.0d0*mass))
vxo = 1.0d0*vxn
return
end subroutine integracaoEuler
Euler integration subroutine
do while ((t + dt) < (tmax)) !time loop
t = t+dt
do i = 1, N !particle loop
do j = 1, N !neighbours of i particle loop
if (i .NE. j) then
if (abs(SQRT(1.0d0*xold(i) - 1.0d0*xold(j))**2) .LE. 1.0d0*a(i) + 1.0d0*a(j)) then
call forcastotais (i, j, m(i), a(i), a(j), xold(i), xold(j))
else
forcax(i) = 1.0d0*flagx(i)*gravidade(m(i))
end if
end if
end do
call integracaoEuler (xold(i), xnew(i), vxold(i), vxnew(i), forcax(i), m(i))
write(i, *) t, xold(i)
end do
end do
Main loop of the program
Sorry for making this really big, to fix it probably must be something easy. Again, I need to really use the equations of classical mechanics for this, not by putting the velocity to change direction when it hits the other sphere or that sort of stuff. I am frustrated with this, and don't know how to fix it (I have been stuck on this for 2 weeks). I've done everything else on the model I'm making (viscosity, cell-link) with a lot of particles, but this problem keeps reappearing and messing up my graphs. Any help is welcome; please make it explicit, since I am new to programming. Thank you in advance.

Cycle doesn't work

In Stata, I have the following variables: latitude, longitude, avg_luminosity. For each observation (1547 total), I need to find a sum (let's call this variable sum_lum) of average luminosities of "neighbours" of this particular pair of latitude and longitude, those whose latitude and longitude lie within 0.5 radius. I have tried the following code:
tempvar sum_temp
forvalues i=1/1547 {
egen `sum_temp' = sum(avg_luminosity) if (latitude<latitude[_n]+0.5 & latitude>latitude[_n]-0.5 & longitude<longitude[_n]+0.5 & longitude>longitude[_n]+0.5)
replace sum_lum[_n]= sum_temp
drop `sum_temp'
}
But the code doesn't work (weights not allowed). Could anyone please help me on this issue?
We don't here have a very good question, as no sample data are given with which to run the code. See https://stackoverflow.com/help/mcve for how to ask a good question. We have that 1547 is the number of observations.
But nevertheless there are various problems identifiable with this code.
First, consider the if qualifier:
if (latitude<latitude[_n]+0.5 & latitude>latitude[_n]-0.5 & longitude<longitude[_n]+0.5 & longitude>longitude[_n]+0.5)
We need to correct a typo there: the last +0.5 should evidently be -0.5.
To focus on the main problem, replace latitude with y and longitude with x
if (y < y[_n]+0.5 & y > y[_n]-0.5 & x < x[_n]+0.5 & x > x[_n]-0.5)
The subscript [_n] just means the current observation and is superfluous:
if (y < y+0.5 & y > y-0.5 & x < x+0.5 & x > x-0.5)
from which it can be seen that the qualification is no qualification: it is always true that (using mathematical notation now) y - 0.5 < y < y + 0.5 and similarly for x.
The intent of this code is to compare any y and any x with the current y and x, but that is not what it does in Stata.
Otherwise put, the guess may be that [_n] has a different interpretation each time round a loop, but that is not the case.
Second, the effect of the loop 1/1547 would, if the code were otherwise correct, would be to repeat exactly the same calculation 1547 times. The intent of the code is no doubt otherwise, but nothing inside the loop uses the loop index i in any way.
Third, neither of these is the problem reported.
replace sum_lum[_n]= sum_temp
fails because of the subscript, which is not allowed with replace before the equals sign: the error message about weights is Stata's guess that you are trying to specify weights. The statement would also fail (to do what you want, or very likely to work at all), because the variable on the right-side should be the temporary variable you have just created.
Fourth, although this is style not syntax, using egen to calculate a sum is overkill. No new variable need be re-created 1547 times only to be droppred.
Here's a guess at what will work:
gen sum_lum = .
local y latitude
local x longitude
quietly forval i = 1/1547 {
summarize avg_luminosity if inrange(`y', `y'[`i'] - 0.5, `y'[`i'] + 0.5) & ///
inrange(`x', `x'[`i'] - 0.5, `x'[`i'] + 0.5), meanonly
replace sum_lum = r(sum) in `i'
}
That loop uses the current observation's latitude and longitude.

Modifying a value on a logarithmic curve

I have one value that is a floating point percentage from 0-100, x, and another value that is a floating point from 0-1, y. As y gets closer to zero, it should reduce the value of x on a logarithmic curve.
So for example, say x = 28.0f and y = 0.8f. Since 0.8f isn't that far from 1.0f it should only reduce the value of x by a small amount, say bringing it down to x = 25.0f or something like that. As y gets closer to zero it should more and more drastically reduce the value of x. The only way I can think of doing this is with a logarithmic curve. I know what I want it to do, but I cannot for the life of me figure out how to implement this in C++. What would this algorithm look like in C++?
It sounds like you want this:
new_x = x * ln((e - 1) * y + 1)
I'm assuming you have the natural log function ln and the constant e. The number multiplied by x is a logarithmic function of y which is 0 when y = 0 and 1 when y = 1.
Here's the logic behind that function (this is basically a math problem, not a programming problem). You want something that looks like the ln function, rising steeply at first and then leveling off. But you want it to start at (0, 0) and then pass through (1, 1), and ln starts at (1, 0) and passes through (e, 1). That suggests that before you do the ln, you do a simple linear shift that takes 0 to 1 and 1 to e: ((e - 1) * y + 1.
We can try with the following assumption: we need a function f(y) so that f(0)=0 and f(1)=1 which follows some logarithmic curve, may be something like f(y)=Alog(B+Cy), with A, B and C constants to be determined.
f(0)=0, so B=1
f(1)=1, so A=1/log(1+C)
So now, just need to find a C value so that f(0.8) is roughly equal to 25/28. A few experiment shows that C=4 is rather close. You can find closer if you want.
So one possibility would be: f(y) = log(1.0 + 4.0*y) / log(5.0)

C++: Finding all combinations of array items divisable to two groups

I believe this is more of an algorithmic question but I also want to do this in C++.
Let me illustrate the question with an example.
Suppose I have N number of objects (not programming objects), each with different weights. And I have two vehicles to carry them. The vehicles are big enough to carry all the objects by each. These two vehicles have their own mileage and different levels of fuel in the tank. And also the mileage depends on the weight it carries.
The objective is to bring these N objects as far as possible. So I need to distribute the N objects in a certain way between the two vehicles. Note that I do not need to bring them the 'same' distance, but rather as far as possible. So example, I want the two vehicles to go 5km and 6 km, rather than one going 2km and other going 7km.
I cannot think of a theoretical closed-form calculation to determine which weights to be loaded in to each vehicle. because remember that I need to carry all the N objects which is a fixed value.
So as far as I can think, I need to try all the combinations.
Could someone advice of an efficient algorithm to try all the combinations?
For example I would have the following:
int weights[5] = {1,4,2,7,5}; // can be more values than 5
float vehicelONEMileage(int totalWeight);
float vehicleTWOMileage(int totalWeight);
How could I efficiently try all the combinations of weights[] with the two functions?
Thw two functions can be assumed as linear functions. I.e. the return value of the two mileage functions are linear functions with (different) negative slopes and (different) offsets.
So what I need to find is something like:
MAX(MIN(vehicleONEMileage(x), vehicleTWOMileage(sum(weights) - x)));
Thank you.
This should be on the cs or the math site.
Simplification: Instead of an array of objects, let's say we can distribute weight linearly.
The function we want to optimize is the minimum of both travel distances. Finding the maximum of the minimum is the same as finding the maximum of the product (Without proof. But to see this, think of the relationship between perimeter and area of rectangles. The rectangle with the biggest area given a perimeter is a square, which also happens to have the largest minimum side length).
In the following, we will scale the sum of all weights to 1. So, a distribution like (0.7, 0.3) means that 70% of all weights is loaded on vehicle 1. Let's call the load of vehicle 1 x and the load of vehicle 1-x.
Given the two linear functions f = a x + b and g = c x + d, where f is the mileage of vehicle 1 when loaded with weight x, and g the same for vehicle 2, we want to maximize
(a*x+b)*(c*(1-x)+d)
Let's ask Wolfram Alpha to do the hard work for us: www.wolframalpha.com/input/?i=derive+%28%28a*x%2Bb%29*%28c*%281-x%29%2Bd%29%29
It tells us that there is an extremum at
x_opt = (a * c + a * d - b * c) / (2 * a * c)
That's all you need to solve your problem efficiently.
The complete algorithm:
find a, b, c, d
b = vehicleONEMileage(0)
a = (vehicleONEMileage(1) - b) * sum_of_all_weights
same for c and d
calculate x_opt as above.
if x_opt < 0, load all weight onto vehicle 2
if x_opt > 1, load all weight onto vehicle 1
else, try to load tgt_load = x_opt*sum_of_all_weights onto vehicle 1, the rest onto vehicle 2.
The rest is a knapsack problem. See http://en.wikipedia.org/wiki/Knapsack_problem#0.2F1_Knapsack_Problem
How to apply this? Use the dynamic programming algorithm described there twice.
for maximizing a load up to tgt_load
for maximizing a load up to (sum_of_all_weights - tgt_load)
The first one, if loaded onto vehicle one, gives you a distribution with slightly less then expected on vehicle one.
The second one, if loaded onto vehicle two, gives you a distribution with slightly more than expected on vehicle two.
One of those is the best solution. Compare them and use the better one.
I leave the C++ part to you. ;-)
I can suggest the following solution:
The total number of combinations is 2^(number of weights). Using a bit logic we can loop through the all combinations and calculate maxDistance. Bits in the combination value show which weight goes to which vehicle.
Note that algorithm complexity is exponential and int has a limited number of bits!
float maxDistance = 0.f;
for (int combination = 0; combination < (1 << ARRAYSIZE(weights)); ++combination)
{
int weightForVehicleONE = 0;
int weightForVehicleTWO = 0;
for (int i = 0; i < ARRAYSIZE(weights); ++i)
{
if (combination & (1 << i)) // bit is set to 1 and goes to vechicleTWO
{
weightForVehicleTWO += weights[i];
}
else // bit is set to 0 and goes to vechicleONE
{
weightForVehicleONE += weights[i];
}
}
maxDistance = max(maxDistance, min(vehicelONEMileage(weightForVehicleONE), vehicleTWOMileage(weightForVehicleTWO)));
}