모든 사이클 찾기


9

I는 유한 세트가 , 함수 및 전체 순서 에 . 의 고유 사이클 수를 찾고 싶습니다 .Sf:SS<SS

주어진 요소 I는 반복적으로 적용하는주기의 길이를 찾기 위해 (또는 브렌 등의) 플로이드의 알고리즘을 사용할 수있는 전송 에 단계; 좀 더 노력하면이 사이클을 식별 할 수 있습니다 (예 : 최소 요소). 문제를 해결하는 나쁜 방법은이 각 요소를 반복하고 결과로 나오는 최소 요소를 삭제하여 중복을 삭제하고 카운트를 반환하는 것입니다. 그러나 이것은 잠재적으로 동일한 요소와 넓은 공간 요구 사항에 대한 많은 패스를 포함합니다.sSfs<

시간과 공간 성능이 더 좋은 방법은 무엇입니까? 필요한 공간을 측정하는 가장 좋은 방법이 무엇인지 잘 모르겠습니다. 가 항등 함수 인 경우 모든주기를 저장하는 모든 방법은 공간을 사용합니다.fΩ(n)


4
공간을 측정하는 자연스러운 방법 중 하나는 S를 n 비트 문자열 세트로, f를 오라클로 간주하는 것입니다. 그런 다음 설명 한 순진한 알고리즘에는 지수 공간이 필요합니다. 다항식 공간 만 사용하는 알고리즘을 찾을 수는 있지만 이것이 가능하지는 않을 것입니다.
이토 쓰요시

그것이 "공간을 측정하는 가장 좋은 방법이 무엇인지 모르겠습니다"라는 의미입니다. 아마도 y가 출력 인 O (poly (n) + y)를 대상으로해야하므로 y가 충분히 작 으면 사용 된 공간이 다항식이됩니다.
찰스

함수의 않습니다 F는 모든 가능한 특성을 가지고? 알고리즘이 S 의 카디널리티 순서대로 시간과 공간을 모두 차지한다는 실질적인 대답이 있다면 알고리즘이 입력 크기를 표현하는 선호하는 방식으로 다항식인지 지수인지 여부는 다소 불분명합니다 .
Niel de Beaudrap 15:08에

@Niel de Beaudrap : 어떤 속성이 유용한 지 잘 모르겠습니다. I는 별개의 사이클의 수는 작고, 비록 아마도 기대 ; 그렇기 때문에 그냥 대신 와 의 함수를 제안했습니다 . 필요한 경우 출력 비트 수에 공간 지수를 기꺼이 사용합니다. O(n3)ynn
찰스

답변:


7

원하는 횟수가 사이클 수를 세는 것이라면 2 | S | 공간의 비트 (플러스 변경). S 또는 f 가 특히 편리한 속성을 가지고 있지 않으면 훨씬 더 잘 할 수 없을 것 같습니다 .

0으로 초기화 된 정수 {0,1,2} ( S의 요소 당 하나)를 저장하는 배열 A로 시작 합니다. 우리는 이것들을 나타냅니다 (unexplored), (partially explored)그리고 (fully explored). 사이클 카운터를 0으로 초기화하십시오. 각 요소  ∈  S 위하여, 다음을 수행 :

  1. A [ s ] =  (fully explored)이면 6 단계로 건너 뜁니다.
  2. A [ s ] ←  (partially explored)를 설정하고 반복자 j  ←  f (s)를 설정하십시오 .
  3. 동안 [ J ] =  (unexplored), 집합 A [ J ] ←  (partially explored)한 세트 J  ←  F (j) .
  4. A [ j ] =  (partially explored)이면 새로운 사이클을 닫았습니다. c 를 1 씩 증가시킵니다 (이주기의 일부 대표에 대한 기록을 유지하려는 경우, j 의 현재 값은 임의의 선택으로 수행됩니다. 물론 이는 선호하는주기에서 반드시 최소 요소 일 필요는 없습니다) order <.) 그렇지 않으면 A [ j ] =  (fully explored)이며, 이는 이미 계산 된 주기로 끝나는 사전 탐색 궤도를 발견했음을 의미합니다. c를 늘리지 마십시오 .
  5. s 에서 시작하는 궤도 가 완전히 탐색 되었음을 나타내려면 j  ←  s를 설정하십시오 .
    A [ j ] =  동안 (partially explored), A [ j ] ←  (fully explored)를 설정하고 j  ←  f (j)를 설정하십시오 .
  6. 다음 요소로 진행 S  ∈  S .

