Схема цифровой логики - экзаменационный вопрос


14

У меня есть вопрос с экзамена, который мне не удалось решить:

Мне нужно построить цифровую логическую схему , который принимает 4 номер бита и возврат , trueесли число 0, 7или 14. У меня есть только один XORвентиль (2 входа), один NOR(3 входа), один NAND(2 входа) и один декодер 3-8.

Я думаю, что этот вопрос неразрешим, я не нашел ни одной комбинации, которая могла бы это сделать. Есть идеи как это решить?


1
Подсказка: учитывая 4 бита и 3-8 декодер, вы должны обрабатывать один из битов по-разному.
Брайан Драммонд

2
@BrianDrummond, но я уже знаю это, и мне все еще не удалось решить это. Каждое решение, которое я пробовал, чувствует, что в нем отсутствует один ИЛИ ворота. Я не могу найти такую ​​комбинацию с заданными воротами, которая может решить проблему ... Обратите внимание, что у меня есть только ОДИН шлюз на тип ...
nrofis

3
@BrianDrummond: если вы опубликуете описание решения, которое, по вашему мнению, существует, мы можем его проверить. Трудно сказать, что решения не существует, но легко проверить, является ли решение допустимым.
Пасаба Пор Акви

2
@ Идо Кесслер ... Я был заинтригован твоим решением, и если твои доказательства верны, извини, что ты удалил его. Пока что ни у кого нет решения. Возможно, если вы включите описание своего алгоритма, это улучшит ответ. Насколько вы уверены, что это правильно и без ошибок?
Тута

3
@jalalipop, я сделал вчера. Ido Kessler и pasaba por aqui были правы, мой профессор сказал, что вопрос был неправильным, и NAND должен быть NOR ....
nrofis

Ответы:


24

Я написал алгоритм на C #, который пробует все возможные комбинации тех Nor 3->1 Xor 2->1 Nand 2->1и Decoder 3->8.

Проработав 7,5 миллионов лет 2 часа, он вернул 42 False. Я считаю, что это доказывает, что на вопрос нет ответа, так как этот алгоритм проверяет каждую возможную комбинацию. :)

Меня попросили описать это, поэтому следующая часть - это объяснение частей кода, часть за частью. TL; DR - вы можете просто пропустить код внизу в конце :)


Давайте поговорим о входных строках, они имеют 0 или 1 состояния и для каждого из возможных входов (от 0 до 15) они имеют разные значения:

для первой строки это выглядит так: 0 1 0 1 0 1 ... вторая: 0 0 1 1 0 0 1 1 ... третья: 0 0 0 0 1 1 1 1 .... как двоичная считая ... у тебя есть идея: P

Итак, я создал объект, который представляет каждую строку в каждом из его состояний:

class BitLine{
    bool[] IsActiveWhenInputIs = new bool[16];
}

Как говорится, bitLine.IsActiveWhenInputIs [5] возвращают, была ли линия активной, когда на входе было 5.

Это код, который создает строки ввода в целом:

var bitLineList = new BitLine[6]; // initialize new array of bitLines
for (int i = 0; i < 6; i++) bitLineList [i] = new BitLine(); // initialize each bitLine
for (int i = 0; i < 16; i++)
{
    for (int j = 0; j < 4; j++)
    {
        int checker = 1 << j; // check whether the j-th bit is activated in the binary representation of the number.
        bitLineList[j].IsActiveWhenInputIs[i] = ((checker & i) != 0); // if it's active, the AND result will be none zero, and so the return value will be true - which is what we need :D
    }
}

Мы также создадим битовые строки «всегда верно» и «всегда ложно» - чтобы обеспечить постоянный ввод «0» или «1».

for (int i = 0; i < 16; i++){
    bitLineList[4].IsActiveWhenInputIs[i] = false;
    bitLineList[5].IsActiveWhenInputIs[i] = true;
}

Теперь, если вы заметили, что мы ищем на самом деле конкретную битовую линию, которая истинна, когда ввод равен 0, 7, 14. Давайте представим ее в нашем классе:

var neededBitLine = new BitLine();
for (int i = 0; i < 16; i++){
    neededBitLine.IsActiveWhenInputIs[i] = ((i % 7) == 0); // be true for any number that is devideble by 7 (0,7,14)
}

Это сделало вещи действительно простыми: то, что мы на самом деле ищем, это способ «подделать» эту необходимуюBitLine из входной битовой строки (именно так я представляю своей программе то, что я хочу, чтобы мой вывод был).

