<?php
/**
* SeekQuarry/Yioop --
* Open Source Pure PHP Search Engine, Crawler, and Indexer
*
* Copyright (C) 2009 - 2026 Chris Pollett chris@pollett.org
*
* LICENSE:
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* @author Chris Pollett chris@pollett.org
* @license https://www.gnu.org/licenses/ GPL3
* @link https://www.seekquarry.com/
* @copyright 2009 - 2026
* @filesource
*/
namespace seekquarry\yioop\tests;
use seekquarry\yioop\library\data_structures\LinearAlgebra;
use seekquarry\yioop\library\summarizers\CentroidWeightedSummarizer;
use seekquarry\yioop\library\UnitTest;
/**
* CentroidWeightedSummarizerTest checks how CentroidWeightedSummarizer
* picks the sentences of a page's summary.
*
* @author Chris Pollett
*/
class CentroidWeightedSummarizerTest extends UnitTest
{
/**
* setUp does nothing, since each case makes its own sentences.
*/
public function setUp()
{
}
/**
* tearDown does nothing, since a case leaves nothing behind.
*/
public function tearDown()
{
}
/**
* picksMatchScoringEverySentenceAgainTestCase checks that
* scoreSentencesVersusAverage, which scores each sentence once and
* then lowers only the scores a pick changes, picks the same sentences
* with the same scores as scoring every sentence again after each
* pick. The sentences share words, and one is given twice, so picks
* change other sentences' scores.
*/
public function picksMatchScoringEverySentenceAgainTestCase()
{
$texts = ["red apple sweet fruit", "green apple sour fruit",
"red car fast", "red apple sweet fruit", "blue sky clear",
"fruit market sells apple pear", "fast red train"];
$vectors = [];
foreach ($texts as $text) {
$vectors[] = LinearAlgebra::normalize(array_count_values(
explode(" ", $text)));
}
$average = CentroidWeightedSummarizer::getAverageSentence($vectors);
$picked = CentroidWeightedSummarizer::scoreSentencesVersusAverage(
$vectors, $average);
$expected = self::scoreEverySentenceAgain($vectors, $average);
$this->assertEqual(array_keys($picked), array_keys($expected),
"the same sentences are picked in the same order");
$close = true;
foreach ($expected as $sentence => $score) {
$close = $close && abs($picked[$sentence] - $score) < 1e-9;
}
$this->assertTrue($close, "each pick has the same score");
}
/**
* scoreEverySentenceAgain picks sentences as scoreSentencesVersusAverage
* did before it kept its scores: each pick works out the inner product
* of the average with every sentence left, takes the largest, and
* takes that sentence's direction out of the average.
*
* @param array $vectors normalized term vectors of the sentences
* @param array $average the normalized average sentence
* @return array sentence index => score, in the order picked
*/
public static function scoreEverySentenceAgain($vectors, $average)
{
$picked = [];
$best = 1;
while ($best > 0) {
$best = -1;
$best_index = -1;
foreach ($vectors as $sentence => $vector) {
$score = LinearAlgebra::dot($average, $vector);
if ($best < $score) {
$best = $score;
$best_index = $sentence;
}
}
if ($best > -1) {
$picked[$best_index] = $best;
foreach ($vectors[$best_index] as $term => $weight) {
$average[$term] -= $average[$term] * $weight;
}
unset($vectors[$best_index]);
}
}
return $picked;
}
}