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

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