특정 N 길이 서브 세트를 확장 할 수없는 것으로 입증 된 모든 문서 식별 코드를 기록하면 더 나은 결과를 얻을 수 있습니다 (N + 1 길이의 서브 세트를 사용하지 않는 것이 좋습니다) . 이것은 가지 치기/최적화의 두 번째 레벨로 시도해 볼 가치가 있습니다.
추가 정리 작업이 필요할 수도 있지만 더 많은 가지 치기 작업을 수행 할 수는 있지만 즉시 마음에 들지는 않습니다. 그래서 여기부터 시작하겠습니다. (가독성을 위해 items
대신 iteritems
, tuple
등의 frozenset
대신 마이크로 옵티 마이 제이션을 사용하는 것을 신경 쓰지는 않습니다. 모든 시퀀스가 계산 된 구조의 지수 크기 인 O(N)
과 비교할 때 거의 중요하지 않습니다. 물론 튜닝/최적화 단계에서 시도해 볼 가치는 있지만).
def allfeasiblesubsets(matrix):
mapping = makemap(matrix)
docids = sorted(mapping.keys())
feasible_len2 = {}
dont_bother = dict((d, set([d])) for d in docids)
for d1, d2 in itertools.combinations(docids, 2):
commonw = mapping[d1].intersection(mapping[d2])
if len(commonw) >= 2:
feasible_len2[d1, d2] = commonw
else:
dont_bother[d1].add(d2)
dont_bother[d2].add(d1)
all_feasible = [feasible_len2]
while all_feasible[-1]:
feasible_Np1 = {}
for ds, ws in all_feasible[-1].items():
md = max(ds)
for d, w in mapping.items():
if d <= md or any(d in dont_bother[d1] for d1 in ds):
continue
commonw = w.intersection(ws)
if len(commonw) >= 2:
feasible_Np1[ds+(d,)] = commonw
all_feasible.append(feasible_Np1)
return all_feasible[:-1]
당신은 내 제안 "더 가지 치기"의 온화한 양식을 적용한 알 수 있습니다 - dont_bother
레코드 만 "호환성"한 DOCID과 다른 사람 사이 (공통의 < 2 개 단어) -이 월 이러한 "호환되지 않는 문서"의 몇 가지 쌍이 있고 간단하고 합리적으로 방해가되지 않는 경우 도움이되지만 더 어려운 "전체"대안처럼 가지 치기에서 강력하지는 않습니다. 나는 또한 feasible*
dicts에있는 모든 키를 중복을 피하기 위해 중복 된 작업을 피하기 위해 docids의 정렬 된 튜플 (itertools.combinations
은 원래 쌍을 제공함)로 유지하려고합니다. OK 표시
mat = [ ['doc']+'tanto va la gatta al lardo che ci lascia lo zampino'.split(),
['uno', 0, 0, 0, 1, 0, 1, 0, 0, 0, 1],
['due', 1, 0, 0, 0, 0, 1, 0, 1, 0, 1],
['tre', 1, 0, 0, 0, 0, 0, 0, 1, 0, 1],
['qua', 0, 0, 0, 1, 0, 1, 0, 1, 0, 1]]
mm = makemap(mat)
print mm
afs = allfeasiblesubsets(mat)
print afs
결과, 다음과 같습니다 :
여기 (이 후, 물론 기능의 itertools
에 대한 import
및 collections
이 같은 파일에) 내가 해봤 작은 예입니다
{'qua': set(['gatta', 'lo', 'ci', 'lardo']), 'tre': set(['lo', 'ci', 'tanto']), 'due': set(['lo', 'ci', 'lardo', 'tanto']), 'uno': set(['gatta', 'lo', 'lardo'])}
[{('due', 'tre'): set(['lo', 'ci', 'tanto']), ('due', 'uno'): set(['lo', 'lardo']), ('qua', 'uno'): set(['gatta', 'lo', 'lardo']), ('due', 'qua'): set(['lo', 'ci', 'lardo']), ('qua', 'tre'): set(['lo', 'ci'])}, {('due', 'qua', 'tre'): set(['lo', 'ci']), ('due', 'qua', 'uno'): set(['lo', 'lardo'])}]
물론 완전히 테스트하지 않았으므로 여전히 버그가 숨어있을 수 있습니다. BTW, 여기에 제공된 결과 (여러 가지 증가하는 길이에 대한 dicts 목록, 각 dict가 docids 세트의 정렬 된 튜플 형식을 키로 설정하고 공통 단어를 값으로 사용함)이 쉽게 게시 될 수 있기를 바랍니다. 중첩 목록과 같이 선호하는 다른 형식으로 처리됩니다.
(중요한 것은 아니지만이 예에서 사용한 텍스트는 오래된 이탈리아 속담입니다 .-)).
귀하의 데이터 구조 나에게 명확하지 않다. 실제로 열 머리글의 2D 행렬이 있음을 의미합니까? 그러면 데이터 구조 자체가 3D가됩니다. 코드를 실행하는 데 사용할 수있는 입력 데이터의 예를 보여주십시오. –
당신의 구조는'[[], []], [[], []]'입니다. 이것은 목록의 목록 중 두 개, 즉 목록의 (암시 적) 튜플입니다. 너가 원하는게 그거야? – badp
데이터 구조는 유연합니다. 그들이 보낸 문서에 매핑되는 단어 (줄기, 낮추 등)입니다. 내가 이진 행렬 수학이 그것을 해결하는 가장 효율적인 방법 일지 모른다고 생각하면서 위에 묘사 된 행렬 포맷에 착수했지만, [doc_id] = set (word1, word2, ...., wordN)의 Alex의 dicts는 그것이 최종 결과를 제공한다면 괜찮아. – ssweens