/// <summary> /// Add new DataTable to existing DataSet /// </summary> /// <param name="dataSet"></param> public new void AddWatchTable(ref DataSet dataSet, string tableName = "") { dataSet.Tables.Add(this.DataTable(tableName)); dataSet.Tables.Add(DistalSegment.DataTable(tableName)); //not sure if necc dataSet.Tables.Add(InputSource.DataTable(tableName)); //not sure if necc base.AddWatchTable(ref dataSet, tableName); }
///<summary> /// Create a new segment on the update cell using connections from /// the set of learning cells for the update info. ///</summary> internal DistalSegment CreateDistalSegment() { DistalSegment distalSegment = this.Cell.CreateDistalSegment(this.CellsToConnect); distalSegment.NumberPredictionSteps = this.NumberPredictionSteps; return(distalSegment); }
/// <summary> /// For this cell, return a <see cref="Segment"/> that is active in the given /// time step. If multiple segments are active, sequence segments are given /// preference. Otherwise, segments with most activity are given preference. /// Original name: getActiveSegment /// </summary> public DistalSegment GetActiveDistalSegment(int t) { DistalSegment bestDistalSegment = null; bool foundSequenceSegment = false; int bestNumberActiveSynapses = 0; foreach (var segment in this.DistalSegments) { int numberActiveSynapses = segment.GetActiveSynapses(t).Count; if (numberActiveSynapses >= Segment.ActivationThreshold) { // Sequence segments are given preference. // Otherwise, segments with most activity are given preference. if (segment.IsSequence) { foundSequenceSegment = true; if (numberActiveSynapses > bestNumberActiveSynapses) { bestNumberActiveSynapses = numberActiveSynapses; bestDistalSegment = segment; } } else if (!foundSequenceSegment && numberActiveSynapses > bestNumberActiveSynapses) { bestNumberActiveSynapses = numberActiveSynapses; bestDistalSegment = segment; } } } return(bestDistalSegment); }
/// <summary> /// Object's identification string based on it's position within parent. /// Used primarly in Watch. /// </summary> /// <returns></returns> public new string ID() { string str = ""; //str = String.Format ( "Synapse [" + Parent.ID () + "]" ); str = String.Format("DistalSynapse[{0}]", DistalSegment.ID()); return(str); }
/// <summary> /// For this column, return the cell with the best matching <see cref="Segment"/> /// (at time t-1 or t). Only consider segments that are predicting cell activation /// to occur in exactly numberPredictionSteps many time steps from now. If no cell /// has a matching segment, then return the cell with the fewest number of segments. /// </summary> /// <param name="t">only consider active segments at time t.</param> /// <param name="numberPredictionSteps">only consider segments that are predicting /// cell activation to occur in exactly this many time steps from now.</param> /// <returns>Tuple containing the best cell and its best <see cref="Segment"/> /// (may be None).</returns> internal Tuple <Cell, DistalSegment> GetBestMatchingCell(int t, int numberPredictionSteps) { Cell bestCell = null; DistalSegment bestDistalSegment = null; int bestNumberActiveSynapses = 0; // Chooses the cell with the best matching segment. foreach (var cell in this.Cells) { DistalSegment distalSegment = cell.GetBestMatchingDistalSegment(t, numberPredictionSteps); if (distalSegment != null) { int numberActiveSynapses = distalSegment.GetActiveSynapses(t).Count; if (numberActiveSynapses > bestNumberActiveSynapses) { bestCell = cell; bestDistalSegment = distalSegment; bestNumberActiveSynapses = numberActiveSynapses; } } } // If there are no active sequences, return the cell with the fewest number of // segments if (bestCell == null) { int bestNumberActiveSegments = int.MaxValue; foreach (var cell in this.Cells) { int numberActiveSegments = cell.DistalSegments.Count; if (numberActiveSegments < bestNumberActiveSegments) { bestNumberActiveSegments = numberActiveSegments; bestCell = cell; } } // Pick a random cell among those with equal segment counts // TODO: is there a more efficient way to do this maybe? var candidates = new List <Cell>(); foreach (var cell in this.Cells) { if (cell.DistalSegments.Count == bestNumberActiveSegments) { candidates.Add(cell); } } if (candidates.Count > 1) { bestCell = candidates[this._random.Next(candidates.Count)]; } // Leave bestSegment null to indicate a new segment is to be added } return(new Tuple <Cell, DistalSegment>(bestCell, bestDistalSegment)); }
/// <summary> /// Creates a new distal segment for this Cell. /// </summary> /// <param name="cellsToConnect"> A set of available cells to add to /// the segmentUpdateList.</param> /// <returns> Created segmentUpdateList</returns> /// <remarks> /// The new segment will initially connect to at most newNumberSynapses /// synapses randomly selected from the set of cells that /// were in the learning state at t-1 (specified by the learningCells parameter). /// </remarks> internal DistalSegment CreateDistalSegment(List <Cell> cellsToConnect) { var newDistalSegment = new DistalSegment(this); foreach (var cell in cellsToConnect) { newDistalSegment.CreateSynapse(cell, Synapse.InitialPermanence); } this.DistalSegments.Add(newDistalSegment); return(newDistalSegment); }
///<summary> /// Add a new <see cref="SegmentUpdate"/> object to this <see cref="Cell"/> /// containing proposed changes to the specified segment. ///</summary> ///<remarks> /// If the segment is None, then a new segment is to be added, otherwise /// the specified segment is updated. If the segment exists, find all active /// synapses for the segment (either at t or t-1) /// and mark them as needing to be updated. If newSynapses is true, then /// Region.newNumberSynapses - len(activeSynapses) new synapses are added to the /// segment to be updated. The (new) synapses are randomly chosen from the set /// of current learning cells (within Region.localityRadius if set). /// /// These segment updates are only applied when the applySegmentUpdates /// method is later called on this Cell. ///</remarks> internal SegmentUpdate UpdateDistalSegmentActiveSynapses(int t, DistalSegment distalSegment, bool newSynapses = false) { // Let ActiveSynapses be the list of active synapses where the originating // cells have their ActiveState output = true at time step t. // (This list is empty if segment = null since the segment doesn't exist.) var activeSynapses = new List <Synapse>(); if (distalSegment != null) { activeSynapses = distalSegment.GetActiveSynapses(t); } var segmentUpdate = new SegmentUpdate(this, distalSegment, activeSynapses, newSynapses); this.SegmentUpdates.Add(segmentUpdate); return(segmentUpdate); }
///<summary> /// This function reinforces each segment in this Cell's SegmentUpdate. /// </summary> /// <remarks> /// Using the segmentUpdate, the following changes are /// performed. If positiveReinforcement is true then synapses on the active /// list get their permanence counts incremented by permanenceInc. All other /// synapses get their permanence counts decremented by permanenceDec. If /// positiveReinforcement is false, then synapses on the active list get /// their permanence counts decremented by permanenceDec. After this step, /// any synapses in segmentUpdate that do yet exist get added with a permanence /// count of initialPerm. These new synapses are randomly chosen from the /// set of all cells that have learnState output = 1 at time step t. ///</remarks> internal void ApplySegmentUpdates(bool positiveReinforcement, int latestCreationStep = -1) { // This loop iterates through a list of SegmentUpdate's and reinforces each segment. foreach (var segmentUpdate in this.SegmentUpdates) { DistalSegment distalSegment = segmentUpdate.DistalSegment; if (distalSegment != null) { if (positiveReinforcement) { distalSegment.UpdatePermanences(segmentUpdate.ActiveDistalSynapses); } else { distalSegment.DecreasePermanences(segmentUpdate.ActiveDistalSynapses); } } // Add new synapses (and new segment if necessary) if (segmentUpdate.AddNewSynapses && positiveReinforcement) { if (distalSegment == null) { // Only add new segment if end cells to connect are available if (segmentUpdate.CellsToConnect.Count > 0) { distalSegment = segmentUpdate.CreateDistalSegment(); } } else if (segmentUpdate.CellsToConnect.Count > 0) { // Add new synapses to existing segment segmentUpdate.CreateDistalSynapses(); } } } // Delete segment update instances after they are applied this.SegmentUpdates.Clear(); }
/// <summary> /// Gets the best matching <see cref="Segment"/>. /// </summary> /// <param name="t">Only consider active segments at time t.</param> /// <param name="numberPredictionSteps">Number of time steps in the future an activation will occur.</param> /// <remarks> /// For this cell (at t or t-1), find the <see cref="Segment"/> (only /// consider sequence segments if isSequence is True, otherwise only consider /// non-sequence segments) with the largest number of active synapses. /// This routine is aggressive in finding the best match. The permanence /// value of synapses is allowed to be below connectedPerm. /// The number of active synapses is allowed to be below activationThreshold, /// but must be above minThreshold. The routine returns that segment. /// If no segments are found, then null is returned. /// </remarks> internal DistalSegment GetBestMatchingDistalSegment(int t, int numberPredictionSteps) { DistalSegment bestDistalSegment = null; int bestNumberActiveSynapses = _minSynapsesPerSegmentThreshold; foreach (var segment in this.DistalSegments) { if (segment.NumberPredictionSteps == numberPredictionSteps) { // Get all the active synapses in the given t time step, no matter connection value int numberActiveSynapses = segment.GetActiveSynapses(t).Count; if (numberActiveSynapses >= bestNumberActiveSynapses) { bestNumberActiveSynapses = numberActiveSynapses; bestDistalSegment = segment; } } } return(bestDistalSegment); }
/// <summary> /// Gets the sequence segment. If it's not null then this cell was predicted to /// become active at current time step. /// </summary> /// <value>The segment predicting or null if none found.</value> public DistalSegment GetSequencePredictingDistalSegment() { DistalSegment predictingDistalSegment = null; try { if (this.PredictiveState[Global.T - 1]) { DistalSegment distalSegment = this.GetActiveDistalSegment(Global.T - 1); if (distalSegment != null && distalSegment.IsSequence) { predictingDistalSegment = distalSegment; } } } catch (InvalidOperationException) { } return(predictingDistalSegment); }
/// <summary> /// Initializes a new instance of the <see cref="DistalSynapse"/> class and /// sets its input source and initial permanance values. /// </summary> /// <param name="distalSeg"> /// </param> /// <param name="inputSource"> /// An object providing source of the input to this synapse (either /// a <see cref="Column"/>'s <see cref="Cell"/> or a special /// <see cref="InputCell"/>). /// </param> /// <param name="permanence">Initial permanence value.</param> public DistalSynapse(DistalSegment distalSeg, Cell inputSource, float permanence) : this(inputSource, permanence) { // Set fields this.DistalSegment = distalSeg; }
/// <summary> /// Initializes a new instance of the <see cref="DistalSynapse"/> class and /// sets its input source and initial permanance values. /// </summary> /// <param name="distalSeg"> /// </param> /// <param name="inputSource"> /// An object providing source of the input to this synapse (either /// a <see cref="Column"/>'s <see cref="Cell"/> or a special /// <see cref="InputCell"/>). /// </param> /// <param name="permanence">Initial permanence value.</param> public DistalSynapse(DistalSegment distalSeg, Cell inputSource, float permanence) : this(inputSource, permanence) { // Set fields this.DistalSegment = distalSeg; }
///<summary> ///Create a new SegmentUpdate that is to modify the state of the Region ///either by adding a new segment to a cell, new synapses to a segemnt, ///or updating permanences of existing synapses on some segment. ///</summary> ///<param name="cell">cell the cell that is to have a segment added or updated. /// </param> ///<param name="distalSegment">the segment that is to be updated (null here means a new /// segment is to be created on the parent cell).</param> ///<param name="activeDistalSynapses">the set of active synapses on the segment /// that are to have their permanences updated.</param> ///<param name="addNewSynapses">set to true if new synapses are to be added to the /// segment (or if new segment is being created) or false if no new synapses /// should be added instead only existing permanences updated.</param> /// public SegmentUpdate(Cell cell, DistalSegment distalSegment, List<Synapse> activeDistalSynapses, bool addNewSynapses = false) { // Set fields this.Cell = cell; this.DistalSegment = distalSegment; this.ActiveDistalSynapses = new List<Synapse>(activeDistalSynapses); this.AddNewSynapses = addNewSynapses; this.CellsToConnect = new List<Cell>(); this.NumberPredictionSteps = 1; this.CreationStep = (int) cell.Statistics.StepCounter; // Set of cells that have LearnState output = true at time step t. var cellsToConnect = new List<Cell>(); // If adding new synapses, find the current set of learning cells within // the Region and select a random subset of them to connect the segment to. // Do not add > 1 synapse to the same cell on a given segment Region region = this.Cell.Column.Region; if (this.AddNewSynapses) { // Gather all cells from segment in order to avoid use them as learning cells. var cellsInSegment = new List<Cell>(); if (distalSegment != null) { foreach (var synapse in distalSegment.Synapses) { if (synapse is DistalSynapse) { cellsInSegment.Add(((DistalSynapse) synapse).InputSource); } } } // Define limits to choose cells to connect. int minY, maxY, minX, maxX; if (region.LocalityRadius > 0) { // Only allow connecting to Columns within locality radius minX = Math.Max(0, cell.Column.PositionInRegion.X - region.LocalityRadius); minY = Math.Max(0, cell.Column.PositionInRegion.Y - region.LocalityRadius); maxX = Math.Min(region.Size.Width - 1, cell.Column.PositionInRegion.X + region.LocalityRadius); maxY = Math.Min(region.Size.Height - 1, cell.Column.PositionInRegion.Y + region.LocalityRadius); } else { // Now I want to allow connections over all the region! // If locality radius is 0, it means 'no restriction' minX = 0; minY = 0; maxX = region.Size.Width - 1; maxY = region.Size.Height - 1; } // Set of cells that have LearnState output = true at time step t. for (int x = minX; x <= maxX; x++) { for (int y = minY; y <= maxY; y++) { Column column = region.GetColumn(x, y); // Skip cells in our own column (don't connect to ourself) if (column != cell.Column) { foreach (var learningCell in column.Cells) { // Skip cells that already are linked to the segment (case it exists). if (learningCell.LearnState[Global.T - 1] && !cellsInSegment.Contains(learningCell)) { cellsToConnect.Add(learningCell); } } } } } } // Basic allowed number of new Synapses int newNumberSynapses = region.NumberNewSynapses; if (distalSegment != null) { newNumberSynapses = Math.Max(0, newNumberSynapses - activeDistalSynapses.Count); } // Clamp at learn cells newNumberSynapses = Math.Min(cellsToConnect.Count, newNumberSynapses); // Randomly choose (newNumberSynapses) learning cells to add connections to if (cellsToConnect.Count > 0 && newNumberSynapses > 0) { this.CellsToConnect = this.ChooseRandomCells(cellsToConnect, newNumberSynapses); } }
///<summary> ///Create a new SegmentUpdate that is to modify the state of the Region ///either by adding a new segment to a cell, new synapses to a segemnt, ///or updating permanences of existing synapses on some segment. ///</summary> ///<param name="cell">cell the cell that is to have a segment added or updated. /// </param> ///<param name="distalSegment">the segment that is to be updated (null here means a new /// segment is to be created on the parent cell).</param> ///<param name="activeDistalSynapses">the set of active synapses on the segment /// that are to have their permanences updated.</param> ///<param name="addNewSynapses">set to true if new synapses are to be added to the /// segment (or if new segment is being created) or false if no new synapses /// should be added instead only existing permanences updated.</param> /// public SegmentUpdate(Cell cell, DistalSegment distalSegment, List <Synapse> activeDistalSynapses, bool addNewSynapses = false) { // Set fields this.Cell = cell; this.DistalSegment = distalSegment; this.ActiveDistalSynapses = new List <Synapse>(activeDistalSynapses); this.AddNewSynapses = addNewSynapses; this.CellsToConnect = new List <Cell>(); this.NumberPredictionSteps = 1; this.CreationStep = (int)cell.Statistics.StepCounter; // Set of cells that have LearnState output = true at time step t. var cellsToConnect = new List <Cell>(); // If adding new synapses, find the current set of learning cells within // the Region and select a random subset of them to connect the segment to. // Do not add > 1 synapse to the same cell on a given segment Region region = this.Cell.Column.Region; if (this.AddNewSynapses) { // Gather all cells from segment in order to avoid use them as learning cells. var cellsInSegment = new List <Cell>(); if (distalSegment != null) { foreach (var synapse in distalSegment.Synapses) { if (synapse is DistalSynapse) { cellsInSegment.Add(((DistalSynapse)synapse).InputSource); } } } // Define limits to choose cells to connect. int minY, maxY, minX, maxX; if (region.LocalityRadius > 0) { // Only allow connecting to Columns within locality radius minX = Math.Max(0, cell.Column.PositionInRegion.X - region.LocalityRadius); minY = Math.Max(0, cell.Column.PositionInRegion.Y - region.LocalityRadius); maxX = Math.Min(region.Size.Width - 1, cell.Column.PositionInRegion.X + region.LocalityRadius); maxY = Math.Min(region.Size.Height - 1, cell.Column.PositionInRegion.Y + region.LocalityRadius); } else { // Now I want to allow connections over all the region! // If locality radius is 0, it means 'no restriction' minX = 0; minY = 0; maxX = region.Size.Width - 1; maxY = region.Size.Height - 1; } // Set of cells that have LearnState output = true at time step t. for (int x = minX; x <= maxX; x++) { for (int y = minY; y <= maxY; y++) { Column column = region.GetColumn(x, y); // Skip cells in our own column (don't connect to ourself) if (column != cell.Column) { foreach (var learningCell in column.Cells) { // Skip cells that already are linked to the segment (case it exists). if (learningCell.LearnState[Global.T - 1] && !cellsInSegment.Contains(learningCell)) { cellsToConnect.Add(learningCell); } } } } } } // Basic allowed number of new Synapses int newNumberSynapses = region.NumberNewSynapses; if (distalSegment != null) { newNumberSynapses = Math.Max(0, newNumberSynapses - activeDistalSynapses.Count); } // Clamp at learn cells newNumberSynapses = Math.Min(cellsToConnect.Count, newNumberSynapses); // Randomly choose (newNumberSynapses) learning cells to add connections to if (cellsToConnect.Count > 0 && newNumberSynapses > 0) { this.CellsToConnect = this.ChooseRandomCells(cellsToConnect, newNumberSynapses); } }
///<summary> /// Add a new <see cref="SegmentUpdate"/> object to this <see cref="Cell"/> /// containing proposed changes to the specified segment. ///</summary> ///<remarks> /// If the segment is None, then a new segment is to be added, otherwise /// the specified segment is updated. If the segment exists, find all active /// synapses for the segment (either at t or t-1) /// and mark them as needing to be updated. If newSynapses is true, then /// Region.newNumberSynapses - len(activeSynapses) new synapses are added to the /// segment to be updated. The (new) synapses are randomly chosen from the set /// of current learning cells (within Region.localityRadius if set). /// /// These segment updates are only applied when the applySegmentUpdates /// method is later called on this Cell. ///</remarks> internal SegmentUpdate UpdateDistalSegmentActiveSynapses(int t, DistalSegment distalSegment, bool newSynapses = false) { // Let ActiveSynapses be the list of active synapses where the originating // cells have their ActiveState output = true at time step t. // (This list is empty if segment = null since the segment doesn't exist.) var activeSynapses = new List<Synapse>(); if (distalSegment != null) { activeSynapses = distalSegment.GetActiveSynapses(t); } var segmentUpdate = new SegmentUpdate(this, distalSegment, activeSynapses, newSynapses); this.SegmentUpdates.Add(segmentUpdate); return segmentUpdate; }
/// <summary> /// Creates a new distal segment for this Cell. /// </summary> /// <param name="cellsToConnect"> A set of available cells to add to /// the segmentUpdateList.</param> /// <returns> Created segmentUpdateList</returns> /// <remarks> /// The new segment will initially connect to at most newNumberSynapses /// synapses randomly selected from the set of cells that /// were in the learning state at t-1 (specified by the learningCells parameter). /// </remarks> internal DistalSegment CreateDistalSegment(List<Cell> cellsToConnect) { var newDistalSegment = new DistalSegment( this ); foreach (var cell in cellsToConnect) { newDistalSegment.CreateSynapse(cell, Synapse.InitialPermanence); } this.DistalSegments.Add(newDistalSegment); return newDistalSegment; }