Skip to content
Snippets Groups Projects
Commit 09d03e97 authored by berleon's avatar berleon
Browse files

Add evaluation & small fixes for transaction logs

parent 943ed45a
No related branches found
No related tags found
No related merge requests found
%% Cell type:code id: tags:
``` python
%matplotlib inline
import numpy as np
import matplotlib.pyplot as plt
import json
import os
from pylab import rcParams
rcParams['figure.figsize'] = 10, 6
```
%% Cell type:code id: tags:
``` python
log_dir = 'log'
```
%% Cell type:code id: tags:
``` python
snapshots = {}
for filename in os.listdir(log_dir):
with open(os.path.join(log_dir, filename), 'r') as f:
snapshots[filename] = json.load(f)
```
%% Cell type:code id: tags:
``` python
for filename, snap in snapshots.items():
if len(snap) != 9:
os.remove(os.path.join(log_dir, filename))
```
%% Cell type:code id: tags:
``` python
snapshots = {fname: snap for fname, snap in snapshots.items() if len(snap) == 9}
print("got {} snapshots".format(len(snapshots)))
```
%% Cell type:code id: tags:
``` python
next(iter(snapshots.values()))
```
%% Cell type:code id: tags:
``` python
def get_all_values(prefix):
all_values = []
for snap in snapshots.values():
snap_values = []
for node, value in snap.items():
if node.startswith(prefix):
snap_values.append(value[0])
all_values.append(snap_values)
return np.array(all_values)
get_all_values('balanced')
```
%% Cell type:code id: tags:
``` python
labels = ['generous', 'balanced', 'greedy']
gbg = np.stack([get_all_values(prefix).flatten() for prefix in labels]).T
```
%% Cell type:code id: tags:
``` python
gbg.shape
```
%% Cell type:code id: tags:
``` python
plt.boxplot(gbg)
plt.xticks(np.arange(1, len(labels)+1), labels)
plt.show()
```
%% Cell type:code id: tags:
``` python
```
{"greedy_2":[84],"balanced_1":[233],"greedy_1":[144],"balanced_2":[113],"greedy_0":[61],"balanced_0":[235],"generous_1":[5],"generous_2":[6],"generous_0":[19]}
{"balanced_1":[108],"greedy_2":[123],"greedy_1":[112],"balanced_2":[40],"greedy_0":[40],"balanced_0":[387],"generous_1":[38],"generous_2":[21],"generous_0":[31]}
{"greedy_2":[248],"balanced_1":[110],"greedy_1":[134],"balanced_2":[143],"greedy_0":[56],"balanced_0":[206],"generous_1":[0],"generous_2":[1],"generous_0":[2]}
{"greedy_2":[77],"balanced_1":[147],"greedy_1":[236],"balanced_2":[106],"greedy_0":[141],"balanced_0":[172],"generous_1":[0],"generous_2":[20],"generous_0":[1]}
{"greedy_2":[31],"balanced_1":[78],"greedy_1":[147],"balanced_2":[272],"greedy_0":[58],"balanced_0":[147],"generous_1":[119],"generous_2":[16],"generous_0":[32]}
{"greedy_2":[91],"balanced_1":[122],"greedy_1":[174],"balanced_2":[171],"greedy_0":[64],"balanced_0":[151],"generous_1":[100],"generous_2":[1],"generous_0":[26]}
{"greedy_2":[39],"balanced_1":[21],"greedy_1":[407],"balanced_2":[132],"greedy_0":[120],"balanced_0":[92],"generous_1":[23],"generous_2":[65],"generous_0":[1]}
...@@ -91,7 +91,11 @@ public abstract class AbstractNode extends UntypedActor implements Serializable ...@@ -91,7 +91,11 @@ public abstract class AbstractNode extends UntypedActor implements Serializable
} }
public Promise<Snapshot> makeSnapshot() throws InterruptedException{ public Promise<Snapshot> makeSnapshot() throws InterruptedException {
return makeSnapshot(true);
}
public Promise<Snapshot> makeSnapshot(boolean useDelay) throws InterruptedException{
String prefix = ""; String prefix = "";
if (this instanceof SuperVisorImpl) { if (this instanceof SuperVisorImpl) {
prefix = "supervisor"; prefix = "supervisor";
...@@ -110,11 +114,13 @@ public abstract class AbstractNode extends UntypedActor implements Serializable ...@@ -110,11 +114,13 @@ public abstract class AbstractNode extends UntypedActor implements Serializable
int i = 0; int i = 0;
for (ActorRef act : getKnownNeighbors().values()) { for (ActorRef act : getKnownNeighbors().values()) {
if(i % 3 == 0){ if(i % 3 == 0){
try { if (useDelay) {
//Add a little delay now and then try {
Thread.sleep(500); //Add a little useDelay now and then
} catch (InterruptedException ex) { Thread.sleep(500);
Exceptions.printStackTrace(ex); } catch (InterruptedException ex) {
Exceptions.printStackTrace(ex);
}
} }
} }
act.tell(new SnapShotBegin(this.currentSnapshotToken), self()); act.tell(new SnapShotBegin(this.currentSnapshotToken), self());
......
...@@ -5,25 +5,41 @@ import fucoin.actions.snap.SnapShotSaveState; ...@@ -5,25 +5,41 @@ import fucoin.actions.snap.SnapShotSaveState;
import org.json.JSONObject; import org.json.JSONObject;
import scala.concurrent.Promise; import scala.concurrent.Promise;
import java.util.ArrayList; import java.util.*;
import java.util.HashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.List;
public class Snapshot { public class Snapshot {
public HashMap<String, Integer> states = new HashMap<>(); public Map<String, Integer> states = new ConcurrentHashMap<String, Integer>();
public List<SnapshotTransaction> transactions = new ArrayList<>(); public List<SnapshotTransaction> transactions = Collections.synchronizedList(new ArrayList<>());
private Promise<Snapshot> complete = Futures.promise(); private Promise<Snapshot> complete = Futures.promise();
@Override @Override
public String toString() { public String toString() {
return "Snapshot{" + StringBuilder sb = new StringBuilder();
"states=" + states + sb.append("Snapshot {\n");
", transactions=" + transactions + sb.append(" States {\n");
'}'; for (String name : states.keySet()) {
sb.append(" " + name + ": " + states.get(name) + "\n");
}
sb.append(" }\n");
sb.append(" Transactions {\n");
for (int i = 0; i < transactions.size(); i++) {
SnapshotTransaction ts = transactions.get(i);
sb.append(" " + ts.amount + " FU's from " + ts.sender + " to " + ts.receiver + "\n");
}
sb.append(" }\n");
sb.append("}\n");
return sb.toString();
} }
public JSONObject toJson() { public JSONObject toJson() {
return null; JSONObject obj = new JSONObject();
for (String key : states.keySet()) {
obj.append(key, states.get(key));
}
return obj;
} }
public void addState(String name, int amount) { public void addState(String name, int amount) {
......
...@@ -26,7 +26,13 @@ public class SnapShotSaveState extends SnapAction { ...@@ -26,7 +26,13 @@ public class SnapShotSaveState extends SnapAction {
for (ActorRef node : abstractNode.getKnownNeighbors().values()) { for (ActorRef node : abstractNode.getKnownNeighbors().values()) {
node.tell(new SnapShotEnd(), self); node.tell(new SnapShotEnd(), self);
} }
snap.completed(); try {
if (! snap.promise().isCompleted()) {
snap.completed();
}
} catch (IllegalStateException e) {
throw e;
}
} }
} }
} }
...@@ -4,7 +4,6 @@ import akka.actor.ActorRef; ...@@ -4,7 +4,6 @@ import akka.actor.ActorRef;
import akka.actor.UntypedActorContext; import akka.actor.UntypedActorContext;
import fucoin.AbstractNode; import fucoin.AbstractNode;
import fucoin.SnapshotTransaction; import fucoin.SnapshotTransaction;
import fucoin.actions.Action;
public class SnapShotSaveTransaction extends SnapAction { public class SnapShotSaveTransaction extends SnapAction {
public SnapshotTransaction transaction; public SnapshotTransaction transaction;
......
...@@ -2,6 +2,7 @@ package fucoin.configurations; ...@@ -2,6 +2,7 @@ package fucoin.configurations;
import akka.actor.ActorRef; import akka.actor.ActorRef;
import akka.dispatch.Futures; import akka.dispatch.Futures;
import akka.dispatch.OnComplete;
import akka.dispatch.OnSuccess; import akka.dispatch.OnSuccess;
import akka.pattern.Patterns; import akka.pattern.Patterns;
import fucoin.Snapshot; import fucoin.Snapshot;
...@@ -11,19 +12,24 @@ import fucoin.actions.transaction.ActionGetAmount; ...@@ -11,19 +12,24 @@ import fucoin.actions.transaction.ActionGetAmount;
import fucoin.actions.transaction.ActionGetAmountAnswer; import fucoin.actions.transaction.ActionGetAmountAnswer;
import fucoin.actions.transaction.ActionNotifyObserver; import fucoin.actions.transaction.ActionNotifyObserver;
import fucoin.configurations.internal.ConfigurationName; import fucoin.configurations.internal.ConfigurationName;
import fucoin.supervisor.SuperVisorLogImpl;
import org.apache.commons.math3.distribution.EnumeratedDistribution; import org.apache.commons.math3.distribution.EnumeratedDistribution;
import org.apache.commons.math3.util.Pair; import org.apache.commons.math3.util.Pair;
import org.json.JSONObject;
import scala.Function1; import scala.Function1;
import scala.PartialFunction;
import scala.concurrent.Await; import scala.concurrent.Await;
import scala.concurrent.Future; import scala.concurrent.Future;
import scala.concurrent.Promise; import scala.concurrent.Promise;
import scala.runtime.BoxedUnit; import scala.runtime.BoxedUnit;
import scala.util.Try;
import java.util.ArrayList;
import java.util.HashMap; import java.io.File;
import java.util.List; import java.io.PrintWriter;
import java.util.Map; import java.nio.file.Path;
import java.nio.file.Paths;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.stream.Stream; import java.util.stream.Stream;
import org.openide.util.Exceptions; import org.openide.util.Exceptions;
...@@ -101,11 +107,12 @@ class WalletSimulation { ...@@ -101,11 +107,12 @@ class WalletSimulation {
@ConfigurationName("GGBWallet") @ConfigurationName("GGBWallet")
public class GGBWalletConfiguration extends AbstractConfiguration { public class GGBWalletConfiguration extends AbstractConfiguration {
private static int n_generous = 1; private static int n_generous = 3;
private static int n_greedy = 1; private static int n_greedy = 3;
private static int n_balanced = 1; private static int n_balanced = 3;
private static double n_steps = 40000; private static int n_steps = 500;
private static String log_filename = "log.json"; private static String logDirectory = "log";
private Map<String, WalletSimulation> simulations; private Map<String, WalletSimulation> simulations;
private HashMap<String,ActorRef> walletMap; private HashMap<String,ActorRef> walletMap;
...@@ -127,9 +134,13 @@ public class GGBWalletConfiguration extends AbstractConfiguration { ...@@ -127,9 +134,13 @@ public class GGBWalletConfiguration extends AbstractConfiguration {
private int currentStep = 0; private int currentStep = 0;
private Promise<Void> simulationFinished = Futures.promise(); private Promise<Void> simulationFinished = Futures.promise();
private double start;
static {
File logDir = new File(logDirectory);
if (!logDir.exists()) {
logDir.mkdir();
}
}
@Override @Override
public void run() { public void run() {
simulations = new HashMap<>(); simulations = new HashMap<>();
...@@ -185,23 +196,40 @@ public class GGBWalletConfiguration extends AbstractConfiguration { ...@@ -185,23 +196,40 @@ public class GGBWalletConfiguration extends AbstractConfiguration {
simulations.put(name, new WalletSimulation(name, allWalletNames, BALANCED_PROBABILITY, simulations.put(name, new WalletSimulation(name, allWalletNames, BALANCED_PROBABILITY,
BALANCED_MIN, BALANCED_MAX, BALANCED_ADAPTION)); BALANCED_MIN, BALANCED_MAX, BALANCED_ADAPTION));
} }
start = System.currentTimeMillis() / 1000.;
try { try {
this.nextTransaction(); this.nextTransaction();
} catch (InterruptedException ex) { } catch (InterruptedException ex) {
Exceptions.printStackTrace(ex); Exceptions.printStackTrace(ex);
} }
simulationFinished.future().onSuccess(new OnSuccess<Void>() { simulationFinished.future().andThen(new OnComplete<Void>() {
@Override @Override
public void onSuccess(Void result) { public void onComplete(Throwable failure, Void success) throws Throwable {
// You can start your algorithm here if you want to. final boolean noDelay = false;
// Alternatively, you can also notify the user that all transactions are finished GGBWalletConfiguration.this.makeSnapshot(noDelay).future().onSuccess(
System.out.println("All random transactions finished!"); new OnSuccess<Snapshot>() {
@Override
public void onSuccess(Snapshot snap) throws Throwable {
JSONObject json = snap.toJson();
TimeZone tz = TimeZone.getTimeZone("UTC");
DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm'Z'");
df.setTimeZone(tz);
String nowAsISO = df.format(new Date());
Path logFilename = Paths.get(GGBWalletConfiguration.logDirectory, nowAsISO + ".json");
try(PrintWriter f = new PrintWriter(logFilename.toString())) {
f.println(json.toString());
}
System.out.println("SNAPSHOT saved under: " + logFilename.toString());
}
}
, context().dispatcher());
} }
}, context().dispatcher()); }, context().dispatcher());
} }
private void nextTransaction() throws InterruptedException { private void nextTransaction() throws InterruptedException {
for(;currentStep < n_steps; currentStep++) { for(;currentStep < n_steps; currentStep++) {
for (WalletSimulation currentWallet : simulations.values()) { for (WalletSimulation currentWallet : simulations.values()) {
if(currentWallet.willSend()){ if(currentWallet.willSend()){
String receiverName = currentWallet.sampleReceiver(); String receiverName = currentWallet.sampleReceiver();
...@@ -229,6 +257,10 @@ public class GGBWalletConfiguration extends AbstractConfiguration { ...@@ -229,6 +257,10 @@ public class GGBWalletConfiguration extends AbstractConfiguration {
} }
} }
} }
if (simulationFinished != null) {
simulationFinished.success(null);
simulationFinished = null;
}
} }
...@@ -246,19 +278,6 @@ public class GGBWalletConfiguration extends AbstractConfiguration { ...@@ -246,19 +278,6 @@ public class GGBWalletConfiguration extends AbstractConfiguration {
} }
return 0; return 0;
} }
@Override
ActorRef initSupervisor() {
superVisor = context().actorOf(
SuperVisorLogImpl.props(log_filename), "SuperVisorImpl");
// Don't ask.
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
return superVisor;
}
@Override @Override
public void onReceive(Object message) { public void onReceive(Object message) {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment