/// <summary>
        /// Creates a new view in which the cols of the matrices are merged. The cols will be in the order
        /// of the input matrices. If two matrices contain a rows with the same colKey, an exception is thrown. All matricies must have the same
        /// MissingValue.
        /// This is a 'view' in the sense that changes to the values in either matrix will be reflected in both.
        /// </summary>
        /// <param name="rowsMustMatch">true, to require all matrices to have the same rowKeys in the same order; false, use an intersection of the
        /// rowKeys in the order of RowKeys of the first matrix.</param>
        /// <param name="matrices">One or more matricies with which to concatinate cols.</param>
        public MergeColsView(bool rowsMustMatch, params Matrix <TRowKey, TColKey, TValue>[] matrices)
        {
            Helper.CheckCondition(matrices.All(m => m.IsMissing(matrices[0].MissingValue)), () => string.Format(CultureInfo.InvariantCulture, Properties.Resource.ExpectedAllMatricesToHaveSameMissingValue));
            _missingValue = matrices[0].MissingValue;

            IEnumerable <TRowKey> rowKeys = matrices[0].RowKeys;
            var colKeys = matrices[0].ColKeys.ToList();

            _colKeyToMatrix = new Dictionary <TColKey, Matrix <TRowKey, TColKey, TValue> >();
            matrices[0].ColKeys.ForEach(colKey => _colKeyToMatrix.Add(colKey, matrices[0]));

            for (int i = 1; i < matrices.Length; i++)
            {
                if (rowsMustMatch)
                {
                    Helper.CheckCondition(Helper.KeysEqual(matrices[0].IndexOfRowKey, matrices[i].IndexOfRowKey), () => string.Format(CultureInfo.InvariantCulture, Properties.Resource.ExpectedRowsOfMatricesToMatch));
                }
                else
                {
                    rowKeys = rowKeys.Intersect(matrices[i].RowKeys);
                }

                colKeys.AddRange(matrices[i].ColKeys);
                matrices[i].ColKeys.ForEach(colKey => _colKeyToMatrix.Add(colKey, matrices[i]));
            }

            Helper.CheckCondition(colKeys.Count == colKeys.Distinct().Count(), () => string.Format(CultureInfo.InvariantCulture, Properties.Resource.ExpectedUniqueRowKeysInMatrix));

            _rowKeys = rowKeys.ToList().AsReadOnly();
            _colKeys = colKeys.AsReadOnly();

            _indexOfRowKey = _rowKeys.Select((key, i) => new KeyValuePair <TRowKey, int>(key, i)).ToDictionary().AsRestrictedAccessDictionary();
            _indexOfColKey = _colKeys.Select((key, i) => new KeyValuePair <TColKey, int>(key, i)).ToDictionary().AsRestrictedAccessDictionary();
        }
Esempio n. 2
0
        /// <summary>
        /// Creates a new view in which the rows of the matrices are merged. The rows will be in the order
        /// of the input matrices. If two matrices contain a rows with the same rowKey, an exception is thrown. All matricies must have the same
        /// MissingValue.
        /// This is a 'view' in the sense that changes to the values in either matrix will be reflected in both.
        /// </summary>
        /// <param name="colsMustMatch">true, to require all matrices to have the same colKeys in the same order; false, use an intersection of the
        /// colKeys in the order of ColKeys of the first matrix.</param>
        /// <param name="matrices">One or more matricies with which to concatinate rows.</param>
        public MergeRowsView(bool colsMustMatch, params Matrix <TRowKey, TColKey, TValue>[] matrices)
        {
            Helper.CheckCondition(matrices.Length > 0, Properties.Resource.ExpectedNonZeroLengthArrayOfMatrices);
            Helper.CheckCondition(matrices.All(m => m.IsMissing(matrices[0].MissingValue)), Properties.Resource.ExpectedAllMatricesToHaveSameMissingValue);
            _missingValue = matrices[0].MissingValue;

            IEnumerable <TColKey> colKeys = matrices[0].ColKeys;
            var rowKeys = matrices[0].RowKeys.ToList();

            _rowKeyToMatrix = new Dictionary <TRowKey, Matrix <TRowKey, TColKey, TValue> >();
            matrices[0].RowKeys.ForEach(rowKey => _rowKeyToMatrix.Add(rowKey, matrices[0]));

            for (int i = 1; i < matrices.Length; i++)
            {
                if (colsMustMatch)
                {
                    Helper.CheckCondition(Helper.KeysEqual(matrices[0].IndexOfColKey, matrices[i].IndexOfColKey), Properties.Resource.ExpectedColumnsToMatch);
                }
                else
                {
                    colKeys = colKeys.Intersect(matrices[i].ColKeys);
                }

                rowKeys.AddRange(matrices[i].RowKeys);
                matrices[i].RowKeys.ForEach(rowKey => _rowKeyToMatrix.Add(rowKey, matrices[i]));
            }

            Helper.CheckCondition(rowKeys.Count == rowKeys.Distinct().Count(), Properties.Resource.ExpectedUniqueRowKeysInMatrix);

            _rowKeys = rowKeys.AsReadOnly();
            _colKeys = colKeys.ToList().AsReadOnly();

            _indexOfRowKey = _rowKeys.Select((key, i) => new KeyValuePair <TRowKey, int>(key, i)).ToDictionary().AsRestrictedAccessDictionary();
            _indexOfColKey = _colKeys.Select((key, i) => new KeyValuePair <TColKey, int>(key, i)).ToDictionary().AsRestrictedAccessDictionary();
        }
