Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

add brute force ANN.

  • Loading branch information...
commit b49e1d11c15a369e85dbc87d25d3319d989dd34f 1 parent 271184b
Kuzuha SHINODA authored
63 lib/Plann/ANN/BruteForce.pm
... ... @@ -0,0 +1,63 @@
  1 +use 5.14.0;
  2 +package Plann::ANN::BruteForce;
  3 +use true;
  4 +use Mouse;
  5 +
  6 +use Plann::ANN::Utils;
  7 +
  8 +with 'Plann::Role::ANN';
  9 +
  10 +=head1 Interface
  11 +
  12 +=head2 Constructors
  13 +
  14 +=head3 new
  15 +
  16 +Create a new Plann::ANN::BruteForce object.
  17 +
  18 +=head4 Parameters
  19 +
  20 +...
  21 +
  22 +=cut
  23 +
  24 +has 'entries' => (
  25 + traits => ['Array'],
  26 + is => 'ro',
  27 + isa => 'ArrayRef[Plann::ANN::Entry]',
  28 + default => sub { [] },
  29 + handles => { _train => 'push' },
  30 +);
  31 +
  32 +=head2 Instance Methods
  33 +
  34 +=head3 train
  35 +
  36 +...
  37 +
  38 +=cut
  39 +
  40 +sub train { shift->_train(@_) }
  41 +
  42 +=head3 search
  43 +
  44 +...
  45 +
  46 +=cut
  47 +
  48 +sub search {
  49 + my $self = shift;
  50 + my ($matrix, $options) = @_;
  51 +
  52 + my $res = [];
  53 + for my $entry (values $self->entries) {
  54 + my $distance = euclidean_distance(map {$_->[0]->[0]} $entry->vector, $matrix);
  55 +
  56 + next if $options->{threshold} && $distance > $options->{threshold};
  57 + push $res, {
  58 + distance => $distance,
  59 + entry => $entry,
  60 + };
  61 + }
  62 + [sort { $a->{distance} <=> $b->{distance} } @$res];
  63 +}
31 lib/Plann/ANN/Entry.pm
... ... @@ -0,0 +1,31 @@
  1 +use 5.14.0;
  2 +package Plann::ANN::Entry;
  3 +use true;
  4 +use Mouse;
  5 +
  6 +use Plann::Subtypes;
  7 +
  8 +has 'vector' => (
  9 + is => 'ro',
  10 + isa => 'Matrix',
  11 + coerce => 1,
  12 + required => 1,
  13 +);
  14 +
  15 +has 'parameters' => (
  16 + is => 'ro',
  17 + isa => 'HashRef',
  18 + default => sub { {} },
  19 +);
  20 +
  21 +sub BUILDARGS {
  22 + my ($self, @args) = @_;
  23 + if (ref $args[0]) {
  24 + if (1 == scalar @args) {
  25 + @args = (vector => $args[0]);
  26 + } else {
  27 + @args = (vector => $args[0], parameters => $args[1]);
  28 + }
  29 + }
  30 + return {@args};
  31 +}
6 lib/Plann/Role/ANN.pm
... ... @@ -0,0 +1,6 @@
  1 +use 5.14.0;
  2 +package Plann::Role::ANN;
  3 +use true;
  4 +use Mouse::Role;
  5 +
  6 +requires qw/search train/;
48 t/usual/ann/brute_force.t
... ... @@ -0,0 +1,48 @@
  1 +use 5.14.0;
  2 +use Test::Most tests => 4;
  3 +
  4 +use Plann::ANN::BruteForce;
  5 +use Plann::ANN::Entry;
  6 +
  7 +my $ann = Plann::ANN::BruteForce->new;
  8 +
  9 +my @entries = (
  10 + Plann::ANN::Entry->new([1,2,3]),
  11 + Plann::ANN::Entry->new([2,3,4]),
  12 + Plann::ANN::Entry->new([100,200,300]),
  13 +);
  14 +
  15 +my $expected = [
  16 + { entry => $entries[1], distance => 0 },
  17 + { entry => $entries[0], distance => 1.73205080756888 },
  18 + { entry => $entries[2], distance => 368.821094841388 },
  19 +];
  20 +
  21 +$ann->train($_) for @entries;
  22 +
  23 +#
  24 +# search
  25 +#
  26 +is_deeply(
  27 + $ann->search($entries[1]->vector),
  28 + $expected
  29 +);
  30 +
  31 +#
  32 +# search with threshold
  33 +#
  34 +pop $expected;
  35 +is_deeply(
  36 + $ann->search($entries[1]->vector, { threshold => 2 }),
  37 + $expected
  38 +);
  39 +is_deeply(
  40 + $ann->search($entries[1]->vector, { threshold => 1.73205080756888 }),
  41 + $expected
  42 +);
  43 +
  44 +pop $expected;
  45 +is_deeply(
  46 + $ann->search($entries[1]->vector, { threshold => 1.73205080756887 }),
  47 + $expected
  48 +);
16 t/usual/ann/entry.t
... ... @@ -0,0 +1,16 @@
  1 +use 5.14.0;
  2 +use Test::Most tests => 2;
  3 +
  4 +use Plann::ANN::Entry;
  5 +
  6 +my $entry;
  7 +
  8 +is_deeply(
  9 + Plann::ANN::Entry->new([1,2,3]),
  10 + Plann::ANN::Entry->new(vector => [1,2,3])
  11 +);
  12 +
  13 +is_deeply(
  14 + Plann::ANN::Entry->new([1,2,3], { threshold => 10 }),
  15 + Plann::ANN::Entry->new(vector => [1,2,3], parameters => { threshold => 10 })
  16 +);

0 comments on commit b49e1d1

Please sign in to comment.
Something went wrong with that request. Please try again.