Skip to content

Commit

Permalink
Merge pull request #19 from koosvary/Release_0.2.0
Browse files Browse the repository at this point in the history
Release 0.2.0
  • Loading branch information
ScottWalkerAU authored Aug 18, 2018
2 parents 86257eb + 3c1bc8f commit 4345e81
Show file tree
Hide file tree
Showing 33 changed files with 1,089 additions and 237 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,7 @@ gradle-app.setting
*.iml
*.ipr
*.iws

api/out
cli/out
client/out
36 changes: 36 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,40 @@

## What's New

### Release Notes - 0.2.0 - August 17th, 2018

#### Improvements

* “Input Data” screen has been overhauled
* Datasets now display as a spreadsheet
* This spreadsheet is editable and updates automatically in local memory
* Edited dataset can be exported to a file
* Will prompt to create a new project when loading dataset if one doesn’t exist
* Will alert the user to select a project when importing a dataset, if one exists and is not selected
* Under the hood changes to the data structure used to store and process datasets in memory
* Improved support for header rows in the dataset
* If the first line of the dataset contains all strings, it is assumed to be a header row.
* This is a temporary workaround and is due to change
* Otherwise, it is assumed there is no header row and default headers will be given
* Default headers follow the A-Z, AA-ZZ format
* Data normalisation and smoothing have been updated to work with new data structure
* Other pre-processing features to come
* The smoothing function by default takes the 2 neighbours on either side of the current value and takes the average of those numbers, which becomes the new value for that index. This continues for all values in the feature and updates values once complete
* Target Expression now updates when a dataset is loaded
* Displays in the form of y=f(x,w,…,z)
* Where y is the last feature in the dataset
* x,w,…,z are each of the other features
* This is a GUI change only, which represents the default target expression used by the search
* The GUI and API are unlinked in this respect. The target expression still cannot be customized in the search
* This will be fixed in the next release
* A variety of new building blocks for expressions have been added under the hood.
* A list of these should be available soon
* These are not currently functional in the GUI


#### Fixes
* “Load Dataset” button now working

### Release Notes - 0.1.0 - May 28th, 2018

#### Improvements
Expand All @@ -17,6 +51,8 @@
* The back end has changed so much practically everything's been
fixed in some way. Or at least broken more nicely.

## Building

### Compiling

All commands are assumed to be made from the root project folder
Expand Down
6 changes: 1 addition & 5 deletions api/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,6 @@ compileTestJava {
options.compilerArgs << "-Xlint:all" << "-Xlint:-processing"
}

test {
useJUnitPlatform()
}