Esempio n. 3
0
        /// <summary>
        /// Creates a new view in which the cols of the matrices are merged. The cols will be in the order
        /// of the input matrices. If two matrices contain a rows with the same colKey, an exception is thrown. All matricies must have the same
        /// MissingValue.
        /// This is a 'view' in the sense that changes to the values in either matrix will be reflected in both.
        /// </summary>
        /// <param name="rowsMustMatch">true, to require all matrices to have the same rowKeys in the same order; false, use an intersection of the
        /// rowKeys in the order of RowKeys of the first matrix.</param>
        /// <param name="matrices">One or more matricies with which to concatinate cols.</param>
        public MergeColsView(bool rowsMustMatch, params Matrix <TRowKey, TColKey, TValue>[] matrices)
        {
            Helper.CheckCondition(matrices.All(m => m.IsMissing(matrices[0].MissingValue)), "Not all matrices have the same missing value.");
            _missingValue = matrices[0].MissingValue;

            IEnumerable <TRowKey> rowKeys = matrices[0].RowKeys;
            var colKeys = matrices[0].ColKeys.ToList();

            _colKeyToMatrix = new Dictionary <TColKey, Matrix <TRowKey, TColKey, TValue> >();
            matrices[0].ColKeys.ForEach(colKey => _colKeyToMatrix.Add(colKey, matrices[0]));

            for (int i = 1; i < matrices.Length; i++)
            {
                if (rowsMustMatch)
                {
                    Helper.CheckCondition(Helper.KeysEqual(matrices[0].IndexOfRowKey, matrices[i].IndexOfRowKey), "The rows of the matrices do not match");
                }
                else
                {
                    rowKeys = rowKeys.Intersect(matrices[i].RowKeys);
                }

                colKeys.AddRange(matrices[i].ColKeys);
                matrices[i].ColKeys.ForEach(colKey => _colKeyToMatrix.Add(colKey, matrices[i]));
            }

            Helper.CheckCondition(colKeys.Count == colKeys.Distinct().Count(), "There are duplicate rows in the matrices.");

            _rowKeys = rowKeys.ToList().AsReadOnly();
            _colKeys = colKeys.AsReadOnly();

            _indexOfRowKey = _rowKeys.Select((key, i) => new KeyValuePair <TRowKey, int>(key, i)).ToDictionary().AsRestrictedAccessDictionary();
            _indexOfColKey = _colKeys.Select((key, i) => new KeyValuePair <TColKey, int>(key, i)).ToDictionary().AsRestrictedAccessDictionary();
        }
