Parallelize preorder tree - java

I want to modify or clone/transform items in a preorder sorted List of tree items in parallel. That is the list traversal starts at a random item in the list and denotes a subtree-traversal (depth, parent-pointer, descendantSize and angleStart/angleEnd is available for a radial view).
My code currently looks like:
items = ((AbsModel<SunburstContainer, SunburstItem>)model).listIterator(pHitItemIndex);
items.next();
for (int i = pHitItemIndex + 1; i < endIndex && items.hasNext(); i++) {
final SunburstItem oldChild = items.next();
final SunburstItem newChild = new SunburstItem(oldChild);
final float newStartAngle =
(oldChild.getAngleStart() - oldRoot.getAngleStart()) * angleFactor;
LOGWRAPPER.debug("angleStart: " + newStartAngle);
newChild.setAngleStart(newStartAngle);
float newEndAngle =
(oldChild.getAngleEnd() - oldChild.getAngleStart()) * angleFactor
+ newChild.getAngleStart();
LOGWRAPPER.debug("angleEnd: " + newEndAngle);
if (newEndAngle > PConstants.TWO_PI) {
newEndAngle = PConstants.TWO_PI;
}
newChild.setAngleEnd(newEndAngle);
newChild.setAngleCenter(newChild.getAngleStart()
+ ((newChild.getAngleEnd() - newChild.getAngleStart()) / 2f));
newChild.setIndexToParent(oldChild.getIndexToParent() - pHitItemIndex);
int newDepth = 0;
LOGWRAPPER.debug("child depth: " + oldChild.getDepth());
LOGWRAPPER
.debug("parent depth: " + model.getItem(oldChild.getIndexToParent()).getDepth());
final int parentDepth = model.getItem(oldChild.getIndexToParent()).getDepth();
if ((parentDepth + 1) != oldChild.getDepth()) {
newDepth = oldDepthMax + 2;
} else {
newDepth = newItems.get(newChild.getIndexToParent()).getDepth() + 1;
}
if (newDepth > depthMax) {
depthMax = newDepth;
}
LOGWRAPPER.debug("newDepth: " + newDepth);
newChild.setDepth(newDepth);
newChild.update(mMappingMode, mBuffer);
newItems.add(newChild);
}
I think about simply partitioning the (sub)list, that is [pHitItemIndex + 1, endIndex] into different parts and submit Callables to an ExecutorService. Currently the whole algorithm is executed in a Callable submitted to an ExecutorService, but I assume I can also simply submit partitions/Callables to the same ExecutorService. I wonder if I would gain any advantage of using actors for instance using Akka, or using the ForkJoin framework.

Sounds like a problem where Parallel Collections in Scala could help out.

Related

Random matching without repeat

I've worked on the project in my school and stuck with an error. I cannot run this code since it has an error 'randA2 is already defined in method main(String[])' How can I fix it?
String [] A = {"Russia", "Saudi_Arabia", "Egypt", "Uruguay"};
int A1 = A.length;
int randA1 = (int)(Math.random()*A1);
int randA2 = (int)(Math.random()*A1);
int randA3 = (int)(Math.random()*A1);
int randA4 = (int)(Math.random()*A1);
while(randA1 == randA2) {
int randA2 = (int)(Math.random()*A1);
}
while(randA1 == randA3) {
int randA3 = (int)(Math.random()*A1);
}
while(randA2 == randA3) {
int randA3 = (int)(Math.random()*A1);
}
while(randA1 == randA4) {
int randA4 = (int)(Math.random()*A1);
}
while(randA2 == randA4) {
int randA4 = (int)(Math.random()*A1);
}
while(randA3 == randA4) {
int randA4 = (int)(Math.random()*A1);
}
String AnnounceA1 = A[randA1] +" " + "VS" + " " + A[randA2];
System.out.println(AnnounceA1);
String AnnounceA2 = A[randA3] +" " + "VS" + " " + A[randA4];
System.out.println(AnnounceA2);
I would like to use another way to solve your problem, all you need is :
String[] contries = {"Russia", "Saudi_Arabia", "Egypt", "Uruguay"};
Collections.shuffle(Arrays.asList(contries));
String announceA1 = contries[0] + " VS " + contries[1];
System.out.println(announceA1);
String announceA2 = contries[2] + " VS " + contries[3];
System.out.println(announceA2);
If you want to reassign a new value to a variable in Java, then you don't need to declare its type again. So your first while loop should look like this:
while (randA1 == randA2) {
randA2 = (int)(Math.random()*A1);
}
But besides this, your code has a logical problem, and it won't actually generate 4 unique random numbers. Actually, if you control which numbers you accept, they aren't really random. I would go with this version:
String[] teams = { "Russia", "Saudi_Arabia", "Egypt", "Uruguay" };
Set<Integer> rands = new HashSet<>();
while (rands.size() < teams.length) {
rands.add((int)(Math.random()*teams.length));
}
String AnnounceA1 = teams[rands[0]] +" " + "VS" + " " + teams[rands[1]];
System.out.println(AnnounceA1);
String AnnounceA2 = teams[rands[2]] +" " + "VS" + " " + teams[rands[3]];
System.out.println(AnnounceA2);
The strategy in my suggested version of your code is using a set to hold 4 random integers (which is the number of teams in your example). It is a property of sets that every entry has to be unique. So, if we iterate this set, adding random integers, we will eventually end up with 4 unique random integers. Then, we can use them to choose team names to display in your output message.
You redefine your vars inside the while loops.
Ommit the int declaration iside the while loops:
...
while(randA1 == randA2) {
randA2 = (int)(Math.random()*A1);
}
while(randA1 == randA3) {
randA3 = (int)(Math.random()*A1);
}
...
Java is a type safety language. This is different to for example JavaScript. Inside JavaScipt the JIT (Just in time compiler) would not complain, because it is allowed to redefine variables, event if the type is changing.

