root/Explorator/trunk/app/controllers/facets_controller.rb @ 121

Revision 121, 14.1 KB (checked in by samuraraujo, 5 years ago)
Line 
1#This Controller is in charge of the facet generation.
2#It implements a algorithms that uses entropy to determinate the weight of each facet.
3#It algorithms is better described in the Explorator spefication.
4#Author: Samur Araujo
5#Date: 25 jun 2008.
6
7#module where the SemanticExpression class is defined.
8require 'query_builder'
9#module where the query class is defined.
10require 'query_factory'
11class FacetsController < ApplicationController
12  #session :disabled => true
13  #The execute method  evaluate a ruby expression.
14  #this method is used to invoke another method of Explorator.
15  #Basically, the UI call this method passing as the expression a
16  # call to the method facet or infer.
17  def execute   
18    eval(params[:exp])
19  end 
20  def create
21    properties= eval(params[:exp]).result   
22    facetgroup=FACETO::FacetGroup.new('<http://www.semanticnavigation.org/2008/faceto#' << params[:name] << '>')
23    facetgroup.rdfs::label=params[:name]
24    facetgroup.faceto::type=RDFS::Resource.new('http://www.semanticnavigation.org/2008/faceto#userdefined')
25    facetgroup.save
26    #it will hold all the facets
27    facets = Array.new
28    properties.each do |predicate|
29      if predicate.instance_of? RDF::Property       
30        #create a object FACETO:Facet for each resource property and add it to the facets array.
31        #This code only creates facets that represents properties. Facets that represents expressions are not considerated here.
32        id =UUID.random_create.to_s
33        facet = FACETO::Facet.new('<http://www.semanticnavigation.org/2008/faceto#' << id << '>')
34        facet.save             
35        facet.faceto::derivedTerm = predicate     
36        facet.faceto::use = predicate         
37        facet.save     
38        #add the facet to the facet array.
39        facets << facet       
40        #Sets the facets for the FacetGroup object.       
41      end       
42    end
43    facetgroup.faceto::facet = facets 
44  end 
45  #the parameter id is the ResourceSet identification in the SetsPool.
46  def facet (id) 
47    #gets a ResourceSet instance in the pool.
48    @resourceset= session[:application].get(id)       
49    #Gets a facet defined by the user in the repository.
50    # FACETO::FacetGroup belong to the ActiveRDF model and the vocabulary FACETO::FacetGroup was defined by the Explorator.
51   
52    #  @groups=FACETO::FacetGroup.find_all()
53    #  @facetgroup=FACETO::FacetGroup.find_by_rdfs::label('Group1').first
54    @groups=FACETO::FacetGroup.find_by_faceto::type(RDFS::Resource.new('http://www.semanticnavigation.org/2008/faceto#userdefined'))
55    @facetgroup=FACETO::FacetGroup.find_by_rdfs::label(params[:name]).first 
56   
57    #Calculates all the facets for a set of resources.
58    entropy_by_set(@resourceset.resources)
59    #render the _facet.rhtml view
60    render :partial => "facet" 
61  end
62  #Infer the facets for the specific set
63  def infer   (id)     
64    #gets a ResourceSet instance in the pool.
65    @resourceset= session[:application].get(id) 
66    @groups=FACETO::FacetGroup.find_by_faceto::type(RDFS::Resource.new('http://www.semanticnavigation.org/2008/faceto#userdefined'))
67   
68    inference(@resourceset.resources,UUID.random_create.to_s)
69    #Calculates all the facets for a set of resources
70    entropy_by_set(@resourceset.resources)   
71    #render the _facet.rhtml view
72    render :partial => "facet" 
73  end
74  #The entropy_by_set method implements the facet algorithm itself.
75  #The algorithm only calculates facets that are defined as resource properties.
76  #Others kind of facets, described in the specification, are not taken into account here.
77  # Calculates the entropy for each facet.
78  def entropy_by_set(_resources) 
79    puts 'FACETANDO...'
80    #store the valid facets
81    @facets = Hash.new
82    @exp=Hash.new
83    if _resources.size() ==0
84      return
85    end
86    #detect using entropy wich facet will be valid
87    if @facetgroup == nil
88      return
89    end   
90   
91    @facetgroup.all_faceto::facet.each do |facet|             
92      #handles the facets that have an hierarchy of values.
93      facetroot = facet.instance_eval("faceto::level1")
94      puts facet
95      if   facetroot  != nil 
96        facet = facetroot
97      end
98      #      if $already_selected  == nil
99      #      $already_selected= Array.new
100      #      end
101      #      if facetroot != nil   
102      #        i=1
103      #        while $already_selected.include?( facetroot )
104      #          i+=1
105      #          facetroot = facet.instance_eval("faceto::level" + i.to_s)
106      #          puts 'teste'+ i.to_s
107      #        end
108      #        if facetroot == nil
109      #          next 
110      #        end
111      #        $already_selected << facetroot     
112      #        facet = facetroot         
113      #           
114      #      end         
115      #the synonym are used when the are 2 or more object properties that describe the same values.
116      #See the definition bellow
117      #      :country rdf:type faceto:Facet ;     
118      #           faceto:derivedTerm fn:country;
119      #           faceto:synonym   :brasil
120      #           faceto:synonym   :america
121      #            faceto:use dp1:region
122      #           faceto:operation 'union'     
123      #    :brasil  faceto:word fn:region/bra;
124      #              faceto:word fn:region/brasil;   
125      #
126      #    :america faceto:word fn:region/americas;
127      #              faceto:word dp:country/americas.
128     
129      synonyms = Hash.new
130      facet.all_faceto::synonym.each{|synonym|
131        synonyms[synonym.all_word] = synonym
132      }     
133      entropy = 0
134      objects = Array.new
135      @exp[facet]= Hash.new
136      puts facet
137      prob_p=0
138      hash_object=Hash.new
139      _resources.each do |resource|       
140        next if !resource.instance_of? RDFS::Resource   
141        qresult = Array.new
142        type = 'normal' #use when there are computedvalue in the facet
143        constraint=nil
144        computedValue =  facet.all_faceto::computedValue           
145        computedValue.each {|cvalue|             
146          begin           
147            type='computed' 
148            #verifies if the computedvalue has a contraint expression
149            if cvalue.faceto::constraint != nil
150              #set the facet for the type contraint
151              type='constraint'               
152              #all contraint computedvalue has a query expression
153              constraint=cvalue.faceto::query                                 
154            end
155            #verifies whether the resource satisfies the constraint(faceto::contraint) in case of exists.
156            if  cvalue.faceto::constraint == nil  || resource.instance_eval(cvalue.faceto::constraint) == true             
157              #the variable will be passed to the exp method to create the expression correctly             
158              if cvalue.faceto::expressionValue != nil 
159                qresult <<  resource.instance_eval(cvalue.faceto::expressionValue)
160                #verifies if the computed value has a queryvalue expresion. This expression is used to get the facet values.
161              elsif cvalue.faceto::queryValues != nil   
162                #get the expression used to filter the elements being faceted
163                constraint=cvalue.faceto::query   
164                #get all possible values for the facet.
165                qresult = qresult |  eval(cvalue.faceto::queryValues)                 
166              else
167                #get a literal value
168                qresult <<  cvalue.faceto::literalValue               
169              end
170              break
171            end
172          rescue
173            print "An error occurred: ",$!, "\n"
174          end     
175        }         
176        #verifies if the facet is a derived type.
177        if computedValue.size() == 0
178          if facet.faceto::use != nil 
179            #get the values based in the property
180            qresult = QueryFactory.new.distinct(:o).where(resource, facet.faceto::use,:o).execute
181          elsif facet.faceto::useInverse != nil 
182            qresult = QueryFactory.new.distinct(:o).where(resource, facet.faceto::useInverse,:o).execute
183          end   
184        end
185       
186        #property :p occurs em :s
187        if qresult.size > 0         
188          prob_p += 1
189        end
190        #frequence that :o occurs for each :s
191        qresult.each do |o|   
192         
193          #gets the default word in case where exists a table of synonyms   
194          synomymswords =nil
195          if synonyms.size() > 0
196            synonyms.keys.each{|words|
197              if words.include?(o)   
198                synomymswords=words
199                o =  synonyms[words].faceto::defaultWord
200                break
201              end
202            }
203          end
204          if hash_object[o] == nil
205            hash_object[o] = 1             
206            #create the query expression for this facet values
207            exp(facet, resource, o,type,synomymswords,constraint) 
208           
209          else
210            hash_object[o] = hash_object[o]+1           
211          end         
212        end
213      end
214     
215      # puts prob_p
216      #calculates the object occurencies
217     
218      hash_object.each_key do |object|     
219        count=   hash_object[object]
220        # puts object
221       
222        #calculate the object probability
223        #puts prob_p.to_f
224        #puts count
225        prob_o = count.to_f / prob_p.to_f
226       
227        if prob_o !=1         
228          objects << object
229        end
230       
231        #puts prob_o
232        #calculate the entropy based on the object probability
233        entropy = entropy + prob_o * Math.log(prob_o)   
234      end     
235      #calculates the objects' cardinality
236      if entropy != 0         
237        cardinalities = Array.new       
238        objects.each do |object|
239          #  puts object
240          h = Hash.new
241          h[object]=hash_object[object]
242          cardinalities << h
243        end       
244        @facets[FACETO::Facet.new(facet)]=cardinalities       
245      end     
246    end       
247   
248  end
249  ####################################################################################
250  #The inference method determines each possible facet, based on each resources properties
251  #The algorithm used is basd on entropy concept.
252  def inference(resources,cid)
253    #all predicates from all resources passed as parameters
254    predicates = Array.new   
255    resources.each do |s|     
256      predicates= predicates | Query.new.distinct(:p).where(s,:p,:o).execute
257    end   
258   
259    #create a object FacetGroup for this instance of resources
260    @facetgroup=FACETO::FacetGroup.new('<http://www.semanticnavigation.org/2008/faceto#' << cid << '>')
261    @facetgroup.rdfs::label=cid
262    @facetgroup.faceto::type=RDFS::Resource.new('http://www.semanticnavigation.org/2008/faceto#infered')
263    @facetgroup.save
264    #it will hold all the facets
265    facets = Array.new
266    #create an object FACETO:Facet for each resource property and add it to the facets array.
267    #This code only creates facets that represents properties. Facets that represents expressions are not considerated here.
268    predicates.each do |predicate|       
269      facet = FACETO::FacetGroup.find_by_faceto::use(predicate).first()
270      if facet == nil
271         
272        id =UUID.random_create.to_s
273        facet = FACETO::Facet.new('<http://www.semanticnavigation.org/2008/faceto#' << id << '>')
274        facet.save     
275        facet.faceto::derivedTerm = predicate     
276        facet.faceto::use = predicate   
277        facet.save     
278      end
279      #add the facet to the facet array.
280      facets << facet
281    end 
282    #Sets the facets for the FacetGroup object.
283    @facetgroup.faceto::facet = facets   
284  end 
285  #create the expression for each facet value.
286  #the expression is different for each facet value.
287  def exp(facet, resource, value,type,words,constraint=nil,header=true,operation='intersection')         
288    #it will store the expression
289    exp = ''   
290    #get the value for a specific property when the value was computed.     
291    if type=='computed' && constraint != nil             
292      exp= '(' + constraint.gsub('resource', "RDFS::Resource.new('"+value.to_s+"')")   + ',:p, :o)'
293    elsif type=='constraint'   
294      exp = @resourceset.expression + "."     
295      #must be a filter expression
296      exp = exp + constraint
297      return  @exp[facet][value] =   exp
298    else       
299      properties = Array.new
300      #gets all properties used to calculated the facet value
301      properties = properties | facet.all_faceto::use
302      #iterate over each property
303      properties.each {|property|       
304        if type=='computed'
305          #gets the value of this property in this resource
306          object  = Query.new.distinct(:o).where(resource,property,:o).execute.to_s
307        else
308          #the value in the interface is the same as than the value that will be in the expression
309          #in this case the value was not computed but derived from a property.
310          object = value.to_s
311        end   
312        if exp == ''
313          exp = "(:s,'" + property.to_s() + "', '"+ object + "')"       
314        else
315          exp = exp + "."+operation+"(:s,'" + property.to_s() + "', '"+ object + "')"       
316        end       
317      }       
318      properties = Array.new
319      properties = properties | facet.all_faceto::useInverse
320      #iterate over each property
321      properties.each {|property|       
322        if type=='computed'
323          #gets the value of this property in this resource
324          object=Query.new.distinct(:o).where(:o,property,resource).execute.to_s
325        else
326          #the value in the interface is the same as than the value that will be in the expression
327          #in this case the value was not computed but derived from a property.
328          object = value.to_s
329        end   
330        if exp == ''
331          exp = "('"+ object + "','" + property.to_s() + "', :s)"   
332        else
333          exp = exp + "."+operation+"('"+ object + "','" + property.to_s() + "', :s)"       
334        end       
335      }         
336    end
337    if words != nil
338      words.each {|word|
339        if word!=value
340          exp = exp + ".union"+ exp(facet, resource, word,type,nil,constraint,false) 
341        end
342      }
343    end
344    if header
345      exp =  "SemanticExpression.new" + exp
346    end
347    puts exp
348    @exp[facet][value] =   exp
349  end
350end
Note: See TracBrowser for help on using the browser.