Synthia
Generic and flexible data structure generator
Playback.java
Go to the documentation of this file.
1 /*
2  Synthia, a data structure generator
3  Copyright (C) 2019-2021 Laboratoire d'informatique formelle
4  Université du Québec à Chicoutimi, Canada
5 
6  This program is free software: you can redistribute it and/or modify
7  it under the terms of the GNU Lesser General Public License as published
8  by the Free Software Foundation, either version 3 of the License, or
9  (at your option) any later version.
10 
11  This program is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU Lesser General Public License for more details.
15 
16  You should have received a copy of the GNU Lesser General Public License
17  along with this program. If not, see <http://www.gnu.org/licenses/>.
18  */
19 package ca.uqac.lif.synthia.sequence;
20 
21 import java.util.ArrayList;
22 import java.util.Arrays;
23 import java.util.Collections;
24 import java.util.List;
25 
27 import ca.uqac.lif.petitpoucet.ComposedPart;
28 import ca.uqac.lif.petitpoucet.NodeFactory;
29 import ca.uqac.lif.petitpoucet.Part;
30 import ca.uqac.lif.petitpoucet.PartNode;
31 import ca.uqac.lif.petitpoucet.function.ExplanationQueryable;
32 import ca.uqac.lif.petitpoucet.function.vector.NthElement;
33 import ca.uqac.lif.synthia.Bounded;
35 import ca.uqac.lif.synthia.Picker;
40 
41 //TODO check constructors whit a list as parameter for m_values
42 /**
43  * Picker that returns values taken from a list. As its name implies,
44  * <tt>Playback</tt> literally replays the values fetched from a list that
45  * was passed to its constructor. It loops back to the beginning when the list
46  * is over (this can optionally be disabled).
47  * <pre>
48  * Playback&lt;Integer&gt; p = new Playback&lt;Integer&gt;(2, 7, 1);
49  * System.out.println(p.pick()); // 2
50  * System.out.println(p.pick()); // 7
51  * System.out.println(p.pick()); // 1
52  * System.out.println(p.pick()); // 2
53  * ...</pre>
54  * Optionally, the picker can be told to start at a different element than the
55  * first one. By default, the picker keeps outputting the last value of the
56  * sequence if more values are requested and the <tt>loop</tt> parameter is
57  * set to false.
58  * @param <T> The type of objects to return
59  * @ingroup API
60  */
61 public class Playback<T> implements Bounded<T>, Shrinkable<T>, ExplanationQueryable, SequenceShrinkable<T>
62 {
63  /**
64  * The values to play back
65  */
66  /*@ non_null @*/ protected T[] m_values;
67 
68  /**
69  * The index of the current value
70  */
71  protected int m_index;
72 
73  /**
74  * The start index
75  */
76  protected int m_startIndex;
77 
78  /**
79  * Whether to loop through the values
80  */
81  protected boolean m_loop;
82 
83  /**
84  * Creates a new Playback picker
85  * @param start_index The position of the first value to return
86  * @param values The values to play back
87  */
88  @SuppressWarnings("unchecked")
89  public Playback(int start_index, /*@ non_null @*/ T ... values)
90  {
91  m_values = values;
92  m_index = start_index;
93  m_startIndex = start_index;
94  m_loop = true;
95  }
96 
97  /**
98  * Creates a new Playback picker
99  * @param values The values to play back
100  */
101  @SuppressWarnings("unchecked")
102  public Playback(/*@ non_null @*/ T ... values)
103  {
104  this(0, values);
105  }
106 
107  /**
108  * Creates a new Playback picker
109  * @param start_index The position of the first value to return
110  * @param values The values to play back
111  */
112  @SuppressWarnings("unchecked")
113  public Playback(int start_index, /*@ non_null @*/ List<T> values)
114  {
115  m_values = (T[]) values.toArray();
116  m_index = start_index;
117  m_startIndex = start_index;
118  }
119 
120  /**
121  * Creates a new Playback picker
122  * @param values The values to play back
123  */
124  public Playback(/*@ non_null @*/ List<T> values)
125  {
126  this(0, values);
127  }
128 
129  /**
130  * Picks the next value in the list of the Playback picker. Typically, this method is expected to return non-null
131  * objects; a <tt>null</tt> return value is used to signal that no more
132  * objects will be produced. That is, once this method returns
133  * <tt>null</tt>, it should normally return <tt>null</tt> on all subsequent
134  * calls.
135  * @return The next value
136  */
137  @Override
138  public T pick()
139  {
140  if (m_index >= m_values.length && !m_loop)
141  {
142  throw new NoMoreElementException();
143  }
144  T f = m_values[m_index];
145  m_index++;
146  if (m_index == m_values.length && m_loop)
147  {
148  m_index = 0;
149  }
150  return f;
151  }
152 
153 
154  /**
155  * Puts the Playback picker back into its initial state. This means that the
156  * sequence of calls to {@link #pick()} will produce the same values
157  * as when the object was instantiated.
158  */
159  @Override
160  public void reset()
161  {
163  }
164 
165 
166  /**
167  * Picks a random string. Typically, this method is expected to return non-null
168  * objects; a <tt>null</tt> return value is used to signal that no more
169  * objects will be produced. That is, once this method returns
170  * <tt>null</tt>, it should normally return <tt>null</tt> on all subsequent
171  * calls.
172  * @return The random string.
173  */
174  @Override
175  public Playback<T> duplicate(boolean with_state)
176  {
178  if (with_state)
179  {
180  lp.m_index = m_index;
181  }
182  if (!this.m_loop){
183  lp.setLoop(false);
184  }
185  return lp;
186  }
187 
188 
189  /**
190  * Set the m_loop attribute of the playback picker. If the attribute is set to false, the next call to
191  * the {@link #pick()} method will return a {@link NoMoreElementException} after
192  * producing the last element of the list.
193  * @param b boolean value to enable playback loop or not
194  * @return The actual instance of the class.
195  */
196  public Playback<T> setLoop(boolean b)
197  {
198  m_loop = b;
199  return this;
200  }
201 
202  /**
203  * Signals if the playback picker picked all the objects from m_values.
204  * Loop attributes must be false. If loop is true, the method will always return false.
205  * @return true if the picker picked all the objects from m_values and false if it's not the case.
206  */
207  @Override
208  public boolean isDone()
209  {
210  return (m_index >= (m_values.length)) && !m_loop;
211  }
212 
213  @Override
214  public Shrinkable<T> shrink(T o, Picker<Float> decision, float m)
215  {
216  return new PickSmallerComparable<T>(this, o);
217  }
218 
219  @Override
220  public PartNode getExplanation(Part p)
221  {
222  return getExplanation(p, NodeFactory.getFactory());
223  }
224 
225  @Override
226  public PartNode getExplanation(Part p, NodeFactory f)
227  {
228  PartNode root = f.getPartNode(p, this);
229  int index = -1;
230  Part head = p.head();
231  if (head != null && head instanceof NthSuccessiveOutput)
232  {
233  index = ((NthSuccessiveOutput) head).getIndex();
234  }
235  if (index < 0 || (!m_loop && index > m_values.length))
236  {
237  // Not a valid part, end there
238  return root;
239  }
240  int actual_index = index % m_values.length;
241  Part new_p = ComposedPart.compose(new NthElement(actual_index), new NthSuccessiveOutput(index));
242  root.addChild(f.getPartNode(new_p, m_values));
243  return root;
244  }
245 
246  @Override
247  public String toString()
248  {
249  StringBuilder out = new StringBuilder();
250  out.append("Playback [");
251  for (int i = 0; i < m_values.length; i++)
252  {
253  if (i > 0)
254  {
255  out.append(",");
256  }
257  out.append(m_values[i]);
258  }
259  out.append("]");
260  return out.toString();
261  }
262 
263  @Override
264  public Shrinkable<T> shrink(T o)
265  {
266  return shrink(o, RandomFloat.instance, 1);
267  }
268 
269  @Override
271  {
272  List<Integer> indices = new ArrayList<Integer>();
273  int num_to_pick = (int) (m * (float) m_values.length);
274  while (indices.size() < num_to_pick)
275  {
276  int index = (int) Math.floor(d.pick() * m_values.length);
277  if (!indices.contains(index))
278  {
279  indices.add(index);
280  }
281  }
282  Collections.sort(indices);
283  List<T> values = new ArrayList<T>(indices.size());
284  for (int index : indices)
285  {
286  values.add(m_values[index]);
287  }
288  return new Playback<T>(values);
289  }
290 
291  @Override
292  public List<T> getSequence()
293  {
294  return Arrays.asList(m_values);
295  }
296 }
ca.uqac.lif.synthia.Picker
Picks an object.
Definition: Picker.java:36
ca.uqac.lif.synthia.sequence.Playback.duplicate
Playback< T > duplicate(boolean with_state)
Picks a random string.
Definition: Playback.java:175
ca.uqac.lif.synthia.Shrinkable
Interface signaling that a picker can be shrunk.
Definition: Shrinkable.java:36
ca.uqac.lif.synthia.sequence.Playback.shrink
Shrinkable< T > shrink(T o)
Shrinks a picker with default parameters.
Definition: Playback.java:264
ca.uqac.lif.synthia.sequence.Playback.pick
T pick()
Picks the next value in the list of the Playback picker.
Definition: Playback.java:138
ca.uqac.lif.synthia.sequence.Playback.Playback
Playback(List< T > values)
Creates a new Playback picker.
Definition: Playback.java:124
ca.uqac.lif.synthia.sequence.Playback.getExplanation
PartNode getExplanation(Part p, NodeFactory f)
Definition: Playback.java:226
ca.uqac.lif.synthia.sequence.Playback.m_index
int m_index
The index of the current value.
Definition: Playback.java:71
ca.uqac.lif.synthia.sequence.Playback.m_values
T[] m_values
The values to play back.
Definition: Playback.java:66
ca.uqac.lif.synthia.sequence.Playback.getExplanation
PartNode getExplanation(Part p)
Definition: Playback.java:220
ca.uqac.lif.synthia.sequence.Playback.reset
void reset()
Puts the Playback picker back into its initial state.
Definition: Playback.java:160
ca.uqac.lif.synthia.relative.PickSmallerComparable
A variant of PickIf that selects an element if it is smaller than a reference object.
Definition: PickSmallerComparable.java:37
ca.uqac.lif.synthia.sequence.Playback.m_loop
boolean m_loop
Whether to loop through the values.
Definition: Playback.java:81
ca.uqac.lif.synthia.sequence.Playback.toString
String toString()
Definition: Playback.java:247
ca.uqac.lif.synthia.random.RandomFloat.instance
static final transient RandomFloat instance
A public static instance of RandomFloat.
Definition: RandomFloat.java:45
ca.uqac.lif.synthia.sequence.Playback
Picker that returns values taken from a list.
Definition: Playback.java:61
ca.uqac.lif.synthia.SequenceShrinkable
Signals that a picker can shrink the sequence of values it has produced since its last reset.
Definition: SequenceShrinkable.java:47
ca.uqac
ca.uqac.lif.synthia.random
Pickers that produce pseudo-random objects such as numbers.
Definition: AffineTransform.java:19
ca.uqac.lif.synthia
Definition: Bounded.java:19
ca.uqac.lif.synthia.sequence.Playback.setLoop
Playback< T > setLoop(boolean b)
Set the m_loop attribute of the playback picker.
Definition: Playback.java:196
ca.uqac.lif.synthia.explanation
Objects related to the explanation of results produced by pickers.
Definition: Explanation.java:19
ca.uqac.lif
ca.uqac.lif.synthia.Bounded
Interface used to signal that a picker enumerates all values from a set.
Definition: Bounded.java:26
ca.uqac.lif.synthia.sequence.Playback.m_startIndex
int m_startIndex
The start index.
Definition: Playback.java:76
ca
ca.uqac.lif.synthia.Picker.pick
T pick()
Picks an object.
ca.uqac.lif.synthia.relative
Pickers that produce a value in relation to another value.
Definition: package-info.java:24
ca.uqac.lif.synthia.sequence.Playback.isDone
boolean isDone()
Signals if the playback picker picked all the objects from m_values.
Definition: Playback.java:208
ca.uqac.lif.synthia.sequence.Playback.shrink
SequenceShrinkable< T > shrink(Picker< Float > d, float m)
Shrinks a picker.
Definition: Playback.java:270
ca.uqac.lif.synthia.random.RandomFloat
Picks a floating point number uniformly in an interval.
Definition: RandomFloat.java:30
ca.uqac.lif.synthia.sequence.Playback.getSequence
List< T > getSequence()
Gets the sequence of values that the picker has produced so far.
Definition: Playback.java:292
ca.uqac.lif.synthia.NoMoreElementException
An exception to throw when a picker can't pick an other element.
Definition: NoMoreElementException.java:25
ca.uqac.lif.synthia.sequence.Playback.shrink
Shrinkable< T > shrink(T o, Picker< Float > decision, float m)
Shrinks a picker.
Definition: Playback.java:214
ca.uqac.lif.synthia.explanation.NthSuccessiveOutput
A Part pointing to the n-th output produced by a picker since its last call to reset().
Definition: NthSuccessiveOutput.java:36