package org.cellocad.MIT.dnacompiler; import org.apache.log4j.Logger; import java.util.ArrayList; import java.util.Arrays; /*********************************************************************** Synopsis [ Default algorithm to assign repressors to gates.] Exhaustive search. Intractable as circuit size grows, but guarantees finding the best score. Two permutations are required: 1. Permute assignment of repressors to gates. 2. Permute choice of all possible RBS-variants of the repressor assignment. ***********************************************************************/ /** * */ public class BuildCircuitsBreadthFirstSearch extends BuildCircuits { /** * Constructor. Search algorithm needs to know about: * * options: * Search settings: iterations, * Score settings: noise margin, roadblocking, toxicity * * gate_library: * Needs to know about the gate library in order to update response functions during assignment. * * roadblock: * Needs to know which input and logic gate promoters are roadblocking * * @param options * @param gate_library * @param roadblock */ public BuildCircuitsBreadthFirstSearch(Args options, GateLibrary gate_library, Roadblock roadblock) { super(options, gate_library, roadblock); } /** * returns void, but sets the list of assigned circuits, which can be accessed through 'get_logic_circuits()' */ @Override public void buildCircuits() { logger = Logger.getLogger(getThreadDependentLoggername()); logger.info("Building circuits by breadth first search"); set_logic_circuits( new ArrayList<LogicCircuit>() ); LogicCircuit lc = get_unassigned_lc(); LogicCircuitUtil.sortGatesByStage(lc); for(Gate g: lc.get_output_gates()) { Evaluate.refreshGateAttributes(g, get_gate_library()); } ArrayList<ArrayList<String>> curr_asns = new ArrayList<ArrayList<String>>(); //needs to start with one element in the array curr_asns.add(new ArrayList<String>()); for(int gi=0; gi<get_unassigned_lc().get_logic_gates().size(); gi++) { ArrayList<ArrayList<String>> next_asns = new ArrayList<ArrayList<String>>(); //foreach current branch for (ArrayList<String> curr_asn : curr_asns) { /** * Update the circuit simulation for the gates that have been assigned thus far */ for(int i=0; i<curr_asn.size(); ++i) { Gate g = lc.get_logic_gates().get(i); g.Name = curr_asn.get(i); Evaluate.refreshGateAttributes(g, get_gate_library()); g.set_unvisited(true); //simulates the RPU's Evaluate.simulateRPU(g, get_gate_library(), get_options()); //computes the gate score based on ON/OFF ratio Evaluate.evaluateGate(g, get_options()); } /** * Gate gc, 'current gate', is the gate that we want to assign now. */ Gate gc = lc.get_logic_gates().get(gi); //adding branches for (Gate libgate : get_gate_library().get_GATES_BY_TYPE().get(gc.Type).values()) { gc.Name = "null"; //setting to null then refreshing clears the attributes assocated with the gate Evaluate.refreshGateAttributes(gc, get_gate_library()); if (!currentlyAssignedGroup(lc, libgate.Group)) { gc.Name = libgate.Name; Evaluate.refreshGateAttributes(gc, get_gate_library()); gc.set_unvisited(true); Evaluate.simulateRPU(gc, get_gate_library(), get_options()); Evaluate.evaluateGate(gc, get_options()); if(get_options().is_check_roadblocking()) { if (get_roadblock().numberRoadblocking(lc, get_gate_library()) > 0) { //logger.info("rb"); continue; } } if(get_options().is_toxicity()) { gc.set_toxtable(get_gate_library().get_GATES_BY_NAME().get(gc.Name).get_toxtable()); Toxicity.evaluateGateToxicity(gc); if (Toxicity.mostToxicRow(gc) < get_options().get_toxicity_threshold()) { //logger.info("tox"); continue; } } if(get_options().is_noise_margin()) { if (!gc.get_scores().is_noise_margin_contract()) { //logger.info("nm"); continue; } } if(gc.get_scores().get_onoff_ratio() < get_options().get_gate_onoff_threshold()) { //continue; } //'continue' will skip these steps, which add the passing assignment for 'gc' to the 'current assignment' list ArrayList<String> pass_asn = new ArrayList<String>(curr_asn); //pass_asn is a list of gate names... //the index order matches the index order of the gates in the 'logic_gates' array pass_asn.add(gc.Name); //curr_asns is a list of passing assignments next_asns.add(new ArrayList<String>(pass_asn)); //logger.info("child: " + gc.Outgoing.To.Name + " gate: " + gc.Name); } } } curr_asns.clear(); // we are about to loop to the next round, so we update 'assignments' with the current assignments. curr_asns = next_asns; Integer[] gate_indexes_assigned = new Integer[gi+1]; for(int i=0; i<(gi+1); ++i) { gate_indexes_assigned[i] = (i+1); } /** * Assignments for gates [1]: 16 * Assignments for gates [1, 2]: 201 * Assignments for gates [1, 2, 3]: 1943 * Assignments for gates [1, 2, 3, 4]: 3961 * Assignments for gates [1, 2, 3, 4, 5]: 4401 * Assignments for gates [1, 2, 3, 4, 5, 6]: 2815 * * Notice that the number of passing assignments can actually decrease from one round to the next */ logger.info("Assignments for gates " + Arrays.toString(gate_indexes_assigned) + ": " + curr_asns.size()); } //logger.info("Final stage assignments: " + assignments.size() + " Gates: " + lc.get_logic_gates().size()); //System.exit(-1); logger.info("\nScoring all assignments..."); /** * Loop through the passing complete assignments (as opposed to partial assignments) * and resimulate/rescore the circuit, then add each circuit to the array of assigned circuits. */ for(ArrayList<String> assignment: curr_asns) { LogicCircuit temp_deep_copy = new LogicCircuit(lc); lc = temp_deep_copy; LogicCircuitUtil.sortGatesByStage(lc); for(int i=0; i<assignment.size(); ++i) { String gate_name = assignment.get(i); Gate g = lc.get_logic_gates().get(i); g.Name = gate_name; } Evaluate.evaluateCircuit(lc, get_gate_library(), get_options()); Toxicity.evaluateCircuitToxicity(lc, get_gate_library()); //logger.info("score_v_growth: " + Util.sc(lc.get_scores().get_score()) + " " + Util.sc(Toxicity.mostToxicRow(lc))); LogicCircuitUtil.sortGatesByIndex(lc); get_logic_circuits().add(lc); } } /** * If group name already exists in the current circuit assignment, return true; * This prevents the assignment of genetic gates belonging to the same group (such as RBS variants or crosstalkers) * * @param lc * @param group_name * @return */ 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; } private Logger logger = Logger.getLogger(getClass()); }