Множеството X в контекста на линейното програмиране обикновено се дефинира чрез линейни неравенства от вида: ax_1 + bx_2 \leq c
За да представим графично това множество, първо трябва да начертаем неговата граница – правата линия, дефинирана от уравнението: ax_1 + bx_2 = c
Общ алгоритъм за начертаване Най-бързият начин да начертаем права в координатна система (x_1, x_2) е чрез намиране на пресечните ѝ точки с осите (т.нар. “отрези”):
Пресечна точка с оста x_2 (когато x_1 = 0):x_1 = 0 \implies bx_2 = c \implies x_2 = \frac{c}{b}
Пресечна точка с оста x_1 (когато x_2 = 0):x_2 = 0 \implies ax_1 = c \implies x_1 = \frac{c}{a}
Нека е дадена правата с уравнение 2x_1 + 3x_2 = 6.
Намиране на точка върху ординатата (x_2): Ако приемем x_1 = 0, уравнението става: 3x_2 = 6 \implies x_2 = \frac{6}{3} = 2 Получаваме точка с координати (0, 2).
Намиране на точка върху абсцисата (x_1): Ако приемем x_2 = 0, уравнението става: 2x_1 = 6 \implies x_1 = \frac{6}{2} = 3 Получаваме точка с координати (3, 0).
Графично представяне: Двете точки се отбелязват в координатната система и през тях се прекарва правата линия.
Точка
x_1 (Абсциса)
x_2 (Ордината)
A
0
2
B
3
0
Определяне на полуравнината (Множество X) Тъй като целта е да определим множеството X за неравенството 2x_1 + 3x_2 \leq 6:
Линията: Представлява границата, където стойността е точно 6.
Областта: За да разберем коя страна на правата да защриховаме, тестваме с точката (0,0): 2(0) + 3(0) = 0 \leq 6
Извод: Тъй като 0 \leq 6 е вярно, търсеното множество е полуравнината, която съдържа началото на координатната система.
2.1.2 Построява се нормалния вектор на целевата функция
Какво е нормален вектор?
В геометрията, нормала към даден обект (права или равнина) е обект, който е перпендикулярен на него.
В двумерното пространство (R^2), нормален вектор на дадена права наричаме всеки вектор, който е ортогонален (сключва ъгъл 90°) с нея. Обикновено за удобство го чертаем с начало в координатното начало (0,0).
Математическо определение:
Ако имаме права p, дефинирана с общото уравнение: p: ax_1 + bx_2 - c = 0
Тогава нормалният вектор \vec{n} се състои директно от коефициентите пред x_1 и x_2: \vec{n} = \begin{pmatrix} n_1 \\ n_2 \end{pmatrix} = \begin{pmatrix} a \\ b \end{pmatrix}
Нормалният вектор е най-лесният начин да определим наклона на една права в аналитичната геометрия.
Коефициентите пред променливите в уравнението директно ни дават координатите на този вектор.
Ако две прави имат пропорционални коефициенти пред x_1 и x_2, те са или успоредни, или съвпадат.
2.1.3 Намиране на оптимален план
Свойство 1: Оптималните планове на множеството 𝑋 не могат да бъдат вътрешни точки за множеството. Ако съществуват такива планове, то те са контурни за множеството 𝑋. Контурът на множеството 𝑋 е образуван от части от правите (отсечки), които съответстват на ограниченията. Точката, в която се пресичат две такива прави се нарича опорен план (връх на множеството 𝑋).
Свойство 2: Двумерната задача може да няма решение (оптимален план), може да има един оптимален план или безброй много, които се изобразяват като отсечка или лъч в множеството 𝑋.
2.2 Задача за планиране на производство
Бутиково кафене предлага два вида еспресо: Супер еспресо и Делукс еспресо. За приготвянето на един килограм от първия вид еспресо са необходими по равни части арабика и робуста, а рецептата за Делукс предвижда смес от арабика и робуста в пропорция 1 към 3. Доставчиците са готови да осигурят 120 кг арабика и 160 кг. робуста. Заведението знае, че няма да може да продаде повече от 150 кг. Делукс еспресо. От всеки продаден килограм Супер еспресо заведението печели 40 EUR, докато печалбата от килограм Делукс възлиза на 50 EUR.
Колко от двата типа еспресо ще препоръчате на кафенето да произведе, за да максимизира печалбата си?
Права търсене на Делукс: (0, 150), (100, 150) Тази права е успоредна на оста x_1.
Покажи
from IPython.display import displayimport matplotlib.pyplot as pltimport numpy as npfrom plotly import graph_objects as gofig, ax = plt.subplots()ax.plot([0, 240], [480, 0], label=r"$0.5 x_1 + 0.25 x_2 = 120$(арабика)")ax.plot([0, 320], [213.33, 0], label=r"$0.5 x_1 + 0.75 x_2 = 160$(робуста)")ax.plot([0, 400], [150, 150], label=r"$x_2 = 150$(търсене на Делукс)")ax.set_xlim((0, 400))ax.set_ylim((0, 500))ax.set_xlabel(r'$x_1$(Супер, кг.)')ax.set_ylabel(r'$x_2$(Делукс, кг.)')ax.legend(loc=0)
Фигура 2.1: Прави на трите ограничения
Покажи
vertices = [ [0, 0], [0, 150], [95, 150], [200, 80], [240, 0]]vertices_x = [v[0] for v in vertices]vertices_y = [v[1] for v in vertices]for v in vertices: ax.annotate(f"({v[0]}, {v[1]})", (v[0], v[1]), textcoords="offset points", xytext=(0, 5) )ax.fill(vertices_x, vertices_y, color='grey', alpha=0.3)display(fig)
Фигура 2.2: Допустимо множество
Целева функция и оптимален план
За да определим оптималния план графично ще начертаем прави, съответстващи на различни нива на печалба.
Целевата функция зависи от две променливи, което означава, че за да я изобразим графично ще трябва да използваме трето измерение.
Покажи
# Create a 3d scatter plot for the vertices of the feasible region with plotlyfig = go.Figure(data=[go.Scatter3d( x=vertices_x, y=vertices_y, z=[0] *len(vertices_x), mode='markers+text', marker=dict(size=2, color='red'), text=[f"({v[0]}, {v[1]}, 0)"for v in vertices], textposition="top center")])# Draw lines connecting the verticesfor i inrange(len(vertices)): x_line = [vertices[i][0], vertices[(i +1) %len(vertices)][0]] y_line = [vertices[i][1], vertices[(i +1) %len(vertices)][1]] z_line = [0, 0] fig.add_trace(go.Scatter3d( x=x_line, y=y_line, z=z_line, mode='lines', line=dict(color='blue', width=2) ))fig.update_layout( title="Целевата функция на проблема с кафето", scene=dict( xaxis_title=r"Super (kg)", yaxis_title=r"Deluxe (kg)", zaxis_title=r"Печалба (Euro)", zaxis=dict(range=[0, 12000]), aspectmode='cube' ), showlegend=False)# Draw the plane of the objective functionX1 = np.linspace(0, 250, 20)X2 = np.linspace(0, 250, 20)X1, X2 = np.meshgrid(X1, X2)Z =40* X1 +50* X2fig.add_trace(go.Surface( x=X1, y=X2, z=Z, opacity=0.5, colorscale='Viridis'))# Draw a plane at level z = 6000z_plane_1 =6000fig.add_trace(go.Surface( x=X1, y=X2, z=np.full(X1.shape, z_plane_1), opacity=0.2, colorscale='Viridis', showscale=False))# Draw a line at the intersection of the objective plane and the z = 10000 planeintersection_x_1 = np.linspace(0, 250, 20)intersection_y_1 = (z_plane_1 -40* intersection_x_1) /50fig.add_trace(go.Scatter3d( x=intersection_x_1, y=intersection_y_1, z=[z_plane_1] *len(intersection_x_1), mode='lines', opacity=0.4, line=dict(color='red', width=3), name='Intersection'))# Draw the intersection line on the xy planefig.add_trace(go.Scatter3d( x=intersection_x_1, y=intersection_y_1, z=[0] *len(intersection_x_1), mode='lines', opacity=0.4, line=dict(color='red', width=2), name='Intersection'))fig.update_layout( title="Целева функция", scene=dict( xaxis_title=r"Super (kg)", yaxis_title=r"Deluxe (kg)", zaxis_title=r"Gewinn (Euro)", zaxis=dict(range=[0, 13000]), yaxis=dict(range=[0, 250]), xaxis=dict(range=[0, 250]), aspectmode='cube' ), showlegend=False)# Draw a plane at the optimal solution z = 12000z_plane_2 =12000fig.add_trace(go.Surface( x=X1, y=X2, z=np.full(X1.shape, z_plane_2), opacity=0.2, colorscale='Viridis', showscale=False))intersection_x = np.linspace(0, 250, 20)intersection_y = (z_plane_2 -40* intersection_x) /50# Draw the intersection line on the xy planefig.add_trace(go.Scatter3d( x=intersection_x, y=intersection_y, z=[z_plane_2] *len(intersection_x), mode='lines', opacity=0.4, line=dict(color='red', width=3), name='Intersection'))fig.add_trace(go.Scatter3d( x=intersection_x, y=intersection_y, z=[0] *len(intersection_x), mode='lines', opacity=0.4, line=dict(color='red', width=3), name='Intersection'))fig.show()
Фигура 2.3: Die Gewinnfunktion, die zulässige Menge und Isolinien des Gewinns bei 6000 und 12000 Euro.
Нека да начертаем тези прави на графиката на допустимото множество. Фигура 2.4 показва графиката на допустимото множество и правите на печалбата от 3000 лв., 50000 лв. и 12000 лв.
Управителят на компания иска да определи какво количество от двата продукта на компанията да произведе за определен период, така че да осигури максимална печалба.
В таблицата са посочени общия брой работни часове, с които разполага всеки отдел, и часовете, нужни за производството на всеки продукт:
Отдел
Продукт 1 (раб. часове за 1 бр.)
Продукт 2 (раб. часове за 1 бр.)
Общ брой налични работни часове
A
1.00
0.35
100
Б
0.30
0.20
36
В
0.20
0.50
50
Печалба за единица
30.00 euro
15.00 euro
-
Съставяне на математическия модел
Първата стъпка е да дефинираме променливите, целта и ограниченията на базата на таблицата.
Неизвестни:
x_1 - количество от Продукт 1
x_2 - количество от Продукт 2
Целева функция (Максимизиране на печалбата):z(x) = 30x_1 + 15x_2 \rightarrow \max
Ограничения (спрямо наличните часове):
Отдел А: x_1 + 0.35x_2 \leq 100
Отдел Б: 0.3x_1 + 0.2x_2 \leq 36
Отдел В: 0.2x_1 + 0.5x_2 \leq 50
Неотрицателност на неизвестните: x_1 \geq 0, x_2 \geq 0
Опростяване на модела и намиране на координати
За по-лесно пресмятане, умножаваме ограниченията за отделите по 10, за да премахнем десетичните дроби. Получаваме следната система:
Намираме пресечните точки (отрезите) на правите с координатните оси, за да дефинираме границите на множеството:
Права p_1: (100, 0) ; (0, 285.71)
Права p_2: (120, 0) ; (0, 180)
Права p_3: (250, 0) ; (0, 100)
Намиране на оптималния план
Точката, в която се намира оптималният план, е пресечната точка на правите p_1 и p_2. Нека я наречем точка A.
т. A = p_1 \cap p_2
За да намерим точните координати на т. A, решаваме системата уравнения, съставена от двете прави: 10x_1 + 3.5x_2 = 10003x_1 + 2x_2 = 360
Решението на системата ни дава координатите на оптималния план: x_1 = 77.89, \quad x_2 = 63.157 \implies \text{т. } A = (77.89, 63.157)
Намираме стойността на целевата функция в т. A: Заместваме получените координати в целевата функция z(x): z(A) = 30x_1 + 15x_2 = 30 \cdot 77.89 + 15 \cdot 63.157 = 3284.1
Предприятие произвежда два вида боя: екстериорна (за външни повърхности) и интериорна (за вътрешни помещения). Производството двете бои изисква три суровини: разтворител, багрило и смола. За производство на един тон екстериорна боя са нужни 6 тона разтворител, един тон багрило и 2 тона смола. За производство на един тон интериорна боя са нужни 4 тона разтворител, 2 тона багрило и 7 тона смола. На разположение са следните количества суровини: 24 тона разтворител, 6 тона багрило и 4 тона смола. Колко тона от всяка боя да произведе предприятието, за да постигне максимална печалба? От продажбата на един тон екстериорна боя предприятието печели 5 000 лв., а от продажбата на един тон интериорна боя - 4 000 лв.
Таблица 2.1: Консумация на материали за производството на интериорна и екстериорна боя и печалба за продаден тон
Екстериорна боя
Интериорна боя
Дневна наличност на ресурс
Разтворител
6
4
24
Багрило
1
2
6
Смола
2
7
4
Печалба (1 000 лв./тон)
5
4
Съставете математически модел, който да намери оптималния план за производство на боите.
БележкаМатематически модел
Целеви променливи:
\begin{align*}
& x_1: \text{ Екстериорна боя (тонове)}\\
& x_2: \text{ Интериорна боя (тонове)}
\end{align*}
Restricted license - for non-production use only - expires 2027-11-29
Set parameter LogToConsole to value 0
Optimal solution: p_exterior = 2.0, p_interior = 0.0