dependencies {
testCompileOnly group: 'org.apiguardian', name: 'apiguardian-api', version: '1.0.0'
testCompile group: 'org.junit.jupiter', name: 'junit-jupiter-params', version: '5.1.0'
Expand All @@ -21,7 +17,7 @@ dependencies {
testRuntimeOnly group: 'org.junit.jupiter', name: 'junit-jupiter-engine', version: '5.1.0'
}

version = '0.1.0'
version = '0.2.0'

jar {
baseName = 'iconic-api'
Expand Down
48 changes: 46 additions & 2 deletions api/src/main/java/org/iconic/ea/data/DataManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,35 @@ public DataManager(String fileName) {
}
}

public void saveDatasetToFile(File fileName) throws IOException {
FileWriter fileWriter = null;

try{
fileWriter = new FileWriter(fileName);
for(int i = 0; i < sampleSize; i++){
List<Number> currentRow = getSampleRow(i);
for(int j = 0; j < currentRow.size()-1; j ++) {
fileWriter.append(String.valueOf(currentRow.get(j)));
fileWriter.append(",");
}
fileWriter.append(String.valueOf(currentRow.get(currentRow.size()-1)));
fileWriter.append(System.getProperty("line.separator"));
}
} catch (Exception ex){
log.error("Error when saving file. File: {}", () -> fileName);
log.error("Exception: {}", ex);
} finally{
try{
fileWriter.flush();
fileWriter.close();
} catch (IOException ex){
log.error("Error when closing FileWriter. File: {}", () -> fileName);
log.error("Exception: {}", ex);
}
}

}

private void importData(String fileName) throws IOException {
this.fileName = fileName;
sampleSize = 0;
Expand Down Expand Up @@ -210,7 +239,22 @@ public int getSampleSize() {
return sampleSize;
}

public List<String> getSampleHeaders() {
return sampleHeaders;
public List<String> getSampleHeaders() { return sampleHeaders; }

// Replaces all data within a header column, identified by headerIndex
// e.g. updating stored data after normalisation
public void setSampleColumn(int headerIndex, ArrayList<Number> values) {
for (int i = 0; i < sampleSize; i++) {
Number value = values.get(i);
dataset.get(sampleHeaders.get(headerIndex)).updateModifiedSample(i, value);
}
}

// Resets all data within a header column, identified by headerIndex, to
// the original data entered by the user
public void resetSampleColumn(int headerIndex) {
for (int i=0; i < sampleSize; i++) {
dataset.get(sampleHeaders.get(headerIndex)).resetModifiedSample(i);
}
}
}
8 changes: 8 additions & 0 deletions api/src/main/java/org/iconic/ea/data/FeatureClass.java
Original file line number Diff line number Diff line change
Expand Up @@ -54,4 +54,12 @@ public boolean isOutput() {
public void setOutput(boolean value) {
this.output = value;
}

public void updateModifiedSample(int index, T value) {
modifiedSamples.set(index, value);
}

public void resetModifiedSample(int index) {
modifiedSamples.set(index, originalSamples.get(index));
}
}
4 changes: 2 additions & 2 deletions api/src/main/java/org/iconic/ea/data/NumericFeatureClass.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
public class NumericFeatureClass extends FeatureClass<Number> {
public NumericFeatureClass(boolean output) {
super(output);
getPreprocessors().add(new Normalise());
getPreprocessors().add(new Offset());
//getPreprocessors().add(new Normalise());
//getPreprocessors().add(new Smooth());
}
}
19 changes: 7 additions & 12 deletions api/src/main/java/org/iconic/ea/data/preprocessing/Normalise.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,10 @@

import java.util.ArrayList;

public class Normalise extends Preprocessor<Number>{
private Number oldMin, oldMax, newMin, newMax;

/**
*
* @param values
*/
@Override
public void apply(ArrayList<Number> values) {
public class Normalise {
private static Number oldMin, oldMax;

public static ArrayList<Number> apply(ArrayList<Number> values, Number newMin, Number newMax) {
oldMin = values.get(0);
oldMax = values.get(0);

Expand All @@ -28,14 +23,14 @@ public void apply(ArrayList<Number> values) {
Number value = map(values.get(i), oldMin, oldMax, newMin, newMax);
values.set(i, value);
}

return values;
}

private double map(Number value, Number oldMin, Number oldMax, Number newMin, Number newMax) {
private static double map(Number value, Number oldMin, Number oldMax, Number newMin, Number newMax) {
return newMin.doubleValue() +
((value.doubleValue() - oldMin.doubleValue())
* (newMax.doubleValue() - newMin.doubleValue()))
/ (oldMax.doubleValue() - oldMin.doubleValue());
}

public void setRange(Number newMin, Number newMax) { this.newMin = newMin; this.newMax = newMax; }
}
72 changes: 72 additions & 0 deletions api/src/main/java/org/iconic/ea/data/preprocessing/Smooth.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package org.iconic.ea.data.preprocessing;

import java.util.ArrayList;
import java.lang.*;

public class Smooth {
private static int N = 2; // N is the number of neighboring data points on either side of the value

/**
* <p>
* Smooths the values of an Array. Alternatively known as "Moving Average Filtering".
* </p>
*
* <p>
* Given an array of values, the function will take the 'N' neighbouring values on either side of the index, take
* the sum of all these values, then update the value of the index to the average of the sum.
* </p>
*
* <p>
* If the span window is outside of the Array bounds, the window will become the minimum reach of both sides.
* </p>
*
* @param values the array that will be smoothed
*/
public static ArrayList<Number> apply(ArrayList<Number> values) {
ArrayList<Number> newValues = new ArrayList<>();

for (int i = 0; i < values.size(); i++) {
// The index of the lowest span from the point
int lowerBound = Math.max(0, i - N);

// The size of the lowest span
int lowerBoundRange = i - lowerBound;

// The index of the highest span from the point
int upperBound = Math.min(values.size() - 1, i + N);

// The size of the highest span
int upperBoundRange = upperBound - i;

// The smallest span of reach for both sides
int span = Math.min(lowerBoundRange, upperBoundRange);

// Find the sum of all values in the span
Double sum = 0.0;
for (int j = i - span; j <= i + span; j++) {
sum += values.get(j).doubleValue();
}

// Average of the span size
newValues.add( 1.0 / (2.0 * span + 1.0) * sum );
}

// Update the old values to the new values
for (int i = 0; i < values.size(); i++) {
values.set(i, newValues.get(i));
}

return newValues;
}

/**
* <p>
* Sets the window size of values to use when smoothing the array of data.
* </p>
*
* @param neighbourSize the number of neighbours on either side of each point to be used for smoothing
*/
public void setNeighbourSize(int neighbourSize) {
this.N = neighbourSize;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,31 +11,33 @@

import static org.junit.jupiter.api.Assertions.assertEquals;

public class AdditionTest {
/**
* Test class for {@link org.iconic.ea.operator.primitive.Addition}
* @author Jasbir Shah
*/
class AdditionTest {
@DisplayName("Test addition using doubles")
@MethodSource("doubleListProvider")
@ParameterizedTest
void addDoublesTest(final List<Double> args, final double expected) {
final FunctionalPrimitive<Double, Double> add = new Addition();
final double delta = 0.001d;
final double delta = 0.001;
final double actual = add.apply(args);

assertEquals(expected, actual, delta);
}

/**
* <p>
* Returns a stream of double n-tuples, where the last member of the tuple is the sum of all the preceeding
* members
* </p>
* <p>Returns a stream of double n-tuples, where the last member of the tuple is the sum of all the preceeding
* members</p>
*
* @return a stream of double n-tuples
*/
private static Stream<Arguments> doubleListProvider() {
return Stream.of(
Arguments.of(Arrays.asList(1.d, -1.d), 0.d),
Arguments.of(Arrays.asList(0.d, -1.d), -1.d),
Arguments.of(Arrays.asList(0.d, 1.d), 1.d)
Arguments.of(Arrays.asList(1.0, -1.0), 0.0),
Arguments.of(Arrays.asList(0.0, -1.0), -1.0),
Arguments.of(Arrays.asList(0.0, 1.0), 1.0)
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package org.iconic.ea.operator.primitive;

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;

import java.util.ArrayList;
import java.util.stream.Stream;

import static org.junit.jupiter.api.Assertions.*;

/**
* Test class for {@link org.iconic.ea.operator.primitive.Constant}
* @author Scott Walker
*/
class ConstantTest {
@DisplayName("Test constants using doubles")
@MethodSource("doubleListProvider")
@ParameterizedTest
void constantDoublesTest(final double arg, final double expected) {
final FunctionalPrimitive<Double, Double> constant = new Constant<>(arg);
final double delta = 0.001;
final double actual = constant.apply(new ArrayList<>());

assertEquals(expected, actual, delta);
}

/**
* <p>Returns a stream of two identical doubles</p>
*
* @return a stream of double n-tuples
*/
private static Stream<Arguments> doubleListProvider() {
return Stream.of(
Arguments.of(1.0, 1.0),
Arguments.of(0.0, 0.0),
Arguments.of(10.0, 10.0)
);
}
}
Loading

0 comments on commit 4345e81

Please sign in to comment.