001/**
002 * Copyright (c) 2011, The University of Southampton and the individual contributors.
003 * All rights reserved.
004 *
005 * Redistribution and use in source and binary forms, with or without modification,
006 * are permitted provided that the following conditions are met:
007 *
008 *   *  Redistributions of source code must retain the above copyright notice,
009 *      this list of conditions and the following disclaimer.
010 *
011 *   *  Redistributions in binary form must reproduce the above copyright notice,
012 *      this list of conditions and the following disclaimer in the documentation
013 *      and/or other materials provided with the distribution.
014 *
015 *   *  Neither the name of the University of Southampton nor the names of its
016 *      contributors may be used to endorse or promote products derived from this
017 *      software without specific prior written permission.
018 *
019 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
020 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
021 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
022 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
023 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
024 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
025 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
026 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
027 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
028 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
029 */
030package org.openimaj.ml.linear.experiments.sinabill;
031
032import java.util.ArrayList;
033import java.util.HashMap;
034import java.util.Iterator;
035import java.util.Map;
036import java.util.Map.Entry;
037
038import org.openimaj.ml.linear.learner.BilinearLearnerParameters;
039import org.openimaj.util.pair.IndependentPair;
040
041import com.google.common.primitives.Doubles;
042
043public class BilinearLearnerParametersLineSearch implements Iterable<BilinearLearnerParameters> {
044        
045        private Map<String,Iterable<?>> itermap = new HashMap<String, Iterable<?>>();
046        private BilinearLearnerParameters base;
047        
048        /**
049         * Set the base paramters. This object will be cloned and set with new values each iteration
050         * @param base
051         */
052        public BilinearLearnerParametersLineSearch(BilinearLearnerParameters base) {
053                this.base = base;
054        }
055        
056        /**
057         * @param key
058         * @param range
059         */
060        public <T> void addIteration(String key, Iterable<T> range){
061                this.itermap.put(key,range);
062        }
063
064        @Override
065        public Iterator<BilinearLearnerParameters> iterator() {
066                final ArrayList<IndependentPair<String, Iterator<?>>> iterators = new ArrayList<IndependentPair<String,Iterator<?>>>();
067                for (Entry<String, Iterable<?>> iterent : this.itermap.entrySet()) {
068                        Iterator<?> iterator = iterent.getValue().iterator();
069//                      iterent.getKey(),iterator
070                        IndependentPair<String, Iterator<?>> pair = new IndependentPair<String,Iterator<?>>(iterent.getKey(), iterator);
071                        iterators.add(pair);
072                }
073                final ArrayList<IndependentPair<String, Object>> current = new ArrayList<IndependentPair<String,Object>>();
074                
075                return new Iterator<BilinearLearnerParameters>() {
076                        @Override
077                        public void remove() {
078                                throw new UnsupportedOperationException();
079                        }
080                        
081                        @Override
082                        public BilinearLearnerParameters next() {
083                                if(current.size() ==  0){
084                                        // It is currently empty, get the first of everything
085                                        for (IndependentPair<String,Iterator<?>> iterip : iterators) {
086                                                Object next = iterip.secondObject().next();
087                                                current.add(IndependentPair.pair(iterip.firstObject(),next));
088                                        }
089                                } else {
090                                        for (int i = 0; i < iterators.size(); i++) {
091                                                IndependentPair<String, Iterator<?>> namedIterator = iterators.get(i);
092                                                String name = namedIterator.firstObject();
093                                                if(namedIterator.secondObject().hasNext()){
094                                                        Object next = namedIterator.secondObject().next();
095                                                        current.set(i, IndependentPair.pair(name,next));
096                                                        break;
097                                                } else {
098                                                        // Refresh this iterator
099                                                        Iterator<?> valueIter = itermap.get(name).iterator();
100                                                        IndependentPair<String, Iterator<?>> pair = new IndependentPair<String,Iterator<?>>(name, valueIter);
101                                                        iterators.set(i, pair);
102                                                        Object next = valueIter.next();
103                                                        current.set(i,IndependentPair.pair(name,next));
104                                                        // and carry on to the next one because we need to tick over
105                                                }
106                                        }
107                                }
108                                
109                                // Turn the current into a BilinearLearnerParameters
110                                BilinearLearnerParameters params = base.clone();
111                                for (IndependentPair<String, Object> namedObject : current) {
112                                        params.put(namedObject.firstObject(), namedObject.secondObject());
113                                }
114                                return params;
115                        }
116                        
117                        @Override
118                        public boolean hasNext() {
119                                for (IndependentPair<String, Iterator<?>> independentPair : iterators) {
120                                        if(independentPair.secondObject().hasNext()) return true;
121                                }
122                                return false;
123                        }
124                };
125        }
126        
127        public static void main(String[] args) {
128                BilinearLearnerParametersLineSearch ls = new BilinearLearnerParametersLineSearch(new BilinearLearnerParameters());
129                ls.addIteration(BilinearLearnerParameters.ETA0_U, Doubles.asList(new double[]{0.1,0.01}));
130                ls.addIteration(BilinearLearnerParameters.ETA0_W, Doubles.asList(new double[]{51,52,53}));
131                
132                for (BilinearLearnerParameters bilinearLearnerParameters : ls) {
133                        System.out.println(bilinearLearnerParameters);
134                }
135        }
136
137        
138
139}