Profit maximization using non linear optimization in pyomo problem framing - optimization

Background
We have 5 items in our portfolio along with the quantity sold, margin and prices of every item from last month. Predicted quantity sold of every item is dependent on its own price (through own price elasticity) and price of every other item (cross price elasticity). I am trying to write an pyomo script to increase prices of every item optimally and maximize the profit.
Example for 5 items after calculating a 5*5 matrix for elasticities.
Predicted quantity sold for every item is following function: Pred(Q1) = exp(p1 * e11 + p2 * e12 + ...... + p5 * e15)
Margin for every item is available.
Current Net profit : P1 * Q1 * Margin1 + ......... + P5 * Q5 * Margin5 = 1000
Objective : Max(P1 * (1+change p1) * Pred(Q1) * Margin 1 + ......... + P5 * (1+change p5) * Pred(Q5) * Margin 5
Constraints:
We can change the price of every item by [-5% , +10%]
Predicted quantity sold of every item with new prices should not change by
more than [-5% , +10%] of current quantities
Maximum profit achieved should be greater than 1000
All prices and quantities should be positive
Need help with programming it in pyomo with n variables and constarints, ipopt is what I think of using but open for recommendation from experts.
#Parameters
model.N = pyo.Param(model.a, initialize = qty_dict)
#Function that returns bounds on variable x
def bounds_for_y(model,l):
return (round(model.N[l]*0.95,0),round(model.N[l]*1.1,0))
#Here l is just a placeholder for set a
#Variable Declaration
model.qty = pyo.Var(model.a, domain = pyo.Integers, bounds = bounds_for_y )
Similarly for price:
#Variable declaration
model.prices = pyo.Var(model.a, domain = pyo.Reals, bounds = bounds_for_x, initialize = price_dict)
enter code here

Related

Multiplication price and profit with 2 number percentage in vb.net

I have a product table where I save the price and the amount of profit.
I want to display the amount of time displayed differently
for example :
price : 8.08
profit : 8
Presentable : 8.08 + (8.08 * 8 / 100) = 8.7264
Now I want the answer to be two decimal places and rounded up.
And the answer should be as follows:
Presentable : 8.08 + (8.08 * 8 / 100) = 8.73
The "C" currency format specifier should do the trick for you.
Dim amount As Decimal = 123.456
System.Console.WriteLine(amount.ToString("C", System.Globalization.CultureInfo.CurrentCulture))
' Prints : $123.46
More info here: https://learn.microsoft.com/en-us/dotnet/standard/base-types/standard-numeric-format-strings#CFormatString
There is a also a Round method, where you can specify to how many decimal places you would like to round the number. So in your case of rounding to 2 decimal places you could make a call like:
System.Math.Round(amount, 2, System.MidPointRounding.AwayFromZero)

How to compute debit, credit amount in Vendor Bill in Odoo?

I am new to Odoo Accounting. I have been encountering a problem in calculating debit and credit amount of Vendor Bill. I have added two new fields in purchase order line, discount_type and discount_amt. The subtotal value must be (price_unit * quantity) - discount. I could compute the subtotal amount. But when I check the journal items, the debit and credit amount are not changed. I mean the discount amount are not subtracted. But when I saved the form, I got the error which said debit and credit were not balanced. How can I do that?
def compute_price_subtotal(self):
for line in self:
line.discount_type = line.purchase_line_id.discount_type
line.discount_amt = line.purchase_line_id.discount_amt
qty = line.quantity or 0
price_unit = line.price_unit or 0
subtotal = price_unit * qty
discount_type = line.discount_type
discount_amount = line.discount_amt
if discount_type == 'fixed':
discount = discount_amount * qty
line.price_subtotal = subtotal - discount
elif discount_type == 'percentage':
discount = subtotal * (discount_amount / 100)
line.price_subtotal = subtotal - discount
else:
line.price_subtotal = subtotal
if line.move_id.type in line.move_id.get_outbound_types():
sign = 1
elif line.move_id.type in line.move_id.get_inbound_types():
sign = -1
else:
sign = 1
price_subtotal = sign * line.price_subtotal
line.update({
'debit': price_subtotal > 0.0 and price_subtotal or 0.0,
'credit': price_subtotal < 0.0 and -price_subtotal or 0.0,
})
The above method is to calculate the price_subtotal, debit and credit.
In the picture, the untaxed amount is 13800 and tax is 690. So the total amount will be 13800 + 690 = 14490. But in the Journal items, it shows 15000 and the subtotal values are different.
This is because you only modify the line you are interested in.
This tries to modify the debit/credit but it is leaving the account move unbalanced.
As this violate a constrains, the modification of the accounting is prevented.
You need to balance the move before updating anything in it.
This involves updating the tax line and the payable/receivable line too.
Once you have all of those lines, you can update the whole account move.
This means that you have to make something like this:
(assuming the calculation is already done)
lines_to_write = [
(1, line_A_id, line_A_values),
(1, tax_line_id, tax_line_values),
(1, receivable_line_id, receivable_line_values)
]
move.write({'line_ids': lines_to_write})
You can get the list of command here
Btw, to recompute the debit and credit when a business field is changed, you can (should) call the method _get_fields_onchange_subtotal_model to get the new values and then to update the account move line with those new values.
One of the reason is the fact that the accounting and the invoice could be in different currency.
Disclaimer: you should modify taxes only if you are sure of what you are doing.
This can have an impact on the user's tax report.

Calculate the discount rate

I have the original price of a commodity and its discounted price.
I currently have some code but it is not working properly.
For example: The price of a pre-discounted commodity is 853.2 $.
The discounted price is 349 $.
That is a 59% discount, but my code shows the wrong numbers.
Dim a1 As String = (Val(pre-discounted_price) - Val(discount_price) * 100 / Val(discount_price)).ToString
Dim a2 As Integer = (853.2 - 349) * 100 / 349
The formula for calculating how much you need to discount something by, to reach a new price is:
100 * (originalprice - newprice) / originalprice
100 * (852.3 - 349) / 852.3 = 59 (0 decimal places)
Checking:
852.3 - (852.3 * 0.59) = 349 (approx)
Your code went wrong because you divided by the newprice

Using DAX for Production Planning

My question is based on building a ramp up for planning production lines.
I have a WIP where a ramp up category is selected to be used for each MSO (Master Sew Order). The Ramp up is based on hour fences (for example 1-6 hours,6-12 hours,etc).
On the WIP, an MSO will have units (example 1,920 units), divided by capacity per hour (80 pcs/hr), to give time needed 24 hours. This then needs to be
calculated based on ramp up, for hours 1-6, 6-12, 12-18, and 18-24 and multiply our by related efficiency.
For example:
Hours 1-6: 20% efficiency * 80 units = 16 units/hr (6 x 16 = 96 units produced)
Hours 6-12: 40% efficiency * 80 units = 32 units/hr (192 units)
Hours 12-18: 60% efficiency * 80 Units = 48 units/hr (288 units)
Hours 18-24: 80% efficiency * 80 units = 64 units/hr (384 units)
Hours 24+: 100% efficiency * 80 units = 80 units/hr ((1920-960)/80)= 12 hours remaining
TOTAL TIME = 36 hours to produce
How would Power BI know to divide up the original 24 hour estimate into parts, multiply by respective efficiency, and return a new result of 36 hours?
Thank you so much in advance!
Kurt
Relationships
I'm not sure how to do this in DAX but you tagged PowerQuery so here's a custom query that computes 36 based on your parameters:
let
MSO = 1920,
Capacity = 80,
Efficiency = {
{6, 0.2},
{12, 0.4},
{18, 0.6},
{24, 0.8},
{#infinity, 1.0}
},
Accumulated = List.Accumulate(Efficiency, [
Remaining = MSO,
RunningHours = 0
], (state, current) =>
let
until = current{0},
eff = current{1},
currentCapacity = eff * Capacity,
RemainingHours = state[Remaining] / currentCapacity,
CappedHours = List.Min({RemainingHours, until - state[RunningHours]})
in [
Remaining = state[Remaining] - currentCapacity * CappedHours,
RunningHours = state[RunningHours] + CappedHours
]),
Result = if Accumulated[Remaining] = 0
then Accumulated[RunningHours]
else error "Not enough time to finish!"
in
Result
The inner lists for Efficiency are of the form time-efficiency-ends,efficiency-value. Plug in infinity to mean the last efficiency never stops.
In a normal iterative programming language you could update state with a for-loop, but in M you need to use List.Accumulate and package all your state into one value.
In your data model you may have MSO in one table containing 2 fields, [Units] and [UnitsPerHour], and another table called EffTable which may store the efficiencies broken out by the hour fences.
Create 4 new calculated columns in your MSO table, one for each hour fence, eg [1--6]:
=
6 * LOOKUPVALUE ( EffTable[Efficiency], EffTable[Hours], "1--6" )
* [UnitsPerHour]
These are fields that hold how many units you would produce in the 4 time slots. Create a new calculated field for the total, [RampUpUnits]:
=
[1--6Hours] + [6--12Hours] + [12--18Hours] + [18--24Hours]
Finally calculate the total time as:
=
24
+ ( [Units] - [RampUpUnits] )
/ [UnitsPerHour]
This calculates the number of hours required for the remaining units and adds it to 24 for the ramp up time.

What function does .NET NPV() use? Doesn't match manual calculations

I am using the NPV() function in VB.NET to get NPV for a set of cash flows.
However, the result of NPV() is not consistent with my results performing the calculation manually (nor the Investopedia NPV calc... which matches my manual results)
My correct manual results and the NPV() results are close, within 5%.. but not the same...
Manually, using the NPV formula:
NPV = C0 + C1/(1+r)^1 + C2/(1+r)^2 + C3/(1+r)^3 + .... + Cn/(1+r)^n
The manual result is stored in RunningTotal
With rate r = 0.04
and period n = 10
Here is my relevant code:
EDIT: Do I have OBOB somewhere?
YearCashOutFlow = CDbl(TxtAnnualCashOut.Text)
YearCashInFlow = CDbl(TxtTotalCostSave.Text)
YearCount = 1
PAmount = -1 * (CDbl(TxtPartsCost.Text) + CDbl(TxtInstallCost.Text))
RunningTotal = PAmount
YearNPValue = PAmount
AnnualRateIncrease = CDbl(TxtUtilRateInc.Text)
While AnnualRateIncrease > 1
AnnualRateIncrease = AnnualRateIncrease / 100
End While
AnnualRateIncrease = 1 + AnnualRateIncrease
' ZERO YEAR ENTRIES
ListBoxNPV.Items.Add(Format(PAmount, "currency"))
ListBoxCostSave.Items.Add("$0.00")
ListBoxIRR.Items.Add("-100")
ListBoxNPVCum.Items.Add(Format(PAmount, "currency"))
CashFlows(0) = PAmount
''''
Do While YearCount <= CInt(TxtLifeOfProject.Text)
ReDim Preserve CashFlows(YearCount)
CashFlows(YearCount) = Math.Round(YearCashInFlow - YearCashOutFlow, 2)
If CashFlows(YearCount) > 0 Then OnePos = True
YearNPValue = CashFlows(YearCount) / (1 + DiscountRate) ^ YearCount
RunningTotal = RunningTotal + YearNPValue
ListBoxNPVCum.Items.Add(Format(Math.Round(RunningTotal, 2), "currency"))
ListBoxCostSave.Items.Add(Format(YearCashInFlow, "currency"))
If OnePos Then
ListBoxIRR.Items.Add((IRR(CashFlows, 0.1)).ToString)
ListBoxNPV.Items.Add(Format(NPV(DiscountRate, CashFlows), "currency"))
Else
ListBoxIRR.Items.Add("-100")
ListBoxNPV.Items.Add(Format(RunningTotal, "currency"))
End If
YearCount = YearCount + 1
YearCashInFlow = AnnualRateIncrease * YearCashInFlow
Loop
EDIT: Using the following values:
Discount Rate = 4%
Life of Project = 10 years
Cash Flow 0 = -78110.00
Cash Flow 1 = 28963.23
Cash Flow 2 = 30701.06
Cash Flow 3 = 32543.12
Cash Flow 4 = 34495.71
Cash Flow 5 = 36565.45
Cash Flow 6 = 38759.38
Cash Flow 7 = 41084.94
Cash Flow 8 = 43550.03
Cash Flow 9 = 46163.04
Cash Flow 10 = 48932.82
Using the calculator at http://www.investopedia.com/calculator/NetPresentValue.aspx
And following the manual "textbook" formula I arrive at the same result:
Net Present Value: $225,761.70
I cannot seem to get NPV() to replicate this result... it spits out $217,078.59
I iterate it manually using the example same value... so they must be using a different function than I am...
The MSDN page example clearly states that the initial expense should be included in the cash flows list.
Normally you wouldn't include the first cashflow in the Visual Basic NPV() function (or at least we don't in the leasing world). You would discount all but the first cash flow, then add that first cash flow amount onto your Net Present Value. Here's an example of what I've done before in a calculation engine (minus error checking to simplify the example):
Dim leaseRentalsDiscounted As Double = 0.0
Dim rebatedCashFlows As IEnumerable(Of LeasePayment) = GetLeaseRentalsPaymentStream()
Dim firstFlow As LeasePayment = rebatedCashFlows(0)
Dim doubleStream As Double() = PaymentToDoubleArray(rebatedCashFlows.Skip(1))
If doubleStream.Length > 0 Then
Dim rate As Decimal = New Decimal(Me.Lease.DiscountRate / 100.0 / 12.0)
leaseRentalsDiscounted = NPV(rate, doubleStream)
End If
leaseRentalsDiscounted += firstFlow.Amount
Return leaseRentalsDiscounted
That could account for your 5% -- I know I've run into an issue like this before. To me, in the manual NPV formula you posted, C0 doesn't need to be in the stream that is discounted, so that's why I don't include it in the NPV() function.
The MSDN page notes that if your cash outflow begins at the beginning of the first period (instead of the end) the first value must be added to the NPV value and not included in the cash flows array.
Your manual calculation shows that your cash outflow (C0) occurs at time zero (present value), which indicates you should follow the MSDN page's suggestion.
Cory Larson is right, in part... but the MSDN documentation seems in error to me.
The problem is that the NPV() function is discounting the very first (n=0) element of the array when it should not; it is beginning at n=1
Even though the MSDN documentation specifics that the first element of the array should be the initial expense this is not the case with their function.
In the NPV() function, the first element of the array (as Cory Larson implied) should be the first real cash flow. Then, after the function returns a result, the result should have the initial expense subtracted.
This is because the NPV() function begins with n=1
using the NPV formula: NPV = C0 + C1/(1+r)^1 + C2/(1+r)^2 + C3/(1+r)^3 + .... + Cn/(1+r)^n
In the manual formula, Cn/(1+r)^n, for n=0 you use your initial expense... then the denominator is 1 (because n=0)
In my opinion, the MSDN example at http://msdn.microsoft.com/en-us/library/microsoft.visualbasic.financial.npv.aspx should be amended to the following:
Exclude the initial -70000 value from the array, shift all element down one in index, and decrease the array size by 1.
Then add the initial expense (-70000) to the variable NetPVal to arrive at the actual result.
Somebody should like MS know about their OBOB :D
(But it's actually a feature, right?)
EDIT: And the section which says " The array must contain at least one negative value (a payment) and one positive value (a receipt)."
In not accurate.
As Cory Larson pointed out: a negative value is not required in the array (and, in fact, should be left out!)