コード例 #1
0
ファイル: IxHalMatrixReader.cs プロジェクト: dzima1/IWI
        /// <summary>
        /// Standardowy konstruktor
        /// </summary>
        /// <param name="workingDirPath">Ścieżka do katalogu z plikiem zapisanej macierzy</param>
        public IxHalMatrixReader(string workingDirPath)
        {
            this.workingDirPath = Misc.provideEndBackslash(workingDirPath);

            reader = new BinaryReader(File.Open(this.workingDirPath + "halMatrix.dat", FileMode.Open, FileAccess.Read, FileShare.Read));

            progress = new ProgressReport(reader.BaseStream.Length, 1);
        }
コード例 #2
0
ファイル: IxHalMatrixReader.cs プロジェクト: dzima1/IWI
        /// <summary>
        /// Resetuje obiekt, zaczynając odczyt pliku macierzy od początku
        /// </summary>
        public void reset()
        {
            reader.BaseStream.Position = 0;

            progress = new ProgressReport(reader.BaseStream.Length, 1);
        }
コード例 #3
0
ファイル: IxHalMatrixMerger.cs プロジェクト: dzima1/IWI
        /// <summary>
        /// Standardowy konstruktor
        /// 
        /// Odczytuje pierwszy wiersz.
        /// </summary>
        /// <param name="reader">Strumień binarny do odczytu macierzy z dysku</param>
        public MatrixMergerDisk(BinaryReader reader)
        {
            this.reader = reader;

            progressReport = new ProgressReport(reader.BaseStream.Length, 1);

            moveNext();
        }
コード例 #4
0
ファイル: IxStdRISearchEngine.cs プロジェクト: dzima1/IWI
        public IxSearchResult search(string searched)
        {
            /* Ztokenizuj fraz� */
            tokenListing.reset();
            tokenListing.addFromText(searched, false);
            uint[] tokensIds = tokenListing.getTokensIds();

            Dictionary<uint, float> resultIds = new Dictionary<uint, float>();

            foreach (uint tokenId in tokensIds)
            {
                /* Dla ka�dego tokenu frazy pobierz list� wyst�pie� */
                Posting[] postings = invIndex.getPostingsByTokenId(tokenId);

                if (tokensIds.Length > 1)
                {
                    /* Sta�y wsp�czynnik IDF dzielony przez wag� pierwszego dokumentu w zbiorze podwynik�w dla tego tokenu */
                    float IDFperMaxRank = (float)(Math.Log(documentsCount / postings.Length) + 1) / postings[0].rank;

                    /* Scal wyniki dla tego tokenu z poprzednimi wynikami */
                    foreach (Posting posting in postings)
                        if (!resultIds.ContainsKey(posting.documentId))
                        {
                            resultIds[posting.documentId] = posting.rank * IDFperMaxRank;
                        }
                        else
                        {
                            resultIds[posting.documentId] += posting.rank * IDFperMaxRank;
                        }
                }
                else
                {
                    /* Nie ma poprzednich wynik�w - przepisz */
                    foreach (Posting posting in postings)
                        resultIds[posting.documentId] = posting.rank;
                }
            }

            /* Zwracany wynik wyszukiwania */
            IxSearchResult result = new IxSearchResult();
            result.documents = new IxDocument[resultIds.Count];

            /* Przepisz wynik ze s�ownika do tablicy, pierwsze sortowanie wg ID dokumentu: wi�ksze szanse na szybszy odczyt tytu��w */
            IEnumerator<KeyValuePair<uint, float>> resultEnumerator = resultIds.OrderByDescending<KeyValuePair<uint, float>, float>(key => key.Key).GetEnumerator();

            ProgressReport progress;

            if (IxSettings.consoleDebug)
            {
                Console.WriteLine("Rewriting result documents' ids and reading titles...");
                progress = new ProgressReport(resultIds.Count, 5);
            }

            int index = 0;

            /* Przepisz wyniki, pobieraj�c nazwy dokument�w */
            while (resultEnumerator.MoveNext())
            {
                result.documents[index] = documentsIndex.getDocumentById(resultEnumerator.Current.Key);
                result.documents[index].Id = resultEnumerator.Current.Key;
                result.documents[index++].rank = resultEnumerator.Current.Value;

                if (IxSettings.consoleDebug)
                    progress.progressOne();
            }

            progress.done();

            /* Teraz posortuj wg malej�cych ocen */
            Array.Sort<IxDocument>(
                result.documents,
                delegate(IxDocument firstDocument, IxDocument nextDocument) { return nextDocument.rank.CompareTo(firstDocument.rank); }
                );

            return result;
        }
