12/10/16 643 Almaty, Kazakhstan
|
Последний раз редактировалось Soul Friend 07.01.2025, 23:07, всего редактировалось 3 раз(а).
mihaildСкормил ваш код в ChatGPT, теперь выводит результат в localhost через streamlit в 3D : 7 вершин посчитал быстро, а вот при расчете 8-ми вершин думал несколько минут. 3D он выводит быстро, а вот вывод в 2D тормозит и занимает время. И вариантов могут быть несколько. У меня для 6 вершин с весом 9 получился другой граф. (Код)
Код: import streamlit as st import networkx as nx import numpy as np from ortools.linear_solver import pywraplp import plotly.graph_objects as go import matplotlib.pyplot as plt
def calculate_and_draw(N): # Создание оптимизационной задачи solver = pywraplp.Solver.CreateSolver("SAT")
# Переменные путей paths = { (i, j, p): solver.IntVar(0, 1, f"path{p}_{i}_{j}") for p in range(1, 4) for i in range(N) for j in range(N) if i != j }
# Переменные для путей через вершину k ptk = {} for i in range(N): for j in range(N): if i != j: for p in [2, 3]: path_through_k = { k: solver.IntVar(0, 1, f"path{p}_{i}_{k}_{j}") for k in range(N) if k not in [i, j] } ptk[(i, j, p)] = path_through_k
# Добавляем ограничения for k, v in path_through_k.items(): solver.Add(paths[(i, k, p - 1)] + paths[(k, j, 1)] >= 2 * v) solver.Add( paths[(i, j, p)] <= sum(v for k, v in path_through_k.items()) + paths[(i, j, p - 1)] )
solver.Add(1 <= paths[(i, j, 3)])
# Целевая функция: минимизация количества рёбер solver.Minimize( sum(paths[(i, j, 1)] for i in range(N) for j in range(N) if i != j) )
# Решение задачи status = solver.Solve() if status != pywraplp.Solver.OPTIMAL: st.error("Не удалось найти оптимальное решение.") return
# Вывод минимального веса min_weight = solver.Objective().Value() st.write(f"Минимальный вес: {min_weight}")
# Построение графа на основе решения G = nx.DiGraph()
# Добавляем вершины for i in range(N): G.add_node(i)
# Списки рёбер для графики edges_oriented = [] edges_bidirectional = []
# Добавляем рёбра for i in range(N): for j in range(N): if i != j: # Ориентированные рёбра if paths[(i, j, 1)].solution_value() == 1: G.add_edge(i, j) edges_oriented.append((i, j)) # Неориентированные рёбра (учитываем два направления) if paths.get((i, j, 1)) and paths.get((j, i, 1)): if paths[(i, j, 1)].solution_value() == 1 and paths[(j, i, 1)].solution_value() == 1: if (j, i) not in edges_bidirectional: edges_bidirectional.append((i, j))
# Генерация координат для вершин pos = { i: ( np.cos(2 * np.pi * i / N), np.sin(2 * np.pi * i / N), 0.5 * (i % 2), ) for i in range(N) }
# 3D график с использованием Plotly fig = go.Figure()
# Отображение ориентированных рёбер (синим цветом с стрелками) for edge in edges_oriented: x = [pos[edge[0]][0], pos[edge[1]][0]] y = [pos[edge[0]][1], pos[edge[1]][1]] z = [pos[edge[0]][2], pos[edge[1]][2]] fig.add_trace(go.Scatter3d( x=x, y=y, z=z, mode='lines+text', line=dict(color='blue', width=4), text=[f"{edge[0]} → {edge[1]}"], textposition="top center" ))
# Отображение неориентированных рёбер (зелёным цветом) for edge in edges_bidirectional: x = [pos[edge[0]][0], pos[edge[1]][0]] y = [pos[edge[0]][1], pos[edge[1]][1]] z = [pos[edge[0]][2], pos[edge[1]][2]] fig.add_trace(go.Scatter3d( x=x, y=y, z=z, mode='lines+text', line=dict(color='green', width=4), text=[f"{edge[0]} ↔ {edge[1]}"], textposition="top center" ))
# Отображение вершин for node, (x, y, z) in pos.items(): fig.add_trace(go.Scatter3d( x=[x], y=[y], z=[z], mode='markers+text', marker=dict(size=10, color='red'), text=[str(node)], textposition="bottom center" ))
fig.update_layout( title="Минимальный граф с радиусом ≤ 3", scene=dict( xaxis_title='X', yaxis_title='Y', zaxis_title='Z' ), showlegend=False )
# Отображение интерактивного 3D графика st.plotly_chart(fig)
# 2D график с использованием NetworkX fig_2d, ax = plt.subplots(figsize=(8, 6))
# Попробуем использовать стандартное положение для рёбер pos_2d = nx.circular_layout(G) # Используем круговую раскладку для 2D
# Построение 2D-графика nx.draw(G, pos_2d, with_labels=True, node_size=500, node_color='red', font_size=16, font_color='white', edge_color='blue', width=2, arrows=True)
# Отображение 2D графика st.pyplot(fig_2d)
# Интерфейс Streamlit st.title("Минимизация веса графа с ограничениями")
# Поле для ввода количества вершин N = st.number_input("Введите количество вершин (N)", min_value=2, step=1)
# Кнопка для расчета if st.button("Рассчитать"): calculate_and_draw(N)
|
|