Теперь, это то , как мы идем дальше: каждый раз , когда мы используем некоторый логический элемент на нашем bitLines как Xor, Nor, Nandили даже Decoder, мы на самом деле создаем новый bitLine \ с. Мы знаем значение каждой из строк в каждом возможном входе от 0 до 15, поэтому мы можем вычислить новое значение bitLine \ s также для каждого возможного ввода!

Нанд Нор и Ксор все просты:

void Xor(BitLine b1, BitLine b2, BitLine outputBitLine)
{
    for (var i = 0; i < 16; i++)
    {
        outputBitLine.IsActiveWhenInputIs[i] = b1.IsActiveWhenInputIs[i] != b2.IsActiveWhenInputIs[i];
    }
}

void Nand(BitLine b1, BitLine b2, BitLine outputBitLine)
{
    for (var i = 0; i < 16; i++)
    {
        outputBitLine.IsActiveWhenInputIs[i] = !(b1.IsActiveWhenInputIs[i] && b2.IsActiveWhenInputIs[i]);
    }
}

void Nor(BitLine b1, BitLine b2, BitLine b3, BitLine outputBitLine)
{
    for (var i = 0; i < 16; i++)
    {
        outputBitLine.IsActiveWhenInputIs[i] = !(b1.IsActiveWhenInputIs[i] || b2.IsActiveWhenInputIs[i] || b3.IsActiveWhenInputIs[i]);
    }
}

Для каждого возможного ввода он представляет, как будет действовать новый BitLine.

Обработка декодера немного сложна, но идея в том, что «если биты на входе представляют число x в двоичном виде, то x-я строка выходного бита будет истинной, тогда как все остальные будут ложными. В отличие от других функция, эта получает массив битовых линий и добавляет 8 новых битовых линий в массив.

void Decoder(BitLine b1, BitLine b2, BitLine b3, List<BitLine> lines, int listOriginalLength)
{
    for (int optionNumber = 0; optionNumber < 8; optionNumber++)
    {
        for (var i = 0; i < 16; i++)
        {
            int sum = 0;
            if (b1.IsActiveWhenInputIs[i]) sum += 4;
            if (b2.IsActiveWhenInputIs[i]) sum += 2;
            if (b3.IsActiveWhenInputIs[i]) sum += 1;

            lines[listOriginalLength+optionNumber].IsActiveWhenInputIs[i] = (sum == optionNumber);
        }
    }
}

Теперь у нас есть все наши основные элементы, поэтому давайте поговорим об алгоритме:

Мы собираемся сделать рекурсивный алгоритм, на каждой глубине он будет пытаться использовать другие элементы (ни \ nand \ xor \ decoder) на доступных в настоящее время линиях битов, а затем установить элемент на непригодный для использования на следующей рекурсивной глубине. Всякий раз, когда мы достигаем дна и у нас больше нет элементов для использования, мы будем проверять, есть ли у нас битлайн, который мы и искали.

Этот код проверяет в любой момент времени, содержит ли текущая группа строк строку, которую мы ищем:

bool CheckIfSolutionExist(List<BitLine> lines, int linesLength BitLine neededLine)
{
    for(int i = 0; i<linesLength; i++){
         if (lines[i].CheckEquals(neededLine))
        {
            return true;
        }

    }
    return false;
}

Эта функция используется для проверки того, равны ли две строки:

bool CheckEquals(BitLine other)
{
    for (var i = 0; i < 16; i++)
    {
        if (this.IsActiveWhenInputIs[i] != other.IsActiveWhenInputIs[i])
        {
            return false;
        }
    }
    return true;
}

Итак, теперь для основной части это основной алгоритм:

bool Solve(List<BitLine> lines, int listLength, bool nand, bool nor, bool xor, bool decoder, BitLine neededLine)
{
    if ((!nand) && (!nor) && (!xor) && (!decoder))
    {
        return CheckIfSolutionExist(lines, listLength, neededLine);
    }
    else
    {
        if (HandleNand(lines, nand, nor, xor, decoder, neededLine,listLength))
        {
            return true;
        }
        if (HandleNor(lines, nand, nor, xor, decoder, neededLine,listLength))
        {
            return true;
        }
        if (HandleXor(lines, nand, nor, xor, decoder, neededLine,listLength))
        {
            return true;
        }
        if (HandleDecoder(lines, nand, nor, xor, decoder, neededLine,listLength))
        {
            return true;
        }
        return false;
    }
}

Эта функция получает список доступных битовых строк, длину списка, логическое значение, представляющее, доступен ли каждый элемент в данный момент (xor / nor / nand / decoder), и битовую линию, представляющую искомую битовую линию.

