/// <summary> /// Tworzy indeks na plik macierzy /// /// Użycie dozwolone w trybie Mode.CREATE. /// </summary> public void createIndex() { IxHalMatrixReader halReader = new IxHalMatrixReader(this.workingDirPath); using (BinaryWriter indexWriter = new BinaryWriter(File.Create(workingDirPath + "halMatrix.idx"))) { KeyValuePair<uint, ArrayRow<uint>> row; uint lastAddedId = 0; long positionBefore = halReader.getPositionInFile(); while ((row = halReader.readNextArrayRow()).Key != 0) { while (lastAddedId++ != row.Key) { indexWriter.Write((long)-1); } indexWriter.Write(positionBefore); positionBefore = halReader.getPositionInFile(); } } halReader.finalize(); }
/// <summary> /// Optymalizuje macierz HAL zapisaną na dysku /// /// Zostaną usunięte wiersze i komórki tokenów, które wystąpiły mniej niż IxSettings.halMinCount razy. /// </summary> public void optimizeMatrix() { IxHalMatrixReader reader = new IxHalMatrixReader(workingDirPath); if (IxSettings.consoleDebug) Console.WriteLine("Calculating tokens for removal set..."); HashSet<uint> tokenRemovalSet = new HashSet<uint>(); KeyValuePair<uint, ArrayRow<uint>> row = reader.readNextArrayRow(); while (row.Key != 0) { if (row.Value.count < IxSettings.halMinCount) tokenRemovalSet.Add(row.Key); row = reader.readNextArrayRow(); reader.getPositionInFile(); } reader.reset(); if (IxSettings.consoleDebug) Console.WriteLine("Removing rows and cells..."); row = reader.readNextArrayRow(); using (BinaryWriter writer = new BinaryWriter(File.Create(altWorkingDirPath + "halMatrixOptimized.dat"))) { while (row.Key != 0) { if (!tokenRemovalSet.Contains(row.Key)) { Row<uint> newRow = new Row<uint>(); newRow.count = row.Value.count; for (int i = 0, count = row.Value.cells.Length; i < count; i++) { if (!tokenRemovalSet.Contains(row.Value.cells[i].Key)) newRow.cells.Add(row.Value.cells[i].Key, row.Value.cells[i].Value); } IxHalStorage.writeRow(writer, new KeyValuePair<uint,Row<uint>>(row.Key, newRow)); } row = reader.readNextArrayRow(); reader.getPositionInFile(); } } reader.finalize(); File.Delete(workingDirPath + "halMatrix.dat"); File.Move(altWorkingDirPath + "halMatrixOptimized.dat", workingDirPath + "halMatrix.dat"); }
/// <summary> /// Oblicza kontekst dla tokenu o wskazanym ID /// /// Jeśli token nie posiada wiersza w tablicy, zwracany jest pusty kontekst (pusta tablica). /// </summary> /// <param name="tokenId">ID tokenu do obliczenia kontekstu</param> /// <returns>Kontekst tokenu lub pusta tablica</returns> public KeyValuePair<uint, int>[] calculateContextForTokenId(uint tokenId) { /* Obiekt czytający macierz */ IxHalMatrixReader matrixReader = new IxHalMatrixReader(workingDirPath); /* Semafor - maksymalna liczba jednocześnie zakolejkowanych wątków ThreadPool */ Semaphore semaphore = new Semaphore(IxSettings.halAnalyzerThreadsNum, IxSettings.halAnalyzerThreadsNum); /* Wiersz tokenu, dla którego liczymy kontekst */ KeyValuePair<uint, ArrayRow<uint>> calculatedForRow = getArrayRow(tokenId); /* Jeśli wiersz tego tokenu nie istnieje, nie obliczysz kontekstu */ if (calculatedForRow.Key == 0) return new KeyValuePair<uint, int>[0]; /* Kalkulator odległości - kontekstu */ IxHalTokenContextCalculator calculator = new IxHalTokenContextCalculator(semaphore, calculatedForRow); /* Wczytaj pierwszą porcję wierszy do porównywania (liczenia odległości) dla tokenu */ KeyValuePair<uint, ArrayRow<uint>>[] calculatedAgainstRows = matrixReader.readArrayRowsChunk(1000); while (calculatedAgainstRows.Length != 0) { /* Zakolejkuj obliczenie odległości dla wczytanych wierszy */ calculator.calculate(calculatedAgainstRows); /* Wczytaj następną porcję wierszy */ calculatedAgainstRows = matrixReader.readArrayRowsChunk(1000); } matrixReader.finalize(); Misc.waitFullSemaphore(semaphore, IxSettings.halAnalyzerThreadsNum); calculator.computeFinalResult(); Misc.waitFullSemaphore(semaphore, IxSettings.halAnalyzerThreadsNum); return calculator.getCalculatedContext(); }
/// <summary> /// Tworzy kontekst dla wszystkich tokenów w macierzy i zapisuje go do pliku /// /// Kontekst jest zarządzalny przez IxHalContext. /// </summary> public void calculateContext() { ProgressReport progressReport; /* Posłuży do zapisywania wyników */ IxHalContext contextWriter = new IxHalContext(workingDirPath, IxHalContext.Mode.CREATE); /* Obiekt czytający dla tokenów, dla których będzie liczony kontekst */ IxHalMatrixReader matrixReader = new IxHalMatrixReader(workingDirPath); matrixReader.setProgressReportPrefix("!"); /* Obiekt czytający dla tokenów, od których liczone będą odległości do kontekstów */ IxHalMatrixReader matrixReaderSub = new IxHalMatrixReader(workingDirPath); /* Semafor maksymalnej liczby jednocześnie zakolejkowanych wątków ThreadPool */ Semaphore semaphore = new Semaphore(IxSettings.halAnalyzerThreadsNum, IxSettings.halAnalyzerThreadsNum); /* Seria wierszy tokenów, dla których aktualnie liczony jest kontekst */ KeyValuePair<uint, ArrayRow<uint>>[] calculatedForRows = matrixReader.readArrayRowsChunk(1000); while (calculatedForRows.Length != 0) { /* Kalkulatory kontekstów */ IxHalTokenContextCalculator[] calculators = IxHalTokenContextCalculator.create(semaphore, calculatedForRows); int calculatorsCount = calculators.Length; /* Porcja wierszy tokenów, od których liczone będą odległości do kontekstów */ KeyValuePair<uint, ArrayRow<uint>>[] calculatedAgainstRows = matrixReaderSub.readArrayRowsChunk(1000); while (calculatedAgainstRows.Length != 0) { progressReport = new ProgressReport(calculatorsCount, 10, "c"); /* Zleć uzupełnianie kontekstów kalkulatorom */ for (int i = 0; i < calculatorsCount; i++) { calculators[i].calculate(calculatedAgainstRows); progressReport.progressOne(); } /* Pobierz następną porcję tokenów, od których liczone są odległości do kontekstów */ calculatedAgainstRows = matrixReaderSub.readArrayRowsChunk(1000); progressReport.done(); } /* Obliczono już cały kontekst dla tej porcji calculatedForRows - zresetuj obiekt czytający */ matrixReaderSub.reset(); Misc.waitFullSemaphore(semaphore, IxSettings.halAnalyzerThreadsNum); progressReport = new ProgressReport(calculatorsCount, 10, "f"); /* Finalizuj obliczanie kontekstów w kalkulatorach */ for (int i = 0; i < calculatorsCount; i++) { calculators[i].computeFinalResult(); progressReport.progressOne(); } Misc.waitFullSemaphore(semaphore, IxSettings.halAnalyzerThreadsNum); progressReport.done(); progressReport = new ProgressReport(calculatorsCount, 10, "w"); /* Przekaż w kolejności wyniki do contextWriter */ for (int i = 0; i < calculatorsCount; i++) { calculators[i].writeDownResult(contextWriter); progressReport.progressOne(); } /* Pobierz kolejną porcję wierszy tokenów, dla których będzie liczony kontekst */ calculatedForRows = matrixReader.readArrayRowsChunk(100); progressReport.done(); } /* Zakończ pracę */ contextWriter.finalize(); }