How to get the evaluation summary of the prediction if a separate test is used

I am trying evaluate the classification results with weka via java code. The code is as follows:
fc.buildClassifier(train);
for (int i = 0; i < test.numInstances(); i++) {
double pred = fc.classifyInstance(test.instance(i));
if(test.classAttribute().value((int) test.instance(i).classValue()).equals(test.classAttribute().value((int) pred))){
System.out.println("ID: " + test.instance(i).value(0)+" -");
}
else{
System.out.println("ID: " + test.instance(i).value(0)+" +");
}
}
When a cross validation is used this can be approached as :
Evaluation eval = new Evaluation(data);
Random rand = new Random(1); // using seed = 1
int folds = 10;
eval.crossValidateModel(cls, data, folds, rand);
System.out.println(eval.toSummaryString());
But if the testing achieved as the first code snippet how toSummaryString can be acquired?
Thank you
You can use below lines.
Evaluation testEval = new Evaluation(trainInstances);
testEval.evaluateModel(Model, testInstances);
testEval.toSummaryString()
Detailed usage of Evaluation class for different scenarios can be found at https://www.programcreek.com/java-api-examples/index.php?api=weka.classifiers.Evaluation

MOA's StreamKM clustering doesn't return any result

I'm currently trying to cluster a great amount of data points into a given amount of clusters and I wanted to try MOA's streaming based k-means StreamKM. A very simple example of what I'm trying to do using random data looks as follows:
StreamKM streamKM = new StreamKM();
streamKM.numClustersOption.setValue(5); // default setting
streamKM.widthOption.setValue(100000); // default setting
streamKM.prepareForUse();
for (int i = 0; i < 150000; i++) {
streamKM.trainOnInstanceImpl(randomInstance(2));
}
Clustering result = streamKM.getClusteringResult();
System.out.println("size = " + result.size());
System.out.println("dimension = " + result.dimension());
The random instances are created as follows:
static DenseInstance randomInstance(int size) {
DenseInstance instance = new DenseInstance(size);
for (int idx = 0; idx < size; idx++) {
instance.setValue(idx, Math.random());
}
return instance;
}
However, when running the given code, no clusters seem to be created:
System.out.println("size = " + result.size()); // size = 0
System.out.println("dimension = " + result.dimension()); // NPE
Is there anything else I need to take care of, or do I have a fundamental misunderstanding of the MOA clustering concepts?
I think prepareForUse() method is not the correct method that initialize the algorithm.
Instead of streamKM.prepareForUse(); , you should use streamKM.resetLearning();.
In short, your code should be like:
StreamKM streamKM = new StreamKM();
streamKM.numClustersOption.setValue(5); // default setting
streamKM.widthOption.setValue(100000); // default setting
streamKM. resetLearning(); // UPDATED CODE LINE !!!
for (int i = 0; i < 150000; i++) {
streamKM.trainOnInstanceImpl(randomInstance(2));
}
Clustering result = streamKM.getClusteringResult();
System.out.println("size = " + result.size());
System.out.println("dimension = " + result.dimension());

load a world asynchronously or without blocking the main thread

