blob: b2d2682396116e5c2a1c8ca0c9111e82b7d911c8 [file] [log] [blame]
Akron33f1dcb2016-10-29 17:27:23 +02001package Krawfish::Koral::Query::Sequence;
2use parent 'Krawfish::Koral::Query';
Akron27fb7432016-12-11 18:07:32 +01003use Krawfish::Log;
Akron33f1dcb2016-10-29 17:27:23 +02004use strict;
5use warnings;
6
Akron18ff5922017-01-13 10:09:45 +01007# TODO: Optimize if there is an identical subquery
Akron84ae6572017-02-03 19:26:36 +01008# in a direct sequence - make this a repetition!!!
Akron18ff5922017-01-13 10:09:45 +01009
Akron27fb7432016-12-11 18:07:32 +010010use constant DEBUG => 0;
11
Akron33f1dcb2016-10-29 17:27:23 +020012sub new {
13 my $class = shift;
Akron4763ea62016-11-02 19:36:18 +010014 my $self = $class->SUPER::new;
15 $self->{array} = [@_];
Akron554e3572016-11-05 12:02:00 +010016 $self->{planned} = 0;
Akrondc9f1162016-11-05 15:31:40 +010017 $self->{info} = undef;
Akron4763ea62016-11-02 19:36:18 +010018 return $self;
Akron33f1dcb2016-10-29 17:27:23 +020019};
20
Akron554e3572016-11-05 12:02:00 +010021
Akron774c5db2016-11-09 16:11:38 +010022# Get number of operands
Akron4763ea62016-11-02 19:36:18 +010023sub size {
24 scalar @{$_[0]->{array}};
25};
26
Akron774c5db2016-11-09 16:11:38 +010027
Akron8aee4a62016-11-14 21:33:12 +010028sub type { 'sequence' };
Akron774c5db2016-11-09 16:11:38 +010029
Akron554e3572016-11-05 12:02:00 +010030
Akron4763ea62016-11-02 19:36:18 +010031# TODO: Order by frequency, so the most common occurrence is at the outside
32sub plan_for {
Akron554e3572016-11-05 12:02:00 +010033 my $self = shift;
Akron573e7ec2016-11-05 19:03:01 +010034 my $index = shift;
Akron774c5db2016-11-09 16:11:38 +010035
Akron554e3572016-11-05 12:02:00 +010036 # Only one element available
37 if ($self->size == 1) {
38
39 # Return this element
Akron573e7ec2016-11-05 19:03:01 +010040 return $self->{array}->[0]->plan_for(
41 $index
Akron554e3572016-11-05 12:02:00 +010042 );
43 };
44
Akron774c5db2016-11-09 16:11:38 +010045 # From a sequence, create a binary tree
46 my $tree = $self->planned_tree;
47
48 return unless $tree;
49
50 return $tree->plan_for($index);
Akron554e3572016-11-05 12:02:00 +010051};
52
Akron774c5db2016-11-09 16:11:38 +010053
Akron7d1dc8e2016-11-13 15:54:11 +010054# Left extensions are always prefered!
Akron774c5db2016-11-09 16:11:38 +010055sub _solve_problems {
Akron554e3572016-11-05 12:02:00 +010056 my $self = shift;
Akron774c5db2016-11-09 16:11:38 +010057
58 return 1 if $self->{planned_array};
59
60 # Cloned for planning
61 my @elements = @{$self->{array}};
62
Akron554e3572016-11-05 12:02:00 +010063 # First pass - mark anchors
Akron774c5db2016-11-09 16:11:38 +010064 my @problems = ();
65 for (my $i = 0; $i < @elements; $i++) {
66
67 # Element in question
68 my $element = $elements[$i];
69
70 if ($element->type eq 'sequence') {
71 # has_constraints ...
72 };
73
74 # Push to problem array
75 unless ($element->maybe_anchor) {
76 push @problems, $i;
Akron554e3572016-11-05 12:02:00 +010077 };
78 };
Akron774c5db2016-11-09 16:11:38 +010079
80 # Second pass
81 # TODO: Order by frequency
82 my $problems = 0;
83 foreach my $p (reverse @problems) {
84
85 # Remove element
86 if ($elements[$p]->is_null) {
87 splice @elements, $p, 1;
88 next;
89 };
90
Akron27fb7432016-12-11 18:07:32 +010091 print_log('kq_seq', $elements[$p]->to_string . " is problematic") if DEBUG;
Akron7d1dc8e2016-11-13 15:54:11 +010092
Akron774c5db2016-11-09 16:11:38 +010093 # Problem has a following anchor
94 if ($elements[$p+1] && $elements[$p+1]->maybe_anchor) {
95 my $next = $elements[$p+1];
Akron27fb7432016-12-11 18:07:32 +010096
97 print_log('kq_seq', 'Extend left with ' . $next->to_string) if DEBUG;
98
Akron7d1dc8e2016-11-13 15:54:11 +010099 splice @elements, $p, 2, $self->builder->ext_left(
Akron774c5db2016-11-09 16:11:38 +0100100 $next,
101 $elements[$p]
102 );
103 }
104
105 # Problem has a preceeding anchor
106 elsif ($elements[$p-1] && $elements[$p-1]->maybe_anchor) {
107 my $previous = $elements[$p-1];
Akron27fb7432016-12-11 18:07:32 +0100108
109 print_log('kq_seq', 'Extend right with ' . $previous->to_string) if DEBUG;
110
Akron7d1dc8e2016-11-13 15:54:11 +0100111 splice @elements, $p-1, 2, $self->builder->ext_right(
Akron774c5db2016-11-09 16:11:38 +0100112 $previous,
113 $elements[$p]
114 );
115 }
Akron7d1dc8e2016-11-13 15:54:11 +0100116
117 # Problem remains
Akron774c5db2016-11-09 16:11:38 +0100118 else {
119 $problems = 1;
120 };
121 };
122
123 # Store as a separate array
124 $self->{planned_array} = \@elements;
125
126 # set variables etc.
127 return if $problems;
128 return 1;
Akron4763ea62016-11-02 19:36:18 +0100129};
130
Akron774c5db2016-11-09 16:11:38 +0100131
132sub planned_tree {
133 my $self = shift;
134
Akron8aee4a62016-11-14 21:33:12 +0100135 # Return tree
Akron774c5db2016-11-09 16:11:38 +0100136 if ($self->{planned_tree}) {
137 return $self->{planned_tree};
138 };
139
140 return unless $self->_solve_problems;
141
142 my @elements = @{$self->{planned_array}};
143
144 my $tree = shift @elements;
145
146 my $builder = $self->builder;
147
148 # TODO: Sort this by frequency
149 foreach (@elements) {
150 $tree = $builder->position(
151 ['precedesDirectly'],
152 $tree,
153 $_
154 )
155 };
156
157 $self->{planned_tree} = $tree;
158 return $tree;
159};
160
161
Akron4763ea62016-11-02 19:36:18 +0100162sub is_any {
Akron554e3572016-11-05 12:02:00 +0100163 my $self = shift;
Akron8aee4a62016-11-14 21:33:12 +0100164 my $tree = $self->planned_tree;
165 return $tree->is_any;
Akron33f1dcb2016-10-29 17:27:23 +0200166};
167
Akron554e3572016-11-05 12:02:00 +0100168
169sub is_null {
Akron8aee4a62016-11-14 21:33:12 +0100170 my $self = shift;
171 my $tree = $self->planned_tree;
172 return $tree->is_null;
Akron554e3572016-11-05 12:02:00 +0100173};
174
Akron1b09c5b2016-11-20 15:59:34 +0100175
176sub maybe_unsorted {
177 my $self = shift;
178 my $tree = $self->planned_tree;
179 return $tree->maybe_unsorted;
180};
181
182
Akron33f1dcb2016-10-29 17:27:23 +0200183sub to_koral_fragment {
184 my $self = shift;
185 return {
186 '@type' => 'koral:group',
187 'operation' => 'operation:sequence',
188 'operands' => [
Akron4763ea62016-11-02 19:36:18 +0100189 map { $_->to_koral_fragment } @{$self->{array}}
Akron33f1dcb2016-10-29 17:27:23 +0200190 ]
191 };
192};
193
Akrona211bf52016-10-29 18:03:29 +0200194sub to_string {
Akron4763ea62016-11-02 19:36:18 +0100195 return join '', map { $_->to_string } @{$_[0]->{array}};
Akrona211bf52016-10-29 18:03:29 +0200196};
197
Akron944091b2016-11-24 16:40:58 +0100198sub from_koral {
199 my $class = shift;
200 my $kq = shift;
201
202 my $importer = $class->importer;
203
204 return $class->new(
205 map { $importer->all($_) } @{$kq->{operands}}
206 );
207};
Akrona211bf52016-10-29 18:03:29 +0200208
Akron33f1dcb2016-10-29 17:27:23 +02002091;
Akron4763ea62016-11-02 19:36:18 +0100210
211
212__END__
213
214Rewrite rules:
215- [Der][alte][Mann]? ->
216 [Der]optExt([alte],[Mann])
217