swh:1:snp:eaebac3f9ac66fd8998e5ac147f1e51ef6d4c587
Raw File
Tip revision: 36108bc5d89e93b463430ef55235972391ba9e53 authored by eftekhari-mhs on 06 April 2022, 20:00:00 UTC
Create AUTHORS.md
Tip revision: 36108bc
DynamicAgent.java
import java.io.IOException;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.Random;
import java.util.Set;

public class DynamicAgent {

	enum dec_mode {
		randomly, min, max, drastic
	}

	enum change_mode {
		inc, dec
	}

	enum Phase {
		normal, waiting, updating
	}

	ArrayList<Integer> all_clocks;
	int estimate;
	int group, first_missing_v;
	int grv;
	int timer_constant = 4;
	int log_n_clocks_bound = 40;
	int timer;
	Phase phase;

	public DynamicAgent() {
		this.group = 1;
		this.all_clocks = new ArrayList<Integer>();
		for (int i = 0; i < log_n_clocks_bound; i++) {
			this.all_clocks.add(0);
		}
		this.phase = Phase.normal;
	}

	public DynamicAgent(Random r) {
		this.estimate = r.nextInt(100);
		this.group = r.nextInt(log_n_clocks_bound / 2);
		this.all_clocks = new ArrayList<Integer>();
		for (int i = 0; i < log_n_clocks_bound; i++) {
			if (i == 0)
				this.all_clocks.add(0);
			else
				this.all_clocks.add(r.nextInt(3 * i + 1));
		}
		switch (r.nextInt(3)) {
		case 0:
			this.phase = Phase.normal;
			break;
		case 1:
			this.phase = Phase.waiting;
			break;
		case 2:
			this.phase = Phase.updating;
			break;

		default:
			throw new IllegalArgumentException("Unexpected value: " + r.nextInt(3));
		}
	}

	public static int rounds_of_computations = 16;
	public static int population_size;
	public static int size_range = 800000;
	public static int logn;
	public static Random rnd;
	public static change_mode cm = change_mode.dec;

	public static void println(Object obj) {
		System.out.println(obj);
	}

	public static void print(Object obj) {
		System.out.print(obj);
	}

	public static void start_simulation() {
		int org_population_size = population_size;
		ArrayList<DynamicAgent> agents = new ArrayList<DynamicAgent>();
		ArrayList<ArrayList<Integer>> existing_signal_values = new ArrayList<ArrayList<Integer>>();
		ArrayList<ArrayList<Integer>> existing_clock_signals = new ArrayList<ArrayList<Integer>>();
		for (int i = 0; i < population_size; i++) {
//			agents.add(new DynamicAgent(rnd));
			agents.add(new DynamicAgent());
		}
//		set_all_regular_grvs(agents, 0); // error = 0;
		long interaction_tikz = 0;

		for (int r = 0; r < rounds_of_computations; r++) {

			int threshold = population_size * logn * 8;
			for (int t = 0; t < threshold; t++) {
				interaction_tikz++;
				if (t % population_size == 0) {
					existing_signal_values.add(aggregate_group_distribution(agents));
					existing_clock_signals.add(aggregate_pairwise_minimum_signal_array(agents));
					MyFileWriter.json_writer(agents, interaction_tikz, false, cm.toString(), org_population_size);
				}
				// pick 2 different agents uniformly at random
				int rec_idx = rnd.nextInt(population_size);
				int sen_idx = rnd.nextInt(population_size);
				while (rec_idx == sen_idx)
					sen_idx = rnd.nextInt(population_size);

				DynamicAgent sen = agents.get(sen_idx);
				DynamicAgent rec = agents.get(rec_idx);

				interact(rec, sen);
			}

			println("end of round " + r);

			println(agents.get(0).all_clocks);
			print_all_existing_estimates(agents);
			if (r == 8)
				adversary(agents);
		}

		MyFileWriter.json_writer(agents, interaction_tikz, true, cm.toString(), org_population_size);
		try {
			MyFileWriter.print_to_file(existing_signal_values, "clock_inits_" + org_population_size);
			MyFileWriter.print_to_file(existing_clock_signals, "clock_signals_" + org_population_size);
		} catch (IOException e) {
			e.printStackTrace();
		}

	}

	public static void main(String[] args) {

		rnd = new Random();
		population_size = 400000;// rnd.nextInt(size_range);
		logn = (int) (Math.log(population_size) / Math.log(2));
		println("n: " + population_size + "   log n: " + logn);
		start_simulation();
	}

	// top-level interaction code
	public static void interact(DynamicAgent u, DynamicAgent v) {
		updating_group(u, v);
		reset_count_down_on_array(u, v);
		for (DynamicAgent a : new DynamicAgent[] { u, v }) {
			update_missing_value(a);
			timer_routine(a);
			if (a.phase == Phase.normal) {
				size_checker(a);
			}
		}

		if (u.phase == Phase.updating && v.phase == Phase.updating) {
			propagate_max_grv(u, v);
		} else if (u.phase == Phase.normal && v.phase == Phase.normal) {
			// both confident that their values are correct
			propagate_max_grv(u, v);
			u.estimate = u.grv;
			v.estimate = v.grv;
		}
	}

	private static void size_checker(DynamicAgent u) {
		if (u.first_missing_v *(1.5) < u.estimate) {
			u.phase = Phase.waiting;
		}
		if (u.first_missing_v /4 > u.estimate) {
			u.phase = Phase.waiting;
		}
	}

	private static void print_all_existing_estimates(ArrayList<DynamicAgent> agents) {
		Set<Integer> outputs = new HashSet<Integer>();
		for (DynamicAgent a : agents) {
			outputs.add(a.estimate);
		}

		System.err.println("output values: " + outputs);
	}

	public static void adversary(ArrayList<DynamicAgent> agents) {
		if (cm == change_mode.inc) {
			print("incrementing population size. ");
			inc_the_population_size(agents);
		} else if (cm == change_mode.dec) {
			print("decrementing population size. ");
			dec_the_population_size(agents, dec_mode.drastic);
		}
	}

	private static void dec_the_population_size(ArrayList<DynamicAgent> agents, dec_mode mode) {
		int dead_agents = rnd.nextInt(population_size);
		population_size -= dead_agents;
		logn = (int) (Math.log(population_size) / Math.log(2));
		if (mode == dec_mode.randomly) {
			for (int i = 0; i < dead_agents; i++) {
				agents.remove(0);
			}
			println("updated* n: " + population_size + "   log n: " + logn);
		}

		if (mode == dec_mode.min) {
			int min = 1;
			int d = dead_agents;
			while (d > 0) {
				for (int j = 0; j < agents.size(); j++) {
					if (d > 0 && agents.get(j).group <= min) {
						agents.remove(j);
						d--;
					}
				}
				min++;
			}
			println("updated* n: " + population_size + "   log n: " + logn);
		}

		if (mode == dec_mode.max) {
			int max = logn;
			int d = dead_agents;
			while (d > 0) {
				for (int j = 0; j < agents.size(); j++) {
					if (d > 0 && agents.get(j).group >= max) {
						agents.remove(j);
						d--;
					}
				}
				max--;
			}
			println("updated* n: " + population_size + "   log n: " + logn);
		}

		if (mode == dec_mode.drastic) {
			if (population_size > 10000) {
				population_size = 500;
			} else if (population_size > 200) {
				population_size = 50;
			}
			logn = (int) (Math.log(population_size) / Math.log(2));
			ArrayList<DynamicAgent> new_agents = new ArrayList<DynamicAgent>();
			for (int j = 0; j < population_size; j++) {
				new_agents.add(agents.get(j));
			}
			agents.clear();
			agents.addAll(new_agents);
			println("updated* n: " + population_size + "   log n: " + logn);
		}
	}

	private static void propagate_max_grv(DynamicAgent u, DynamicAgent v) {
		u.grv = v.grv = Math.max(u.grv, v.grv);

	}

	static void timer_routine(DynamicAgent u) {
		int threshold = 4 * u.first_missing_v;

		if (u.phase != Phase.normal) {
			u.timer++;
		}
		if (u.timer >= threshold) { // timer hits the threshold
			if (u.phase == Phase.waiting) {
				// every agent must have almost equal "first_missing_value"
				// thus, we can use it as a mutual timer bound
				u.grv = generate_regular_grv();
				u.timer = 1;
				u.phase = Phase.updating;
			} else if (u.phase == Phase.updating) {
				u.estimate = u.grv;
				u.phase = Phase.normal;
				u.timer = 0;
				// must wait for some inconsistency to trigger internal_timer
			}
		}
	}

	private static void updating_group(DynamicAgent u, DynamicAgent v) {
		if (rnd.nextBoolean())
			u.group += 1;
		else {
			v.group = 1;
		}
	}

	private static void update_missing_value(DynamicAgent u) {
		// looking for the first zero
		boolean zeros = false;
//		int loglogn = (int) (Math.log(Math.log(population_size)/Math.log(2))/Math.log(2));
		int start = 2;
		if (u.estimate > 10)
			start = (int) Math.floor((1 + Math.log(u.estimate)) / Math.log(2));

		for (int i = start; i < u.all_clocks.size(); i++) {
			if (u.all_clocks.get(i) == 0) {
				u.first_missing_v = i - 1;
				zeros = true;
				return;
			}
		}
		if (!zeros) {
			u.first_missing_v = u.all_clocks.size() - 1;
		}
	}

	private static void inc_the_population_size(ArrayList<DynamicAgent> agents) {
		int count_new_agents = rnd.nextInt(1000 * population_size);

		ArrayList<DynamicAgent> new_agents = new ArrayList<DynamicAgent>();
		for (int i = 0; i < count_new_agents; i++) {
			new_agents.add(new DynamicAgent());
		}

		population_size += count_new_agents;
		logn = (int) (Math.log(population_size) / Math.log(2));

//		set_all_regular_grvs(new_agents, 0); // error = 0;

		agents.addAll(new_agents);
		println("updated* n: " + population_size + "   log n: " + logn);
	}

	private static void reset_count_down_on_array(DynamicAgent u, DynamicAgent v) {
		ArrayList<Integer> clk_u = new ArrayList<Integer>();
		ArrayList<Integer> clk_v = new ArrayList<Integer>();
		clk_u = u.all_clocks;
		clk_v = v.all_clocks;

		// special case for direct contact
		for (int i = 1; i < clk_u.size(); i++) {
			int max_i = Math.max(clk_u.get(i), clk_v.get(i));
			clk_u.set(i, Math.max(0, max_i - 1));
			clk_v.set(i, Math.max(0, max_i - 1));
		}

		int c = u.timer_constant;
		// special case for direct contact
		clk_u.set(u.group, u.group * c);
		clk_v.set(u.group, u.group * c);
		clk_v.set(v.group, v.group * c);
		clk_u.set(v.group, v.group * c);
	}

	public static ArrayList<Integer> aggregate_group_distribution(ArrayList<DynamicAgent> agents) {
		ArrayList<Integer> clv = new ArrayList<Integer>();
//		clv.add(logn);
		int limit = agents.get(0).log_n_clocks_bound;

		for (int i = 1; i < limit; i++) {
			clv.add(0);
		}

		for (DynamicAgent a : agents) {
			clv.set(a.group, clv.get(a.group) + 1);
		}

		return clv;
	}

	public static ArrayList<Integer> aggregate_pairwise_minimum_signal_array(ArrayList<DynamicAgent> agents) {
		ArrayList<Integer> clv = new ArrayList<Integer>();
		clv.addAll(agents.get(0).all_clocks);

		for (DynamicAgent a : agents) {
			for (int i = 1; i < clv.size(); i++) {
				clv.set(i, Math.min(a.all_clocks.get(i), clv.get(i)));
			}
		}

//		clv.set(0, logn);
		return clv;
	}

	static int generate_regular_grv() {
		int g = 1;
		while (rnd.nextBoolean()) {
			g++;
		}
		return g;
	}

}
back to top