I'm working on a minigames plugin. After an arena finishes it should be regenerated - I use the unload and load trick. It has an obvious disadvantage - it freezes the server for a while to prepare spawn areas. I decided to put the arena reset code into an runnable asynchronous task runTaskAsynchronously(). However, when the server tries to run the code inside the thread, it throws an exception:
Caused by: java.lang.IllegalStateException: Asynchronous entity world add!
Here's a part of my code:
getServer().getScheduler().runTaskAsynchronously(this, new Runnable()
{
#Override
public void run()
{
String w_name = world.getName();
getServer().unloadWorld(world.getName(), false);
world = getServer().createWorld(new WorldCreator(w_name));
}
});
Any suggestions how to deal with this problem?
Bukkit doesn't like it when you try to edit anything through the API in an async task. Reading and processing is fine but bukkit enforces nothing when it comes to thread safety and thus affecting the world with more than 1 thread can cause issues.
Try splitting up your arena reset into smaller chunks and spreading out the operation over several ticks with a series of synchronous tasks, might help with the performance.
This isn't my code but it does a decent job of demonstrating the idea https://gist.github.com/aadnk/5443172
-- You can load worlds async using this: http://pastebin.com/K9CuVMS5 --
No you cannot, and if you tried it would have a high chance of world corruption. But if you don't care about it this is what you can do:
Bukkit loads worlds via Bukkit.createWorld(WorldCreator) which activates Server.createWorld(WorldCreator) which activates:
Validate.notNull(creator, "Creator may not be null");
String name = creator.name();
ChunkGenerator generator = creator.generator();
File folder = new File(this.getWorldContainer(), name);
World world = this.getWorld(name);
WorldType type = WorldType.getType(creator.type().getName());
boolean generateStructures = creator.generateStructures();
if(world != null) {
return world;
} else if(folder.exists() && !folder.isDirectory()) {
throw new IllegalArgumentException("File exists with the name \'" + name + "\' and isn\'t a folder");
} else {
if(generator == null) {
generator = this.getGenerator(name);
}
WorldLoaderServer converter = new WorldLoaderServer(this.getWorldContainer());
if(converter.isConvertable(name)) {
this.getLogger().info("Converting world \'" + name + "\'");
converter.convert(name, new ConvertProgressUpdater(this.console));
}
int dimension = 10 + this.console.worlds.size();
boolean used = false;
do {
Iterator sdm = this.console.worlds.iterator();
while(sdm.hasNext()) {
WorldServer hardcore = (WorldServer)sdm.next();
used = hardcore.dimension == dimension;
if(used) {
++dimension;
break;
}
}
} while(used);
boolean var25 = false;
ServerNBTManager var24 = new ServerNBTManager(this.getWorldContainer(), name, true);
WorldData worlddata = var24.getWorldData();
if(worlddata == null) {
WorldSettings internal = new WorldSettings(creator.seed(), EnumGamemode.getById(this.getDefaultGameMode().getValue()), generateStructures, var25, type);
internal.setGeneratorSettings(creator.generatorSettings());
worlddata = new WorldData(internal, name);
}
worlddata.checkName(name);
WorldServer var26 = (WorldServer)(new WorldServer(this.console, var24, worlddata, dimension, this.console.methodProfiler, creator.environment(), generator)).b();
if(!this.worlds.containsKey(name.toLowerCase())) {
return null;
} else {
var26.scoreboard = this.getScoreboardManager().getMainScoreboard().getHandle();
var26.tracker = new EntityTracker(var26);
var26.addIWorldAccess(new WorldManager(this.console, var26));
var26.worldData.setDifficulty(EnumDifficulty.EASY);
var26.setSpawnFlags(true, true);
this.console.worlds.add(var26);
if(generator != null) {
var26.getWorld().getPopulators().addAll(generator.getDefaultPopulators(var26.getWorld()));
}
this.pluginManager.callEvent(new WorldInitEvent(var26.getWorld()));
System.out.print("Preparing start region for level " + (this.console.worlds.size() - 1) + " (Seed: " + var26.getSeed() + ")");
if(var26.getWorld().getKeepSpawnInMemory()) {
short short1 = 196;
long i = System.currentTimeMillis();
for(int j = -short1; j <= short1; j += 16) {
for(int k = -short1; k <= short1; k += 16) {
long l = System.currentTimeMillis();
if(l < i) {
i = l;
}
if(l > i + 1000L) {
int chunkcoordinates = (short1 * 2 + 1) * (short1 * 2 + 1);
int j1 = (j + short1) * (short1 * 2 + 1) + k + 1;
System.out.println("Preparing spawn area for " + name + ", " + j1 * 100 / chunkcoordinates + "%");
i = l;
}
BlockPosition var27 = var26.getSpawn();
var26.chunkProviderServer.getChunkAt(var27.getX() + j >> 4, var27.getZ() + k >> 4);
}
}
}
this.pluginManager.callEvent(new WorldLoadEvent(var26.getWorld()));
return var26.getWorld();
}
}
Now by creating you own world loader, you can make it so it only generates a chunk every tick or so.