コード例 #5
0
ファイル: IxHalOnDemCtxComp.cs プロジェクト: dzima1/IWI
        /// <summary>
        /// Podaje kontekst dla wskazanego tokenu
        /// 
        /// Jeśli kontekst znajduje się w pamięci podręcznej, zwraca go. W przeciwnym wypadku tworzona jest tymczasowa macierz HAL,
        /// na której będzie liczony kontekst tokenu. Kontekst jest obcinany do długości IxSettings.halNearestCutoff.
        /// </summary>
        /// <param name="tokenId">ID tokenu do podania kontekstu</param>
        /// <returns>Kontekst tokenu</returns>
        public KeyValuePair<uint, int>[] getNearestForTokenId(uint tokenId, int[] halWindow)
        {
            ProgressReport progress;

            string tokenWindowId = tokenId.ToString() + halWindow.Aggregate(halWindow[0].ToString(), (s, i) => s + " " + i.ToString()); // http://stackoverflow.com/questions/1822811/int-array-to-string/1823413#1823413

            if (nearest.ContainsKey(tokenWindowId))
                return nearest[tokenWindowId];

            // TODO uwaga na tokeny zawierające liczby oraz na stopsłowa (nie powinny się znajdować, bo to co trafia do indeksu jest filtrowane)

            Matrix<uint> matrix = new Matrix<uint>();

            /* Zaczynamy od analizy tokenów powiązanych z tym, czyli zawartych w dokumentach, gdzie
             * występuje token, dla którego liczymy */
            Posting[] documents = invIndex.getPostingsByTokenId(tokenId);

            if (IxSettings.consoleDebug)
            {
                progress = new ProgressReport(documents.Length, 5);

                Console.WriteLine("Analiza HAL dokumentów zawierających token...");
            }

            /* Nie analizować dwukrotnie tych samych dokumentów */
            HashSet<uint> alreadyAnalyzedDocuments = new HashSet<uint>();

            Semaphore semaphore = new Semaphore(IxSettings.halAnalyzerThreadsNum, IxSettings.halAnalyzerThreadsNum);

            /* Przeanalizuj wszystkie dokumenty, w których wystąpił token, dla którego liczymy */
            foreach (Posting document in documents)
            {
                uint[] documentTokens;

                /* Pobierz tokeny dokumentu */
                try
                {
                    documentTokens = fwdIndex.getDocumentTokenList(document.documentId, IxSettings.halOnDemandMainDocumentsMinLength);
                }
                catch (ArgumentOutOfRangeException)
                {
                    continue;
                }

                if (documentTokens.Length == 0)
                    continue;

                semaphore.WaitOne();

                /* Zleć analizę dokumentu */
                ThreadPool.QueueUserWorkItem(new WaitCallback(analyzeDocument), new AnalyzerThreadData(
                        documentTokens,
                        semaphore,
                        new Analyzer<uint>(matrix, halWindow),
                        null
                    ));

                alreadyAnalyzedDocuments.Add(document.documentId);

                if (IxSettings.consoleDebug)
                    progress.progressOne();
            }

            for (int i = 0; i < IxSettings.halAnalyzerThreadsNum; i++)
                semaphore.WaitOne();

            semaphore.Release(IxSettings.halAnalyzerThreadsNum);

            if (IxSettings.consoleDebug)
                progress.done();

            if (IxSettings.halOnDemandExtendedAnalysis)
            {
                /* Konieczne jeszcze będzie przeanalizowanie pozostałych dokumentów, w których wystąpiły
                 * wszystkie tokeny, które wystąpiły w dokumentach, w których wystąpił ten, dla którego
                 * liczymy. Zdanie złożone opisujące podobnie złożony proces... */
                uint[] rowsIds = matrix.rows.Keys.ToArray<uint>();
                uint[] cellsIds = matrix.getRow(tokenId).cells.Keys.ToArray<uint>();

                if (IxSettings.consoleDebug)
                {
                    progress = new ProgressReport(rowsIds.Length + cellsIds.Length, 20);

                    Console.WriteLine("Obliczanie zbioru tokenów powiązanych do uwzględnienia w analizie...");
                }

                /* Tokeny, których zawierające je dokumentów analiza także jest konieczna. Przy okazji stanowi to zbiór tokenów,
                 * których analiza (uwzględnienie w analizie HAL) ma wpływ na wynik kontekstu tokenu, dla którego liczymy (ważna
                 * jest jedynie zwiększona odległość, którą wprowadza, ale wiersz tokenu głównego nie zawiera komórki dla tego tokenu) */
                HashSet<uint> tokensIdsToAnalyze = new HashSet<uint>();

                /* Wylistuj tokeny z wierszy macierzy HAL */
                foreach (uint rowsId in rowsIds)
                {
                    tokensIdsToAnalyze.Add(rowsId);

                    if (IxSettings.consoleDebug)
                        progress.progressOne();
                }

                Array.Resize<uint>(ref rowsIds, 0); // Zwolnij pamięć

                /* Wylistuj tokeny z komórek wiersza tokenu, dla którego liczymy kontekst */
                foreach (uint cellsId in cellsIds)
                {
                    if (!tokensIdsToAnalyze.Contains<uint>(cellsId))
                        tokensIdsToAnalyze.Add(cellsId);

                    if (IxSettings.consoleDebug)
                        progress.progressOne();
                }

                Array.Resize<uint>(ref cellsIds, 0); // Zwolnij pamięć

                if (IxSettings.consoleDebug)
                {
                    progress.done();

                    progress = new ProgressReport(tokensIdsToAnalyze.Count, 1);

                    Console.WriteLine("Analiza dokumentów zawierających tokeny powiązane...");
                }

                // analyzeDocument - performance, analyzeDocumentRelated - saves memory
                WaitCallback analysisCallback = IxSettings.halFastExtendedAnalysis
                    ? new WaitCallback(analyzeDocument)
                    : new WaitCallback(analyzeDocumentRelated);

                /* Pobieraj listę dokumentów dla każdego z tokenów i analizuj te, których jeszcze nie przeliczano */
                foreach (uint tokenIdToAnalyze in tokensIdsToAnalyze)
                {
                    if (tokenIdToAnalyze == tokenId)
                        continue;

                    /* Dokumenty, w których wystąpił token */
                    documents = invIndex.getPostingsByTokenId(tokenIdToAnalyze);

                    foreach (Posting document in documents)
                    {
                        if (alreadyAnalyzedDocuments.Contains<uint>(document.documentId))
                            continue; // Ten dokument już analizowano

                        uint[] documentTokens;

                        /* Pobierz tokenu dokumentu */
                        try
                        {
                            documentTokens = fwdIndex.getDocumentTokenList(document.documentId, IxSettings.halOnDemandExtendedDocumentsMinLength);
                        }
                        catch (ArgumentOutOfRangeException)
                        {
                            continue;
                        }

                        if (documentTokens.Length == 0)
                            continue;

                        semaphore.WaitOne();

                        /* Zakolejkuj analizę dokumentu */
                        ThreadPool.QueueUserWorkItem(
                            analysisCallback,
                            new AnalyzerThreadData(
                                documentTokens,
                                semaphore,
                                new Analyzer<uint>(matrix, halWindow),
                                tokensIdsToAnalyze
                            )
                        );

                        alreadyAnalyzedDocuments.Add(document.documentId);
                    }

                    if (IxSettings.consoleDebug)
                        progress.progressOne();
                }

                for (int i = 0; i < IxSettings.halAnalyzerThreadsNum; i++)
                    semaphore.WaitOne();

                if (IxSettings.consoleDebug)
                    progress.done();
            }

            /* Użyj kalkulatora kontekstu na macierzy HAL */
            ContextComputer<uint> nearestComputer = new ContextComputer<uint>(matrix);

            KeyValuePair<uint, int>[] result = nearestComputer.getNearest(tokenId);

            /* Skróć wynik - podany pełen kontekst */
            if (result.Length > IxSettings.halNearestCutoff)
                Array.Resize<KeyValuePair<uint, int>>(ref result, IxSettings.halNearestCutoff);

            nearest[tokenWindowId] = result;
            nearestChanged = true;

            return result;
        }