На каждом этапе он проверяет, есть ли у нас какие-либо элементы для использования, если нет - он проверяет, архивируем ли мы нашу необходимую битовую линию.

Если у нас все еще есть больше элементов, то для каждого элемента он вызывает функцию, которая должна обрабатывать создание новых битовых линий с использованием этих элементов и последующее обращение к следующей рекурсивной глубине.

Следующие функции-обработчики довольно просты, их можно перевести как «выберите 2 \ 3 из доступных битовых линий и объедините их, используя соответствующий элемент. Затем вызовите следующую глубину рекурсии, просто на этот раз она не будет содержать». этот элемент!

это функции:

bool HandleNand(List<BitLine> lines, int listLength, bool nand, bool nor, bool xor, bool decoder, BitLine neededLine)
{
    if (nand)
    {
        for (int i = 0; i < listLength; i++)
        {
            for (int j = i; j < listLength; j++)
            {
                BitLine.Nand(lines[i], lines[j],lines[listLength]);
                if (Solve(lines,listLength+1, false, nor, xor, decoder, neededLine))
                {
                    return true;
                }
            }
        }
    }
    return false;
}

bool HandleXor(List<BitLine> lines,  int listLength, bool nand, bool nor, bool xor, bool decoder, BitLine neededLine)
{
    if (xor)
    {
        for (int i = 0; i < listLength; i++)
        {
            for (int j = i; j < listLength; j++)
            {
                BitLine.Xor(lines[i], lines[j],lines[listLength]);
                if (Solve(lines,listLength+1, nand, nor, false, decoder, neededLine))
                {
                    return true;
                }

            }
        }
    }
    return false;
}

bool HandleNor(List<BitLine> lines, int listLength, bool nand, bool nor, bool xor, bool decoder, BitLine neededLine)
{
    if (nor)
    {
        for (int i = 0; i < listLength; i++)
        {
            for (int j = i; j < listLength; j++)
            {
                for (int k = j; k < listLength; k++)
                {
                    BitLine.Nor(lines[i], lines[j], lines[k],lines[listLength]);
                    if (Solve(lines,listLength+1, nand, false, xor, decoder, neededLine))
                    {
                        return true;
                    }

                }
            }
        }
    }
    return false;
}

bool HandleDecoder(List<BitLine> lines, int listLength, bool nand, bool nor, bool xor, bool decoder, BitLine neededLine)
{
    if (decoder)
    {
        for (int i = 0; i < listLength; i++)
        {
            for (int j = i; j < listLength; j++)
            {
                for (int k = j; k < listLength; k++)
                {
                    BitLine.Decoder(lines[i], lines[j], lines[k],lines,listLength);
                    if (Solve(lines,listLength+8, nand, nor, xor, false, neededLine))
                    {
                        return true;
                    }
                }
            }
        }
    }
    return false;
}

И это все, мы просто вызываем эту функцию с нужной линией, которую мы ищем, и она проверяет каждую возможную комбинацию электрических частей, чтобы проверить, можно ли объединить их таким образом, чтобы в итоге одна строка была выводится с необходимыми значениями.

* обратите внимание, что я все время использую один и тот же список, поэтому мне не нужно постоянно создавать новые экземпляры битовых линий. По этой причине я даю ему буфер 200.


