UTS OPTIMASI
Garry Julius 20204920003
| Kontak | : \(\downarrow\) |
| garryjuliuspermana@gmail.com | |
| (https://www.instagram.com/boring.garr/) | |
| RPubs | https://rpubs.com/garr/ |
library
import numpy as np
import numpy.linalg as la
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import axes3d
import pulp
import math
from math import *
import scipy.optimize as soptlibrary(lpSolve)
library(gMOIP)Soal 1
Find the maximum solution
\[max \space Z=4x+3y\] Suppose that the objective function is subject to the following constraints: \[\begin{align*} x≥0 \\ y≥2 \\ 2y≤25-x \\ 4y≤2x-8 \\ y≤2x-5 \\ \end{align*}\]
Solve these problems using mathematical model and R packages (please explain it step-by-step).
## (0.0, 25.0)
## (0.0, 11.0)
\[\begin{align*} &Line \space 1 & & Line \space 2& \\ 4y & \leq 2x-8 & y & \geq 2 \\ 2y & \leq 25-x & y & \geq 2 \\ 2y & \leq 25-x & 4y & \leq 2x-8 \\ \end{align*}\]
PERHITUNGAN Z
\[ Z = 4x + 3y\]
Hitung nilai Z :
1) \[\begin{align*} 4y & \leq 2x-8 \space and \space y \geq 2 \\ {x-4 \over 2} & = 2 \\ 4 &= x-4 \\ x &= 8 \\ y &= 2 \\ Z & =(4\times 8)+ (3\times 2)=38 \end{align*}\]
2) \[\begin{align*} 4y & \leq 2x-8 \space and \space 2y \leq 25-x \\ {x-4 \over 2} & = {25-x \over 2} \\ 2x-8 &= 50-2x \\ 4x & = 58 \\ x &= 14.5 \\ y &= 5.25 \\ Z & =(4\times 14.5)+ (3\times 5.25)=73.75 \end{align*}\]
3) \[\begin{align*} 2y & \leq 25-x \space and \space y \geq 2 \\ {25-x \over 2} & = 2 \\ 25-x &= 4 \\ x &= 21 \\ y &= 2 \\ Z & =(4\times 21)+ (3\times 2)=90 \end{align*}\]
Maka dari 3 hasil di atas yang menghasilkan nilai maximum adalah \(2y \leq 25-x \space and \space y \geq 2\) dan menghasilkan nilai \(90\).
Alternatif cepat dengan Coding R.
max_z <- c(4,3)
LHS <- matrix(c(1,2,
-2,4,
-2,1,
0,1)
,ncol=2, byrow=TRUE)
arah_kendala <- c("<=","<=","<=",">=")
RHS <- c(25,-8,-5,2)
# Penyelesaian
model <- lp ("max",
max_z,
LHS,
arah_kendala,
RHS,
compute.sens = TRUE)
print(model)## Success: the objective function is 90
model$solution## [1] 21 2
Soal 2
Let say you are working as consultant for a boutique car manufacturer, producing luxury cars. They run on one-month (30 days) cycles, we have one cycle to show we can provide value. There is one robot, 2 engineers and one detailer in the factory. The detailer has some holiday off, so only has 21 days available.
The 2 cars need different time with each resource:
| Resource time | Car A | Car B |
|---|---|---|
| Robot | 3 days | 4 days |
| Engineer | 5 days | 6 days |
| Detailer | 1.5 days | 3 days |
Car A provides $30,000 profit, whilst Car B offers $45,000 profit. At the moment, they produce 4 of each car per month, for $300,000 profit. Not bad at all, but we think we can do better for them.
## (0.0, 25.0)
## (0.0, 11.0)
max_z <- c(30000,45000)
LHS <- matrix(c(3,4,
5,6,
1.5,3)
,ncol=2, byrow=TRUE)
arah_kendala <- c("<=","<=","<=")
RHS <- c(30,60,21)
# Penyelesaian
model <- lp ("max",
max_z,
LHS,
arah_kendala,
RHS,
compute.sens = TRUE)
print(model)## Success: the objective function is 330000
model$solution## [1] 2 6
p1 <- plotPolytope(
LHS,
RHS,
max_z,
type = rep("c", ncol(LHS)),
crit = "max",
faces = rep("c", ncol(LHS)),
plotFaces = TRUE,
plotFeasible = TRUE,
plotOptimum = FALSE,
labels = NULL
) + ggplot2::ggtitle("Feasible region only")
p1Soal 3
Let say you would like to make some sausages and you have the following ingredients available:
| Ingredient | Cost ($/kg) | Availability (kg) |
|---|---|---|
| Chicken | 4.32 | 30 |
| Wheat | 2.46 | 20 |
| Starch | 1.86 | 17 |
Assume that you will make 2 types of sausage:
- Economy (>40% Chicken)
- Premium (>60% Chicken)
- One sausage is 50 grams (0.05 kg)
According to government regulations of Indonesia:
- The most starch you can use in your sausages is 25%.
- You have a contract with a butcher, and have already purchased 23 kg Chicken, that must go in your sausages.
- You have a demand for 350 economy sausages and 500 premium sausages.
So, please figure out how to optimize the cost effectively to blend your sausages.
model = pulp.LpProblem("Cost minimising blending problem", pulp.LpMinimize)## C:\Users\Lenovo\ANACON~1\envs\py10\lib\site-packages\pulp\pulp.py:1352: UserWarning: Spaces are not permitted in the name. Converted to '_'
## warnings.warn("Spaces are not permitted in the name. Converted to '_'")
sausage_types = ['economy', 'premium']
ingredients = ['chicken','wheat','starch']
ing_weight = pulp.LpVariable.dicts("weight kg",
((i, j) for i in sausage_types for j in ingredients),
lowBound=0,
cat='Continuous')# Objective Function
model += (
pulp.lpSum([
4.32 * ing_weight[(i, 'chicken')]
+ 2.46 * ing_weight[(i, 'wheat')]
+ 1.86 * ing_weight[(i, 'starch')]
for i in sausage_types])
)# Constraints
# 350 economy and 500 premium sausages at 0.05 kg
model += pulp.lpSum([ing_weight['economy', j] for j in ingredients]) == 350 * 0.05
model += pulp.lpSum([ing_weight['premium', j] for j in ingredients]) == 500 * 0.05
# Economy has >= 40% chicken, premium >= 60% chicken
model += ing_weight['economy', 'chicken'] >= (
0.4 * pulp.lpSum([ing_weight['economy', j] for j in ingredients]))
model += ing_weight['premium', 'chicken'] >= (
0.6 * pulp.lpSum([ing_weight['premium', j] for j in ingredients]))
# Sausages must be <= 25% starch
model += ing_weight['economy', 'starch'] <= (
0.25 * pulp.lpSum([ing_weight['economy', j] for j in ingredients]))
model += ing_weight['premium', 'starch'] <= (
0.25 * pulp.lpSum([ing_weight['premium', j] for j in ingredients]))
# We have at most 30 kg of chicken, 20 kg of wheat and 17 kg of starch available
model += pulp.lpSum([ing_weight[i, 'chicken'] for i in sausage_types]) <= 30
model += pulp.lpSum([ing_weight[i, 'wheat'] for i in sausage_types]) <= 20
model += pulp.lpSum([ing_weight[i, 'starch'] for i in sausage_types]) <= 17
# We have at least 23 kg of chicken to use up
model += pulp.lpSum([ing_weight[i, 'chicken'] for i in sausage_types]) >= 23# Solve our problem
model.solve()## 1
pulp.LpStatus[model.status]## 'Optimal'
for var in ing_weight:
var_value = ing_weight[var].varValue
print ("The weight of {0} in {1} sausages is {2} kg".format(var[1], var[0], var_value))## The weight of chicken in economy sausages is 7.0 kg
## The weight of wheat in economy sausages is 6.125 kg
## The weight of starch in economy sausages is 4.375 kg
## The weight of chicken in premium sausages is 16.0 kg
## The weight of wheat in premium sausages is 2.75 kg
## The weight of starch in premium sausages is 6.25 kg
total_cost = pulp.value(model.objective)
print ("The total cost is €{} for 350 economy sausages and 500 premium sausages".format(round(total_cost, 2)))## The total cost is €140.96 for 350 economy sausages and 500 premium sausages
Soal 4
Please visualize a contour plot of the following function:
\[f(x,y)=x^2+y^2+3xy\]
How coordinate descent works
f <- function(x, y) {
x^2 + y^2 + 3* x * y
}
n <- 30
xpts <- seq(-1.5, 1.5, len = n)
ypts <- seq(-1.5, 1.5, len = n)
gr <- expand.grid(x = xpts, y = ypts)
feval <- with(gr, matrix(f(x, y), nrow = n, ncol = n))
par(mar = c(5, 4, 1, 1))
contour(xpts, ypts, feval, nlevels = 20, xlab = "x", ylab = "y")
points(-1, -1, pch = 19, cex = 2)
abline(h = -1)How Steepest descent works
def f(x):
return x[0]**2 + x[1]**2 + 3* x[0] * x[1]
def df(x):
return np.array([2*x[0]+3*x[1], 3*x[0]+2*x[1]])fig = plt.figure()
ax = fig.add_subplot(projection='3d')
xmesh, ymesh = np.mgrid[-2:2:50j,-2:2:50j]
fmesh = f(np.array([xmesh, ymesh]))
ax.plot_surface(xmesh, ymesh, fmesh)How Newton Method worksx
def Newton_Raphson_Optimize(Grad, Hess, x,y, epsilon=0.000001, nMax = 200):
#Initialization
i = 0
iter_x, iter_y, iter_count = np.empty(0),np.empty(0), np.empty(0)
error = 10
X = np.array([x,y])
#Looping as long as error is greater than epsilon
while np.linalg.norm(error) > epsilon and i < nMax:
i +=1
iter_x = np.append(iter_x,x)
iter_y = np.append(iter_y,y)
iter_count = np.append(iter_count ,i)
print(X)
X_prev = X
X = X - np.linalg.inv(Hess(x,y)) @ Grad(x,y)
error = X - X_prev
x,y = X[0], X[1]
return X, iter_x,iter_y, iter_count
def f_2(x,y):
return x**2 + y**2 + 3*x*y
def Grad_f_2(x,y):
g1 = 2*x+3*y
g2 = 3*x+2*y
return np.array([g1,g2])
def Hessian_f_2(x,y):
return np.array([[.02,0],[0,-.2]])
root_nr,iter_x_nr,iter_y_nr, iter_count_nr = Newton_Raphson_Optimize(Grad_f_2,Hessian_f_2,-2,-.01, nMax = 25)## [-2. -0.01]
## [199.5 -30.11]
## [-15234. 2661.29]
## [1108972.5 -199235.81]
## [-79902906. 14442993.59]
## [ 5.74393866e+09 -1.03967066e+09]
## [-4.12699328e+11 7.47227026e+10]
## [ 2.96488281e+13 -5.36854019e+12]
## [-2.12995295e+15 3.85678479e+14]
## [ 1.5301357e+17 -2.7706831e+16]
## [-1.09923188e+19 1.99042841e+18]
## [ 7.8967530e+20 -1.4299007e+20]
## [-5.67293443e+22 1.02722387e+22]
## [ 4.07536927e+24 -7.37945538e+23]
## [-2.92769727e+26 5.30131382e+25]
## [ 2.10322323e+28 -3.80840139e+27]
## [-1.51093079e+30 2.73591069e+29]
## [ 1.08543488e+32 -1.96544600e+31]
## [-7.79763626e+33 1.41195325e+33]
## [ 5.60173002e+35 -1.01433058e+35]
## [-4.02421685e+37 7.28683139e+36]
## [ 2.89094997e+39 -5.23477382e+38]
## [-2.07682440e+41 3.76059984e+40]
## [ 1.49196618e+43 -2.70157061e+42]
## [-1.07181092e+45 1.94077650e+44]
x = np.linspace(-3,3,100)
y = np.linspace(-1,1,100)
X, Y = np.meshgrid(x, y)
Z = f_2(X, Y)
#Angles needed for quiver plot
anglesx_nr = iter_x_nr[1:] - iter_x_nr[:-1]
anglesy_nr = iter_y_nr[1:] - iter_y_nr[:-1]
fig = plt.figure(figsize = (16,8))
#Surface plot
ax = fig.add_subplot(1, 2, 1, projection='3d')
ax.plot_surface(X,Y,Z,rstride = 5, cstride = 5, cmap = 'jet', alpha = .4, edgecolor = 'none' )
ax.plot(iter_x_nr,iter_y_nr, f_2(iter_x_nr,iter_y_nr),color = 'darkblue', marker = 'o', alpha = .4, label = 'Newton')
ax.legend()
#Rotate the initialization to help viewing the graph
#ax.view_init(45, 280)
ax.set_xlabel('x')
ax.set_ylabel('y')
#Contour plot
ax = fig.add_subplot(1, 2, 2)
ax.contour(X,Y,Z, 60, cmap = 'jet')
#Plotting the iterations and intermediate values## <matplotlib.contour.QuadContourSet object at 0x000001C4BF275B10>
ax.scatter(iter_x_nr,iter_y_nr,color = 'darkblue', marker = 'o', label = 'Newton')
ax.quiver(iter_x_nr[:-1], iter_y_nr[:-1], anglesx_nr, anglesy_nr, scale_units = 'xy', angles = 'xy', scale = 1, color = 'darkblue', alpha = .3)
ax.legend()
ax.set_title('Newton Method')
plt.show()How Conjugate Gradient works
def f(x1, x2):
return x1**2 + x2**22 + 3* x1 * x2def gradient(x1, x2):
return np.array([2*x1+3*x2, 3*x1+2*x2])
def norm(matrice_1x2):
n_line = matrice_1x2.shape[0]
N = 0
for i in range(n_line):
N += matrice_1x2[i]**2
return math.sqrt(N)x1, x2 = 50,50
t = 0.1
epsilon = pow(10,-6)
grad_f = gradient(x1, x2)
n_grad = norm(grad_f)
i = 1
evolution_X1_X2 = [[x1, x2]]
while n_grad > epsilon:
direction = -grad_f
x1, x2 = x1 + t*direction[0], x2 + t*direction[1]
evolution_X1_X2 = np.vstack((evolution_X1_X2, [x1, x2]))
grad_f = gradient(x1, x2)
n_grad = norm(grad_f)
i +=1
evolution_X1 = evolution_X1_X2[:, 0]
evolution_X2 = evolution_X1_X2[:, 1]x1 = np.linspace(2, 3.5, 150)
x2 = np.linspace(0.25, 1.75, 150)
X1, X2 = np.meshgrid(x1, x2)
Z = f(X1, X2)
fig = plt.figure(figsize = (10,7))
contours = plt.contour(X1, X2, Z, 20)
plt.clabel(contours, inline = True, fontsize = 10)
plt.title("Evolution of the cost function during gradient descent with level circles", fontsize=15)
plt.plot(evolution_X1, evolution_X2)
plt.plot(evolution_X1, evolution_X2, '*', label = "Cost function")
plt.xlabel('x1', fontsize=11)
plt.ylabel('x2', fontsize=11)
plt.colorbar()## <matplotlib.colorbar.Colorbar object at 0x000001C4C9DFAB30>
plt.legend(loc = "upper right")
plt.show()