Генерация последовательностей сборки через кластеризацию и оптимизацию
This commit is contained in:
parent
deee7b4329
commit
862a61b1e7
3 changed files with 141 additions and 20 deletions
|
@ -0,0 +1,82 @@
|
|||
import networkx as nx
|
||||
|
||||
|
||||
class GraphProcessor:
|
||||
graph = None
|
||||
|
||||
def __init__(self, adjacency_matrix):
|
||||
self.adjacency_matrix = adjacency_matrix
|
||||
self.graph = self.load_graph_from_data()
|
||||
|
||||
def load_graph_from_data(self):
|
||||
G = nx.Graph()
|
||||
|
||||
for part1, neighbors in self.adjacency_matrix.items():
|
||||
for neighbor in neighbors:
|
||||
G.add_edge(part1, neighbor)
|
||||
|
||||
return G
|
||||
|
||||
|
||||
class EdgeBetweensClustering:
|
||||
def __init__(self, graph):
|
||||
self.graph = graph.copy()
|
||||
self.clusters = []
|
||||
|
||||
def cluster(self):
|
||||
while self.graph.number_of_edges() > 0:
|
||||
edge_betweens = nx.edge_betweenness_centrality(self.graph)
|
||||
max_betweens_edge = max(edge_betweens, key=edge_betweens.get)
|
||||
self.graph.remove_edge(*max_betweens_edge)
|
||||
components = list(nx.connected_components(self.graph))
|
||||
if components not in self.clusters:
|
||||
self.clusters.append(components)
|
||||
return []
|
||||
|
||||
def get_clusters(self):
|
||||
return self.clusters
|
||||
|
||||
|
||||
class ClusterisationSequenceUseCase:
|
||||
def call(self, adjacency_matrix):
|
||||
graph_processor = GraphProcessor(adjacency_matrix)
|
||||
G = graph_processor.load_graph_from_data()
|
||||
ebc = EdgeBetweensClustering(G)
|
||||
ebc.cluster()
|
||||
clusters = ebc.get_clusters()
|
||||
|
||||
for i in range(len(clusters)):
|
||||
for j in range(len(clusters[i])):
|
||||
clusters[i][j] = list(clusters[i][j])
|
||||
|
||||
# Создание списка последовательностей сборки
|
||||
assembly_sequences = []
|
||||
for cluster in clusters:
|
||||
sequence = []
|
||||
for component in cluster:
|
||||
sequence.extend(component)
|
||||
assembly_sequences.append(sequence)
|
||||
|
||||
return assembly_sequences
|
||||
|
||||
|
||||
# # Вызов функции
|
||||
# adjacency_matrix = {
|
||||
# 'body_down': ['sol_gear', 'planet_gear', 'planet_gear003', 'planet_gear004', 'planet_gear005', 'planet_gear002', 'body_up', 'bolt', 'bolt2', 'bolt3', 'bolt4'],
|
||||
# 'sol_gear': ['body_down', 'output_shaft', 'planet_gear', 'planet_gear003', 'planet_gear004', 'planet_gear005', 'planet_gear002'],
|
||||
# 'output_shaft': ['sol_gear', 'planet_gear', 'planet_gear003', 'planet_gear004', 'planet_gear005', 'planet_gear002', 'body_up'],
|
||||
# 'planet_gear': ['body_down', 'sol_gear', 'output_shaft'],
|
||||
# 'planet_gear003': ['body_down', 'sol_gear', 'output_shaft'],
|
||||
# 'planet_gear004': ['body_down', 'sol_gear', 'output_shaft'],
|
||||
# 'planet_gear005': ['body_down', 'sol_gear', 'output_shaft'],
|
||||
# 'planet_gear002': ['body_down', 'sol_gear', 'output_shaft'],
|
||||
# 'body_up': ['body_down', 'output_shaft', 'bolt', 'bolt2', 'bolt3', 'bolt4'],
|
||||
# 'bolt': ['body_down', 'body_up'],
|
||||
# 'bolt2': ['body_down', 'body_up'],
|
||||
# 'bolt3': ['body_down', 'body_up'],
|
||||
# 'bolt4': ['body_down', 'body_up']
|
||||
# }
|
||||
# print(adjacency_matrix)
|
||||
# use_case = ClusterisationSequenceUseCase()
|
||||
# assembly_sequences = use_case.call(adjacency_matrix)
|
||||
# print(assembly_sequences)
|
|
@ -7,6 +7,7 @@ import json
|
|||
import FreeCAD as App
|
||||
from geometric_feasibility_predicate.main import main as asm_analysis
|
||||
from constraints_operator import collect_assembly_settings
|
||||
from clusterisation_sequences import ClusterisationSequenceUseCase
|
||||
|
||||
|
||||
# === Для работы с json-файлами. Работает. ===
|
||||
|
@ -94,42 +95,80 @@ def simplify_adjacency_matrix(assembly_settings, adjacency_matrix):
|
|||
}
|
||||
|
||||
for part in adjacency_matrix["allParts"]:
|
||||
if part not in fasteners:
|
||||
simplified_matrix["allParts"].append(part)
|
||||
neighbors = [
|
||||
neighbor for neighbor in adjacency_matrix["matrix"].get(part, [])
|
||||
if neighbor not in fasteners
|
||||
]
|
||||
if neighbors or part not in fasteners:
|
||||
simplified_matrix["matrix"][part] = neighbors
|
||||
# Добавляем все детали, включая крепеж, в simplified_matrix["allParts"]
|
||||
simplified_matrix["allParts"].append(part)
|
||||
|
||||
# Получаем соседей, исключая только крепежные элементы
|
||||
neighbors = [
|
||||
neighbor for neighbor in adjacency_matrix["matrix"].get(part, [])
|
||||
if neighbor not in fasteners
|
||||
]
|
||||
|
||||
# Если у части есть соседи, добавляем их в матрицу
|
||||
if neighbors:
|
||||
simplified_matrix["matrix"][part] = neighbors
|
||||
|
||||
return simplified_matrix
|
||||
|
||||
def restore_full_sequence(assembly_settings, sequence):
|
||||
full_sequence = []
|
||||
sequence_set = set(sequence)
|
||||
|
||||
for item in sequence:
|
||||
full_sequence.append(item)
|
||||
def restore_full_sequence(assembly_settings, sequences):
|
||||
full_sequences = []
|
||||
|
||||
for sequence in sequences:
|
||||
full_sequence = []
|
||||
sequence_set = set(sequence)
|
||||
|
||||
# Сначала добавляем все детали в полную последовательность
|
||||
for item in sequence:
|
||||
full_sequence.append(item)
|
||||
|
||||
# Теперь добавляем крепежные элементы после элемента с наибольшим порядковым номером
|
||||
for setting in assembly_settings:
|
||||
if setting.get("Type") == "fastener_set":
|
||||
parent = setting["Parent"]
|
||||
child = setting["Child"]
|
||||
if parent in sequence_set and child in sequence_set:
|
||||
full_sequence.append(setting["Fasteners"])
|
||||
fasteners = setting["Fasteners"]
|
||||
|
||||
# Проверяем, если родитель и ребенок в последовательности
|
||||
if (parent in sequence_set) and (child in sequence_set):
|
||||
# Находим индексы родителя и ребенка в полной последовательности
|
||||
parent_index = full_sequence.index(parent)
|
||||
child_index = full_sequence.index(child)
|
||||
|
||||
# Находим максимальный индекс между родителем и ребенком
|
||||
max_index = max(parent_index, child_index)
|
||||
|
||||
# Проверяем, содержатся ли крепежные элементы уже в последовательности
|
||||
if not any(fastener in full_sequence for fastener in fasteners):
|
||||
# Добавляем крепежные элементы после элемента child
|
||||
full_sequence[max_index + 1:max_index + 1] = fasteners
|
||||
|
||||
full_sequences.append(full_sequence)
|
||||
|
||||
return full_sequences
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
return full_sequence
|
||||
|
||||
|
||||
def main():
|
||||
|
||||
|
||||
App.open('/home/markvoltov/GitProjects/framework/test_models/test_reductor.FCStd')
|
||||
if App.ActiveDocument:
|
||||
intersection_geometry, sequences, topologyMatrix = asm_analysis()
|
||||
print(sequences)
|
||||
assembly_settings = collect_assembly_settings()
|
||||
|
||||
assembly_settings = collect_assembly_settings()
|
||||
print(assembly_settings)
|
||||
simplified_matrix = simplify_adjacency_matrix(assembly_settings, topologyMatrix)
|
||||
|
||||
|
||||
assembly_sequences = ClusterisationSequenceUseCase().call(topologyMatrix['matrix'])
|
||||
# print('Последовательности 1', assembly_sequences)
|
||||
assembly_sequences_simplified= ClusterisationSequenceUseCase().call(simplified_matrix['matrix'])
|
||||
# print('Последовательности 2',assembly_sequences_simplified)
|
||||
assembly_sequences_restored = restore_full_sequence(assembly_settings, assembly_sequences_simplified)
|
||||
print('Последовательности 3',assembly_sequences_restored)
|
||||
else:
|
||||
print('Ошибка. Нет активного документа!')
|
||||
|
||||
|
|
Binary file not shown.
Loading…
Add table
Add a link
Reference in a new issue