Beispiel #1
0
        /// <summary>
        /// Constructs a Circuit given a Dictionary of all the gates,
        /// List of all outputs, and List of all inputs
        /// </summary>
        public Circuit(Dictionary <Sketch.Shape, Dictionary <int, Tuple <Shape, int> > > shapesAndTheirInputs,
                       List <Shape> outputs, List <Shape> inputs,
                       Dictionary <Sketch.Shape, CircuitElement> subCircuits)
            : this()
        {
            // Build global inputs
            foreach (Shape inputShape in inputs)
            {
                INPUT input = new INPUT(inputShape.Name, inputShape.Bounds, inputShape.Orientation);
                shapesToElements.Add(inputShape, input);
                globalInputs.Add(input);
            }

            // Build global outputs
            foreach (Shape outputShape in outputs)
            {
                OUTPUT output = new OUTPUT(outputShape.Name, outputShape.Bounds);
                shapesToElements.Add(outputShape, output);
                globalOutputs.Add(output);
            }

            // Build logic gates within the circuit
            foreach (var shapeAndInputs in shapesAndTheirInputs)
            {
                Shape gateShape = shapeAndInputs.Key;
                Gate  gateElement;

                // If the shape is not a gate, or is already in the circuit, skip it.
                if (!LogicDomain.IsGate(gateShape.Type) || shapesToElements.ContainsKey(gateShape))
                {
                    continue;
                }

                // If it's a subcircuit, roll our own circuit element.
                else if (subCircuits.Keys.Contains(gateShape))
                {
                    SubCircuit associatedSub = (SubCircuit)subCircuits[gateShape];
                    associatedSub = new SubCircuit(gateShape.Name, gateShape.Bounds, gateShape, associatedSub.inputs, associatedSub.outputs,
                                                   associatedSub.behavior, gateShape.Orientation);
                    gateElement            = associatedSub;
                    subCircuits[gateShape] = associatedSub;
                }

                // Otherwise, create an element normally.
                else
                {
                    gateElement = createGate(gateShape.Name, gateShape.Bounds, gateShape.Orientation, gateShape.Type);
                }

                if (gateElement == null)
                {
                    throw new Exception("failed to create gate!");
                }

                shapesToElements.Add(gateShape, gateElement);
                gates.Add(gateElement);
            }

            connectEverything(shapesAndTheirInputs);
        }
Beispiel #2
0
 /// <summary>
 /// Returns a pair of the minimum (first) and maximum (second) number of outputs that this shape can have.
 /// </summary>
 /// <param name="shape"></param>
 /// <returns></returns>
 public IntRange NumberOutputs(ShapeType shape)
 {
     if (shape == LogicDomain.SUBCIRCUIT)
     {
         return(new IntRange(1, int.MaxValue)); // we check validity in checkSubcircuits()
     }
     else if (LogicDomain.IsGate(shape))
     {
         return(new IntRange(1, 1));
     }
     return(new IntRange(1, int.MaxValue));
 }
        /// <summary>
        /// Runs the tests!
        /// </summary>
        /// <param name="sketch"></param>
        /// <param name="filename"></param>
        public override void run(Sketch.Sketch sketch, string filename)
        {
            // store the first filename as a way to tell what user we're working on.
            if (_filename == null)
            {
                _filename = filename;
            }

            Dictionary <ShapeType, MutablePair <int, int> > sketchResults = new Dictionary <ShapeType, MutablePair <int, int> >();

            foreach (ShapeType type in LogicDomain.Gates)
            {
                sketchResults.Add(type, MutablePair.Create(0, 0));
            }

            Sketch.Sketch handLabeled = sketch.Clone();

            _pipeline.process(sketch);

            foreach (Sketch.Shape correctShape in handLabeled.Shapes)
            {
                if (!LogicDomain.IsGate(correctShape.Type))
                {
                    continue;
                }

                Sketch.Shape resultShape = sketch.ShapesL.Find(delegate(Sketch.Shape s) { return(s.GeometricEquals(correctShape)); });

                if (resultShape == null)
                {
                    throw new Exception("Could not find shape.");
                }

                sketchResults[correctShape.Type].Item1++;
                if (resultShape.Type == correctShape.Type)
                {
                    sketchResults[correctShape.Type].Item2++;
                }
            }

            _results.Add(sketchResults);
        }
Beispiel #4
0
        /// <summary>
        /// Connects not bubbles to gates and wires
        /// </summary>
        /// <param name="gate"></param>
        private void connectNotBubble(LogicGate bubble)
        {
            LogicGate parentGate = null;
            WireMesh  wire       = null;

            // Get the components this not bubble is connected to
            foreach (Shape connected in bubble.Shape.ConnectedShapes)
            {
                if (LogicDomain.IsGate(connected.Type) && parentGate == null)
                {
                    parentGate = _logicGates[connected];
                }
                else if (LogicDomain.IsWire(connected.Type))
                {
                    wire = _wireMeshes[connected];
                }
            }

            // If this is not connected to a gate, connect it like a normal logic gate
            if (parentGate == null)
            {
                connectWiresTo(bubble);
                return;
            }

            // Is this bubble on the output or the input?
            Sketch.EndPoint connectingEndpoint =
                parentGate.Shape.ClosestEndpointFrom(bubble.Shape);
            bool isInput = parentGate.ShouldBeInput(connectingEndpoint);

            if (isInput)
            {
                wire.ConnectDependent(bubble);
                parentGate.ConnectInput(bubble, 0);
            }
            else
            {
                wire.ConnectSource(bubble, 0);
                parentGate.ConnectOutput(bubble, 0);
            }
        }
