package org.cellocad.MIT.dnacompiler; /** * Created by Bryan Der on 3/26/14. */ import lombok.Getter; import lombok.Setter; import org.cellocad.MIT.dnacompiler.Gate.GateType; import java.util.*; //import org.sbolstandard.core2.ComponentDefinition; //import org.sbolstandard.core2.ModuleDefinition; /** * * LogicCircuit is used as the DAG data structure, containing Gates connected by Wires. * * An abstract circuit is a Boolean circuit. * An assigned circuit has repressors assigned to gates. * Assigned LogicCircuits are ranked by score. * */ public class LogicCircuit{ /** * * Default constructor * */ public LogicCircuit(){ _Wires = new ArrayList<Wire>(); _Gates = new ArrayList<Gate>(); } /** * * Constructor to make LogicCircuit from DAGW (dag = abstract circuit) * */ public LogicCircuit(ArrayList<Gate> Gates, ArrayList<Wire> Wires){ // used to make abstract circuit from frontend handoff _Gates = new ArrayList<Gate>(); _Wires = new ArrayList<Wire>(); for(Gate g:Gates) { _Gates.add(g); } for(Wire w:Wires) { _Wires.add(w); } reconnectCircuit(); categorizeGates(); setGateTypes(); } /** * * Copy constructor * */ public LogicCircuit(LogicCircuit lc){ // copy constructor _Gates = lc.get_Gates(); _Wires = lc.get_Wires(); _index = _number_of_logic_circuits; _number_of_logic_circuits++; _scores = new Scores(lc.get_scores()); _truthtable = lc._truthtable; _netlist = lc._netlist; _gate_types = lc._gate_types; _assignment_name = lc._assignment_name; reconnectCircuit(); categorizeGates(); setGateTypes(); LogicCircuitUtil.sortGatesByStage(this); // re-arrange the _Gates in the order of output, logic, and input ArrayList<Gate> all_Gates = new ArrayList<Gate>(); all_Gates.addAll(_output_gates); all_Gates.addAll(_logic_gates); all_Gates.addAll(_input_gates); _Gates = all_Gates; } /** * * Gate and Wire objects must "point" to each other in memory in a connected circuit * */ public void reconnectCircuit() { //Copy _Gates ArrayList<Gate> new_Gates = new ArrayList<Gate>(); ArrayList<Wire> new_Wires = new ArrayList<Wire>(); if (_Gates != null) { for (int i=0; i<_Gates.size(); i++) { Gate g = new Gate(_Gates.get(i)); new_Gates.add(g); } } //Copy _Wires if (_Wires != null) { for (int i = 0; i< _Wires.size(); i++) { Wire w = new Wire(_Wires.get(i)); new_Wires.add(w); } } //after making deep copies of _Gates/_Wires, the _Gates/_Wires have the proper data but the new objects need to be reconnected in memory for (int i = 0; i < new_Gates.size(); i++) { if (_Gates.get(i).Outgoing != null) { //Outgoing is a wire int index = _Gates.get(i).Outgoing.Index; for(Wire w: new_Wires) { if(w.Index == index) { new_Gates.get(i).Outgoing = w; } } } } for (int i = 0; i < new_Wires.size(); i++) { if (_Wires.get(i).From != null) { //From is a gate int index = _Wires.get(i).From.Index; for(Gate g: new_Gates) { if(g.Index == index) { new_Wires.get(i).From = g; } } } if (_Wires.get(i).To != null) { //To is a gate int index = _Wires.get(i).To.Index; for(Gate g: new_Gates) { if(g.Index == index) { new_Wires.get(i).To = g; } } } if (_Wires.get(i).Next != null) { //Next is a wire int index = _Wires.get(i).Next.Index; for(Wire w: new_Wires) { if(w.Index == index) { new_Wires.get(i).Next = w; } } } } _Gates = new_Gates; _Wires = new_Wires; } public void reconnectCircuitByIndexes() { for(Gate g: this.get_Gates()) { for(Wire w: this.get_Wires()) { if (g.Outgoing_wire_index == w.Index) { g.Outgoing = w; } } for(String x: g.get_variable_names()) { for(Wire w: g.get_variable_wires().get(x)) { for(Gate g2: this.get_Gates()) { if(w.From_index == g2.Index) { w.From = g2; } if(w.To_index == g2.Index) { w.To = g2; } } for(Wire w2: this.get_Wires()) { if(w.Next_index == w2.Index) { w.Next = w2; } } } } } for(Wire w: this.get_Wires()) { for(Gate g: this.get_Gates()) { if(w.From_index == g.Index) { w.From = g; } if(w.To_index == g.Index) { w.To = g; } } } for(Wire w1: this.get_Wires()) { for(Wire w2: this.get_Wires()) { if(w1.Next_index == w2.Index && w1.Next_index != -1) { w1.Next = w2; } } } } public String toString(){ String s = ""; s += printGraph(); s += LogicCircuit.this.printLogicRPU(); return s; } /** * * prints a list of gates, and the children for each gate. * if it's an assigned circuit, also print the score and toxicity of each gate. * * Example: * ----- Logic Circuit #552 ----- * OUTPUT_OR 0110 output_YFP 0 (2,1) 1.5905 tox:0.02 * NOR 0100 NOT_rbs2-QacR 1 (4,3) tox:0.05 * NOR 0010 NOT_rbs0-SrpR 2 (5,3) tox:0.93 * NOR 1000 NOT_rbs2-LitR 3 (4,5) tox:0.52 * INPUT 0011 input_pTac 4 * INPUT 0101 input_pTet 5 * */ public String printGraph(){ String s = String.format("\n----- Logic Circuit #%d -----\n", _index); for (int i = 0; i < _Gates.size(); ++i) { Gate gi = _Gates.get(i); s += String.format("%-12s", gi.Type); s += String.format("%-18s", BooleanLogic.logicString(gi.get_logics())); s += String.format("%-18s", gi.Name); s += String.format("%-3d", gi.Index); String child_indx = "("; for(Gate child: gi.getChildren()) { child_indx += child.Index +","; } child_indx = child_indx.substring(0,child_indx.length()-1); if(gi.Type != GateType.INPUT) child_indx += ")"; s += String.format("%-12s", child_indx); if(gi.get_scores().get_score() != -1.0000) { s += String.format("%6.2f", gi.get_scores().get_score()); //onoff_ratio or noise_margin } if(gi.get_toxicity().size() > 0) { s += " tox:" + String.format("%-3.2f", Toxicity.mostToxicRow(gi)); } s += "\n"; } s += "\n"; return s; } public String printRPUTable() { String s = "\n"; s += String.format("%14s", "truth table") + "\t"; for(int j=this.get_Gates().size()-1; j>=0; --j) { Gate g = this.get_Gates().get(j); String name; if(g.Group.equals("") || g.Group == null) { name = g.Name; } else{ name = g.Group; } s += String.format("%7s", name) + "\t"; } s += "\n"; for(int i=0; i<get_Gates(GateType.OUTPUT, GateType.OUTPUT_OR).get(0).get_logics().size(); ++i){ s += String.format("%14s", this.getLogicRow(i)) + "\t"; for(int j=this.get_Gates().size()-1; j>=0; --j) { Gate g = this.get_Gates().get(j); if (g.get_logics().size() > 0 && g.get_outrpus().size() > 0){ s += String.format("%7s", String.format("%4.2f",g.get_outrpus().get(i))) + "\t"; } } s += "\n"; } return s; } public String printAssignment(){ String s = ""; for (int i = 0; i < _Gates.size(); ++i) { Gate gi = _Gates.get(i); s += String.format("%-3d", gi.get_distance_to_input()); s += String.format("%-12s", gi.Type); s += String.format("%-18s", BooleanLogic.logicString(gi.get_logics())); s += String.format("%-18s", gi.Name); s += String.format("%-3d", gi.Index); String child_indx = "("; for(Gate child: gi.getChildren()) { child_indx += child.Index +","; } child_indx = child_indx.substring(0,child_indx.length()-1); if(gi.Type != GateType.INPUT) child_indx += ")"; s += String.format("%-12s", child_indx); s += "\n"; } s += "\n"; return s; } /** * * * print RPUs and incoming RPUs for all rows of all gates. * print scores for all gates. * print toxicity values if available. * * Example: * * Circuit_score = 1.59047 maxRPU = 51.79068 avgRPU = 28.63099 maxTox = 0.02418 avgTox = 0.02998 * * output_YFP Gate=1.59047 * _OUTPUT_OR [ 0 0 ]: 0 0.038 0.056: 0.094 multiplied_tox: 0.05 * _OUTPUT_OR [ 0 1 ]: 1 0.031 3.628: 3.659 multiplied_tox: 0.02 * _OUTPUT_OR [ 1 0 ]: 1 4.503 0.053: 4.557 multiplied_tox: 0.03 * _OUTPUT_OR [ 1 1 ]: 0 0.031 0.053: 0.084 multiplied_tox: 0.02 * * NOT_rbs2-QacR Gate=1.81409 * _NOR 2 [ 0 0 ]: 0 0.020 4.886: 0.056 individual_tox: 0.05 * _NOR 2 [ 0 1 ]: 1 0.020 0.269: 3.628 individual_tox: 0.05 * _NOR 2 [ 1 0 ]: 0 8.792 0.279: 0.053 individual_tox: 0.05 * _NOR 2 [ 1 1 ]: 0 8.792 0.267: 0.053 individual_tox: 0.05 * */ public String printLogicRPU() { //header String s = String.format("Circuit_score = %-8.5f", _scores.get_score()); //if(Args.toxicity) { s += " " + String.format("Cell_growth = %-8.5f", Toxicity.mostToxicRow(this)); //} s += "\n\n"; //body for(Gate gate: _Gates) { s += printLogicRPU(gate); } return s; } public String printLogicRPU(Gate g) { //my improved output format String s = ""; if (g.get_logics().size() > 0 && g.get_outrpus().size() > 0){ s += g.Name + " Gate=" + String.format("%-6.5f",g.get_scores().get_score()) + "\n"; for(int i=0; i<g.get_outrpus().size(); ++i){ String child_rpu = ""; if(g.Type != GateType.INPUT) { for(Gate child: g.getChildren()) { child_rpu += String.format("%8.3f", child.get_outrpus().get(i)); } //child_rpu = String.format("%4.3f", sum_incoming_rpus.get(i)); } String dist2in = " "; if(g.Type != GateType.INPUT && g.Type != GateType.OUTPUT_OR && g.Type != GateType.OUTPUT) { dist2in = String.format("%4s", g.get_distance_to_input()); } //String tagged_gate_type = "_" + g.Type; // for grepping purposes to make truth table figure String logic_i = Integer.toString(g.get_logics().get(i)); if(g.get_logics().get(i) == 2) { logic_i = "-"; //dontcare } s += String.format("%11s", g.Type) + " " + dist2in + " " + String.format("%11s: %-6s", getLogicRow(i), logic_i); //s += String.format("%11s: %6.3f", child_rpu, g.get_outrpus().get(i)); s += String.format("%18s: %6.3f", child_rpu, g.get_outrpus().get(i)); if(!g.get_toxicity().isEmpty()) { if (g.get_toxicity().size() > 0 && g.Type != GateType.OUTPUT && g.Type != GateType.OUTPUT_OR) s += String.format("%18s: %3.2f", "individual_tox", g.get_toxicity().get(i)); else if (g.get_toxicity().size() > 0 && (g.Type == GateType.OUTPUT || g.Type == GateType.OUTPUT_OR)) s += String.format("%18s: %3.2f", "multiplied_tox", g.get_toxicity().get(i)); } s += "\n"; } } s += "\n"; return s; } public String printNetlist() { String s = ""; for (int i = 0; i < _Gates.size(); ++i) { Gate gi = _Gates.get(i); s += String.format("%-3d", gi.Index); s += String.format("%-12s", gi.Type); String child_indx = "("; for(Gate child: gi.getChildren()) { child_indx += child.Index +","; } child_indx = child_indx.substring(0,child_indx.length()-1); if(gi.Type != GateType.INPUT) child_indx += ")"; s += String.format("%-12s", child_indx); s += "\n"; } return s; } /** * * Example: * * returned string for row=0 of a 3-input circuit: [ 0 0 0 ] * returned string for row=7 of a 3-input circuit: [ 1 1 1 ] */ public String getLogicRow(int row) { String logic_row = "[ "; for(Gate g: _input_gates) { logic_row += g.get_logics().get(row) + " "; } logic_row += "]"; logic_row = logic_row.replace("2","-"); //dont-care return logic_row; } /** * * Categories: Input, Output, Logic(NOR), Logic(AND) * * sorted by distance to input * */ public void categorizeGates() { ArrayList<Gate> all_gates = new ArrayList<Gate>(); ArrayList<Gate> input_gates = new ArrayList<Gate>(); ArrayList<Gate> logic_gates = new ArrayList<Gate>(); ArrayList<Gate> output_gates = new ArrayList<Gate>(); for(Gate g: _Gates) { if(g.Type == GateType.INPUT) { input_gates.add(g); } else if(g.Type == GateType.OUTPUT || g.Type == GateType.OUTPUT_OR) { output_gates.add(g); } else { GateUtil.calculateDistanceToFarthestInput(g); g.RIndex = logic_gates.size() + 1; logic_gates.add(g); } } // sort _logic_gates by their distance_to_input, from far to close Collections.sort(logic_gates, new Comparator<Gate>() { public int compare(Gate g1, Gate g2) { int result = 0; if ( (g1.get_distance_to_input() - g2.get_distance_to_input()) > 1e-10 ){ result = -1; } else if ( (g1.get_distance_to_input() - g2.get_distance_to_input()) < -1.0e-10){ result = 1; } else if ( (g1.get_distance_to_input() - g2.get_distance_to_input() == 0) ) { if(g1.Index < g2.Index) { return -1; } else { return 1; } } return result; } } ); _output_gates = output_gates; _logic_gates = logic_gates; _input_gates = input_gates; all_gates.addAll(output_gates); all_gates.addAll(logic_gates); all_gates.addAll(input_gates); } public String assignment() { String assignment = ""; for(Gate g: this._logic_gates) { assignment += g.Name + " "; } return assignment; } /** * * Order the logic gates according to the given eugene construct design. * * Done prior to generating a plasmid. * */ /*public void reorderLogicGates(ArrayList<String> eugene_construct) { ArrayList<Gate> gates = new ArrayList<Gate>(); gates.addAll(_logic_gates); gates.addAll(_output_gates); ArrayList<Gate> ordered_Gates = new ArrayList<Gate>(); for(String eugene_gate_name: eugene_construct) { String gate_name = eugene_gate_name.substring(1,eugene_gate_name.length()); String orientation = eugene_gate_name.substring(0, 1); for(Gate g: gates) { if(g.Name.equals(gate_name)) { if(orientation.equals("f") || orientation.equals("+")) { g.set_direction("+"); } else if(orientation.equals("r") || orientation.equals("-")) { g.set_direction("-"); } ordered_Gates.add(g); } } } gates = ordered_Gates; Collections.reverse(gates); ArrayList<Gate> all_Gates = new ArrayList<Gate>(); all_Gates.addAll(gates); all_Gates.addAll(_input_gates); _Gates = all_Gates; }*/ public void setGateTypes() { HashMap<GateType, ArrayList<Gate>> gate_types = new HashMap<GateType, ArrayList<Gate>>(); for(Gate g: this.get_Gates()) { if(!gate_types.containsKey(g.Type)) { gate_types.put(g.Type, new ArrayList<Gate>()); } gate_types.get(g.Type).add(g); } _gate_types = gate_types; } ///////////////////////// // // Getters and Setters // ///////////////////////// public ArrayList<Gate> get_Gates(GateType gtype) { ArrayList<Gate> gates = new ArrayList<Gate>(); for(Gate g: _Gates) { if(g.Type == gtype) { gates.add(g); } } return gates; } public ArrayList<Gate> get_Gates(GateType gtype1, GateType gtype2) { ArrayList<Gate> gates = new ArrayList<Gate>(); for(Gate g: _Gates) { if(g.Type == gtype1 || g.Type == gtype2) { gates.add(g); } } return gates; } public HashMap<GateType, ArrayList<Gate>> get_logic_gate_types() { HashMap<GateType, ArrayList<Gate>> logic_gate_types = new HashMap<GateType, ArrayList<Gate>>(); for(GateType gtype: _gate_types.keySet()) { if(gtype != GateType.INPUT && gtype != GateType.OUTPUT && gtype != GateType.OUTPUT_OR ) { logic_gate_types.put(gtype, _gate_types.get(gtype)); } } return logic_gate_types; } ///////////////////////// // // Private member data // ///////////////////////// @Getter @Setter private static int _number_of_logic_circuits; @Getter @Setter private int _index; @Getter @Setter private String _assignment_name = ""; @Getter @Setter private ArrayList<Wire> _Wires = new ArrayList<Wire>(); @Getter @Setter private ArrayList<Gate> _Gates = new ArrayList<Gate>(); @Getter @Setter private ArrayList<Gate> _input_gates = new ArrayList<Gate>(); @Getter @Setter private ArrayList<Gate> _logic_gates = new ArrayList<Gate>(); @Getter @Setter private ArrayList<Gate> _output_gates = new ArrayList<Gate>(); @Getter @Setter private List<String> _truthtable = new ArrayList<String>(); @Getter @Setter private HashMap<GateType, ArrayList<Gate>> _gate_types = new HashMap<GateType, ArrayList<Gate>>(); @Getter @Setter private Scores _scores = new Scores(); @Getter @Setter private String _netlist = new String(); @Getter @Setter private ArrayList<ArrayList<Part>> _sensor_module_parts = new ArrayList<ArrayList<Part>>(); @Getter @Setter private ArrayList<ArrayList<Part>> _sensor_plasmid_parts = new ArrayList<ArrayList<Part>>(); @Getter @Setter private ArrayList<ArrayList<Part>> _circuit_module_parts = new ArrayList<ArrayList<Part>>(); @Getter @Setter private ArrayList<ArrayList<Part>> _circuit_plasmid_parts = new ArrayList<ArrayList<Part>>(); @Getter @Setter private ArrayList<ArrayList<Part>> _output_module_parts = new ArrayList<ArrayList<Part>>(); @Getter @Setter private ArrayList<ArrayList<Part>> _output_plasmid_parts = new ArrayList<ArrayList<Part>>(); }