Skip to content

Commit

Permalink
Initial commit: basic Java template, password cracker
Browse files Browse the repository at this point in the history
  • Loading branch information
nicoprocessor committed Jun 17, 2017
0 parents commit 4646dd4
Show file tree
Hide file tree
Showing 9 changed files with 331 additions and 0 deletions.
55 changes: 55 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839

# User-specific stuff:
.idea/**/workspace.xml
.idea/**/tasks.xml
.idea/dictionaries

# Sensitive or high-churn files:
.idea/**/dataSources/
.idea/**/dataSources.ids
.idea/**/dataSources.xml
.idea/**/dataSources.local.xml
.idea/**/sqlDataSources.xml
.idea/**/dynamic.xml
.idea/**/uiDesigner.xml

# Gradle:
.idea/**/gradle.xml
.idea/**/libraries

# CMake
cmake-build-debug/

# Mongo Explorer plugin:
.idea/**/mongoSettings.xml

## File-based project format:
*.iws

## Plugin-specific files:

# IntelliJ
/out/
*.iml
.settings/
.classpath
.project
*.swp
.idea/

# mpeltonen/sbt-idea plugin
.idea_modules/

# JIRA plugin
atlassian-ide-plugin.xml

# Cursive Clojure plugin
.idea/replstate.xml

# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties
Binary file added bin/AI/DNA.class
Binary file not shown.
Binary file added bin/AI/Main.class
Binary file not shown.
Binary file added bin/AI/Population.class
Binary file not shown.
16 changes: 16 additions & 0 deletions src/AI/DNA.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package AI;

/**
* Created by Nicola on 6/16/2017.
*/
public class DNA {
String genes;

public DNA(String _genes) {
this.genes = _genes;
}

public String getGenes() {
return this.genes;
}
}
151 changes: 151 additions & 0 deletions src/AI/Population.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
package AI;

import util.RandomUtil;

import java.util.ArrayList;
import java.util.HashMap;

/**
* Created by Nicola on 6/16/2017.
*/
public class Population {
private ArrayList<DNA> population = new ArrayList();
private double mutationRate;
private int maxPopulation;
private String target;

// Population class constructor
public Population(double mutationRate, int maxPopulation, String target) {
this.mutationRate = mutationRate;
this.maxPopulation = maxPopulation;
this.target = target;
}

//Initialize random population
public void initPopulation() {
for (int i = 0; i < maxPopulation; i++)
this.getPopulation().add(new DNA(RandomUtil.randomString(target.length())));
}

//Perform natural selection on the population: members
//with higher fitness score have higher probability of
//being select for reproduction
public String naturalSelection() {
HashMap<DNA, Integer> fitnessScores = calcPopulationFitness(this.target);
if (fitnessScores.size() == 1) return (String) fitnessScores.keySet().toArray()[0];
ArrayList<DNA> matingPool = matingPool(fitnessScores);
ArrayList<DNA> newGeneration = new ArrayList<>();

//Selection and reproduction
for (int i = 0; i < maxPopulation; i++) {
newGeneration.add(reproduce(
matingPool.get(RandomUtil.min_maxBoundedInt(0, matingPool.size() - 1)),
matingPool.get(RandomUtil.min_maxBoundedInt(0, matingPool.size() - 1))));
}

//Replace population
this.population.clear();
this.setPopulation(newGeneration);
return null;
}

// Calculate fitness for each member in the given population
public HashMap<DNA, Integer> calcPopulationFitness(String target) {
HashMap<DNA, Integer> fitnessValues = new HashMap<>();
int maxFitnessScore = 0;
DNA maxDNAfitnessScore = null;

for (int i = 0; i < maxPopulation; i++) {
DNA indexDNA = this.getPopulation().get(i);
int indexFitness = calcIndividualFitness(indexDNA, target);

if (indexFitness > maxFitnessScore) {
maxFitnessScore = indexFitness;
maxDNAfitnessScore = indexDNA;
}

//If optimal solution is found then return a single element -> this situation will be treated
//in the calling method
if (maxFitnessScore == target.length()) {
fitnessValues.clear();
fitnessValues.put(indexDNA, indexFitness);
break;
}
fitnessValues.put(indexDNA, indexFitness);
}

//DEBUG
System.out.println("max fitness: " + maxDNAfitnessScore.getGenes() + " score: " + maxFitnessScore);
return fitnessValues;
}

// Evaluate every single fitness score for each member in the population
// In this case fitness score is incremented if the n-th gene (in this case the n-th letter)
// corresponds to the n-th character of the target string
public int calcIndividualFitness(DNA dna, String target) {
int fitnessScore = 0;
String genes = dna.getGenes();

for (int i = 0; i < target.length(); i++)
if (genes.charAt(i) == target.charAt(i))
fitnessScore++;

return fitnessScore;
}

//Create a mating pool selecting a couple of DNAs from the population,
// evaluating each of them with their fitness score
public ArrayList<DNA> matingPool(HashMap<DNA, Integer> fitnessScores) {
ArrayList<DNA> poll = new ArrayList<>();

for (DNA indexDNA : fitnessScores.keySet())
for (int i = 0; i < fitnessScores.get(indexDNA); i++)
poll.add(indexDNA);

return poll;
}

//Create a new DNA given the 2 parents' DNAs
//taking 50% genetic information from each one + consider
//mutation rate
public DNA reproduce(DNA p1, DNA p2) {
StringBuilder sb = new StringBuilder();
sb.append(p1.getGenes().substring(0, p1.getGenes().length() / 2));
sb.append(p2.getGenes().substring(p2.getGenes().length() / 2, p2.getGenes().length()));

//perform mutation
char[] child = new char[sb.length()];
sb.getChars(0, sb.length(), child, 0);

for (int i = 0; i < sb.length(); i++)
if (RandomUtil.extractWithRate(this.getMutationRate()))
child[i] = RandomUtil.randomChar();

return new DNA(new String(child));
}

//Getters and setters
public double getMutationRate() {
return mutationRate;
}

public void setMutationRate(double mutationRate) {
this.mutationRate = mutationRate;
}

public int getMaxPopulation() {
return maxPopulation;
}

public void setMaxPopulation(int maxPopulation) {
this.maxPopulation = maxPopulation;
}

public ArrayList<DNA> getPopulation() {
return this.population;
}

public void setPopulation(ArrayList<DNA> population) {
this.population = population;
}
}
39 changes: 39 additions & 0 deletions src/main/Main.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package main;

