Skip to content

Commit

Permalink
First Take on All-Logging Black-Box Process
Browse files Browse the repository at this point in the history
  • Loading branch information
thomasWeise committed Mar 6, 2020
1 parent bf7cef4 commit 02c826f
Show file tree
Hide file tree
Showing 7 changed files with 361 additions and 9 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,15 +44,15 @@ First, you need to add the following repository, which is a repository that can
```

Than you can add the dependency on our `aitoa-code` repository into your `dependencies` section.
Here, `0.8.37` is the current version of `aitoa-code`.
Here, `0.8.38` is the current version of `aitoa-code`.
Notice that you may have more dependencies in your `dependencies` section, say on `junit`, but here I just put the one for `aitoa-code` as example.

```xml
<dependencies>
<dependency>
<groupId>com.github.thomasWeise</groupId>
<artifactId>aitoa-code</artifactId>
<version>0.8.37</version>
<version>0.8.38</version>
</dependency>
</dependencies>
```
Expand Down
4 changes: 2 additions & 2 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

<groupId>aitoa</groupId>
<artifactId>aitoa-code</artifactId>
<version>0.8.37</version>
<version>0.8.38</version>
<packaging>jar</packaging>
<name>aitoa-code</name>
<description>Example Source Codes from the Book "Introduction to Optimization Algorithms"</description>
Expand Down Expand Up @@ -44,7 +44,7 @@
<project.reporting.outputEncoding>${encoding}</project.reporting.outputEncoding>
<java.source.version>1.8</java.source.version>
<junit.version>4.13</junit.version>
<oshi.version>4.3.0</oshi.version>
<oshi.version>4.4.2</oshi.version>
<slf4j.version>1.7.30</slf4j.version>
<project.mainClass>aitoa.utils.logs.PostProcessor</project.mainClass>
</properties>
Expand Down
42 changes: 39 additions & 3 deletions src/main/java/aitoa/structure/BlackBoxProcessBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ public class BlackBoxProcessBuilder<X, Y>
/** the expected log length */
private int m_expectedLogLength;

/** should we log all data? */
private boolean m_logAll;

/** Create the base class of the black box problem */
public BlackBoxProcessBuilder() {
super();
Expand Down Expand Up @@ -315,28 +318,61 @@ final long[] _createLog() {
Integer.highestOneBit(this.m_expectedLogLength * 3), 2)];
}

/**
* Will the generated black box process log every single FE?
*
* @return {@code true} if every single FE is logged,
* {@code false} otherwise.
*/
public final boolean isLoggingAll() {
return this.m_logAll;
}

/**
* Set whether or not this builder should lock every single FE
*
* @param logAll
* {@code true} if every single FE should be logged,
* {@code false} otherwise
* @return this builder
*/
public final BlackBoxProcessBuilder<X, Y>
setLogAll(final boolean logAll) {
this.m_logAll = logAll;
return this;
}

/**
* The internal version used to create the instance of the
* black box problem. This method is overridden by the test
* version of the black-box process builder.
*
* @return the problem instance
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
@SuppressWarnings({ "unchecked", "rawtypes", "resource" })
IBlackBoxProcess<X, Y> _get() {
if (this.m_logAll && (this.m_logPath == null)) {
throw new IllegalArgumentException(
"No log path is provided, while logging is set to ALL."); //$NON-NLS-1$
}

if (this.m_mapping == null) {
// search space == solution space
if (this.m_logPath == null) {
return new _BlackBoxProcess1NoLog(this);
}
return new _BlackBoxProcess1Log(this);
return this.m_logAll //
? new _BlackBoxProcess1LogAll(this)//
: new _BlackBoxProcess1Log(this);
}

// search and solution space are different
if (this.m_logPath == null) {
return new _BlackBoxProcess2NoLog(this);
}
return new _BlackBoxProcess2Log(this);
return this.m_logAll //
? new _BlackBoxProcess2LogAll(this)//
: new _BlackBoxProcess2Log(this);
}

/**
Expand Down
150 changes: 150 additions & 0 deletions src/main/java/aitoa/structure/_BlackBoxProcess1LogAll.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
package aitoa.structure;

import java.io.BufferedWriter;
import java.io.IOException;

import aitoa.utils.IOUtils;
import aitoa.utils.IOUtils.IOConsumer;

/**
* The black-box problem class for black box problems where the
* search and solution space are the same and logging takes
* place. Here, however, <em>all</em> data is logged.
*
* @param <X>
* the search and solution space
*/
final class _BlackBoxProcess1LogAll<X>
extends _BlackBoxProcessBase<X, X> {

/** the log file */
private final BufferedWriter m_logWriter;
/** the log */
private long[] m_log;
/** the log size */
private int m_logSize;

/**
* Instantiate the black box problem
*
* @param builder
* the builder to copy the data from
*/
_BlackBoxProcess1LogAll(
final BlackBoxProcessBuilder<X, X> builder) {
super(builder);

this.m_logWriter = builder._createLogWriter();
this.m_log = builder._createLog();

// enqueue into terminator thread if needed only after
// initialization is complete
if (this.m_maxTime < Long.MAX_VALUE) {
_TerminationThread._enqueue(this);
}
}

/** {@inheritDoc} */
@Override
public final void close() throws IOException {
// make sure we are dequeued from terminator
this._terminate();

// write the log information and then close log
IOUtils.synchronizedIO(() -> {
try (final BufferedWriter out = this.m_logWriter) {
_BlackBoxProcessBase._writeLog(this.m_log,
this.m_logSize, this.m_startTime, out);
this.m_log = null;
out.write('\n');
this._printInfos(out);
if (this.m_consumedFEs > 0L) {
out.write("\n# BEST_X\n"); //$NON-NLS-1$
this.m_searchSpace.print(this.m_bestX, out);
out.write("\n# END_BEST_X"); //$NON-NLS-1$
}
}
});

// validate result: throw error if invalid
this.m_searchSpace.check(this.m_bestX);
}

/** {@inheritDoc} */
@Override
public final double evaluate(final X y) {
if (this.m_terminated) {
// if we have already terminated, straight quit
return Double.POSITIVE_INFINITY;
}
final long fes = ++this.m_consumedFEs; // increase fes
// evaluate
final double result = this.m_f.evaluate(y);

final long time = System.currentTimeMillis();
// store the log information
final int size = this.m_logSize;
final int newSize = Math.addExact(size, 3);
if (newSize > this.m_log.length) { // grow log
this.m_log = _BlackBoxProcessBase._growLog(this.m_log);
}
// store log point
this.m_log[size] = Double.doubleToLongBits(result);
this.m_log[size + 1] = fes;
this.m_log[size + 2] = time;
this.m_logSize = newSize;

// did we improve
if (result < this.m_bestF) {// yes, we did
// so remember a copy of this best solution
this.m_bestF = result;
this.m_searchSpace.copy(y, this.m_bestX);
this.m_lastImprovementFE = fes; // and the current FE
// and the time when the improvement was made
this.m_lastImprovementTime = time;

// check if we have exhausted the granted runtime or
// reached the quality goal
if ((this.m_lastImprovementTime >= this.m_endTime)
|| (result <= this.m_goalF)) {
this._terminate();// terminate: we are finished
}
}

// check if we have exhausted the granted FEs
if (fes >= this.m_maxFEs) {
this._terminate();// terminate: no more FEs
}
// return result
return result;
}

/** {@inheritDoc} */
@Override
public final void getBestY(final X dest) {
if (this.m_consumedFEs > 0L) {
this.m_searchSpace.copy(this.m_bestX, dest);
} else {
throw new IllegalStateException(//
"No FE consumed yet."); //$NON-NLS-1$
}
}

/** {@inheritDoc} */
@Override
public final void printLogSection(final String sectionName,
final IOConsumer<BufferedWriter> printer)
throws IOException {
IOUtils.synchronizedIO(() -> {
this.m_logWriter.write(LogFormat.COMMENT_CHAR);
this.m_logWriter.write(' ');
this.m_logWriter.write(sectionName);
this.m_logWriter.newLine();
printer.accept(this.m_logWriter);
this.m_logWriter.write(LogFormat.COMMENT_CHAR);
this.m_logWriter.write(" END_"); //$NON-NLS-1$
this.m_logWriter.write(sectionName);
this.m_logWriter.newLine();
});
}
}
Loading

0 comments on commit 02c826f

Please sign in to comment.