Skip to content

Commit

Permalink
Prepare for v55.1.0
Browse files Browse the repository at this point in the history
  • Loading branch information
apete committed Dec 22, 2024
1 parent aa55f22 commit 7263069
Show file tree
Hide file tree
Showing 11 changed files with 879 additions and 807 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ Added / Changed / Deprecated / Fixed / Removed / Security

> Corresponds to changes in the `develop` branch since the last release
## [55.1.0] – 2024-12-22

### Added

#### org.ojalgo.data
Expand All @@ -28,6 +30,10 @@ Added / Changed / Deprecated / Fixed / Removed / Security

- Sorting is no longer parallel/multi-threaded. The previous implementations made use of the common `ForkJoinPool`.

#### org.ojalgo.data

- Creating a JMX bean (to monitor throughput) with `BatchNode` is now optional, and the default is to not create them. (Used to always create them.)

#### org.ojalgo.netio

- The `FromFileReader` and `ToFileWriter` interfaces and their implementations used to extend and delegate to code in the `org.ojalgo.type.function` package. Much of what was in that package has been moved to and merged with stuff in the `org.ojalgo.netio` package.
Expand Down
1,581 changes: 798 additions & 783 deletions jdeps.txt

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>org.ojalgo</groupId>
<artifactId>ojalgo</artifactId>
<version>55.0.2</version>
<version>55.1.0</version>
<name>ojAlgo</name>
<description>oj! Algorithms - ojAlgo - is Open Source Java code that has to do with mathematics, linear algebra and optimisation.</description>
<packaging>jar</packaging>
Expand Down Expand Up @@ -48,7 +48,7 @@
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<version.java>11</version.java>
<version.org.junit.jupiter>5.11.3</version.org.junit.jupiter>
<version.org.junit.jupiter>5.11.4</version.org.junit.jupiter>
<version.org.openjdk.jmh>1.37</version.org.openjdk.jmh>
</properties>
<dependencies>
Expand Down Expand Up @@ -144,7 +144,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.11.1</version>
<version>3.11.2</version>
<executions>
<execution>
<id>attach-javadocs</id>
Expand Down
11 changes: 11 additions & 0 deletions src/main/java/org/ojalgo/data/batch/BatchManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ public final class BatchManager {
private final File myBatchRootDirectory;
private ExecutorService myExecutor = null;
private Integer myFragmentation = null;
private boolean myManaged = false;
private IntSupplier myParallelism = null;
private Integer myQueueCapacity = null;

Expand Down Expand Up @@ -76,6 +77,14 @@ public BatchManager fragmentation(final int fragmentation) {
return this;
}

/**
* @see BatchNode.Builder#managed(boolean
*/
public BatchManager managed(final boolean managed) {
myManaged = managed;
return this;
}

public <T> BatchNode.Builder<T> newNodeBuilder(final String nodeName, final DataInterpreter<T> dataInterpreter) {

Builder<T> retVal = BatchNode.newBuilder(new File(myBatchRootDirectory, nodeName), dataInterpreter);
Expand All @@ -96,6 +105,8 @@ public <T> BatchNode.Builder<T> newNodeBuilder(final String nodeName, final Data
retVal.queue(myQueueCapacity.intValue());
}

retVal.managed(myManaged);

return retVal;
}

Expand Down
32 changes: 26 additions & 6 deletions src/main/java/org/ojalgo/data/batch/BatchNode.java
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,8 @@ public static final class Builder<T> {
private ExecutorService myExecutor = null;
private int myFragmentation = 64;
private final DataInterpreter<T> myInterpreter;
private boolean myManaged = false;
private int myParallelism = Parallelism.CORES.getAsInt();

private int myQueueCapacity = 1024;

Builder(final File directory, final DataInterpreter<T> interpreter) {
Expand Down Expand Up @@ -101,6 +101,14 @@ public BatchNode.Builder<T> fragmentation(final int fragmentation) {
return this;
}

/**
* Do you want a JMX bean to keep track of throughput?
*/
public BatchNode.Builder<T> managed(final boolean managed) {
myManaged = managed;
return this;
}

/**
* @see #parallelism(IntSupplier)
*/
Expand Down Expand Up @@ -173,6 +181,10 @@ ShardedFile getShardedFile() {
return ShardedFile.of(myDirectory, "Shard.data", this.getFragmentation());
}

boolean isManaged() {
return myManaged;
}

}

private static final class TwoStepWrapper<T> implements TwoStepMapper<T, Boolean> {
Expand Down Expand Up @@ -233,12 +245,20 @@ public static <T> BatchNode<T> newInstance(final File directory, final DataInter
myProcessor = builder.getProcessor();
myQueueCapacity = builder.getQueueCapacity();

myWriterManger = new Throughput();
myReaderManager = new Throughput();
if (builder.isManaged()) {

myWriterManger = new Throughput();
myReaderManager = new Throughput();

String name = builder.getName();
MBeanUtils.register(myWriterManger, name + "-Writer");
MBeanUtils.register(myReaderManager, name + "-Reader");
String name = builder.getName();
MBeanUtils.register(myWriterManger, name + "-Writer");
MBeanUtils.register(myReaderManager, name + "-Reader");

} else {

myWriterManger = null;
myReaderManager = null;
}
}

/**
Expand Down
3 changes: 1 addition & 2 deletions src/main/java/org/ojalgo/data/cluster/GeneralisedKMeans.java
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,7 @@ public final class GeneralisedKMeans<T> implements ClusteringAlgorithm<T> {
* (the set of items in a cluster).
* @param distanceCalculator A function that calculates the distance between two points.
*/
public GeneralisedKMeans(final Function<Collection<T>, List<T>> centroidInitialiser,
final Function<Collection<T>, T> centroidUpdater,
public GeneralisedKMeans(final Function<Collection<T>, List<T>> centroidInitialiser, final Function<Collection<T>, T> centroidUpdater,
final ToDoubleBiFunction<T, T> distanceCalculator) {

super();
Expand Down
26 changes: 21 additions & 5 deletions src/main/java/org/ojalgo/data/cluster/GreedyClustering.java
Original file line number Diff line number Diff line change
@@ -1,20 +1,26 @@
package org.ojalgo.data.cluster;

import static org.ojalgo.function.constant.PrimitiveMath.POSITIVE_INFINITY;
import static org.ojalgo.function.constant.PrimitiveMath.THIRD;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Function;
import java.util.function.ToDoubleBiFunction;

/**
* Greedy clustering algorithm. Assigns each item to the nearest centroid, creating new centroids as needed.
* Will only pass through the data once. The centroids are recalculated as the clusters are updated.
* Will only pass through the data once. The centroids are recalculated as the clusters are updated (not with
* every single update, but continuously during the process).
*/
public final class GreedyClustering<T> implements ClusteringAlgorithm<T> {

private final List<T> myCentroids = new ArrayList<>();
private final List<AtomicInteger> myUpdates = new ArrayList<>();
private final Function<Collection<T>, T> myCentroidUpdater;
private final ToDoubleBiFunction<T, T> myDistanceCalculator;
private final double myDistanceThreshold;
Expand All @@ -24,8 +30,9 @@ public final class GreedyClustering<T> implements ClusteringAlgorithm<T> {
* (the set of items in a cluster).
* @param distanceCalculator A function that calculates the distance between two points.
* @param distanceThreshold The maximum distance between a point and a centroid for the point to be
* assigned to that cluster. The points are always assigned to the nearest centroid among the
* already existing clusters. This threshold determines when a new cluster should be created.
* assigned to that cluster. The points are always assigned to the cluster of the nearest centroid
* among the already existing clusters. This threshold determines when a new cluster should be
* created.
*/
public GreedyClustering(final Function<Collection<T>, T> centroidUpdater, final ToDoubleBiFunction<T, T> distanceCalculator,
final double distanceThreshold) {
Expand All @@ -46,7 +53,7 @@ public List<Set<T>> cluster(final Collection<T> input) {
for (T point : input) {

int indexOfBestExisting = -1;
double minDistance = Double.MAX_VALUE;
double minDistance = POSITIVE_INFINITY;

for (int i = 0; i < myCentroids.size(); i++) {
T centroid = myCentroids.get(i);
Expand All @@ -62,14 +69,23 @@ public List<Set<T>> cluster(final Collection<T> input) {

Set<T> cluster = clusters.get(indexOfBestExisting);
cluster.add(point);
myCentroids.set(indexOfBestExisting, myCentroidUpdater.apply(cluster));
int nbMembers = cluster.size();

AtomicInteger clusterUpdates = myUpdates.get(indexOfBestExisting);
double nbUpdates = clusterUpdates.incrementAndGet();

if (nbUpdates / nbMembers >= THIRD) {
myCentroids.set(indexOfBestExisting, myCentroidUpdater.apply(cluster));
clusterUpdates.set(0);
}

} else {

Set<T> newCluster = new HashSet<>();
newCluster.add(point);
clusters.add(newCluster);
myCentroids.add(point);
myUpdates.add(new AtomicInteger());
}
}

Expand Down
8 changes: 4 additions & 4 deletions src/main/java/org/ojalgo/data/cluster/Point.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@
public final class Point implements Comparable<Point> {

/**
* Primarily used when constructing test cases and similar. For real world applications you should use
* {@link Point#convert(List, Function)} instead.
* Primarily used when constructing test cases and similar. For real world applications you should
* probably use {@link Point#convert(List, Function)} instead.
*/
public static final class Factory {

Expand Down Expand Up @@ -44,8 +44,8 @@ public void reset() {
* <ol>
* <li>Calculate, and store, distances between all the points (to enable statistical analysis, and speed
* up the following steps)
* <li>Perform statistical analysis of the distances to determine a suitable distance threshold (to get
* the threshold needed for greedy clustering)
* <li>Perform statistical analysis of the distances to determine a suitable distance threshold for greedy
* clustering
* <li>Perform greedy clustering to get an initial set of centroids
* <li>Filter out centroids/clusters corresponding to extremely small clusters (This determines the 'k')
* <li>Perform k-means clustering to refine the clusters and centroids
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/org/ojalgo/netio/ReaderWriterBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ static ExecutorService executor() {
if (EXECUTOR == null) {
synchronized (ReaderWriterBuilder.class) {
if (EXECUTOR == null) {
EXECUTOR = DaemonPoolExecutor.newCachedThreadPool("ojAlgo IO");
EXECUTOR = DaemonPoolExecutor.newCachedThreadPool("ojAlgo-IO");
}
}
}
Expand Down
10 changes: 8 additions & 2 deletions src/main/java/org/ojalgo/optimisation/integer/IntegerSolver.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import java.math.BigDecimal;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicBoolean;
Expand Down Expand Up @@ -222,11 +223,16 @@ public Result solve(final Result kickStarter) {

Map<Comparator<NodeKey>, MultiviewSet<NodeKey>.PrioritisedView> views = new ConcurrentHashMap<>();

ProcessingService.INSTANCE.process(strategy.getWorkerPriorities(), workerStrategy -> {
List<Comparator<NodeKey>> workerPriorities = strategy.getWorkerPriorities();
for (Comparator<NodeKey> workerPriority : workerPriorities) {
views.computeIfAbsent(workerPriority, myDeferredNodes::newView);
}

ProcessingService.INSTANCE.process(workerPriorities, workerPriority -> {

boolean workerNormalExit = solverNormalExit.get();

MultiviewSet<NodeKey>.PrioritisedView view = views.computeIfAbsent(workerStrategy, myDeferredNodes::newView);
MultiviewSet<NodeKey>.PrioritisedView view = views.computeIfAbsent(workerPriority, myDeferredNodes::newView);

RingLogger nodePrinter = this.newPrinter();

Expand Down
1 change: 0 additions & 1 deletion src/test/java/org/ojalgo/data/cluster/KaggleTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ static MallCustomer parse(final String line) {

if (parts.length != 5 && !ASCII.isDigit(parts[0].charAt(0))) {
throw new IllegalArgumentException("Invalid input line: " + line);

}

int customerID = Integer.parseInt(parts[0]);
Expand Down

0 comments on commit 7263069

Please sign in to comment.