Skip to content

Commit

Permalink
fix tests
Browse files Browse the repository at this point in the history
  • Loading branch information
Dennis Eichhorn committed Apr 24, 2024
1 parent efd5580 commit af9a7e1
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 33 deletions.
53 changes: 40 additions & 13 deletions Business/Recommendation/MemoryCF.php
Original file line number Diff line number Diff line change
Expand Up @@ -150,28 +150,55 @@ private function weightedItemRank(string $itemId, array $distances, array $users
}

/**
* Find potential items/users which are a good match for a user/item.
* Find similar users
*
* The algorithm uses the ratings of a a user and tries to find other users who have similar rating behavior and then searches for high rated items that the user doesn't have yet.
*
* This can be used to find items for a specific user (aka might be interested in) or to find users who might be interested in this item
* @param array $ranking Array of item ratings (e.g. products, movies, ...)
*
* option 1 - find items
* ranking[itemId] = itemRank (how much does specific user like item)
* rankings[userId][itemId] = itemRank
* @return array
*
* option 2 - find user
* ranking[userId] = itemRank (how much does user like specific item)
* rankings[itemId][userId] = itemRank
* option 1 searches for items, option 2 searches for users
* @since 1.0.0
*/
public function bestMatchUser(array $ranking, int $size = 10) : array
{
$ranking = $this->normalizeRanking([$ranking]);
$ranking = $ranking[0];

$euclidean = $this->euclideanDistance($ranking, $this->rankings);
// $cosine = $this->cosineDistance($ranking, $this->rankings);

\asort($euclidean);
// \asort($cosine);

$size = \min($size, \count($this->rankings));
$matches = [];

$distancePointer = \array_keys($euclidean);
// $anglePointer = \array_keys($cosine);

// Inspect items of the top n comparable users
for ($i = 0; $i < $size; ++$i) {
// $uId = $i % 2 === 0 ? $distancePointer[$i] : $anglePointer[$i];
$uId = $distancePointer[$i];

if (!\in_array($uId, $matches)) {
$matches[] = $uId;
}
}

return $matches;
}

/**
* Find potential users which are a good match for a user.
*
* @param array $ranking Array of item ratings (e.g. products, movies, ...)
*
* @return array
*
* @since 1.0.0
*/
public function bestMatch(array $ranking, int $size = 10) : array
public function bestMatchItem(array $ranking, int $size = 10) : array
{
$ranking = $this->normalizeRanking([$ranking]);
$ranking = $ranking[0];
Expand All @@ -194,13 +221,13 @@ public function bestMatch(array $ranking, int $size = 10) : array
$distances = $i % 2 === 0 ? $euclidean : $cosine;

foreach ($this->rankings[$uId] as $iId => $_) {
// Item is not already in dataset and not in historic dataset (we are only interested in new)
// Item is already in dataset or in historic dataset (we are only interested in new)
if (isset($matches[$iId]) || isset($ranking[$iId])) {
continue;
}

// Calculate the expected rating the user would give based on what the best comparable users did
$matches[$iId] = $this->weightedItemRank($iId, $distances, $this->rankings, $size);
$matches[$iId] = $this->weightedItemRank((string) $iId, $distances, $this->rankings, $size);
}
}

Expand Down
12 changes: 0 additions & 12 deletions Math/Topology/MetricsND.php
Original file line number Diff line number Diff line change
Expand Up @@ -74,16 +74,10 @@ public static function manhattan(array $a, array $b) : float
*
* @return float
*
* @throws InvalidDimensionException
*
* @since 1.0.0
*/
public static function euclidean(array $a, array $b) : float
{
if (\count($a) !== \count($b)) {
throw new InvalidDimensionException(\count($a) . 'x' . \count($b));
}

$dist = 0.0;
foreach ($a as $key => $e) {
$dist += \abs($e - $b[$key]) ** 2;
Expand All @@ -100,16 +94,10 @@ public static function euclidean(array $a, array $b) : float
*
* @return float
*
* @throws InvalidDimensionException
*
* @since 1.0.0
*/
public static function cosine(array $a, array $b) : float
{
if (\count($a) !== \count($b)) {
throw new InvalidDimensionException(\count($a) . 'x' . \count($b));
}

$dotProduct = 0;
foreach ($a as $id => $_) {
$dotProduct += $a[$id] * $b[$id];
Expand Down
10 changes: 7 additions & 3 deletions Router/SocketRouter.php
Original file line number Diff line number Diff line change
Expand Up @@ -129,21 +129,25 @@ public function route(
}

foreach ($destination as $d) {
if (!($d['active'] ?? true)) {
continue;
}

if ((!isset($d['verb']) || $d['verb'] === RouteVerb::ANY)
|| $verb === RouteVerb::ANY
|| ($verb & $d['verb']) === $verb
) {
// if csrf is required but not set
if (isset($d['csrf']) && $d['csrf'] && $csrf === null) {
if (($d['csrf'] ?? false) && $csrf === null) {
return ['dest' => RouteStatus::INVALID_CSRF];
}

// if permission check is invalid
if (isset($d['permission']) && !empty($d['permission'])
if (!empty($d['permission'] ?? null)
&& ($account === null || $account->id === 0)
) {
return ['dest' => RouteStatus::NOT_LOGGED_IN];
} elseif (isset($d['permission']) && !empty($d['permission'])
} elseif (!empty($d['permission'] ?? null)
&& !($account?->hasPermission(
$d['permission']['type'] ?? 0,
$d['permission']['unit'] ?? $unitId,
Expand Down
6 changes: 3 additions & 3 deletions Router/WebRouter.php
Original file line number Diff line number Diff line change
Expand Up @@ -150,16 +150,16 @@ public function route(
|| ($verb & $d['verb']) === $verb
) {
// if csrf is required but not set
if (isset($d['csrf']) && $d['csrf'] && $csrf === null) {
if (($d['csrf'] ?? false) && $csrf === null) {
return ['dest' => RouteStatus::INVALID_CSRF];
}

// if permission check is invalid
if (isset($d['permission']) && !empty($d['permission'])
if (!empty($d['permission'] ?? null)
&& ($account === null || $account->id === 0)
) {
return ['dest' => RouteStatus::NOT_LOGGED_IN];
} elseif (isset($d['permission']) && !empty($d['permission'])
} elseif (!empty($d['permission'] ?? null)
&& !($account?->hasPermission(
$d['permission']['type'] ?? 0,
$d['permission']['unit'] ?? $unitId,
Expand Down
19 changes: 17 additions & 2 deletions tests/Business/Recommendation/MemoryCFTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
#[\PHPUnit\Framework\Attributes\TestDox('phpOMS\tests\Business\Recommendation\MemoryCFTest: Article affinity/correlation')]
final class MemoryCFTest extends \PHPUnit\Framework\TestCase
{
public function testBestMatch() : void
public function testBestMatchUser() : void
{
$memory = new MemoryCF([
'A' => [1.0, 2.0],
Expand All @@ -33,7 +33,22 @@ public function testBestMatch() : void

self::assertEquals(
['B', 'C'],
$memory->bestMatch([2.2, 4.1], 2)
$memory->bestMatchUser([2.2, 4.1], 2)
);
}

public function testBestMatchItem() : void
{
$memory = new MemoryCF([
'A' => [1.0, 2.0],
'B' => [2.0, 4.0],
'C' => [2.5, 4.0],
'D' => [4.5, 5.0],
]);

self::assertEquals(
[1 => 0.0],
$memory->bestMatchItem([2.2], 2)
);
}
}

0 comments on commit af9a7e1

Please sign in to comment.