따라서 f 에 의해 유도 된 궤도 중 각주기 는 한 번 계산됩니다. 대표자로 기록한 요소는 서로 다른주기의 요소가됩니다. 메모리 요구 사항은 2 | S | 배열 A의 경우, 사이클 수 의 경우 O (log | S |) 및 기타 승산과 끝.

각 요소 s  ∈  S 는 적어도 두 번 방문합니다. 한 번은 A [ s ] 값이 에서 (unexplored)로 변경 될 때 (partially explored)한 번,로 변경 될 때 한 번입니다 (fully explored). 모든 노드가 재 방문 된 후 다시 방문한 총 횟수는 (fully explored)이를 실패한 새주기를 찾으려는 시도 횟수로 제한됩니다. S | — S의 모든 요소를 ​​반복하는 메인 루프에서 발생합니다 . 따라서 우리는이 과정이 최대 3 | S | 노드 방문, 노드 방문 또는 재 방문 횟수를 모두 계산합니다.

주기의 대표적인 요소를 추적하고이를 최소한의 요소로 만들고 싶다면 노드 방문 수를 4 |로 제한 할 수 있습니다. S |, 4 단계에서 추가 "사이클 주위 랩"을 추가하여 루프를 닫는 것보다 작은 대표를 찾으십시오. f 아래의 궤도 가 주기로 구성된 경우이 추가 작업을 피할 수 있지만 임의의 f 는 해당되지 않습니다 .


훌륭합니다. 이것은 내가 생각했던 어리석은 공간 알고리즘에서 향상됩니다. 실제로는 대표자가 필요하지 않습니다. 알고리즘에 유용 할 수 있도록 소개 했습니다. O(|S|log|S|)<
찰스

다항식 공간보다 많은 공간을 사용하지 않고 총 사이클이 적은 경우 공간을 훨씬 적게 사용하는 방법이 있는지 궁금합니다. 아 상관없이 이것은 내 필요를 위해 할 것입니다.
찰스

1
이것은 # L에 있어야한다고 생각합니다 (매트릭스 전원 사용). 이것이 # L-hard가 될 수 있습니까?
Kaveh

@Charles : #cycles ∈ o ( | S | ) 를 알고 있으면 개선 사항을 제공하는 최근 답변을 참조하십시오 . 폴리 로그 이상을 사용합니다 | S | 공간과 시간과의 관계를 바꾸고 싶다면 더 좋을 것입니다.
Niel de Beaudrap

@Niel de Beaudrap : 감사합니다! 둘 다 +1 이 알고리즘은 데이터가 메모리에 맞는 한 가장 적합합니다. 일단 유출되면 다른 것을 사용하는 것을 볼 것입니다. (캐시에 모든 것을 담을 수 있다면 다른 쪽이 더 나을 수도 있지만 너무 번거로울 수 있습니다.)
Charles

5

주기가 매우 적은 경우 공간을 덜 사용하지만 종료하는 데 시간이 훨씬 더 오래 걸리는 알고리즘이 있습니다.

[편집] 내 이전 런타임 분석은 우리가 방문한 노드가 이전에 샘플링 된 노드 중 하나인지 여부를 결정하는 데 중요한 비용을 놓쳤습니다. 이 답변은 이것을 수정하기 위해 약간 수정되었습니다.

우리는 다시 S의 모든 요소를 ​​반복합니다 . 우리는 요소의 궤도 탐험  ∈  S를 , 우리는 우리가 다시 건너 여부를 확인 할 수 있도록하기 위해, 우리가 방문한 것을 노드에서 샘플. 우리는 또한 이전에 방문했던 공통 주기로 끝나는 (따라서주기와 등가 인) 궤도의 결합 인 '구성 요소'의 샘플 목록을 유지합니다.