Это полная программа:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApp2
{
    public class BitLine
    {
        public bool[] IsActiveWhenInputIs = new bool[16];

        public static void Xor(BitLine b1, BitLine b2, BitLine outputBitLine)
        {
            for (var i = 0; i < 16; i++)
            {
                outputBitLine.IsActiveWhenInputIs[i] = b1.IsActiveWhenInputIs[i] != b2.IsActiveWhenInputIs[i];
            }
        }

        public static void Nand(BitLine b1, BitLine b2, BitLine outputBitLine)
        {
            for (var i = 0; i < 16; i++)
            {
                outputBitLine.IsActiveWhenInputIs[i] = !(b1.IsActiveWhenInputIs[i] && b2.IsActiveWhenInputIs[i]);
            }
        }

        public static void Nor(BitLine b1, BitLine b2, BitLine b3, BitLine outputBitLine)
        {
            for (var i = 0; i < 16; i++)
            {
                outputBitLine.IsActiveWhenInputIs[i] = !(b1.IsActiveWhenInputIs[i] || b2.IsActiveWhenInputIs[i] || b3.IsActiveWhenInputIs[i]);
            }
        }

        public static void Decoder(BitLine b1, BitLine b2, BitLine b3, List<BitLine> lines, int listOriginalLength)
        {
            for (int optionNumber = 0; optionNumber < 8; optionNumber++)
            {
                for (var i = 0; i < 16; i++)
                {
                    int sum = 0;
                    if (b1.IsActiveWhenInputIs[i]) sum += 4;
                    if (b2.IsActiveWhenInputIs[i]) sum += 2;
                    if (b3.IsActiveWhenInputIs[i]) sum += 1;

                    lines[listOriginalLength + optionNumber].IsActiveWhenInputIs[i] = (sum == optionNumber);
                }
            }
        }

        public bool CheckEquals(BitLine other)
        {
            for (var i = 0; i < 16; i++)
            {
                if (this.IsActiveWhenInputIs[i] != other.IsActiveWhenInputIs[i])
                {
                    return false;
                }
            }
            return true;
        }

    }

    public class Solver
    {
        bool CheckIfSolutionExist(List<BitLine> lines, int linesLength, BitLine neededLine)
        {
            for (int i = 0; i < linesLength; i++)
            {
                if (lines[i].CheckEquals(neededLine))
                {
                    return true;
                }

            }
            return false;
        }

        bool HandleNand(List<BitLine> lines, int listLength, bool nand, bool nor, bool xor, bool decoder, BitLine neededLine)
        {
            if (nand)
            {
                for (int i = 0; i < listLength; i++)
                {
                    for (int j = i; j < listLength; j++)
                    {
                        BitLine.Nand(lines[i], lines[j], lines[listLength]);
                        if (Solve(lines, listLength + 1, false, nor, xor, decoder, neededLine))
                        {
                            return true;
                        }
                    }
                }
            }
            return false;
        }

        bool HandleXor(List<BitLine> lines, int listLength, bool nand, bool nor, bool xor, bool decoder, BitLine neededLine)
        {
            if (xor)
            {
                for (int i = 0; i < listLength; i++)
                {
                    for (int j = i; j < listLength; j++)
                    {
                        BitLine.Xor(lines[i], lines[j], lines[listLength]);
                        if (Solve(lines, listLength + 1, nand, nor, false, decoder, neededLine))
                        {
                            return true;
                        }

                    }
                }
            }
            return false;
        }

        bool HandleNor(List<BitLine> lines, int listLength, bool nand, bool nor, bool xor, bool decoder, BitLine neededLine)
        {
            if (nor)
            {
                for (int i = 0; i < listLength; i++)
                {
                    for (int j = i; j < listLength; j++)
                    {
                        for (int k = j; k < listLength; k++)
                        {
                            BitLine.Nor(lines[i], lines[j], lines[k], lines[listLength]);
                            if (Solve(lines, listLength + 1, nand, false, xor, decoder, neededLine))
                            {
                                return true;
                            }

                        }
                    }
                }
            }
            return false;
        }

        bool HandleDecoder(List<BitLine> lines, int listLength, bool nand, bool nor, bool xor, bool decoder, BitLine neededLine)
        {
            if (decoder)
            {
                for (int i = 0; i < listLength; i++)
                {
                    for (int j = i; j < listLength; j++)
                    {
                        for (int k = j; k < listLength; k++)
                        {
                            BitLine.Decoder(lines[i], lines[j], lines[k], lines, listLength);
                            if (Solve(lines, listLength + 8, nand, nor, xor, false, neededLine))
                            {
                                return true;
                            }
                        }
                    }
                }
            }
            return false;
        }

        public bool Solve(List<BitLine> lines, int listLength, bool nand, bool nor, bool xor, bool decoder, BitLine neededLine)
        {
            if ((!nand) && (!nor) && (!xor) && (!decoder))
            {
                return CheckIfSolutionExist(lines, listLength, neededLine);
            }
            else
            {
                if (HandleNand(lines, listLength, nand, nor, xor, decoder, neededLine))
                {
                    return true;
                }
                if (HandleNor(lines, listLength, nand, nor, xor, decoder, neededLine))
                {
                    return true;
                }
                if (HandleXor(lines, listLength, nand, nor, xor, decoder, neededLine))
                {
                    return true;
                }
                if (HandleDecoder(lines, listLength, nand, nor, xor, decoder, neededLine))
                {
                    return true;
                }
                return false;
            }
        }
    }

    class Program
    {
        public static void Main(string[] args)
        {
            List<BitLine> list = new List<BitLine>();
            var bitLineList = new BitLine[200];
            for (int i = 0; i < 200; i++) bitLineList[i] = new BitLine();

            // set input bit:
            for (int i = 0; i < 16; i++)
            {
                for (int j = 0; j < 4; j++)
                {
                    int checker = 1 << j;
                    bitLineList[j].IsActiveWhenInputIs[i] = ((checker & i) != 0);
                }
            }

            // set zero and one constant bits:
            for (int i = 0; i < 16; i++)
            {
                bitLineList[4].IsActiveWhenInputIs[i] = false;
                bitLineList[5].IsActiveWhenInputIs[i] = true;
            }

            list.AddRange(bitLineList);

            var neededBitLine = new BitLine();
            for (int i = 0; i < 16; i++)
            {
                neededBitLine.IsActiveWhenInputIs[i] = (i%7==0); // be true for any number that is devideble by 7 (0,7,14)
            }

            var solver = new Solver();
            Console.WriteLine(solver.Solve(list, 6, true, true, true, true, neededBitLine));
            Console.ReadKey();
        }
    }
}

