using System; using System.Collections.Generic; using System.Text; using System.Xml; using System.IO; namespace Inteaktivni { public class Net : ICloneable { public List Inputs { get; private set; } public List Outputs { get; private set; } public List Gates { get; private set; } public Dictionary pins = new Dictionary(); /// /// Třída zastupující celou síť, která mi svtupy, výstupy a hralda /// public Net() { Inputs = new List(); Outputs = new List(); Gates = new List(); } public static Net ParseNet(string fileName) { if (!File.Exists(Program.MainPath + "\\" + fileName)) { Console.WriteLine("Nenalezen soubor " + Program.MainPath + "\\" + fileName); return null; } XmlTextReader xtr = new XmlTextReader(Program.MainPath + "\\" + fileName); Net n = new Net(); if (xtr.EOF) return n; while (xtr.Read()) { if (xtr.NodeType == XmlNodeType.Element) { switch (xtr.Name) { case "input": Pin p = new Pin(xtr["id"], xtr["x"], xtr["y"], xtr["w"], xtr["h"]); n.Inputs.Add(p); if (n.pins.ContainsKey(p.Id)) Console.WriteLine("ID " + p.Id + " neni unikatni!"); else n.pins.Add(p.Id, p); break; case "output": n.Outputs.Add(new Pin(xtr["id"], xtr["x"], xtr["y"], xtr["w"], xtr["h"])); break; case "gate": Gate g = new Gate(xtr["type"], xtr["x"], xtr["y"], xtr["w"], xtr["h"]); Gate.ParseGate(g, xtr.ReadSubtree()); n.Gates.Add(g); foreach (Pin pn in g.Outputs) if (n.pins.ContainsKey(pn.Id)) Console.WriteLine("ID " + pn.Id + " neni unikatni!"); else n.pins.Add(pn.Id, pn); break; default: break; } } } return n; } public bool[] SolveNet(bool[] inputs) { bool[] outputs = new bool[Outputs.Count]; if (inputs.Length != Inputs.Count) { Console.WriteLine("Pocet vstupu se neshoduje s poctem vstupnich hodnot"); return outputs; } // naplnění vstupních pinů for (int i = 0; i < inputs.Length; i++) Inputs[i].Value = inputs[i] ? PortValue.True : PortValue.False; bool solved = false; while (!solved) { solved = true; // přenesení z výstupů na svtupy foreach (Gate g in Gates) foreach (Pin p in g.Inputs) p.Value = pins[p.Id].Value; // výpočet foreach (Gate g in Gates) g.Count(); foreach (Pin p in Outputs) { if (pins[p.Id].Value == PortValue.Unknown) { solved = false; break; } } } // naplnění výstupů for (int i = 0; i < Outputs.Count; i++) outputs[i] = pins[Outputs[i].Id].Value == PortValue.True ? true : false; return outputs; } public List SolveInterativeNet(bool[] inputs) { bool[] outputs = new bool[Outputs.Count]; if (inputs.Length != Inputs.Count) { Console.WriteLine("Pocet vstupu se neshoduje s poctem vstupnich hodnot"); return null; } // naplnění vstupních pinů for (int i = 0; i < inputs.Length; i++) Inputs[i].Value = inputs[i] ? PortValue.True : PortValue.False; List outNets = new List(); bool solved = false; while (!solved) { outNets.Add((Net)this.Clone()); solved = true; // přenesení z výstupů na svtupy foreach (Gate g in Gates) foreach (Pin p in g.Inputs) p.Value = pins[p.Id].Value; // výpočet foreach (Gate g in Gates) g.Count(); foreach (Pin p in Outputs) { if (pins[p.Id].Value == PortValue.Unknown) { solved = false; break; } } } // naplnění výstupů for (int i = 0; i < Outputs.Count; i++) Outputs[i].Value = pins[Outputs[i].Id].Value; outNets.Add((Net)this.Clone()); return outNets; } /// /// pro resetování mezi öpakovanými testy /// public void resetNet() { foreach (Pin p in pins.Values) p.Value = PortValue.Unknown; foreach (Gate g in Gates) { if (g.InnerNet != null) g.InnerNet.resetNet(); } } #region ICloneable Members public object Clone() { Net n = new Net(); foreach (Pin p in Inputs) { Pin clone = (Pin)p.Clone(); n.Inputs.Add(clone); n.pins.Add(clone.Id, clone); } foreach (Pin p in Outputs) n.Outputs.Add((Pin)p.Clone()); foreach (Gate g in Gates) { Gate colneG = (Gate)g.Clone(); n.Gates.Add(colneG); foreach (Pin pn in colneG.Outputs) n.pins.Add(pn.Id, pn); } return n; } #endregion } /// /// Třída pro pin (vstup/výstup) /// public class Pin : ICloneable { public PortValue Value { get; set; } public string Id { get; set; } public int X { get; set; } public int Y { get; set; } public int W { get; set; } public int H { get; set; } public Pin(string id, int x, int y, int w, int h, PortValue pv) { Id = id; X = x; Y = y; W = w; H = h; Value = pv; } public Pin(string id, string x, string y, string w, string h) { Id = id; Value = PortValue.Unknown; int i; if (int.TryParse(x, out i)) X = i; if (int.TryParse(y, out i)) Y = i; if (int.TryParse(w, out i)) W = i; if (int.TryParse(h, out i)) H = i; } public Pin(string id) { Id = id; Value = PortValue.Unknown; /* X = x; Y = y; W = w; H = h;*/ } #region ICloneable Members public object Clone() { return new Pin(Id, X, Y, W, H, Value); } #endregion } /// /// Třída popistující hradlo se vstupy a výstupy, může obsahovat i vnitřní síť /// public class Gate : ICloneable { public GateType GType { get; private set; } public List Inputs { get; private set; } public List Outputs { get; private set; } public Net InnerNet { get; private set; } public int X { get; private set; } public int Y { get; private set; } public int W { get; private set; } public int H { get; private set; } public Gate(GateType gateType, int x, int y, int w, int h) { Inputs = new List(); Outputs = new List(); GType = gateType; X = x; Y = y; W = w; H = h; } public Gate(string gateType, string x, string y, string w, string h) { Inputs = new List(); Outputs = new List(); switch (gateType.ToLower()) { case "and": GType = GateType.And; break; case "or": GType = GateType.Or; break; case "xor": GType = GateType.Xor; break; case "not": GType = GateType.Not; break; default: GType = GateType.Net; InnerNet = Net.ParseNet(gateType); break; } int i; if (int.TryParse(x, out i)) X = i; if (int.TryParse(y, out i)) Y = i; if (int.TryParse(w, out i)) W = i; if (int.TryParse(h, out i)) H = i; } public static void ParseGate(Gate g, XmlReader xr) { if (xr.EOF) return; while (xr.Read()) { if (xr.NodeType == XmlNodeType.Element) switch (xr.Name) { case "input": g.Inputs.Add(new Pin(xr["id"])); break; case "output": g.Outputs.Add(new Pin(xr["id"])); break; default: break; } } int c = g.Inputs.Count; for (int i = 0; i < c; i++) { Pin p = g.Inputs[i]; p.Y = g.Y - 10; p.X = g.X + g.W / 2 - (c / 2 - i) * 10; p.W = 10; p.H = 10; } Pin pn = g.Outputs[0]; pn.Y = g.Y + g.H; pn.X = g.X + g.W / 2 - 5; pn.W = 10; pn.H = 10; } public void Count() { foreach (Pin p in Inputs) if (p.Value == PortValue.Unknown) return; // nemůže vypočítat switch (GType) { case GateType.And: Outputs[0].Value = PortValue.True; foreach (Pin p in Inputs) if (p.Value == PortValue.False) Outputs[0].Value = PortValue.False; break; case GateType.Or: Outputs[0].Value = PortValue.False; foreach (Pin p in Inputs) if (p.Value == PortValue.True) Outputs[0].Value = PortValue.True; break; case GateType.Xor: int t = 0; foreach (Pin p in Inputs) if (p.Value == PortValue.True) t++; Outputs[0].Value = (t % 2) == 0 ? PortValue.False : PortValue.True; break; case GateType.Not: Outputs[0].Value = Inputs[0].Value == PortValue.True ? PortValue.False : PortValue.True; break; case GateType.Net: bool[] i = new bool[Inputs.Count]; for (int j = 0; j < Inputs.Count; j++) // naplnění vstupů i[j] = Inputs[j].Value == PortValue.True ? true : false; bool[] o = InnerNet.SolveNet(i); for (int j = 0; j < Outputs.Count; j++) // naplnění vstupů Outputs[j].Value = o[j] ? PortValue.True : PortValue.False; break; default: break; } } #region ICloneable Members public object Clone() { Gate g = new Gate(GType, X, Y, W, H); foreach (Pin p in Inputs) g.Inputs.Add((Pin)p.Clone()); foreach (Pin p in Outputs) g.Outputs.Add((Pin)p.Clone()); return g; // klonovat inner net není potřeba, neí to v zadání } #endregion } /// /// Enumerace pro typy hradel /// public enum GateType { And, Or, Xor, Not, Net } /// /// enumerace pro hodnoty portů /// public enum PortValue { Unknown, True, False } }