Beispiel #5
0
        /// <summary>
        /// Compute the energy function that we are trying to maximize.
        /// </summary>
        /// <param name="sketch"></param>
        /// <returns>an unbounded double representing the energy of the sketch</returns>
        private double computeEnergy(FeatureSketch featureSketch)
        {
            Sketch.Sketch sketch = featureSketch.Sketch;
            featureSketch.hasConsistentSubstrokes();
            sketch.CheckConsistency();
            double energy    = 0;
            var    shapes    = sketch.ShapesL;
            int    numShapes = shapes.Count;
            int    numGates  = shapes.FindAll(s => LogicDomain.IsGate(s.Type)).Count;

            foreach (Shape shape in shapes)
            {
                // Add energy for every connection
#if false
                // This is a bad idea. It favors interpretations with more connections, which basically means
                // that everything should alternate wire-text-wire-text-wire-...
                foreach (Shape connected in shape.ConnectedShapes)
                {
                    if (connected == shape)
                    {
                        continue;
                    }
                    if (connected.Type != LogicDomain.WIRE)
                    {
                        continue;
                    }
                    double connectionDistance = double.PositiveInfinity;
                    foreach (EndPoint endpoint in connected.Endpoints)
                    {
                        connectionDistance = Math.Min(shape.minDistanceTo(endpoint.X, endpoint.Y), connectionDistance);
                    }
                    connectionDistance = Math.Max(connectionDistance, 0.001); // avoid problems when connection distance is close to zero
                    energy            += 1 + 1 / connectionDistance;
                }
#endif

                // Add the context match score
                energy += (double)_domain.ClosestContext(shape).Item1 / numShapes;

                // Get recognition results
                RecognitionResult result     = RecognizeAsType(shape, shape.Type, featureSketch);
                double            confidence = result.Confidence;

                // Add the recognition score
                energy += confidence / numShapes;

#if false
                // Gate orientation also contributes
                if (LogicDomain.IsGate(shape.Type))
                {
                    // Determine the recognizer's and the connector's orientation values,
                    // in the range [0, 2Pi]
                    double orientation      = result.Orientation;
                    double otherOrientation = _domain.OrientShape(shape, sketch);

                    // Orientation might be off by PI...
                    double dist1 = Math.Abs(otherOrientation - orientation);
                    double dist2 = Math.Abs(otherOrientation - Math.PI - orientation);
                    double dist  = Math.Min(dist1, dist2);

                    // Add orientation score
                    double twoPI = 2 * Math.PI;
                    energy += (1 - (dist / twoPI)) / numGates;
                }
#endif
            }
            return(energy);
        }
Beispiel #6
0
        /// <summary>
        /// Checks whether the sketch is valid, and returns a bool indicating this.
        /// Adds any errors it comes across to the _parseErrors list.
        ///
        /// Looks for:
        ///    * Basic consistency via sketch.CheckConsistency
        ///    * Gates connected to only wires
        ///    * Wires not connected to wires
        ///    * Text connected to at most one wire
        /// </summary>
        /// <param name="sketch">The sketch to check the validity of</param>
        /// <returns>A bool, which is true if the sketch is valid</returns>
        private bool CheckSketch(Sketch.Sketch sketch)
        {
            bool valid = true;

            // Check basic sketch consistency, will (rightly) throw an exception if it finds something wrong.
            // Eventually we should not need this, for the sketch should always pass this, but it's a useful check for now.
            sketch.CheckConsistency();

            foreach (Sketch.Shape shape in sketch.Shapes)
            {
                #region Gate Checks
                if (LogicDomain.IsGate(shape.Type))
                {
                    // Each gate should be connected to only wires
                    foreach (Sketch.Shape connected in shape.ConnectedShapes)
                    {
                        if (!LogicDomain.IsWire(connected.Type))
                        {
                            valid = false;
                            _parseErrors.Add(new ParseError("Gate " + shape.Name + " is connected to something that is not a wire, " + connected.Name + "of type " + connected.Type.Name,
                                                            "This gate is connected to something that is not a wire.  Draw wires between them or group them together.", shape));
                        }
                    }
                }
                #endregion

                #region Wire Checks
                else if (LogicDomain.IsWire(shape.Type))
                {
                    // Wires shouldn't be connected to other wires
                    foreach (Sketch.Shape connected in shape.ConnectedShapes)
                    {
                        if (shape != connected && LogicDomain.IsWire(connected.Type))
                        {
                            valid = false;
                            _parseErrors.Add(new ParseError("Wire " + shape.Name + " is connected to another wire, " + connected.Name,
                                                            "This wire is connected to another wire.  Try grouping these wires together.", shape));
                        }
                    }
                }
                #endregion

                #region Input/Output Checks
                else if (LogicDomain.IsText(shape.Type))
                {
                    // Text should only be connected to wires, if anything.
                    foreach (Sketch.Shape wire in shape.ConnectedShapes)
                    {
                        if (!LogicDomain.IsWire(wire.Type))
                        {
                            valid = false;
                            _parseErrors.Add(new ParseError("Text " + shape.Name + " should only be connected to a wire, but is connected to a " + wire.Type.Name + ".",
                                                            shape.Name + " should only be connected to a wire, but is connected to a " + wire.Type.Name + ".", shape));
                        }
                    }
                }
                #endregion
            }

            return(valid);
        }