コード例 #6
0
ファイル: IxHalCreator.cs プロジェクト: dzima1/IWI
        /// <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();
        }
コード例 #7
0
ファイル: IxHALIRSearchEngine.cs プロジェクト: dzima1/IWI
        /// <summary>
        /// Wyszukuje dokumenty wg zadanej frazy z użyciem funkcjonalności HAL, która może być sparametryzowana
        /// 
        /// Można podać frazę prostą, wtedy wyszukiwanie następuje zgodnie z domyślnymi ustawieniami z IxSettings.
        /// Jeśli natomiast podana fraza będzie zawierała 11 parametrów, oddzielonych od siebie i szukanych tokenów
        /// znakami "/" (slash), zostaną użyte sparsowane parametry. Sparametryzowana fraza wyszukiwania musi mieć
        /// postać: <b>wyszukiwane tokeny/f/f/i/i/f/f/i[]/i/i/b/i</b>, gdzie: f - float, i - integer, i[] - kilka liczb
        /// integer oddzielonych spacją, b - boolean. Parametry to po kolei: straightMultiplier, relatedMultiplier,
        /// relatedSearchCount, relatedFoundMinCount, relFoundRateIfContainsStraight, relFoundRateIfNotContainsStraight,
        /// halWindow, skipFirstNRelated, maxUsedRelatedDistanceSum, relatedDistanceRelativeToFirst, speechPartFiltering
        /// (patrz dokumentacja funkcji getDocumentsIdsByTokenIdWithHAL()).
        /// </summary>
        /// <param name="searched"></param>
        /// <returns>Wynik wyszukiwania IxHALSearchResult</returns>
        public IxSearchResult search(string searched)
        {
            string[] parts = searched.Split(new char[] { '/' });

            #region HAL search parameters
            float straightMultiplier = IxSettings.halSearchTokensRate;
            float relatedMultiplier = IxSettings.halSearchRelTokensRate;
            int relatedSearchCount = IxSettings.halSearchRelTokensCount;
            int relatedFoundMinCount = IxSettings.halSearchRelTokensReqCount;
            float relFoundRateIfContainsStraight = IxSettings.halSearchRelFoundRateIfContainsStraight;
            float relFoundRateIfNotContainsStraight = IxSettings.halSearchRelFoundRateIfNotContainsStraight;
            int[] halWindow = IxSettings.defaultHalWindow;
            int skipFirstNRelated = IxSettings.halSkipFirstNRelated;
            int maxUsedRelatedDistanceSum = IxSettings.halMaxRelatedDistanceSum;
            bool relatedDistanceRelativeToFirst = IxSettings.halRelatedDistanceRelativeFirst;
            HalSpeechPartFiltering speechPartFiltering = HalSpeechPartFiltering.NONE;

            if (parts.Length == 12)
            {
                try
                {
                    straightMultiplier = float.Parse(parts[1].Trim());
                    relatedMultiplier = float.Parse(parts[2].Trim());
                    relatedSearchCount = int.Parse(parts[3].Trim());
                    relatedFoundMinCount = int.Parse(parts[4].Trim());
                    relFoundRateIfContainsStraight = float.Parse(parts[5].Trim());
                    relFoundRateIfNotContainsStraight = float.Parse(parts[6].Trim());

                    string[] halWindowParts = parts[7].Split(new char[] { ' ' });

                    halWindow = new int[halWindowParts.Length];
                    int halWindowIndex = 0;

                    for (int i = 0; i < halWindowParts.Length; i++)
                    {
                        if (halWindowParts[i].Equals(""))
                            continue;

                        halWindow[halWindowIndex++] = int.Parse(halWindowParts[i]);
                    }

                    Array.Resize<int>(ref halWindow, halWindowIndex);

                    skipFirstNRelated = int.Parse(parts[8].Trim());
                    maxUsedRelatedDistanceSum = int.Parse(parts[9].Trim());
                    relatedDistanceRelativeToFirst = bool.Parse(parts[10].Trim());
                    speechPartFiltering = (HalSpeechPartFiltering)int.Parse(parts[11]);
                }
                catch (FormatException)
                {
                    return new IxHALSearchResult("Search error: improper parameters (phrase/f/f/i/i/f/f/HAL window/i/i/b/i)");
                }
            }
            #endregion

            /* Wyłuskaj z wyszukiwanej frazy tokeny */
            tokenListing.reset();
            tokenListing.addFromText(parts[0], false);
            uint[] tokensIds = tokenListing.getTokensIds();

            Dictionary<uint, float> resultIds = new Dictionary<uint, float>();

            KeyValuePair<string, KeyValuePair<string, int>[]>[] halContexts = new KeyValuePair<string, KeyValuePair<string, int>[]>[tokensIds.Length];
            KeyValuePair<string, int>[] halContextsSoughtCounts = new KeyValuePair<string, int>[tokensIds.Length];
            uint halContextIndex = 0;

            /* Wyszukuj po kolei tokeny */
            foreach (uint tokenId in tokensIds)
            {
                Dictionary<uint, float> subResultIds;
                int relatedSoughtCount;

                /* Pobierz wyniki dla pojedynczego tokenu z frazy, kontekst jest zapisywany bezpośrednio w halContexts[halContextIndex],
                 * dokumenty i liczba wyszukanych tokenów kontekstu trzeba będzie zsumować/przepisać */
                getDocumentsIdsByTokenIdWithHAL(tokenId, straightMultiplier, relatedMultiplier, relatedSearchCount, relatedFoundMinCount, relFoundRateIfContainsStraight, relFoundRateIfNotContainsStraight, halWindow, skipFirstNRelated, maxUsedRelatedDistanceSum, relatedDistanceRelativeToFirst, speechPartFiltering, out subResultIds, out halContexts[halContextIndex], out relatedSoughtCount);

                /* Zapisz liczbę wyszukwianych tokenów z kontekstu */
                halContextsSoughtCounts[halContextIndex] = new KeyValuePair<string, int>(halContexts[halContextIndex].Key, relatedSoughtCount);

                /* Zsumuj wynik dokumentów z dotychczasowymi wynikami */
                foreach (KeyValuePair<uint, float> oneResult in subResultIds)
                    if (resultIds.ContainsKey(oneResult.Key))
                        resultIds[oneResult.Key] += oneResult.Value;
                    else
                        resultIds.Add(oneResult.Key, oneResult.Value);

                halContextIndex++;
            }

            /* Zwracany wynik wyszukiwania */
            IxHALSearchResult result = new IxHALSearchResult();
            result.documents = new IxDocument[resultIds.Count];
            result.context = halContexts;
            result.contextSoughtCounts = halContextsSoughtCounts;

            /* Przepisz wynik ze słownika do tablicy, pierwsze sortowanie wg ID dokumentu: większe szanse na szybszy odczyt tytułów */
            IEnumerator<KeyValuePair<uint, float>> resultEnumerator = resultIds.OrderByDescending<KeyValuePair<uint, float>, float>(key => key.Key).GetEnumerator();

            ProgressReport progress;

            if (IxSettings.consoleDebug)
            {
                Console.WriteLine("Rewriting result documents' ids and reading titles...");
                progress = new ProgressReport(resultIds.Count, 5);
            }

            int index = 0;

            /* Przepisz wyniki, pobierając nazwy dokumentów */
            while (resultEnumerator.MoveNext())
            {
                result.documents[index] = documentsIndex.getDocumentById(resultEnumerator.Current.Key);
                result.documents[index++].rank = resultEnumerator.Current.Value;

                if (IxSettings.consoleDebug)
                    progress.progressOne();
            }

            progress.done();

            /* Teraz posortuj wg malejących ocen */
            Array.Sort<IxDocument>(
                result.documents,
                delegate(IxDocument firstDocument, IxDocument nextDocument) { return nextDocument.rank.CompareTo(firstDocument.rank); }
                );

            return result;
        }