Алгоритм поиска всех последовательностей матрицы смежности через Depth First Search (DFS)
This commit is contained in:
parent
c1e7882cbb
commit
ea742b26d7
2 changed files with 126 additions and 14 deletions
|
@ -1,4 +1,4 @@
|
|||
{
|
||||
"cadFilePath":"",
|
||||
"outPath":""
|
||||
"cadFilePath":"/home/idontsudo/framework/geometric_feasibility_predicate/cubes.FCStd",
|
||||
"outPath":"/home/idontsudo/framework/geometric_feasibility_predicate/out/"
|
||||
}
|
|
@ -1,11 +1,112 @@
|
|||
# Алгоритм генерации графа И/ИЛИ c помощью вычисления матрицы смежности
|
||||
import FreeCAD as App
|
||||
import uuid
|
||||
import os
|
||||
import json
|
||||
from typing import List, Dict, Any, TypeVar, Callable, Type, cast
|
||||
from itertools import repeat
|
||||
|
||||
|
||||
def isInListRange(listIn, index):
|
||||
try:
|
||||
listIn[index]
|
||||
return False
|
||||
except:
|
||||
return True
|
||||
|
||||
|
||||
class AllSequences:
|
||||
all_sequences = None
|
||||
adj_matrix = None
|
||||
topologyIds = None
|
||||
adj_matrix_names = None
|
||||
|
||||
def __init__(self, adj_matrix) -> None:
|
||||
self.adj_matrix = adj_matrix
|
||||
self.all_possible_sequences(self.adj_matrix)
|
||||
self.matrix_by_name()
|
||||
pass
|
||||
|
||||
def matrix_by_name(self):
|
||||
result = self.all_sequences
|
||||
inc = 0
|
||||
for matrix in self.all_sequences:
|
||||
for index in range(len(matrix)):
|
||||
result[inc][index] = list(filter(lambda el: el.get(
|
||||
'number') == matrix[index]+1, self.topologyIds))[0].get('name')
|
||||
inc += 1
|
||||
self.adj_matrix_names = result
|
||||
pass
|
||||
|
||||
def find_all_sequences(self, adj_matrix):
|
||||
sequences = []
|
||||
num_vertices = len(adj_matrix)
|
||||
|
||||
def dfs(vertex, sequence):
|
||||
sequence.append(vertex)
|
||||
|
||||
if len(sequence) == num_vertices:
|
||||
sequences.append(sequence)
|
||||
return
|
||||
|
||||
for i in range(num_vertices):
|
||||
if adj_matrix[vertex][i] == 1 and i not in sequence:
|
||||
dfs(i, sequence.copy())
|
||||
|
||||
for i in range(num_vertices):
|
||||
dfs(i, [])
|
||||
|
||||
self.all_sequences = sequences
|
||||
|
||||
def findId(self, listMatrix, id):
|
||||
def filter_odd_num(in_num):
|
||||
if in_num['name'] == id:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
return list(filter(filter_odd_num, listMatrix))[0]['number']
|
||||
|
||||
def iter_paths(self, adj, min_length=6, path=None):
|
||||
if not path:
|
||||
for start_node in range(len(adj)):
|
||||
yield from self.iter_paths(adj, min_length, [start_node])
|
||||
else:
|
||||
if len(path) >= min_length:
|
||||
yield path
|
||||
if path[-1] in path[:-1]:
|
||||
return
|
||||
current_node = path[-1]
|
||||
for next_node in range(len(adj[current_node])):
|
||||
if adj[current_node][next_node] == 1:
|
||||
yield from self.iter_paths(adj, min_length, path + [next_node])
|
||||
|
||||
def allUnique(self, x):
|
||||
seen = set()
|
||||
return not any(i in seen or seen.add(i) for i in x)
|
||||
|
||||
def all_possible_sequences(self, matrix):
|
||||
topologyIds = []
|
||||
topologyMatrixNumber = {}
|
||||
inc = 0
|
||||
for k, v in matrix.items():
|
||||
inc += 1
|
||||
topologyIds.append({"name": k, "number": inc})
|
||||
inc = 0
|
||||
for k, v in matrix.items():
|
||||
inc += 1
|
||||
topologyMatrixNumber[inc] = list(
|
||||
map(lambda el: self.findId(topologyIds, el), v))
|
||||
self.topologyIds = topologyIds
|
||||
adj = []
|
||||
matrixSize = matrix.keys().__len__()
|
||||
inc = 0
|
||||
for k, v in topologyMatrixNumber.items():
|
||||
adj.append(list(repeat(0, matrixSize)))
|
||||
for el in v:
|
||||
adj[inc][el-1] = 1
|
||||
inc += 1
|
||||
return self.find_all_sequences(adj)
|
||||
|
||||
|
||||
# вспомогательный класс для работы с FreeCad API
|
||||
class FreeCadRepository:
|
||||
_solids = []
|
||||
|
||||
|
@ -59,8 +160,10 @@ def to_class(c: Type[T], x: Any) -> dict:
|
|||
return cast(Any, x).to_dict()
|
||||
|
||||
# Вспомогательный класс который делает генрацию JSON на основе пайтон обьектов
|
||||
|
||||
|
||||
class AdjacencyMatrix:
|
||||
matrixError: Dict[str,str] = {}
|
||||
matrixError: Dict[str, str] = {}
|
||||
all_parts: List[str]
|
||||
first_detail: str
|
||||
matrix: Dict[str, List[str]]
|
||||
|
@ -77,17 +180,19 @@ class AdjacencyMatrix:
|
|||
if el == self.first_detail:
|
||||
return i
|
||||
i = +1
|
||||
|
||||
def validateMatrix(self):
|
||||
for el in self.all_parts:
|
||||
if(self.matrix.get(el) == None):
|
||||
if (self.matrix.get(el) == None):
|
||||
self.matrixError[el] = 'Not found adjacency ' + el
|
||||
|
||||
@staticmethod
|
||||
def from_dict(obj: Any) -> 'AdjacencyMatrix':
|
||||
assert isinstance(obj, dict)
|
||||
all_pars = from_list(from_str, obj.get("allPars"))
|
||||
first_detail = from_str(obj.get("firstDetail"))
|
||||
matrix = from_dict(lambda x: from_list(from_str, x), obj.get("matrix"))
|
||||
|
||||
|
||||
return AdjacencyMatrix(all_pars, first_detail, matrix)
|
||||
|
||||
def to_dict(self) -> dict:
|
||||
|
@ -96,7 +201,7 @@ class AdjacencyMatrix:
|
|||
result["firstDetail"] = from_str(self.first_detail)
|
||||
result["matrix"] = from_dict(
|
||||
lambda x: from_list(from_str, x), self.matrix)
|
||||
if(self.matrixError.values().__len__() == 0):
|
||||
if (self.matrixError.values().__len__() == 0):
|
||||
result['matrixError'] = None
|
||||
else:
|
||||
result['matrixError'] = self.matrixError
|
||||
|
@ -120,7 +225,9 @@ def adjacency_matrix_from_dict(s: Any) -> AdjacencyMatrix:
|
|||
def adjacency_matrix_to_dict(x: AdjacencyMatrix) -> Any:
|
||||
return to_class(AdjacencyMatrix, x)
|
||||
|
||||
# Вспомогательный класс для работы с Freecad
|
||||
# Вспомогательный класс для работы с Freecad
|
||||
|
||||
|
||||
class FreeCadMetaModel(object):
|
||||
|
||||
def __init__(self, label, vertex) -> None:
|
||||
|
@ -329,7 +436,8 @@ class CadAdjacencyMatrix:
|
|||
first_detail=GetFirstDetailUseCase().call(),
|
||||
matrix=matrix,
|
||||
)
|
||||
# Матрица основанная на соприкосновении обьектов
|
||||
# Матрица основанная на соприкосновении обьектов
|
||||
|
||||
def matrixBySurfaces(self):
|
||||
matrix = {}
|
||||
for part in FreeCadRepository().getAllSolids():
|
||||
|
@ -347,6 +455,7 @@ class CadAdjacencyMatrix:
|
|||
matrix=matrix
|
||||
)
|
||||
|
||||
|
||||
def main():
|
||||
env = FS.readJSON('env.json')
|
||||
cadFile = env['cadFilePath']
|
||||
|
@ -354,12 +463,15 @@ def main():
|
|||
if (cadFile == None):
|
||||
return TypeError('CadFile not found env.json')
|
||||
App.open(u'' + cadFile)
|
||||
|
||||
|
||||
# Получение матрицы
|
||||
matrixOut = CadAdjacencyMatrix().primitiveMatrix().to_dict()
|
||||
topologyMatrix = CadAdjacencyMatrix().primitiveMatrix()
|
||||
import json
|
||||
# Запись результата
|
||||
FS.writeFile(json.dumps(matrixOut, ensure_ascii=False, indent=4), outPath,'out.json')
|
||||
sequences = json.dumps({"sequences": AllSequences(
|
||||
topologyMatrix.matrix).adj_matrix_names}, ensure_ascii=False, indent=4)
|
||||
FS.writeFile(sequences, outPath, 'sequences.json')
|
||||
FS.writeFile(json.dumps(topologyMatrix.to_dict(),
|
||||
ensure_ascii=False, indent=4), outPath, 'adjacency_matrix.json')
|
||||
|
||||
|
||||
main()
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue