package org.cellocad.MIT.dnacompiler; /** * Created by Bryan Der on 3/26/14. */ import org.apache.log4j.Logger; import java.util.*; public class BuildCircuitsSteepestAscent extends BuildCircuits { public BuildCircuitsSteepestAscent(Args options, GateLibrary gate_library, Roadblock roadblock) { super(options, gate_library, roadblock); } private boolean currentlyAssignedGroup(LogicCircuit lc, String group_name) { for(Gate g: lc.get_logic_gates()) { if(g.Group.equals(group_name)) { return true; } } return false; } @Override public void buildCircuits(){ logger = Logger.getLogger(getThreadDependentLoggername()); logger.info("Enumerating logic circuits using steepest ascent..."); Random generator = new Random(); double max_score = 0.0; LogicCircuit lc = new LogicCircuit(get_unassigned_lc()); for(int traj=0; traj<get_options().get_hill_trajectories(); ++traj) { set_best_score( 0.0 ); //initial random for (int i = 0; i < lc.get_logic_gates().size(); ++i) { Gate g = lc.get_logic_gates().get(i); g.Name = "null"; } for (int i = 0; i < lc.get_logic_gates().size(); ++i) { Gate g = lc.get_logic_gates().get(i); LinkedHashMap<String, ArrayList<Gate>> groups_of_type = get_gate_library().get_GATES_BY_GROUP().get(g.Type); ArrayList<String> group_names = new ArrayList<String>(groups_of_type.keySet()); Collections.shuffle(group_names); for (String group_name : group_names) { if (!currentlyAssignedGroup(lc, group_name)) { ArrayList<Gate> gates_of_group = new ArrayList<Gate>(groups_of_type.get(group_name)); Collections.shuffle(gates_of_group); g.Name = gates_of_group.get(0).Name; } } } Evaluate.evaluateCircuit(lc, get_gate_library(), get_options()); for (Gate g : lc.get_logic_gates()) { Evaluate.evaluateGate(g, get_options()); } //logger.info(lc.printGraph()); for (int i = 0; i < get_options().get_hill_iterations(); ++i) { //choose Gate A LogicCircuit save_lc = new LogicCircuit(lc); int A_gate_index = generator.nextInt(lc.get_logic_gates().size()); Gate A_gate = lc.get_logic_gates().get(A_gate_index); HashMap<String, Double> B_gate_choices = getGateBChoices(lc, A_gate.Name); String best_B_gate_name = ""; Double best_B_gate_score = 0.0; for(String B_gate_name: B_gate_choices.keySet()) { if(B_gate_choices.get(B_gate_name) > best_B_gate_score) { best_B_gate_name = B_gate_name; best_B_gate_score = B_gate_choices.get(B_gate_name); } } if(get_gate_library().get_GATES_BY_NAME().containsKey(best_B_gate_name)) { Gate B_gate = get_gate_library().get_GATES_BY_NAME().get(best_B_gate_name); String A_gate_name = new String(A_gate.Name); String B_gate_name = new String(B_gate.Name); String A_gate_group = new String(A_gate.Group); String B_gate_group = new String(B_gate.Group); String A_regulator = new String(A_gate.Group); String B_regulator = new String(B_gate.Group); //1. if second gate is used, swap if(isNextGateCurrentlyUsed(lc, B_gate)) { int B_gate_index = 0; for(int j=0; j<lc.get_logic_gates().size(); ++j) { if(lc.get_logic_gates().get(j).Name.equals(B_gate.Name)) { B_gate_index = j; } } lc.get_logic_gates().get(A_gate_index).Name = B_gate_name; lc.get_logic_gates().get(B_gate_index).Name = A_gate_name; lc.get_logic_gates().get(A_gate_index).Group = B_gate_group; lc.get_logic_gates().get(B_gate_index).Group = A_gate_group; lc.get_logic_gates().get(A_gate_index).Regulator = B_regulator; lc.get_logic_gates().get(B_gate_index).Regulator = A_regulator; } //2. if second gate is unused, substitute else { lc.get_logic_gates().get(A_gate_index).Name = B_gate_name; lc.get_logic_gates().get(A_gate_index).Group = B_gate_group; lc.get_logic_gates().get(A_gate_index).Regulator = B_regulator; } set_n_total_assignments( get_n_total_assignments() + 1 ); Evaluate.evaluateCircuit(lc, get_gate_library(), get_options()); if(get_options().is_toxicity()) { Toxicity.evaluateCircuitToxicity(lc, get_gate_library()); } if(get_options().is_check_roadblocking() == false || get_roadblock().numberRoadblocking(lc, get_gate_library()) == 0 ) { if(get_options().is_toxicity() == false || Toxicity.mostToxicRow(lc) > get_options().get_toxicity_threshold()) { if(get_options().is_noise_margin() && lc.get_scores().is_noise_margin_contract() == true) { set_best_score( lc.get_scores().get_score() ); get_logic_circuits().add(new LogicCircuit(lc)); } } } } } logger.info("STEEPEST_ASCENT " + String.format("%-8s", "#" + traj) + " score:" + Util.sc(get_best_score()) + " tox:" + Util.sc(Toxicity.mostToxicRow(lc)) + " nm:" + Util.sc(lc.get_scores().get_noise_margin()) + " rb:" + get_roadblock().numberRoadblocking(lc, get_gate_library())); set_best_score ( 0.0 ); } } private boolean isNextGateCurrentlyUsed(LogicCircuit A_lc, Gate B_gate) { boolean is_used = false; for(int i=0; i<A_lc.get_logic_gates().size(); ++i) { String gate_name = A_lc.get_logic_gates().get(i).Name; if(B_gate.Name.equals(gate_name)) { is_used = true; break; } } return is_used; } private HashMap<String, Double> getGateBChoices(LogicCircuit lc, String A_gate_name) { LogicCircuit save_lc = new LogicCircuit(lc); Evaluate.evaluateCircuit(save_lc, get_gate_library(), get_options()); HashMap<String, Double> gate_B_choices = new HashMap<>(); HashSet<String> allowed_B_gates = new HashSet<>(); Gate A_gate = get_gate_library().get_GATES_BY_NAME().get(A_gate_name); int A_gate_index = 0; for(int j=0; j<lc.get_logic_gates().size(); ++j) { if(lc.get_logic_gates().get(j).Name.equals(A_gate.Name)) { A_gate_index = j; } } ArrayList<Gate> gates_of_type = new ArrayList<Gate>(get_gate_library().get_GATES_BY_TYPE().get(A_gate.Type).values()); for(Gate g: gates_of_type) { //disallow same gate if(g.Name.equals(A_gate.Name)) { continue; } //allow RBS variant if(g.Group.equals(A_gate.Group)) { allowed_B_gates.add(g.Name); } //allow non-duplicate groups if (!currentlyAssignedGroup(lc, g.Group)) { allowed_B_gates.add(g.Name); } } int A_rb = get_roadblock().numberRoadblocking(save_lc, get_gate_library()); Double A_growth = Toxicity.mostToxicRow(save_lc); Double A_score = save_lc.get_scores().get_score(); for(String B_gate_name: allowed_B_gates) { Gate B_gate = get_gate_library().get_GATES_BY_NAME().get(B_gate_name); A_gate_name = new String(A_gate.Name); B_gate_name = new String(B_gate.Name); String A_gate_group = new String(A_gate.Group); String B_gate_group = new String(B_gate.Group); String A_regulator = new String(A_gate.Group); String B_regulator = new String(B_gate.Group); //1. if second gate is used, swap if(isNextGateCurrentlyUsed(lc, B_gate)) { int B_gate_index = 0; for(int j=0; j<lc.get_logic_gates().size(); ++j) { if(lc.get_logic_gates().get(j).Name.equals(B_gate.Name)) { B_gate_index = j; } } lc.get_logic_gates().get(A_gate_index).Name = B_gate_name; lc.get_logic_gates().get(B_gate_index).Name = A_gate_name; lc.get_logic_gates().get(A_gate_index).Group = B_gate_group; lc.get_logic_gates().get(B_gate_index).Group = A_gate_group; lc.get_logic_gates().get(A_gate_index).Regulator = B_regulator; lc.get_logic_gates().get(B_gate_index).Regulator = A_regulator; } //2. if second gate is unused, substitute else { lc.get_logic_gates().get(A_gate_index).Name = B_gate_name; lc.get_logic_gates().get(A_gate_index).Group = B_gate_group; lc.get_logic_gates().get(A_gate_index).Regulator = B_regulator; } Evaluate.evaluateCircuit(lc, get_gate_library(), get_options()); if(get_options().is_toxicity()) { Toxicity.evaluateCircuitToxicity(lc, get_gate_library()); } int B_rb = get_roadblock().numberRoadblocking(lc, get_gate_library()); Double B_growth = Toxicity.mostToxicRow(lc); Double B_score = new Double(lc.get_scores().get_score()); revert(lc, save_lc); /*if(B_score > A_score) { gate_B_choices.put(B_gate_name, B_score); }*/ if(A_rb > 0) { if(B_rb < A_rb) { //logger.info("roadblocking, adding " + B_gate_name); gate_B_choices.put(B_gate_name, B_score); } } else if(A_growth < get_options().get_toxicity_threshold()) { if(B_growth > A_growth) { //logger.info("toxic, adding " + B_gate_name); gate_B_choices.put(B_gate_name, B_growth); } } else { if(B_score > A_score) { if(B_growth > get_options().get_toxicity_threshold() && B_rb == 0) { //logger.info("regular, adding " + B_gate_name); gate_B_choices.put(B_gate_name, B_score); } } } } //System.exit(-1); return gate_B_choices; } //debugging purposes. private void checkReuseError(LogicCircuit lc) { for(int i=0; i<lc.get_logic_gates().size()-1; ++i) { for(int j=i+1; j<lc.get_logic_gates().size(); ++j) { if(lc.get_logic_gates().get(i).Group.equals(lc.get_logic_gates().get(j).Group)) { throw new IllegalStateException("Repressor reuse error in simulated annealing, \n" + lc.get_logic_gates().get(i).Name + " " + lc.get_logic_gates().get(j).Name); } } } } //if rejected, reset the Name for all logic gates. private void revert(LogicCircuit B_lc, LogicCircuit A_lc) { for(int i=0; i<A_lc.get_logic_gates().size(); ++i) { B_lc.get_logic_gates().get(i).Name = A_lc.get_logic_gates().get(i).Name; B_lc.get_logic_gates().get(i).Group = A_lc.get_logic_gates().get(i).Group; B_lc.get_logic_gates().get(i).Regulator = A_lc.get_logic_gates().get(i).Regulator; } Evaluate.evaluateCircuit(B_lc, get_gate_library(), get_options()); } private Logger logger = Logger.getLogger(getClass()); }