불가능한 요청과 "비용 0"이 같은 값으로 반환된다 — 그리고 벤치마크의 70%가 여기에 걸린다
#tflow가 요구 유량 f에 도달하지 못하면 0을 돌려준다. 호출자는 "9를 보낼 수 없다"와 "9를 공짜로 보냈다"를 구분할 방법이 없다. 세 구현(Problem2.cc:112, Problem2i.cc:112, Problem2ii.cc:115) 모두 동일하다.
//when tflow == f(given flow) finish loop if (tflow == f) break; } if (tflow < f) return 0; // ← 실패도 0, 진짜 비용 0도 0 return tcost;
이론적 지적이 아니다. 커밋된 Problem2ii.out은 10개 그래프 중 7개에 대해 cost: 0을 기록하고 있고, 이는 problem1.out의 최대 유량(graph1=4, 4=5, 5=4, 6=2, 7=2, 8=2, 9=0)이 전부 9 미만인 것과 정확히 일치한다. 즉 저자의 벤치마크 데이터셋 중 실제로 답이 나오는 것은 graph0(109), graph2(136), graph3(18) 세 개뿐이다.
필자가 g++ -std=c++14 -Wall -Wextra -O2로 빌드해 재현한 결과도 커밋된 로그와 동일했고, 모호성을 직접 확인하기 위해 두 개의 최소 입력을 만들어 돌렸다. 용량 9·비용 0인 간선 하나짜리 실현 가능 그래프와, 용량 1짜리 실현 불가능 그래프가 같은 문자열을 인쇄한다.
$ ./Problem2ii data/zerocost 9 # "2 1 / 0 1 9 0" — 가능, 참값 0 result: given flow: 9, cost: 0 $ ./Problem2ii data/infeas 9 # "2 1 / 0 1 1 7" — 불가능 result: given flow: 9, cost: 0 $ ./Problem2ii data/graph1 9 # 최대 유량 4 < 9 result: given flow: 9, cost: 0 $ ./Problem2 data/graph1 4 # 실현 가능한 유량으로 바꾸면 result: given flow: 4, cost: 80 // 2, 2i, 2ii 모두 80
이 결함이 보고서까지 오염시킨다. Problem 2의 Analysis 절은 "V=12, E=12로 주어진 Graph1에 대한 결과로 각각 1.63, 0.75, 0.58초"를 세 구현의 성능 차이 근거로 제시하는데, graph1은 답이 나오지 않는 그래프다. 측정된 것은 "M=9를 만드는 비용"이 아니라 "더 이상 증가 경로가 없을 때까지 탐색하다 포기하는 비용"이다. 워크로드 자체가 다르다. 반면 같은 절의 Graph2(4.38 / 2.67 / 1.03초)는 cost: 136이 나오는 유효한 케이스이므로 이 비교만 유효하다.