File Coverage

blib/lib/WordNet/Similarity/lch.pm
Criterion Covered Total %
statement 7 9 77.7
branch n/a
condition n/a
subroutine 3 3 100.0
pod n/a
total 10 12 83.3


line stmt bran cond sub pod time code
1             # WordNet::Similarity::lch.pm version 2.04
2             # (Last update $Id: lch.pm,v 1.24 2008/03/27 06:21:17 sidz1979 Exp $)
3             #
4             # Semantic Similarity Measure package implementing the measure
5             # described by Leacock and Chodorow (1998).
6             #
7             # Copyright (c) 2005,
8             #
9             # Ted Pedersen, University of Minnesota Duluth
10             # tpederse at d.umn.edu
11             #
12             # Siddharth Patwardhan, University of Utah, Salt Lake City
13             # sidd at cs.utah.edu
14             #
15             # Jason Michelizzi, Univeristy of Minnesota Duluth
16             # mich0212 at d.umn.edu
17             #
18             # This program is free software; you can redistribute it and/or
19             # modify it under the terms of the GNU General Public License
20             # as published by the Free Software Foundation; either version 2
21             # of the License, or (at your option) any later version.
22             #
23             # This program is distributed in the hope that it will be useful,
24             # but WITHOUT ANY WARRANTY; without even the implied warranty of
25             # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26             # GNU General Public License for more details.
27             #
28             # You should have received a copy of the GNU General Public License
29             # along with this program; if not, write to
30             #
31             # The Free Software Foundation, Inc.,
32             # 59 Temple Place - Suite 330,
33             # Boston, MA 02111-1307, USA.
34             #
35             # ------------------------------------------------------------------
36              
37             package WordNet::Similarity::lch;
38              
39             =head1 NAME
40              
41             WordNet::Similarity::lch - Perl module for computing semantic relatedness
42             of word senses using the method described by Leacock and Chodorow (1998).
43              
44             =head1 SYNOPSIS
45              
46             use WordNet::Similarity::lch;
47              
48             use WordNet::QueryData;
49              
50             my $wn = WordNet::QueryData->new();
51              
52             my $myobj = WordNet::Similarity::lch->new($wn);
53              
54             my $value = $myobj->getRelatedness("car#n#1", "bus#n#2");
55              
56             ($error, $errorString) = $myobj->getError();
57              
58             die "$errorString\n" if($error);
59              
60             print "car (sense 1) <-> bus (sense 2) = $value\n";
61              
62             =head1 DESCRIPTION
63              
64             This module computes the semantic relatedness of word senses according
65             to a method described by Leacock and Chodorow (1998). This method counts up
66             the number of edges between the senses in the 'is-a' hierarchy of WordNet.
67             The value is then scaled by the maximum depth of the WordNet 'is-a'
68             hierarchy. A relatedness value is obtained by taking the negative log
69             of this scaled value.
70              
71             =head2 Methods
72              
73             =over
74              
75             =cut
76              
77 4     4   6775 use strict;
  4         9  
  4         102  
78 4     4   17 use Exporter;
  4         9  
  4         128  
79 4     4   2168 use WordNet::Similarity::DepthFinder;
  0            
  0            
80              
81             our @ISA = qw/WordNet::Similarity::DepthFinder/;
82              
83             our $VERSION = '2.04';
84              
85             =item $lch->setPosList()
86              
87             This method is internally called to determine the parts of speech
88             this measure is capable of dealing with.
89              
90             Parameters: none.
91              
92             Returns: none.
93              
94             =cut
95              
96             sub setPosList
97             {
98             my $self = shift;
99             $self->{n} = 1;
100             $self->{v} = 1;
101             }
102              
103             =item $lch->getRelatedness ($synset1, $synset2)
104              
105             Computes the relatedness of two word senses using a node counting scheme.
106             For details on how relatedness is computed, see the Discussion section
107             below.
108              
109             Parameters: two word senses in "word#pos#sense" format.
110              
111             Returns: Unless a problem occurs, the return value is the relatedness
112             score. If no path exists between the two word senses, then a large
113             negative number is returned. If an error occurs, then the error level
114             is set to non-zero and an error string is created (see the description
115             of getError()). Note: the error level will also be set to 1 and an error
116             string will be created if no path exists between the words.
117              
118             =cut
119              
120             sub getRelatedness
121             {
122             my $self = shift;
123             my $wps1 = shift;
124             my $wps2 = shift;
125             my $wn = $self->{wn};
126              
127             my $class = ref $self || $self;
128              
129             unless ($wn) {
130             $self->{errorString} .= "\nError (${class}::getRelatedness()) - ";
131             $self->{errorString} .= "A WordNet::QueryData object is required.";
132             $self->{error} = 2;
133             return undef;
134             }
135              
136             # Initialize traces.
137             $self->{traceString} = "";
138              
139             # JM 1-21-04
140             # moved input validation code to parseWps() in a super-class
141             my $ret = $self->parseWps ($wps1, $wps2);
142             ref $ret or return $ret;
143             my ($word1, $pos1, $sense1, $offset1, $word2, $pos2, $sense2, $offset2)
144             = @{$ret};
145              
146             my $pos = $pos1;
147              
148             # Now check if the similarity value for these two synsets is in
149             # fact in the cache... if so return the cached value.
150             my $relatedness =
151             $self->{doCache} ? $self->fetchFromCache ($wps1, $wps2) : undef;
152             defined $relatedness and return $relatedness;
153              
154             # Now get down to really finding the relatedness of these two.
155              
156             # JM 3-9-04
157             # Modified to use the methods of DepthFinder et al.
158              
159             my @LCSs = $self->getLCSbyPath ($offset1, $offset2, $pos1, 'offset');
160              
161             # check if there is no path between synsets
162             unless (defined $LCSs[0]) {
163             return $self->UNRELATED;
164             }
165              
166             # find the LCS (well, path really) that is in the deepest taxonomy
167             my $maxdepth = -1;
168             my $length;
169             foreach (@LCSs) {
170             my $lcs;
171             ($lcs, $length) = @{$_};
172              
173             my @roots = $self->getTaxonomies ($lcs, $pos1);
174              
175             foreach my $root (@roots) {
176             my $depth = $self->getTaxonomyDepth ($root, $pos1);
177             unless (defined $depth) {
178             $self->{error} = $self->{error} < 1 ? 1 : $self->{error};
179             $self->{errorString} .="\nWarning (${class}::getRelatedness()) - ";
180             $self->{errorString} .= "Taxonomy depth for $root undefined.";
181             return undef;
182             }
183             $maxdepth = $depth if $depth > $maxdepth;
184             }
185             }
186              
187             if ($maxdepth <= 0) {
188             $self->{error} = $self->{error} < 1 ? 1 : $self->{error};
189             $self->{errorString} .= "\nWarning (${class}::getRelatedness()) - ";
190             $self->{errorString} .= "Max depth of taxonomy is not positive.";
191             return undef;
192             }
193              
194             my $score = log (2 * $maxdepth / $length);
195              
196             $self->storeToCache ($offset1, $offset2, $score);
197              
198             return $score;
199             }
200              
201             1;
202              
203             __END__