Esempio n. 4
0
        /// <summary>
        /// Creates a new view in which the rows of the matrices are merged. The rows will be in the order
        /// of the input matrices. If two matrices contain a rows with the same rowKey, an exception is thrown. All matricies must have the same
        /// MissingValue.
        /// This is a 'view' in the sense that changes to the values in either matrix will be reflected in both.
        /// </summary>
        /// <param name="colsMustMatch">true, to require all matrices to have the same colKeys in the same order; false, use an intersection of the
        /// colKeys in the order of ColKeys of the first matrix.</param>
        /// <param name="matrices">One or more matricies with which to concatinate rows.</param>
        public MergeRowsView(bool colsMustMatch, params Matrix <TRowKey, TColKey, TValue>[] matrices)
        {
            Helper.CheckCondition(matrices.Length > 0, () => Properties.Resource.ExpectedNonZeroLengthArrayOfMatrices);
            Helper.CheckCondition(matrices.All(m => m.IsMissing(matrices[0].MissingValue)), () => Properties.Resource.ExpectedAllMatricesToHaveSameMissingValue);
            _missingValue = matrices[0].MissingValue;

            IEnumerable <TColKey> colKeys = matrices[0].ColKeys;
            var rowKeys = matrices[0].RowKeys.ToList();

            _rowKeyToMatrix = new Dictionary <TRowKey, Matrix <TRowKey, TColKey, TValue> >();
            matrices[0].RowKeys.ForEach(rowKey => _rowKeyToMatrix.Add(rowKey, matrices[0]));

            for (int i = 1; i < matrices.Length; i++)
            {
                if (colsMustMatch)
                {
                    Helper.CheckCondition(Helper.KeysEqual(matrices[0].IndexOfColKey, matrices[i].IndexOfColKey), () => Properties.Resource.ExpectedColumnsToMatch);
                }
                else
                {
                    colKeys = colKeys.Intersect(matrices[i].ColKeys);
                }

                //rowKeys.AddRange(matrices[i].RowKeys);
                foreach (var rowKey in matrices[i].RowKeys)
                {
                    if (_rowKeyToMatrix.ContainsKey(rowKey))
                    {
                        var prevMatrix = _rowKeyToMatrix[rowKey];
                        // check that all the values are identical. not that GetValueOrMissing().Equals is not safe because missing value may be null.
                        Helper.CheckCondition <System.ArgumentException>(colKeys.All(colKey =>
                                                                                     prevMatrix.IsMissing(rowKey, colKey) ?
                                                                                     matrices[i].IsMissing(rowKey, colKey) :
                                                                                     prevMatrix[rowKey, colKey].Equals(matrices[i].GetValueOrMissing(rowKey, colKey))), Properties.Resource.ThereAreDuplicateRowsWhichDoNotHDupRowsNonIdenticalValues);
                    }
                    else
                    {
                        _rowKeyToMatrix.Add(rowKey, matrices[i]);
                        rowKeys.Add(rowKey);
                    }
                }
                //matrices[i].RowKeys.ForEach(rowKey => _rowKeyToMatrix.Add(rowKey, matrices[i]));
            }

            Helper.CheckCondition(rowKeys.Count == rowKeys.Distinct().Count(), () => Properties.Resource.ExpectedUniqueRowKeysInMatrix);

            _rowKeys = rowKeys.AsReadOnly();
            _colKeys = colKeys.ToList().AsReadOnly();

            _indexOfRowKey = _rowKeys.Select((key, i) => new KeyValuePair <TRowKey, int>(key, i)).ToDictionary().AsRestrictedAccessDictionary();
            _indexOfColKey = _colKeys.Select((key, i) => new KeyValuePair <TColKey, int>(key, i)).ToDictionary().AsRestrictedAccessDictionary();
        }
