001/* Copyright (C) 2013 TU Dortmund
002 * This file is part of AutomataLib, http://www.automatalib.net/.
003 * 
004 * AutomataLib is free software; you can redistribute it and/or
005 * modify it under the terms of the GNU Lesser General Public
006 * License version 3.0 as published by the Free Software Foundation.
007 * 
008 * AutomataLib is distributed in the hope that it will be useful,
009 * but WITHOUT ANY WARRANTY; without even the implied warranty of
010 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
011 * Lesser General Public License for more details.
012 * 
013 * You should have received a copy of the GNU Lesser General Public
014 * License along with AutomataLib; if not, see
015 * http://www.gnu.de/documents/lgpl.en.html.
016 */
017package net.automatalib.util.automata.random;
018
019import java.util.ArrayList;
020import java.util.Collection;
021import java.util.Collections;
022import java.util.List;
023import java.util.Random;
024
025import net.automatalib.automata.MutableAutomaton;
026import net.automatalib.commons.util.collections.CollectionsUtil;
027import net.automatalib.commons.util.random.RandomUtil;
028
029public class AbstractRandomAutomatonGenerator<S, I, T, SP, TP, A extends MutableAutomaton<S,I,T,SP,TP>> {
030        
031        protected final RandomUtil random;
032        protected final List<? extends I> inputs;
033        protected final List<? extends SP> spList;
034        protected final List<? extends TP> tpList;
035        protected final ArrayList<S> states;
036        protected final A automaton;
037        
038        public AbstractRandomAutomatonGenerator(
039                        Random random,
040                        Collection<? extends I> inputs,
041                        Collection<? extends SP> stateProps,
042                        Collection<? extends TP> transProps,
043                        A automaton) {
044                this.random = new RandomUtil(random);
045                
046                if(stateProps == null)
047                        spList = Collections.singletonList(null);
048                else
049                        spList = CollectionsUtil.randomAccessList(stateProps);
050                        
051                if(transProps == null)
052                        tpList = Collections.singletonList(null);
053                else
054                        tpList = CollectionsUtil.randomAccessList(transProps);
055                
056                this.inputs = CollectionsUtil.randomAccessList(inputs);
057                this.states = new ArrayList<>();
058                this.automaton = automaton;
059        }
060        
061        public A getAutomaton() {
062                return automaton;
063        }
064        
065        
066        protected SP randomStateProperty() {
067                return random.choose(spList);
068        }
069        
070        protected TP randomTransProperty() {
071                return random.choose(tpList);
072        }
073        
074        protected S randomState() {
075                return random.choose(states);
076        }
077        
078        protected S randomDistinctState(int stateIdx) {
079                if(states.size() == 1)
080                        return null;
081                
082                int idx = random.getRandom().nextInt(states.size() - 1);
083                
084                if(idx >= stateIdx)
085                        idx++;
086                
087                return states.get(idx);
088        }
089        
090        protected I randomInput() {
091                return random.choose(inputs);
092        }
093        
094        public void addStates(int numStates) {
095                states.ensureCapacity(states.size() + numStates);
096                
097                for(int i = 0; i < numStates; i++) {
098                        S state = automaton.addState(randomStateProperty());
099                        states.add(state);
100                }
101        }
102        
103        public void chooseInitial() {
104                S init = random.choose(states);
105                automaton.setInitial(init, true);
106        }
107        
108        public void chooseIntials(int num) {
109                List<S> inits = random.sampleUnique(states, num);
110                
111                for(S init : inits)
112                        automaton.setInitial(init, true);
113        }
114
115}