import AI.Population;

/**
* Created by Nicola on 6/16/2017.
*/
public class Main {
final static String target = "Test sentence";
final static int populationDimension = 500;
final static double mutationRate = 0.01;

public static void main(String[] args) {
int i = 0;
double e, s;
//Population lifecycle
Population p = new Population(mutationRate, populationDimension, target);
p.initPopulation();

s = System.currentTimeMillis();
while (true) {
//TODO definitely not the best way!
try {
System.out.print("Generation: " + ++i + "\t");
String result = p.naturalSelection();


if (result != null) {
break;
}
} catch (ClassCastException ex) {
//TODO that catch!
break;
}
}
e = System.currentTimeMillis();
System.out.println("Execution time: " + (e - s)/1000 + " seconds" + "\tgenerations: " + i);
}
}
34 changes: 34 additions & 0 deletions src/tests/PopulationTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package tests;

import AI.DNA;
import AI.Population;
import org.junit.Test;

import java.util.ArrayList;

import static org.junit.Assert.*;

/**
* Created by Nicola on 6/16/2017.
*/
public class PopulationTest {
//Population p = new Population(new ArrayList<DNA>());
// @Test
// public void calcIndividualFitness() throws Exception {
// }


//Can't be used since there's randomness in the code, given by
//mutation rate
// @Test
// public void reproduce_oddLengthDNA_sameParent() throws Exception {
// DNA d1 = new DNA("This is a test!");
// assertEquals("This is a test!", p.reproduce(d1, d1).getGenes());
// }
//
// @Test
// public void reproduce_evenLengthDNA_sameParent() throws Exception {
// DNA d1 = new DNA("This is a test");
// assertEquals("This is a test", p.reproduce(d1, d1).getGenes());
// }
}
36 changes: 36 additions & 0 deletions src/util/RandomUtil.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package util;

import java.util.ArrayList;
import java.util.concurrent.ThreadLocalRandom;

/**
* Created by Nicola on 6/16/2017.
*/
public class RandomUtil {
public static int min_maxBoundedInt(int min, int max) {
return ThreadLocalRandom.current().nextInt(min, max + 1);
}

public static char randomChar() {
return (char) min_maxBoundedInt(32, 122);
}

public static String randomString(int length) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < length; i++) {
sb.append(randomChar());
}
return sb.toString();
}

//TODO consider improving this algorithm
public static boolean extractWithRate(double rate){
rate *= 100;
ArrayList<Integer> l = new ArrayList();

//Fill arrays
for(int i = 0; i<100 - rate; i++) l.add(0);
for(int i = 0; i<rate; i++) l.add(1);
return (l.get(min_maxBoundedInt(0, l.size()-1)) == 1) ? true : false;
}
}

0 comments on commit 4646dd4

Please sign in to comment.