Надеюсь, на этот раз это веское объяснение: P


6
Возможно, вы захотите включить общее описание того, как работает этот вид решателя. Не сразу видно, прочитав этот полностью незакомментированный дамп кода.
Дэйв Твид

2
Это интригующее решение, и я надеюсь, что вы можете предоставить описание алгоритма. Вы делали подобные тесты, чтобы доказать метод? (Кстати, я , как тонкий Дуглас Адамс ссылка)
Тута

2
Я добавлю, что я попробовал этот алгоритм с некоторым тестовым примером, который я мог проверить: x == 2, x == 3, x == 4, ..., x == 11. Поскольку это занимает много времени, я замечаю, что x% 3 == 0 и x% 5 == 0 также могут быть невозможны, и я не мог найти ответ на них обоих. Но алгоритм вернул true для всех вышеупомянутых случаев, для которых я нашел решение вручную.
Идо Кесслер

3
+1! @IdoKessler. Можете ли вы попробовать изменить 2-битный вход NAND на 2-битный вход NOR и проверить, дает ли ваше программное обеспечение решение? На самом деле, с этими воротами вместо NAND, есть решение.
следующий взлом

3
@ next-hack вернул True, когда я изменил его на использование 2-битного NOR
Ido Kessler

8

Это не ответ, чтобы отказаться от наиболее очевидного решения.

б1б2б4б8

б2б4

(ни {Иксзнак равно0,Иксзнак равно3,Иксзнак равно6}) NAND (б2 исключающее б4)

б1б4б8

Тем не менее, упрощение предыдущего выражения:

(Иксзнак равно0 или Иксзнак равно3 или Иксзнак равно6) или (б2знак равноб4)

это не ожидаемое

(Иксзнак равно0 или Иксзнак равно3 или Иксзнак равно6) и (б2знак равноб4)

По этой причине, я считаю вероятной ошибкой в ​​этом вопросе «nand» gate a »или« one ».


2
Может быть, это правда, я тоже не нашел ответа.
nrofis

2
+1. Я верю, что ты прав, а NAND должен быть NOR.
Брайан Драммонд

2

Действительным ответом на ваш вопрос будет любая схема, которая всегда возвращает true. Потому что он вернет истину также, если введенные числа 0,7 или 14.

Я думаю, что вопрос должен явно задавать вопрос о схеме, которая выводит истину, если входные числа равны 0,7 или 14. И в противном случае выводит ложь.


2
Вау, я не ожидал такого ответа. Схема должна возвращать истину тогда и только тогда, когда входной сигнал равен 0, 7 или 14 ...
nrofis

1
именно так.
Агустин Тена

2
+1 за тщательное изучение спецификаций. Это плохая инженерия при получении такой спецификации от клиента. В этом случае правильный ответ - указать клиенту проблему со спецификацией и проверить, что он действительно хочет. Но, для экзаменационного вопроса это показывает мышление из коробки, и это правильно дает очень простой ответ.
Олин Латроп

-3

Это выполнимо. Как подсказка, средние два бита равны для всех этих битовых комбинаций, поэтому их сохранение приведет к 0, который затем может быть входом для декодера с двумя другими битами. Остальные вентили применяются к трем выходам декодера для обеспечения правильного однобитового выхода.


Уже сделал это. Я не нашел ни одной комбинации, которая бы решала вопрос ...
nrofis

Используйте xor, чтобы уменьшить четыре бита до трех бит для декодера. Декодер будет иметь три выхода, которые равны 1 для трех совпадающих шаблонов. Не объединяйте их и не используйте nand gate как инвертор.
Джон

4
@John ... Ваше решение дает 6 терминов продукта (не упрощено), 3 из которых являются недействительными. Другими словами, хотя ваше решение возвращает true для 0, 7 или 14; он также возвращает true для 1, 6 или 8.
Tut
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.