Esempio n. 5
0
        /// <summary>
        /// Creates a new view in which the rows of the matrices are merged. The rows will be in the order
        /// of the input matrices. If two matrices contain a rows with the same rowKey, an exception is thrown. All matricies must have the same
        /// MissingValue.
        /// This is a 'view' in the sense that changes to the values in either matrix will be reflected in both.
        /// </summary>
        /// <param name="colsMustMatch">true, to require all matrices to have the same colKeys in the same order; false, use an intersection of the
        /// colKeys in the order of ColKeys of the first matrix.</param>
        /// <param name="matrices">One or more matricies with which to concatinate rows.</param>
        public MergeRowsView(bool colsMustMatch, params Matrix <TRowKey, TColKey, TValue>[] matrices)
        {
            Helper.CheckCondition(matrices.Length > 0, "At least once matrix expected.");
            Helper.CheckCondition(matrices.All(m => m.IsMissing(matrices[0].MissingValue)), "Not all matrices have the same missing value.");
            _missingValue = matrices[0].MissingValue;

            IEnumerable <TColKey> colKeys = matrices[0].ColKeys;
            var rowKeys = matrices[0].RowKeys.ToList();

            _rowKeyToMatrix = new Dictionary <TRowKey, Matrix <TRowKey, TColKey, TValue> >();
            matrices[0].RowKeys.ForEach(rowKey => _rowKeyToMatrix.Add(rowKey, matrices[0]));

            for (int i = 1; i < matrices.Length; i++)
            {
                if (colsMustMatch)
                {
                    Helper.CheckCondition(Helper.KeysEqual(matrices[0].IndexOfColKey, matrices[i].IndexOfColKey), "The columns of the two matrices do not match");
                }
                else
                {
                    colKeys = colKeys.Intersect(matrices[i].ColKeys);
                }

                //rowKeys.AddRange(matrices[i].RowKeys);
                foreach (var rowKey in matrices[i].RowKeys)
                {
                    if (_rowKeyToMatrix.ContainsKey(rowKey))
                    {
                        var prevMatrix = _rowKeyToMatrix[rowKey];
                        // check that all the values are identical. not that GetValueOrMissing().Equals is not safe because missing value may be null.
                        Helper.CheckCondition <System.ArgumentException>(colKeys.All(colKey =>
                                                                                     prevMatrix.IsMissing(rowKey, colKey) ?
                                                                                     matrices[i].IsMissing(rowKey, colKey) :
                                                                                     prevMatrix[rowKey, colKey].Equals(matrices[i].GetValueOrMissing(rowKey, colKey))), "There are duplicate rows which do not have identical values.");
                    }
                    else
                    {
                        _rowKeyToMatrix.Add(rowKey, matrices[i]);
                        rowKeys.Add(rowKey);
                    }
                }
                //matrices[i].RowKeys.ForEach(rowKey => _rowKeyToMatrix.Add(rowKey, matrices[i]));
            }

            Helper.CheckCondition(rowKeys.Count == rowKeys.Distinct().Count(), "There are duplicate rows in the matrices.");

            _rowKeys = rowKeys.AsReadOnly();
            _colKeys = colKeys.ToList().AsReadOnly();

            _indexOfRowKey = _rowKeys.Select((key, i) => new KeyValuePair <TRowKey, int>(key, i)).ToDictionary().AsRestrictedAccessDictionary();
            _indexOfColKey = _colKeys.Select((key, i) => new KeyValuePair <TColKey, int>(key, i)).ToDictionary().AsRestrictedAccessDictionary();
        }
Esempio n. 6
0
        //private Converter<int, TVal> _fnStateToTVal;
        //private Converter<TVal, int> _fnTValToState;

        /// <summary>
        /// Creates a this wrapper.
        /// </summary>
        /// <param name="binaryMatrixToWrap">Must have values that map to 0/1</param>
        /// <param name="multistateKeyToOrderedBinaryKeys">First key is multistate name (e.g. 1@A#B#C), the value is an enumeration of binary keys that map to the multistate keys.
        /// The order specifies the state value in multistate space. (e.g. 1@A is state 0, 1@B is state 2, 1@C is state 2)</param>
        /// <param name="convertTValToMultinomial">Specifies how to convert from TVal to 0,1,2,3... and back. 0/1 are used for binary, 0..N are assumed to be used by the multistate matrix.</param>
        public BinaryToMultistateView(
            Matrix <TRowKey, TColKey, TVal> binaryMatrixToWrap,
            IEnumerable <KeyValuePair <TRowKey, IEnumerable <TRowKey> > > multistateKeyToOrderedBinaryKeys,
            ValueConverter <TVal, Multinomial> convertTValToMultinomial)
        {
            _binaryMatrix        = binaryMatrixToWrap;
            _multKeyToBinaryKeys = multistateKeyToOrderedBinaryKeys.Select(pair =>
                                                                           new KeyValuePair <TRowKey, List <TRowKey> >(pair.Key, pair.Value.ToList())).ToDictionary();
            //_fnStateToTVal = fnStateToTVal;
            //_fnTValToState = fnTValToBinaryState;
            _cnvrtTValToState = convertTValToMultinomial;

            _rowKeys       = new ReadOnlyCollection <TRowKey>(multistateKeyToOrderedBinaryKeys.Select(pair => pair.Key).ToList());
            _indexOfRowKey = new RestrictedAccessDictionary <TRowKey, int>(_rowKeys.Select((key, idx) => new KeyValuePair <TRowKey, int>(key, idx)).ToDictionary());
        }
