com.ciphertool.zodiacengine.CipherSolutionExecutor.java Source code

Java tutorial

Introduction

Here is the source code for com.ciphertool.zodiacengine.CipherSolutionExecutor.java

Source

/**
 * Copyright 2012 George Belden
 * 
 * This file is part of ZodiacEngine.
 * 
 * ZodiacEngine is free software: you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any later
 * version.
 * 
 * ZodiacEngine is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
 * details.
 * 
 * You should have received a copy of the GNU General Public License along with
 * ZodiacEngine. If not, see <http://www.gnu.org/licenses/>.
 */

package com.ciphertool.zodiacengine;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.annotation.Required;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.ciphertool.zodiacengine.dao.CipherDao;
import com.ciphertool.zodiacengine.dto.CipherDto;
import com.ciphertool.zodiacengine.entities.Cipher;
import com.ciphertool.zodiacengine.enumerations.ApplicationDurationType;
import com.ciphertool.zodiacengine.genetic.adapters.SolutionChromosome;
import com.ciphertool.zodiacengine.util.SolutionEvaluator;
import com.ciphertool.zodiacengine.util.SolutionGenerator;

public class CipherSolutionExecutor {
    private static Logger log = Logger.getLogger(CipherSolutionExecutor.class);
    @SuppressWarnings("unused")
    private static BeanFactory factory;
    private static ApplicationDurationType applicationDurationType;
    private static long applicationRunMillis;
    private static long numIterations;
    private static int maxThreads;
    private static CipherDao cipherDao;
    private static String cipherName;
    private static long queueTaskLimit;
    private static SolutionGenerator solutionGenerator;
    private static SolutionEvaluator solutionEvaluator;

    /**
     * @param args
     * @throws InterruptedException
     */
    public static void main(String[] args) throws InterruptedException {
        // Spin up the Spring application context
        setUp();

        CipherDto cipherDto = null;

        Cipher cipher = cipherDao.findByCipherName(cipherName);

        long start = System.currentTimeMillis();

        ExecutorService executor = Executors.newFixedThreadPool(maxThreads);

        cipherDto = new CipherDto(String.valueOf(0), cipher);

        /*
         * We want to generate and validate a specific number of solutions, no
         * matter how long it takes.
         */
        if (applicationDurationType == ApplicationDurationType.ITERATION) {
            if (numIterations <= 0) {
                throw new IllegalArgumentException(
                        "ApplicationDurationType set to ITERATION, but numIterations was not set or was set incorrectly.");
            }

            log.info("Beginning solution generation.  Generating " + numIterations + " solutions using "
                    + maxThreads + " threads.");

            for (long i = 1; i <= numIterations; i++) {
                Runnable cipherTask = new CipherSolutionSynchronizedRunnable(solutionGenerator, solutionEvaluator,
                        cipherDto);

                executor.execute(cipherTask);
            }

            // Make executor accept no new threads and finish all existing
            // threads in the queue
            executor.shutdown();
        }
        /*
         * We want to generate and validate solutions for a set amount of time,
         * no matter how many we can generate in that time period.
         */
        else if (applicationDurationType == ApplicationDurationType.TEMPORAL) {
            if (applicationRunMillis <= 0) {
                throw new IllegalArgumentException(
                        "ApplicationDurationType set to TEMPORAL, but applicationRunMillis was not set or was set incorrectly.");
            }

            log.info("Beginning solution generation.  Generating solutions for " + applicationRunMillis
                    + "ms using " + maxThreads + " threads.");

            long count = 0;

            while (true) {
                Runnable cipherTask = new CipherSolutionSynchronizedRunnable(solutionGenerator, solutionEvaluator,
                        cipherDto);

                executor.execute(cipherTask);

                /*
                 * This is a fairly rudimentary way of managing the number of
                 * tasks sent to the executor.
                 * 
                 * If we don't manage it somehow, the app will get bogged down
                 * by the continuous while loop and performance will degrade
                 * significantly.
                 */
                if (++count >= queueTaskLimit) {
                    count = 0;

                    executor.shutdown();

                    /*
                     * We are mainly concerned about blocking until all tasks
                     * are finished, so the timeout is not a big concern.
                     */
                    executor.awaitTermination(1, TimeUnit.MINUTES);

                    executor = Executors.newFixedThreadPool(maxThreads);

                    if ((System.currentTimeMillis() - start) > applicationRunMillis) {
                        break;
                    }
                }
            }

            // Make executor stop immediately
            executor.shutdownNow();
        }

        // Wait until all threads are finished
        while (!executor.isTerminated()) {
        }

        SolutionChromosome solutionMostMatches = cipherDto.getSolutionMostMatches();
        SolutionChromosome solutionMostUnique = cipherDto.getSolutionMostUnique();
        SolutionChromosome solutionMostAdjacent = cipherDto.getSolutionMostAdjacent();

        /*
         * Print out summary information
         */
        log.info("Took " + (System.currentTimeMillis() - start) + "ms to generate and validate "
                + cipherDto.getNumSolutions() + " solutions.");
        log.info("Highest total matches achieved: " + solutionMostMatches.getTotalMatches());
        log.info("Average total matches: " + (cipherDto.getTotalMatchSum() / cipherDto.getNumSolutions()));
        log.info("Best solution found: " + solutionMostMatches);
        log.info("Most unique matches achieved: " + solutionMostUnique.getUniqueMatches());
        log.info("Average unique matches: " + (cipherDto.getUniqueMatchSum() / cipherDto.getNumSolutions()));
        log.info("Solution with most unique matches found: " + solutionMostUnique);
        log.info("Most adjacent matches achieved: " + solutionMostAdjacent.getAdjacentMatchCount());
        log.info("Average adjacent matches: " + (cipherDto.getAdjacentMatchSum() / cipherDto.getNumSolutions()));
        log.info("Solution with most adjacent matches found: " + solutionMostAdjacent);
    }