Finding matching objects in Java

I'm currently trying to match 2 objects based on their values. Except, it's not a.a = a.a, but a.a = a.b and a.b = b.a. This means that overriding equals is an option but it's certainly not the right option.
While sorting these objects will make the matching time quicker, the population will be small so it is unnecessary. Also, compareTo isn't exactly right either for the same reason given for equals.
Do I simply make my own method in case? There will be 4 fields to match which is why I am not using an if statement up front.
public boolean isOpposite(Object other) {
return (this.a == other.b) ? true : false;
}
There is also the possibility that the object will implement/extend a base object to take on more fields and implement its own way of matching.
I'm considering using a LinkedList because I know it to be quicker for use than ArrayList, however I've also been considering Maps.
Edit: better explanation of objects
public class Obj {
public String a;
public String b;
public String c;
public double d;
}
The relationships are as follows:
Obj obj1, obj2;
obj1.a == obj2.b //.equals for String of course
obj1.b == obj2.a
obj1.c == obj2.c
obj1.d == obj2.d * -1
Overriding the equals or compareTo is not the right way to go, as you've mentioned. Because there is an assumption that both methods should be transitive, i.e. A eq B and B eq C => A eq C but it doesn't hold for the "opposite" objects. It's good to know, because you can't define a equivalence class and partition it into subsets, but you need to find all the pairs (depending on your use case).
Not sure, what is your goal. If you have some containers with such objects and you need to find all pairs that suffice the condition, then I am afraid you'd need to do n^2 comparisons.
I'll probably create two hash sets, one with the originals and second with the opposites and ask if the second hash set contains the opposite of each member of original hash set.
I've done some testing and determined that the cleanest way I knew how to implement this was with using ArrayList<Obj>.
This was my implementation:
public static List<ObjGroup> getNewSampleGroup(int size) {
List<ObjGroup> sampleGroup = new ArrayList<ObjGroup>();
sampleGroup.add(new ObjGroup((generateNumbers(size, 1)))); //Positives
sampleGroup.add(new ObjGroup((generateNumbers(size, -1)))); //Negatives
return sampleGroup;
}
private static List<Obj> generateNumbers(int size, int x) {
List<Obj> sampleGroup = new ArrayList<Obj>();
for (int i = 0; i < size; i ++) {
Random rand = new Random();
String randC;
String randA;
String randB;
double randD;
if (x == 1) {
randD = rand.nextInt((maxP - minP + 1) + minP);
randA = "aval";// + String.valueOf(rand.nextInt((max - min + 1) + min));
randB = "bval";// + String.valueOf(rand.nextInt((max - min + 1) + min));
randC = "cval";// + String.valueOf(rand.nextInt((max - min + 1) + min));
} else {
randD = rand.nextInt((maxP - minP + 1) + minP) * -1;
randA = "bval";// + String.valueOf(rand.nextInt((max - min + 1) + min));
randB = "aval";// + String.valueOf(rand.nextInt((max - min + 1) + min));
randC = "cval";// + String.valueOf(rand.nextInt((max - min + 1) + min));
}
sampleGroup.add(new Obj(randA, randB, randC, randD));
}
return sampleGroup;
}
public List<ObjGroup> findMatches(List<ObjGroup> unmatchedList) {
List<Obj> pivotPos = unmatchedList.get(0).getObjs(); //First grouping are positives
List<Obj> pivotNeg = unmatchedList.get(1).getObjs(); //Second grouping are negatives
List<ObjGroup> matchedList = new ArrayList<ObjGroup>();
long iterations = 0;
Collections.sort(pivotPos);
Collections.sort(pivotNeg, Collections.reverseOrder());
for (Iterator<Obj> iteratorPos = pivotPos.iterator(); iteratorPos.hasNext();) {
final Obj focus = iteratorPos.next();
iteratorPos.remove(); //Remove this once pulled as you won't match it again.
for (Iterator<Obj> iteratorNeg = pivotNeg.iterator(); iteratorNeg.hasNext();) {
final Obj candidate = iteratorNeg.next();
if (compare(focus, candidate)) {
matchedList.add(new ObjGroup(new ArrayList<Obj>() {
{
add(focus);
add(candidate);
}
}));
iteratorNeg.remove(); //Remove this once matched as you won't match it again.
break;
}
iterations ++;
}
iterations ++;
}
return matchedList;
}
I ran this against a sample size of 4,000,000 psuedo random Obj objects. This was my output:
Starting matching test.
18481512007 iterations.
3979042 matched objects.
10479 unmatched objects.
Processing time: 44 minutes.
There were 1989521 number of matches found.
Closing matching test.

Categories

Resources