001/*
002 * $Id$
003 */
004
005package edu.jas.vector;
006
007
008import java.io.Reader;
009import java.math.BigInteger;
010import java.util.ArrayList;
011import java.util.List;
012import java.util.Random;
013
014import org.apache.logging.log4j.LogManager;
015import org.apache.logging.log4j.Logger;
016
017import edu.jas.kern.StringUtil;
018import edu.jas.structure.ModulFactory;
019import edu.jas.structure.RingElem;
020import edu.jas.structure.RingFactory;
021
022
023/**
024 * GenVectorModul implements a generic vector factory with RingElem entries.
025 * Vectors of n columns over C.
026 * @author Heinz Kredel
027 */
028
029public class GenVectorModul<C extends RingElem<C>> implements ModulFactory<GenVector<C>, C> {
030
031
032    private static final Logger logger = LogManager.getLogger(GenVectorModul.class);
033
034
035    public final RingFactory<C> coFac;
036
037
038    public final int cols;
039
040
041    public final GenVector<C> ZERO;
042
043
044    public final List<GenVector<C>> BASIS;
045
046
047    private final static Random random = new Random();
048
049
050    public final static float DEFAULT_DENSITY = 0.5f;
051
052
053    private final float density = DEFAULT_DENSITY;
054
055
056    /**
057     * Constructor for GenVectorModul.
058     */
059    @SuppressWarnings("unchecked")
060    public GenVectorModul(RingFactory<C> b, int s) {
061        coFac = b;
062        cols = s;
063        ArrayList<C> z = new ArrayList<C>(cols);
064        for (int i = 0; i < cols; i++) {
065            z.add(coFac.getZERO());
066        }
067        ZERO = new GenVector<C>(this, z);
068        BASIS = new ArrayList<GenVector<C>>(cols);
069        List<C> cgens = coFac.generators();
070        ArrayList<C> v;
071        for (int i = 0; i < cols; i++) {
072            for (C g : cgens) {
073                v = new ArrayList<C>(z);// z.clone();
074                v.set(i, g);
075                BASIS.add(new GenVector<C>(this, v));
076            }
077        }
078        logger.info("{} module over {} constructed", cols, coFac);
079    }
080
081
082    /**
083     * Get the String representation as RingElem.
084     * @see java.lang.Object#toString()
085     */
086    @Override
087    public String toString() {
088        StringBuffer s = new StringBuffer();
089        s.append(coFac.getClass().getSimpleName());
090        s.append("[" + cols + "]");
091        return s.toString();
092    }
093
094
095    /**
096     * Get a scripting compatible string representation.
097     * @return script compatible representation for this ElemFactory.
098     * @see edu.jas.structure.ElemFactory#toScript()
099     */
100    @Override
101    public String toScript() {
102        // Python case
103        StringBuffer s = new StringBuffer("Vec(");
104        String f = null;
105        try {
106            f = ((RingElem<C>) coFac).toScriptFactory(); // sic
107        } catch (Exception e) {
108            f = coFac.toScript();
109        }
110        s.append(f + "," + cols + " )");
111        return s.toString();
112    }
113
114
115    /**
116     * getZERO.
117     * @return ZERO.
118     */
119    public GenVector<C> getZERO() {
120        return ZERO;
121    }
122
123
124    /**
125     * Get a list of the generating elements.
126     * @return list of generators for the algebraic structure.
127     * @see edu.jas.structure.ElemFactory#generators()
128     */
129    public List<GenVector<C>> generators() {
130        return BASIS;
131    }
132
133
134    /**
135     * Is this structure finite or infinite.
136     * @return true if this structure is finite, else false.
137     * @see edu.jas.structure.ElemFactory#isFinite()
138     */
139    public boolean isFinite() {
140        return coFac.isFinite();
141    }
142
143
144    /**
145     * Comparison with any other object.
146     * @see java.lang.Object#equals(java.lang.Object)
147     */
148    @Override
149    @SuppressWarnings("unchecked")
150    public boolean equals(Object other) {
151        if (!(other instanceof GenVectorModul)) {
152            return false;
153        }
154        GenVectorModul omod = (GenVectorModul) other;
155        if (cols != omod.cols) {
156            return false;
157        }
158        if (!coFac.equals(omod.coFac)) {
159            return false;
160        }
161        return true;
162    }
163
164
165    /**
166     * Hash code for this vector module.
167     * @see java.lang.Object#hashCode()
168     */
169    @Override
170    public int hashCode() {
171        int h;
172        h = cols;
173        h = 37 * h + coFac.hashCode();
174        return h;
175    }
176
177
178    /**
179     * Get the vector for a.
180     * @param a long
181     * @return vector corresponding to a.
182     */
183    public GenVector<C> fromInteger(long a) {
184        C c = coFac.fromInteger(a);
185        return BASIS.get(0).scalarMultiply(c);
186    }
187
188
189    /**
190     * Get the vector for a.
191     * @param a long
192     * @return vector corresponding to a.
193     */
194    public GenVector<C> fromInteger(BigInteger a) {
195        C c = coFac.fromInteger(a);
196        return BASIS.get(0).scalarMultiply(c);
197    }
198
199
200    /**
201     * From List of coefficients.
202     * @param v list of coefficients.
203     * @return vector from v.
204     */
205    public GenVector<C> fromList(List<C> v) {
206        if (v == null) {
207            return ZERO;
208        }
209        if (v.size() > cols) {
210            throw new IllegalArgumentException("size v > cols " + v + " > " + cols);
211        }
212        List<C> r = new ArrayList<C>(cols);
213        r.addAll(v);
214        // pad with zeros if required:
215        for (int i = r.size(); i < cols; i++) {
216            r.add(coFac.getZERO());
217        }
218        return new GenVector<C>(this, r);
219    }
220
221
222    /**
223     * Random vector.
224     * @param k size of random coefficients.
225     * @return random vector.
226     */
227    public GenVector<C> random(int k) {
228        return random(k, density, random);
229    }
230
231
232    /**
233     * Random vector.
234     * @param k size of random coefficients.
235     * @param q density of nonzero coefficients.
236     * @return random vector.
237     */
238    public GenVector<C> random(int k, float q) {
239        return random(k, q, random);
240    }
241
242
243    /**
244     * Random vector.
245     * @param k size of random coefficients.
246     * @param random is a source for random bits.
247     * @return a random element.
248     */
249    public GenVector<C> random(int k, Random random) {
250        return random(k, density, random);
251    }
252
253
254    /**
255     * Random vector.
256     * @param k size of random coefficients.
257     * @param q density of nonzero coefficients.
258     * @param random is a source for random bits.
259     * @return a random element.
260     */
261    public GenVector<C> random(int k, float q, Random random) {
262        List<C> r = new ArrayList<C>(cols);
263        for (int i = 0; i < cols; i++) {
264            if (random.nextFloat() < q) {
265                r.add(coFac.random(k));
266            } else {
267                r.add(coFac.getZERO());
268            }
269        }
270        return new GenVector<C>(this, r);
271    }
272
273
274    /**
275     * copy vector.
276     * @param c vector.
277     * @return copy of vector c.
278     */
279    public GenVector<C> copy(GenVector<C> c) {
280        if (c == null) {
281            return c;
282        }
283        return c.copy();
284    }
285
286
287    /**
288     * Parse a vector from a String. Syntax: [ c, ..., c ]
289     * @param s String with vector.
290     * @return parsed vector.
291     */
292    public GenVector<C> parse(String s) {
293        int i = s.indexOf("[");
294        if (i >= 0) {
295            s = s.substring(i + 1);
296        }
297        i = s.indexOf("]");
298        if (i >= 0) {
299            s = s.substring(0, i);
300        }
301        List<C> vec = new ArrayList<C>(cols);
302        String e;
303        C c;
304        do {
305            i = s.indexOf(",");
306            if (i >= 0) {
307                e = s.substring(0, i);
308                s = s.substring(i + 1);
309                c = coFac.parse(e);
310                vec.add(c);
311            }
312        } while (i >= 0);
313        if (s.trim().length() > 0) {
314            c = coFac.parse(s);
315            vec.add(c);
316        }
317        return new GenVector<C>(this, vec);
318    }
319
320
321    /**
322     * Parse a vector from a Reader.
323     * @param r Reader containing a vector.
324     * @return parsed vector.
325     */
326    public GenVector<C> parse(Reader r) {
327        String s = StringUtil.nextPairedString(r, '[', ']');
328        return parse(s);
329    }
330
331}