    /**
     * Spins up the Spring application context
     */
    private static void setUp() {
        ApplicationContext context = new ClassPathXmlApplicationContext("beans-zodiac.xml");

        factory = context;

        log.info("Spring context created successfully!");
    }

    /**
     * @param setMaxThreads
     */
    @Required
    public void setMaxThreads(int maxThreads) {
        CipherSolutionExecutor.maxThreads = maxThreads;
    }

    /**
     * @param applicationDurationType
     */
    @Required
    public void setApplicationDurationType(ApplicationDurationType applicationDurationType) {
        CipherSolutionExecutor.applicationDurationType = applicationDurationType;
    }

    /**
     * Not required since the duration type may not be iteration-based.
     * 
     * @param numIterations
     */
    public void setNumIterations(long numIterations) {
        CipherSolutionExecutor.numIterations = numIterations;
    }

    /**
     * Not required since the duration type may not be temporal.
     * 
     * @param numIterations
     */
    public void setApplicationRunMillis(long applicationRunMillis) {
        CipherSolutionExecutor.applicationRunMillis = applicationRunMillis;
    }

    /**
     * @param cipherDao
     *            the cipherDao to set
     */
    @Required
    public void setCipherDao(CipherDao cipherDao) {
        CipherSolutionExecutor.cipherDao = cipherDao;
    }

    /**
     * @param cipherName
     *            the cipherName to set
     */
    @Required
    public void setCipherName(String cipherName) {
        CipherSolutionExecutor.cipherName = cipherName;
    }

    /**
     * @param queueTaskLimit
     *            the queueTaskLimit to set
     */
    @Required
    public void setQueueTaskLimit(long queueTaskLimit) {
        CipherSolutionExecutor.queueTaskLimit = queueTaskLimit;
    }

    /**
     * @param solutionGenerator
     *            the solutionGenerator to set
     */
    @Required
    public void setSolutionGenerator(SolutionGenerator solutionGenerator) {
        CipherSolutionExecutor.solutionGenerator = solutionGenerator;
    }

    /**
     * @param solutionEvaluator
     *            the solutionEvaluator to set
     */
    @Required
    public void setSolutionEvaluator(SolutionEvaluator solutionEvaluator) {
        CipherSolutionExecutor.solutionEvaluator = solutionEvaluator;
    }
}