빈 컴포넌트 목록을 초기화하십시오 complist. 각 구성 요소는 해당 구성 요소의 샘플 모음으로 표시됩니다. 또한 samples일부 구성 요소 또는 다른 구성 요소의 샘플로 선택된 모든 요소를 ​​저장 하는 검색 트리 를 유지 관리합니다 . Gn 까지의 정수 시퀀스라고 하자 . 부울 술어를 계산하여 멤버쉽을 효율적으로 판별 할 수 있습니다. 예를 들어, 2의 거듭 제곱 또는 일부 정수 p에 대해 완벽한 p 번째 거듭 제곱 . 각각  ∈  S , 다음을 수행하십시오

  1. s 가에 있으면 samples5 단계로 건너 뜁니다.
  2. 빈 목록 cursample, 반복자 j  ← f ( s ) 및 카운터 t  ← 1을 초기화합니다 .
  3. 반면 j는 하지 않을 samples:
    - 만약 t  ∈  G , 삽입 J 모두에 cursamplesamples.
    t를 증가 시키고 j  ←  f (j)를 설정 합니다.
  4. j 가에 있는지 확인하십시오 cursample. 그렇지 않은 경우 이전에 살펴본 구성 요소를 발견했습니다. 구성 요소 j가 속한 구성 요소를 확인 하고 모든 요소를 cursample적절한 요소에 삽입하여 기능 complist을 보강하십시오. 우리는 삽입 : 그렇지 않으면, 우리는 우리가 적어도 한 번 이전에 발견 된 사이클의 대표자가 발생하지 않고주기를 통과 한 것을 의미 현재의 궤도에서 요소를 다시 발생했습니다 cursample, 새로 발견 구성 요소에서 샘플의 모음으로,에 complist.
  5. 다음 요소로 진행 S  ∈  S .

들어 N  = | S |, X (n)을 예상 사이클 수 ( 예 :  X (n)n 1/3 )를 설명하는 모노톤 증가 함수로 하고 Y (n) = y (n)  log ( n ) ∈ Ω ( X (n)  log ( n ))은 메모리 사용량의 목표를 결정하는 모노톤 증가 함수입니다 ( 예 :  y (n)n 1/2 ). 각 성분에서 하나의 샘플을 저장하려면 최소한 X (n)  log ( n ) 공간이 필요하므로 y (n)  ∈ Ω ( X (n) )이 필요합니다 .

  • 우리가 샘플링하는 궤도의 요소가 많을수록 궤도 끝의주기에서 샘플을 신속하게 선택하여 해당주기를 빠르게 감지 할 가능성이 높습니다. 점근 적 관점에서 볼 때, 메모리 한계가 허용하는 한 많은 샘플을 얻는 것이 합리적입니다. G 보다 n 보다 작은 예상 y (n) 요소 를 갖도록 G 를 설정할 수도 있습니다 . — S 에서 궤도의 최대 길이 가 L 일 것으로 예상되면 , GL  /  y (n) 의 정수 배로 할 수 있습니다 . — 예상 길이가 없으면 n  /  y (n) 마다 한 번만 샘플링하면

    집단; 이것은 어쨌든 샘플 사이의 간격의 상한입니다.

  • 새 구성 요소를 찾을 때 이전에 방문한 S의 요소를 탐색하기 시작하면 (새 구성 요소가 발견되었거나 이전의 터미널주기가 이미 발견 된 구성 요소) 최대 n  /  y ( n) 이전에 샘플링 된 요소를 만나는 반복; 이것은 새로운 구성 요소를 찾으려고 시도 할 때마다 중복 노드를 순회합니다. 우리가 만드는 때문에 N 등의 시도를, 우리는 중복 요소 방문 S를 대부분에서 N 2  /  Y (n)의 총 시간.

  • 멤버십을 테스트하는 데 필요한 작업 samples은 O ( y (n)  log  y (n) )이며, 방문 할 때마다 반복됩니다.이 검사의 누적 비용은 O ( n 2  log  y (n )입니다. 또한, 각각의 수집 물에 샘플을 추가하는 비용도 있으며, 이는 누적 적으로 O ( y (n)  log  y (n) )입니다. 마지막으로, 이전에 발견 된 구성 요소를 다시 만날 때마다 우리는 어떤 구성 요소를 재발견했는지 결정하기 위해 최대 X (n)  log *  y (n) 시간을 소비해야합니다 . 이 작업은 최대 n 번 발생할 수 있으므로 누적 작업은 n X (n)  log  y (n)으로 제한 됩니다.

따라서 우리가 방문하는 노드가 샘플 중 하나인지 여부를 확인하기 위해 수행 된 누적 작업은 런타임을 지배합니다.이 비용은 O ( n 2  log  y (n) )입니다. 그런 다음 y (n) 을 가능한 작게 만들어야 합니다. 즉, O ( X (n) )입니다.

따라서, 하나의 O ((그주기에있는 최종 요소의 수와 동일 함)의 사이클 수를 열거 할 수 X (n)은  로그 ( N ))의 공간, O 복용 ( N 2  로그  X (N) ) 여기서 X (n) 은 예상 사이클 수입니다.


1

공용체 집합 데이터 구조를 사용하여 동일한 요소를 여러 번 통과하는 것을 피할 수 있습니다 . 각 소자 위에 통과 한 포함하는 세트 unioning 세트로 함유 . 이것은 여전히 ​​많은 메모리를 사용합니다.ssf(s)

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.