Synthia
Generic and flexible data structure generator
AffineTransform.java
Go to the documentation of this file.
1 /*
2  Synthia, a data structure generator
3  Copyright (C) 2019-2020 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.random;
20 
22 import ca.uqac.lif.synthia.Picker;
24 import ca.uqac.lif.synthia.util.Mutator;
25 
26 /**
27  * Applies an affine transform to a value produced by another picker.
28  * It takes two parameters <i>m</i> and <i>b</i>. If <i>x</i> is
29  * the value produced by the picker, the affine transforms returns
30  * <i>mx</i>+<i>b</i>.
31  * <p>
32  * This class is abstract; it has two concrete descendants,
33  * {@link AffineTransformInteger} and {@link AffineTransformFloat}.
34  * @param <T> The type of number produced (i.e. <tt>Float</tt>,
35  * <tt>Integer</tt>, etc.)
36  * @ingroup API
37  */
38 public abstract class AffineTransform<T extends Number> extends Mutator<T> implements Shrinkable<T>
39 {
40  /**
41  * The slope of the affine transform
42  */
43  protected float m_m;
44 
45  /**
46  * The intercept of the affine transform
47  */
48  protected float m_b;
49 
50  /**
51  * Creates a new instance of affine transform
52  * @param picker The underlying number picker
53  * @param m The slope of the affine transform
54  * @param b The intercept of the affine transform
55  */
56  public AffineTransform(/*@ non_null @*/ Picker<? extends T> picker, /*@ non_null @*/ Number m, /*@ non_null @*/ Number b)
57  {
58  super(picker);
59  m_m = m.floatValue();
60  m_b = b.floatValue();
61  }
62 
63  @Override
64  public void reset()
65  {
66  m_picker.reset();
67  }
68 
69  /**
70  * Applies the affine transform to the next floating point number
71  * produced by the underlying picker
72  * @return The transformed float
73  */
74  protected float pickFloat()
75  {
76  return m_picker.pick().floatValue() * m_m + m_b;
77  }
78 
79  /**
80  * Affine transform producing <tt>int</tt>s
81  */
82  public static class AffineTransformInteger extends AffineTransform<Integer>
83  {
84  /**
85  * Creates a new instance of affine transform
86  * @param picker The underlying number picker
87  * @param m The slope of the affine transform
88  * @param b The intercept of the affine transform
89  */
90  public AffineTransformInteger(/*@ non_null @*/ Picker<? extends Integer> picker, /*@ non_null @*/ Number m, /*@ non_null @*/ Number b)
91  {
92  super(picker, m, b);
93  }
94 
95  @Override
96  public Integer pick()
97  {
98  return (int) super.pickFloat();
99  }
100 
101  @Override
102  public AffineTransformInteger duplicate(boolean with_state)
103  {
104 
105  AffineTransformInteger ati = new AffineTransformInteger(m_picker.duplicate(with_state), m_m, m_b);
106  return ati;
107 
108  }
109 
110  @SuppressWarnings("unchecked")
111  @Override
112  public AffineTransformInteger shrink(Integer o, Picker<Float> decision, float magnitude)
113  {
114  if (!(m_picker instanceof Shrinkable))
115  {
116  throw new CannotShrinkException(m_picker);
117  }
118  int source_value = (int) Math.floor((o - m_b) / m_m);
119  return new AffineTransformInteger(((Shrinkable<Integer>) m_picker).shrink(source_value, decision, 1), m_m, m_b);
120  }
121 
122  @Override
123  public Shrinkable<Integer> shrink(Integer o)
124  {
125  return shrink(o, RandomFloat.instance, 1);
126  }
127  }
128 
129  /**
130  * Affine transform producing <tt>float</tt>s
131  */
132  public static class AffineTransformFloat extends AffineTransform<Float>
133  {
134  /**
135  * Creates a new instance of affine transform
136  * @param picker The underlying number picker
137  * @param m The slope of the affine transform
138  * @param b The intercept of the affine transform
139  */
140  public AffineTransformFloat(/*@ non_null @*/ Picker<? extends Float> picker, /*@ non_null @*/ Number m, /*@ non_null @*/ Number b)
141  {
142  super(picker, m, b);
143  }
144 
145  @Override
146  public Float pick()
147  {
148  return pickFloat();
149  }
150 
151  @Override
152  public AffineTransformFloat duplicate(boolean with_state)
153  {
154  return new AffineTransformFloat(m_picker.duplicate(with_state), m_m, m_b);
155  }
156 
157  @SuppressWarnings("unchecked")
158  @Override
159  public AffineTransformFloat shrink(Float o, Picker<Float> decision, float magnitude)
160  {
161  if (!(m_picker instanceof Shrinkable))
162  {
163  throw new CannotShrinkException(m_picker);
164  }
165  float source_value = (o - m_b) / m_m;
166  return new AffineTransformFloat(((Shrinkable<Float>) m_picker).shrink(source_value, decision, 1), m_m, m_b);
167  }
168 
169  @Override
170  public Shrinkable<Float> shrink(Float o)
171  {
172  return shrink(o, RandomFloat.instance, 1);
173  }
174  }
175 }
ca.uqac.lif.synthia.Picker
Picks an object.
Definition: Picker.java:36
ca.uqac.lif.synthia.random.AffineTransform.reset
void reset()
Puts the picker back into its initial state.
Definition: AffineTransform.java:64
ca.uqac.lif.synthia.Shrinkable
Interface signaling that a picker can be shrunk.
Definition: Shrinkable.java:36
ca.uqac.lif.synthia.util.Mutator.m_picker
Picker<? extends T > m_picker
The underlying picker producing the values to transform.
Definition: Mutator.java:38
ca.uqac.lif.synthia.util
Miscellaneous pickers performing various functions.
Definition: ArrayPicker.java:19
ca.uqac.lif.synthia.Shrinkable.shrink
Shrinkable< T > shrink(T o, Picker< Float > d, float m)
Shrinks a picker.
ca.uqac
ca.uqac.lif.synthia
Definition: Bounded.java:19
ca.uqac.lif.synthia.random.AffineTransform
Applies an affine transform to a value produced by another picker.
Definition: AffineTransform.java:38
ca.uqac.lif
ca
ca.uqac.lif.synthia.Picker.pick
T pick()
Picks an object.
ca.uqac.lif.synthia.random.AffineTransform.m_b
float m_b
The intercept of the affine transform.
Definition: AffineTransform.java:48
ca.uqac.lif.synthia.random.AffineTransform.AffineTransform
AffineTransform(Picker<? extends T > picker, Number m, Number b)
Creates a new instance of affine transform.
Definition: AffineTransform.java:56
ca.uqac.lif.synthia.util.Mutator
A picker that applies a transformation ("mutation") on the value produced by another picker.
Definition: Mutator.java:33
ca.uqac.lif.synthia.random.AffineTransform.pickFloat
float pickFloat()
Applies the affine transform to the next floating point number produced by the underlying picker.
Definition: AffineTransform.java:74
ca.uqac.lif.synthia.Picker.duplicate
Picker< T > duplicate(boolean with_state)
Creates a copy of the picker.
ca.uqac.lif.synthia.Picker.reset
void reset()
Puts the picker back into its initial state.
ca.uqac.lif.synthia.random.AffineTransform.m_m
float m_m
The slope of the affine transform.
Definition: AffineTransform.java:43
ca.uqac.lif.synthia.CannotShrinkException
An exception to throw when a picker can't pick an other element.
Definition: CannotShrinkException.java:25