source: src/tre/tre @ 0a58b3f

Last change on this file since 0a58b3f was 0a58b3f, checked in by to <to@…>, 10 years ago

Ruby version update

  • Property mode set to 100755
File size: 11.5 KB
Line 
1#!/usr/bin/env ruby
2# -*- coding: iso-8859-2 -*-
3
4# $: << "#{ENV['HOME']}/.local/lib/utt"
5$: << "/usr/local/lib/utt"
6
7require 'getoptlong'
8require 'seg.rb'
9
10opts = GetoptLong.new(
11[ '--help',     '-h',   GetoptLong::NO_ARGUMENT ],
12[ '--debug',    '-d',   GetoptLong::NO_ARGUMENT ],
13[ '--format',   '-F',   GetoptLong::REQUIRED_ARGUMENT ],
14[ '--info',     '-I',   GetoptLong::REQUIRED_ARGUMENT ],
15[ '--span',     '-s',   GetoptLong::REQUIRED_ARGUMENT ],
16[ '--maxsize',          GetoptLong::REQUIRED_ARGUMENT ],
17[ '--forest',           GetoptLong::NO_ARGUMENT ],
18[ '--ground',           GetoptLong::NO_ARGUMENT ],
19[ '--only-trees','-t',  GetoptLong::NO_ARGUMENT ])
20
21$helptext=
22"The program generates trees from the graph output by dgp. dgp must\n"+
23"must be run with '--info=ds' option.\n\n"+
24"Command:       tre [options]\n\n"+
25"Options:\n"+
26"--help         -h      Print help (this text) and exit.\n"+
27"--debug        -d      Verbose output. For developers only.\n"+
28"--format=s     -F s    Output format. Recognized values:\n"+
29"                               a       root + list of arcs\n"+
30"                               p       parenthesized notation\n"+
31"                               h       human readable indented tree format\n"+
32"                       Multiple values are allowed. (default p)\n"+
33"--info=s       -I s    Information printed. Recognized values:\n"+
34"                               n       node identifier\n"+
35"                               f       surface form\n"+
36"                               m       morphological information\n"+
37"                               l       arc labels\n"+
38"--only-trees   -t      Do not copy input. Print trees only.\n"
39
40$DEBUG=false
41$FORMAT='p'
42$INFO='DEFAULT'
43$ONLYTREES=false
44$START=nil
45$END=nil
46$FOREST=false
47$MAXSIZE=nil
48
49opts.each do |opt, arg|
50  case opt
51  when '--help'
52    print $helptext
53    exit 0
54  when '--debug'
55    $DEBUG=true
56  when '--format'
57    $FORMAT=arg
58  when '--info'
59    $INFO=arg
60  when '--only-trees'
61    $ONLYTREES=true
62  when '--forest'
63    $FOREST=true
64  when '--ground'
65    $GROUND=true
66  when '--maxsize'
67    $MAXSIZE=arg.to_i
68  when '--span'
69    $START,$END = arg.split ','
70  else
71    print "Unknown option #{opt}. Ignored.\n"
72  end
73end
74
75if $INFO=='DEFAULT'
76  case $FORMAT
77    when 'p','a'
78    $INFO='nl'
79    when 'h'
80    $INFO='fmnl'
81  end
82end
83
84$dgpsep=';'
85
86def tre(input)
87  $gphid=[]
88  $form=[]
89  $lem=[]
90  $ord1=[]
91  $count=0
92  nodes=[]
93  prevpos=-1
94  tokennumber=0
95  for line in input
96    seg=Seg.new(line)
97    print line unless $ONLYTREES || seg.field(3) == 'EOS'
98   
99    if dgp=seg['dgp']
100      if nodes==[] && seg[3]!='BOS'
101        print "A sentence must start with BOS segment. Aborting.\n"
102        return
103      end
104
105      id=dgp[/^\d+/].to_i
106
107      if gph=seg['gph']
108        $gphid[id]=gph[/^\d+/].to_i
109      else
110        print "No gph field. Aborting.\n"
111        return
112      end
113
114      $form[$gphid[id]] = seg[4]
115      $lem[$gphid[id]] = seg['lem']
116      $ord1[$gphid[id]] = if prevpos==seg[1].to_i then tokennumber
117                         else prevpos=seg[1].to_i; tokennumber+=1 end
118             
119      nodes[id] = [seg[1].to_i,seg[2].to_i,dgp]
120
121      if seg[3]=='EOS'
122
123        $pref = "#{seg[1]} #{seg[2]} SYN *"
124
125        parsegraph(nodes)
126
127        set_ord #(0...(nodes.length)).each{|i| set_distance_from_i i }
128
129        printgraph if $DEBUG
130
131        if $GROUND
132          printground
133        else
134          thetrees = $FOREST ? genforest : gentrees
135         
136          output_trees thetrees
137         
138          print line unless $ONLYTREES
139         
140          $gphid=[]   # POWTÓRZENIE
141          $form=[]
142          $lem=[] 
143          $ord1=[]
144          $count=0     
145          nodes=[]
146          prevpos=-1
147          tokennumber=0
148        end
149      end
150    end
151  end
152end
153
154
155def output_trees trees
156  for t in trees
157    $count += 1
158    # t1=ground(t)
159
160    t1=t
161
162    span = $FOREST ? " span:" + (ground_tree_min(t1).to_s + ","+ground_tree_max(t1).to_s)+";" : ""
163    case $FORMAT
164    when /a/
165      print "#{$pref} tre:#{$count}#{span} #{arcsinfo(t1[0],t1[1])}"
166#       print arcsinfo(t1[0],t1[1])
167      print "\n"
168    when /p/
169      print "#{$pref}#{span} tre:#{$count} par:"
170      printpar(t1[0],t1[1])
171      print "\n"
172    when /h/
173      print "#\n# tree #{$count}\n# ------\n"
174      printtree_dgp(t1[0],t1[1],0)
175    end
176  end
177end
178
179
180def nodeinfo(id)
181  info=""
182  gphid = $gphid[id]
183  if $INFO =~ /o/
184    info += $ord1[gphid].to_s + '/' + gphid.to_s + '/' + id.to_s
185    info += '.' if $INFO =~ /[nfm]/
186  end
187  if $INFO =~ /n/
188    info += gphid.to_s                           
189    info += '.' if $INFO =~ /[fm]/
190  end
191  if $INFO =~ /f/
192    info += $form[gphid] 
193    info += ';' if $INFO =~ /m/
194  end
195  if $INFO =~ /m/
196    info += $lem[gphid] 
197  end
198  info
199end
200
201
202def arcsinfo(root,arcs)
203  "head:#{nodeinfo(root)} links:" + arcs.map{|a| "(#{($INFO =~ /l/) ? a[2]+":" : ""}#{nodeinfo(a[0])}-#{nodeinfo(a[1])})"}.join("")
204#   for a in arcs
205#     print ';'
206#     print "#{a[2]}:" if $INFO =~ /l/
207#       print nodeinfo(a[0])+'-'+nodeinfo(a[1])
208#   end
209end
210
211def printtree(root,arcs,o)
212  if o==0
213        print "# %-16s" % "root: "
214  end
215  print nodeinfo(root),"\n"
216  for arc in arcs.select{ |a| a[0]==root }.sort{|a,b| a[1]<=>b[1] }
217    print '# ',"   "*(o+1)
218    print "%-16s" % (arc[2]+": ")
219    printtree(arc[1],arcs,o+1)
220  end
221end
222
223def printtree_dgp(root,arcs,o)
224  if o==0
225        print "%-16s" % "root: "
226  end
227  print nodeinfo(root),"\n"
228  for arc in arcs.select{ |a| a[0]==root }.sort{|a,b| a[1]<=>b[1] }
229    print "   "*(o+1)
230    print "%-16s" % (arc[2]+": ")
231    printtree_dgp(arc[1],arcs,o+1)
232  end
233end
234
235# old:
236# def printpar(root,arcs)
237#   print nodeinfo(root)
238#   deps = arcs.select{ |a| a[0]==root }.sort{|a,b| a[1]<=>b[1] }
239#   unless deps == []
240#     print '('
241#     cont=false
242#     for arc in deps
243#       if cont then print ',' else cont=true end
244#       print arc[2],':' if $INFO =~ /l/
245#       printpar(arc[1],arcs)
246#     end
247#     print ')'
248#   end
249# end
250
251def printpar(root,arcs)
252 
253  ldeps = arcs.select{|a| a[0]==root and $gphid[a[1]] < $gphid[root]}.sort{|a,b| $gphid[a[1]]<=>$gphid[b[1]] }
254  rdeps = arcs.select{|a| a[0]==root and $gphid[a[1]] > $gphid[root]}.sort{|a,b| $gphid[a[1]]<=>$gphid[b[1]] }
255
256  for arc in ldeps
257    print ' ('
258    print arc[2].upcase if $INFO =~ /l/
259    printpar(arc[1],arcs)
260    print ')'
261  end
262
263  print ' ',nodeinfo(root)
264
265  for arc in rdeps
266    print ' ('
267    print arc[2].upcase if $INFO =~ /l/
268    printpar(arc[1],arcs)
269    print ')'
270  end
271end
272
273
274def ground_tree_min t
275  ([t[0]]+t[1].map{|e| [e[0],e[1]]}).flatten.min
276end
277
278def ground_tree_max t
279  ([t[0]]+t[1].map{|e| [e[0],e[1]]}).flatten.max
280end
281
282
283
284def parsegraph(nodes)
285
286  $n   =nodes.length
287  $sat =[]; $vis =[]; $succ=[]; $lhs =[]; $arcs=[]; $pos=[]; $len=[]; $ord=[]; $distance={}
288
289  for dgp in nodes
290
291    parts  = dgp[2].split($dgpsep,7)
292
293    if parts[3]==nil || parts[4]==nil || parts[5]==nil
294      $stderr.print "ERR: tre requires dgp be called with '--info=ds' option. Aborting.\n"
295      exit
296    end
297
298    i      = parts[0].to_i
299    $pos[i] = dgp[0].to_i
300    $len[i] = dgp[1].to_i
301    $sat << i if parts[1]=="s"
302
303    $arcs |= parts[2].scan(/\([^()]+\)/).map{ |a| case a
304                                          when /\-\-(\w+):(\d+)/
305                                            # [i, $2.to_i, $1, $3.to_i, $4.to_i]
306                                            [i, $2.to_i, $1, 0, 0]
307                                          when /\+\+(\w+):(\d+)/
308                                            # [$2.to_i, i, $1, $3.to_i, $4.to_i]
309                                            [$2.to_i, i, $1, 0, 0]
310                                          end }
311    $succ |= parts[3][1..-2].split(',').map{|x| [x.to_i,i]}
312    $vis  |= parts[4][1..-2].split(',').map{|x| [x.to_i,i]} 
313    $lhs  |= parts[5][1..-2].split(',').map{|x| [x.to_i,i]} + [[i,i]]
314
315  end
316
317end
318
319
320def ground(t)
321  [ $gphid[t[0]] , t[1].map{|a| [$gphid[a[0]],$gphid[a[1]],a[2]]} ]
322end 
323
324
325#NOWE-START
326
327def successors i
328  $succ.select{|e| e[0]==i}.map{|e| e[1]}
329end
330
331def predecessors i
332  $succ.select{|e| e[1]==i}.map{|e| e[0]}
333end
334
335def start_nodes
336  $succ.map{|e| e[1]}.map{|e| predecessors(e)}.uniq.map{|e| e[0]}
337end
338
339def end_nodes
340  $succ.map{|e| e[0]}.map{|e| successors(e)}.uniq.map{|e| e[0]}
341end
342
343def set_ord
344  positions = $pos.uniq.sort
345  (0...$n).each{|i| $ord[i] = positions.index($pos[i]) }
346end
347
348
349def set_distance_from_i i
350  set_distance_from_i_to_jth_successors_to_v i, i, 1
351end
352
353def set_distance_from_i_to_jth_successors_to_v i, j , v
354  succ = successors(j)
355  for j1 in succ
356    $distance[[i,j1]] = v
357    set_distance_from_i_to_jth_successors_to_v i, j1, v+1
358  end
359end
360
361#NOWE-END
362
363
364def gentrees
365  bos=0; eos=$n-1;
366  gentrees2 bos, eos
367end
368
369
370def genforest
371  forest=[]
372  for bos in start_nodes
373    for eos in end_nodes # tu s± te¿ wierzcho³ki poprzedzaj±ce!!!
374      next if $ord[bos] > $ord[eos] or ($MAXSIZE != nil and $ord[eos] - $ord[bos] > $MAXSIZE+1)
375      forest += gentrees2(bos,eos)
376    end
377  end
378  forest
379end
380
381def gentrees2 bos, eos
382  $thetrees=[];
383  roots = (bos..eos).select{|i| $vis.include? [i,eos]}.select{|i| $vis.include? [bos,i]}
384
385  if $DEBUG then print "ROOTS: #{roots.inspect}\n" end
386  for root in roots
387    gentrees3 bos, eos, root
388  end
389  $thetrees
390end
391
392def gentrees3 bos, eos, root
393  $theroot=root
394  $thebos=bos
395  $theeos=eos
396  for r in buildR(root , eos, [])
397    (rmin,rmax,rtree) = r
398    buildR(bos, rmin, rtree)
399  end
400end
401
402def buildR(min, max, tree)
403  if $DEBUG then print "buildR--#{min}--#{max}--#{tree.inspect}\n" end
404  trees=[]
405  for arc in $arcs.select{|a| a[0]==max && $vis.include?([min,a[1]]) }
406    if $DEBUG then print "ARC: #{arc.inspect}\n" end
407    for r in buildR(arc[1],arc[0],tree+[arc])                 #!!! buildR(a[1],a[3],tree+[a])
408      # for r in buildR(arc[4],arc[3],tree+[arc])                 #!!! buildR(a[1],a[3],tree+[a])
409      (rmin,rmax,rarcs) = r
410      for l in buildR(min,rmin,rarcs)
411        (lmin,lmax,larcs) = l
412        trees << [lmin,rmax,larcs]
413      end
414    end
415  end
416  for i in (0...$n).select{|i| $succ.include?([i,max])}.select{|i| $lhs.include?([min,i])}
417    for l in buildL(min,i,tree)
418      (lmin,lmax,larcs) = l
419      trees << [lmin,lmax,larcs]
420    end
421  end
422  trees 
423end
424   
425
426def buildL(min,max,tree)
427  if $DEBUG then print "buildL--#{min}--#{max}--#{tree.inspect}\n" end
428  if $pos[min]==$pos[max]
429    if min==$thebos && max==$thebos
430      $thetrees.push [$theroot,tree]
431      if $DEBUG then print "adding tree: #{tree.inspect}\n" end
432    end
433    return [[max,max,tree]]
434  end
435  trees=[]
436  for arc in $arcs.select{|a| a[1]==max && $lhs.include?([min,a[0]]) }
437    if $DEBUG then print "ARC: #{arc.inspect}\n" end
438     for r in buildR(arc[0],arc[1],tree+[arc]) ### buildR(arc[3],max,tree+[arc])
439     #for r in buildR(arc[3],arc[4],tree+[arc]) ### buildR(arc[3],max,tree+[arc])
440      (rmin,rmax,rarcs) = r
441      for l in buildL(min,rmin,rarcs)
442        (lmin,lmax,larcs) = l
443        trees << [lmin,lmax,larcs]
444      end
445    end
446  end
447  trees
448end
449
450
451def printgraph()
452  print "N:    #{$n}\n"
453  print "SAT:  #{set_to_s($sat)}\n"
454  print "SUCC: #{rel_to_s($succ)}\n"
455  print "VIS:  #{rel_to_s($vis)}\n"
456  print "LHS:  #{rel_to_s($lhs)}\n"
457  print "ARCS: #{arcs_to_s($arcs)}\n"
458end
459
460
461def printground
462  for i in 1...($form.length-1)
463    print "#{$ord1[i]} #{$form[i]} #{$lem[i]} "
464    print $arcs.select{|a| $ord1[$gphid[a[1]]] == $ord1[i]}.map{|a| "#{a[2]}:#{$ord1[$gphid[a[0]]]}"}.sort.uniq.join(' ')
465    print "\n"
466  end
467end
468
469
470def set_to_s(s) "{#{s.join(',')}}" end
471def rel_to_s(r) "{#{r.map{|p| "(#{p[0]},#{p[1]})"}.join(',')}}" end
472def arc_to_s(q) "-#{q[0]}-#{q[2]}-#{q[1]}/#{q[3]}" end
473def arcs_to_s(a) "{#{a.map{|q| arc_to_s(q)}.join(',')}}" end
474
475######################################################################
476
477tre($stdin)
Note: See TracBrowser for help on using the repository browser.