Esempio n. 7
0
        //private Converter<int, TVal> _fnStateToTVal;
        //private Converter<TVal, int> _fnTValToState;


        /// <summary>
        /// Creates a this wrapper.
        /// </summary>
        /// <param name="multistateMatrixToWrap"></param>
        /// <param name="multistateKeyToOrderedBinaryKeys">First key is multistate name (e.g. 1@A#B#C), the value is an enumeration of binary keys that map to the multistate keys.
        /// The order specifies the state value in multistate space. (e.g. 1@A is state 0, 1@B is state 2, 1@C is state 2)</param>
        /// <param name="convertTValToInt">Specifies how to convert from TVal to 0,1,2,3... and back. 0/1 are used for binary, 0..N are assumed to be used by the multistate matrix.</param>
        public MultistateToBinaryView(
            Matrix <TRowKey, TColKey, TVal> multistateMatrixToWrap,
            IEnumerable <KeyValuePair <TRowKey, IEnumerable <TRowKey> > > multistateKeyToOrderedBinaryKeys,
            ValueConverter <TVal, int> convertTValToInt)
        //Converter<int, TVal> fnStateToTVal,
        //Converter<TVal, int> fnTValToBinaryState)
        {
            _multistateMatrix           = multistateMatrixToWrap;
            _binaryKeyToMultKeyAndState = multistateKeyToOrderedBinaryKeys.SelectMany(mAndB =>
                                                                                      mAndB.Value.Select((b, idx) =>
                                                                                                         new KeyValuePair <TRowKey, KeyValuePair <TRowKey, int> >(b, new KeyValuePair <TRowKey, int>(mAndB.Key, idx)))).ToDictionary();
            _cnvrtTValToState = convertTValToInt;
            //_fnStateToTVal = fnStateToTVal;
            //_fnTValToState = fnTValToBinaryState;

            _rowKeys       = new ReadOnlyCollection <TRowKey>(multistateKeyToOrderedBinaryKeys.SelectMany(pair => pair.Value).ToList());
            _indexOfRowKey = new RestrictedAccessDictionary <TRowKey, int>(_rowKeys.Select((key, idx) => new KeyValuePair <TRowKey, int>(key, idx)).ToDictionary());
        }
Esempio n. 8
0
        private void RenameColsViewInternal(Matrix <TRowKey, TColKey, TValue> parentMatrix, IEnumerable <KeyValuePair <TColKey, TColKey> > newNameAndOldNameSequence)
        {
            NewKeyToOldKey = newNameAndOldNameSequence.ToDictionary(pair => pair.Key, pair => pair.Value).AsRestrictedAccessDictionary();

            var unmatchedCols = NewKeyToOldKey.Values.Except(parentMatrix.ColKeys).ToList();

            Helper.CheckCondition(unmatchedCols.Count == 0, Properties.Resource.ExpectedEveryRemappedColKeyToBeInOriginalMatrix, unmatchedCols.StringJoin(","));

            ParentMatrix = parentMatrix;

            _colKeys       = NewKeyToOldKey.Select(pair => pair.Key).ToList().AsReadOnly();
            _indexOfColKey = _colKeys.Select((key, idx) => new KeyValuePair <TColKey, int>(key, idx)).ToDictionary(kvp => kvp.Key, kvp => kvp.Value).AsRestrictedAccessDictionary();

            NewIndexToOldIndex =
                (
                    from newIndex in Enumerable.Range(0, ColCount)
                    let newKey = ColKeys[newIndex]
                                 let oldKey = NewKeyToOldKey[newKey]
                                              let oldIndex = parentMatrix.IndexOfColKey[oldKey]
                                                             select oldIndex
                ).ToList().AsReadOnly();
        }
Esempio n. 9
0
        internal void InitializeIndexMaps()
        {
            var rowKeys = new Dictionary <TRowKey, int>(_rowKeys.Count);
            var colKeys = new Dictionary <TColKey, int>(_colKeys.Count);

            int rowIdx = 0;

            foreach (TRowKey rowKey in RowKeys)
            {
                rowKeys.Add(rowKey, rowIdx);
                rowIdx++;
            }

            int colIdx = 0;

            foreach (TColKey colKey in ColKeys)
            {
                colKeys.Add(colKey, colIdx);
                colIdx++;
            }
            _indexOfRowKey = rowKeys.AsRestrictedAccessDictionary();
            _indexOfColKey = colKeys.AsRestrictedAccessDictionary();
        }