побудова схема для поділу на 3


12

Логічний контур в ТКС в основному DAG , що складається з і, або, не ворота, а то , що відомо «функціональна повнота» вони можуть обчислити всі можливі функції. наприклад, це основний принцип в АЛУ .

Завдання: створіть схему, щоб визначити, чи 8-двійкове розрядне число ділиться на 3, і якимось чином візуалізувати ваш результат (тобто на якомусь зображенні)

Критерії оцінювання виборців ґрунтуються на тому, чи добре узагальнюється код для створення схеми до довільних розмірних чисел та чи створена алгоритмічно візуалізація є компактною / збалансованою, але все ще читабельною (тобто візуалізація ручним розташуванням не дозволена). тобто візуалізація призначена лише для n = 8, але код ідеально підходить для всіх 'n'. виграшний запис - це просто найкращий голос.

Дещо схоже питання: Створіть множувальну машину за допомогою логічних воріт NAND


2
Набагато краще. Однак "узагальнення" та "естетичне" не є об'єктивними. Усі питання повинні мати об'єктивний критерій виграшу. Якщо ви хочете застосувати ці характеристики, використовуйте популярність-конкурс. Якщо ви хочете найкоротший код, використовуйте код-гольф. Якщо ви хочете скласти комбінацію обох, використовуйте код-виклик, але вкажіть формулу. Наприклад 1,25 * голосів - 0,25 * довжина, як це питання: codegolf.stackexchange.com/questions/23581/eiffel-tower-in-3d/…
рівень річки Св.

Гаразд зробив ті chgs, які ви просите. THX для зворотного зв'язку.
взн

О, я думаю, що складені VHDL або Verilog після всіх його оптимізацій повинні дати найкоротшу відповідь. Я спробую пізніше.
Кирило Кулаков

1
Кращими критеріями виграшу буде ворота-гольф
TheDoctor

@Лікар ??? що таке gate-golf? цей тег не існує. Примітка до учасників: будь ласка, вкажіть, яким мовним / візуалізаційним інструментом ви користуєтесь. якщо хтось ще хоче ввести коментар PLZ. інакше прийме тоніт переможця. Thx багато респондентів, поки що це стало "BTE" краще, ніж очікувалося!
vzn

Відповіді:


7

схема обчислення числа модуля 3

Графік підтримує 3 булеви на кожному рівні i. Вони представляють той факт, що біти i високого порядку числа дорівнюють 0, 1 або 2 мод 3. На кожному рівні ми обчислюємо наступні три біти на основі попередніх трьох біт і наступного вхідного біта.

Ось код python, який створив графік. Просто змініть N, щоб отримати іншу кількість біт, або K, щоб отримати інший модуль. Запустіть вихід програми python через крапку, щоб генерувати зображення.

N = 8
K = 3
v = ['0']*(K-1) + ['1']
ops = {}

ops['0'] = ['0']
ops['1'] = ['1']
v = ['0']*(K-1) + ['1']
for i in xrange(N):
  ops['bit%d'%i] = ['bit%d'%i]
  ops['not%d'%i] = ['not','bit%d'%i]
  for j in xrange(K):
    ops['a%d_%d'%(i,j)] = ['and','not%d'%i,v[(2*j)%K]]
    ops['b%d_%d'%(i,j)] = ['and','bit%d'%i,v[(2*j+1)%K]]
    ops['o%d_%d'%(i,j)] = ['or','a%d_%d'%(i,j),'b%d_%d'%(i,j)]
  v = ['o%d_%d'%(i,j) for j in xrange(K)]

for i in xrange(4):
  for n,op in ops.items():
    for j,a in enumerate(op[1:]):
      if ops[a][0]=='and' and ops[a][1]=='0': op[j+1]='0'
      if ops[a][0]=='and' and ops[a][2]=='0': op[j+1]='0'
      if ops[a][0]=='and' and ops[a][1]=='1': op[j+1]=ops[a][2]
      if ops[a][0]=='and' and ops[a][2]=='1': op[j+1]=ops[a][1]
      if ops[a][0]=='or' and ops[a][1]=='0': op[j+1]=ops[a][2]
      if ops[a][0]=='or' and ops[a][2]=='0': op[j+1]=ops[a][1]

for i in xrange(4):
  used = set(['o%d_0'%(N-1)])|set(a for n,op in ops.items() for a in op[1:])
  for n,op in ops.items():
    if n not in used: del ops[n]

print 'digraph {'
for n,op in ops.items():
  if op[0]=='and': print '%s [shape=invhouse]' % n
  if op[0]=='or': print '%s [shape=circle]' % n
  if op[0]=='not': print '%s [shape=invtriangle]' % n
  if op[0].startswith('bit'): print '%s [color=red]' % n
  print '%s [label=%s]' % (n,op[0])
  for a in op[1:]: print '%s -> %s' % (a,n)
print '}'

чудово! також використовували graphviz ... крихітний каламбур, в діаграмі є невикористані АН / АБО. Також пропонуємо, можливо, виділити вхідні біти іншим кольором, щоб показати їх місця
vzn

@vzn: Гаразд, виправлено.
Кіт Рендалл

12

Глибина: 7 (логарифмічна), 18x AND, 6x OR, 7x XOR, 31 хвіртка (лінійна)

Дозвольте мені обчислити цифру суми в базовій четвертій, модуль три:

7-шарова схема з чітко видною ієрархічною структурою

схема, намальована в Логісімі

Узагальнення, формально (сподіваюся, дещо читабельне):

balance (l, h) = {
  is1: l & not h,
  is2: h & not l,
}

add (a, b) = 
  let aa = balance (a.l, a.h)
      bb = balance (b.l, b.h)
  in  { l:(a.is2 & b.is2) | (a.is1 ^ b.is1),
        h:(a.is1 & b.is1) | (a.is2 ^ b.is2)}

pairs [] = []
pairs [a] = [{h:0, l:a}]
pairs [rest.., a, b] = [pairs(rest..).., {h:a, l:b}]

mod3 [p] = p
mod3 [rest.., p1, p2] = [add(p1, p2), rest..]

divisible3 number =
  let {l: l, h: h} = mod3 $ pairs number
  in  l == h

тепер англійською:

Поки в кількості більше двох біт, візьміть дві найнижчі пари бітів і підсумовуйте їх за модулем 3, потім додайте результат до зворотного числа числа, а потім поверніться, якщо остання пара дорівнює нулю за модулем 3. Якщо є непарне кількість бітів у кількості, додайте додатковий нульовий біт у верхній частині, а потім відшліфуйте з постійним поширенням значення.

Додавання до задньої частини замість спереду гарантує, що дерево додавання є врівноваженим деревом, а не зв'язаним списком. Це, у свою чергу, забезпечує логарифмічну глибину у кількості бітів: п’ять воріт та три рівні для скасування пари та додатковий затвор у кінці.

Звичайно, якщо бажана приблизна планарність, перейдіть верхню пару, незмінену, до наступного шару, а не загортаючи його на передню. Це легше сказати, ніж реалізувати (навіть у псевдокоді). Якщо кількість бітів у кількості є потужністю дві (як це стосується будь-якої сучасної комп’ютерної системи станом на березень 2014 року), однак самотні пари не будуть виникати.

Якщо прошарок зберігає місцевість / здійснює мінімізацію довжини маршруту, він повинен підтримувати схему читабельності.

Цей код Ruby створить схему для будь-якої кількості бітів (навіть одного). Щоб надрукувати, відкрийте в Logisim та експортуйте як зображення:

require "nokogiri"

Port = Struct.new :x, :y, :out
Gate = Struct.new :x, :y, :name, :attrs
Wire = Struct.new :sx, :sy, :tx, :ty

puts "Please choose the number of bits: "
bits = gets.to_i

$ports = (1..bits).map {|x| Port.new 60*x, 40, false};
$wires = [];
$gates = [];

toMerge = $ports.reverse;

def balance a, b
y = [a.y, b.y].max
$wires.push Wire.new(a.x   , a.y , a.x   , y+20),
          Wire.new(a.x   , y+20, a.x   , y+40),
          Wire.new(a.x   , y+20, b.x-20, y+20),
          Wire.new(b.x-20, y+20, b.x-20, y+30),
          Wire.new(b.x   , b.y , b.x   , y+10),
          Wire.new(b.x   , y+10, b.x   , y+40),
          Wire.new(b.x   , y+10, a.x+20, y+10),
          Wire.new(a.x+20, y+10, a.x+20, y+30)
$gates.push Gate.new(a.x+10, y+70, "AND Gate", negate1: true),
          Gate.new(b.x-10, y+70, "AND Gate", negate0: true)
end

def sum (a, b, c, d)
y = [a.y, b.y, c.y, d.y].max
$wires.push Wire.new(a.x   , a.y , a.x   , y+40),
          Wire.new(a.x   , y+40, a.x   , y+50),
          Wire.new(a.x   , y+40, c.x-20, y+40),
          Wire.new(c.x-20, y+40, c.x-20, y+50),
          Wire.new(b.x   , b.y , b.x   , y+30),
          Wire.new(b.x   , y+30, b.x   , y+50),
          Wire.new(b.x   , y+30, d.x-20, y+30),
          Wire.new(d.x-20, y+30, d.x-20, y+50),
          Wire.new(c.x   , c.y , c.x   , y+20),
          Wire.new(c.x   , y+20, c.x   , y+50),
          Wire.new(c.x   , y+20, a.x+20, y+20),
          Wire.new(a.x+20, y+20, a.x+20, y+50),
          Wire.new(d.x   , d.y , d.x   , y+10),
          Wire.new(d.x   , y+10, d.x   , y+50),
          Wire.new(d.x   , y+10, b.x+20, y+10),
          Wire.new(b.x+20, y+10, b.x+20, y+50)
$gates.push Gate.new(a.x+10, y+90, "XOR Gate"),
          Gate.new(b.x+10, y+80, "AND Gate"),
          Gate.new(c.x-10, y+80, "AND Gate"),
          Gate.new(d.x-10, y+90, "XOR Gate")
$wires.push Wire.new(a.x+10, y+90, a.x+10, y+100),
          Wire.new(b.x+10, y+80, b.x+10, y+90 ),
          Wire.new(b.x+10, y+90, a.x+30, y+90 ),
          Wire.new(a.x+30, y+90, a.x+30, y+100),
          Wire.new(d.x-10, y+90, d.x-10, y+100),
          Wire.new(c.x-10, y+80, c.x-10, y+90 ),
          Wire.new(c.x-10, y+90, d.x-30, y+90 ),
          Wire.new(d.x-30, y+90, d.x-30, y+100)
$gates.push Gate.new(d.x-20, y+130, "OR Gate"),
          Gate.new(a.x+20, y+130, "OR Gate")
end

def sum3 (b, c, d)
y = [b.y, c.y, d.y].max
$wires.push Wire.new(b.x   , b.y , b.x   , y+20),
          Wire.new(b.x   , y+20, b.x   , y+30),
          Wire.new(b.x   , y+20, d.x-20, y+20),
          Wire.new(d.x-20, y+20, d.x-20, y+30),
          Wire.new(c.x   , c.y , c.x   , y+60),
          Wire.new(c.x   , y+60, b.x+30, y+60),
          Wire.new(b.x+30, y+60, b.x+30, y+70),
          Wire.new(d.x   , d.y , d.x   , y+10),
          Wire.new(d.x   , y+10, d.x   , y+30),
          Wire.new(d.x   , y+10, b.x+20, y+10),
          Wire.new(b.x+20, y+10, b.x+20, y+30),
          Wire.new(b.x+10, y+60, b.x+10, y+70)
$gates.push Gate.new(b.x+10, y+60 , "AND Gate"),
          Gate.new(d.x-10, y+70 , "XOR Gate"),
          Gate.new(b.x+20, y+100, "OR Gate" )
end

while toMerge.count > 2  
puts "#{toMerge.count} left to merge"
nextToMerge = []
while toMerge.count > 3
 puts "merging four"
 d, c, b, a, *toMerge = toMerge
 balance a, b
 balance c, d
 sum *$gates[-4..-1]
 nextToMerge.push *$gates[-2..-1] 
end
if toMerge.count == 3
 puts "merging three"
 c, b, a, *toMerge = toMerge
 balance b, c
 sum3 a, *$gates[-2..-1]
 nextToMerge.push *$gates[-2..-1]
end
nextToMerge.push *toMerge
toMerge = nextToMerge
puts "layer done"
end

if toMerge.count == 2
b, a = toMerge
x = (a.x + b.x)/2
x -= x % 10
y = [a.y, b.y].max
$wires.push Wire.new(a.x , a.y , a.x , y+10),
          Wire.new(a.x , y+10, x-10, y+10),
          Wire.new(x-10, y+10, x-10, y+20),
          Wire.new(b.x , b.y , b.x , y+10),
          Wire.new(b.x , y+10, x+10, y+10),
          Wire.new(x+10, y+10, x+10, y+20)
$gates.push Gate.new(x, y+70, "XNOR Gate")
toMerge = [$gates[-1]]
end

a = toMerge[0]
$wires.push Wire.new(a.x, a.y, a.x, a.y+10)
$ports.push Port.new(a.x, a.y+10, true)

def xy (x, y)
"(#{x},#{y})"
end
circ = Nokogiri::XML::Builder.new encoding: "UTF-8" do |xml|
xml.project version: "1.0" do
xml.lib name: "0", desc: "#Base"
xml.lib name: "1", desc: "#Wiring"
xml.lib name: "2", desc: "#Gates"
xml.options
xml.mappings
xml.toolbar do
  xml.tool lib:'0', name: "Poke Tool"
  xml.tool lib:'0', name: "Edit Tool"
end #toolbar
xml.main name: "main"
xml.circuit name: "main" do
  $wires.each do |wire|
    xml.wire from: xy(wire.sx, wire.sy), to: xy(wire.tx, wire.ty)
  end #each 
  $gates.each do |gate|
    xml.comp lib: "2", name: gate.name, loc: xy(gate.x, gate.y) do
      xml.a name: "facing", val: "south"
      xml.a name: "size", val: "30"
      xml.a name: "inputs", val: "2"
      if gate.attrs
        gate.attrs.each do |name, value|
          xml.a name: name, val: value 
        end #each
      end #if
    end #comp
  end #each
  $ports.each.with_index do |port, index|
    xml.comp lib: "1", name: "Pin", loc: xy(port.x, port.y) do
      xml.a name: "tristate", val: "false"
      xml.a name: "output",   val: port.out.to_s
      xml.a name: "facing",   val: port.out ? "north" : "south"
      xml.a name: "labelloc", val: port.out ? "south" : "north"
      xml.a name: "label",    val: port.out ? "out" : "B#{index}"
    end #port
  end #each
end #circuit
end #project
end #builder

File.open "divisibility3.circ", ?w do |file|
file << circ.to_xml
end

puts "done"

нарешті, коли я попросив створити вихід на 32 біти, мій лайтер генерує це. Правда, це не дуже компактно для дуже широких входів:

13-шарова чудовисько з великою кількістю витраченого простору


виглядає дійсно чудово & найкраща схема / макет поки що. на якій мові знаходиться код? який лайтер ви використовували, якщо такий є? лайтер попросили бути алгоритмом, і треба припустити, що алгоритм не використовувався (макет руки), якщо не зазначено ...
vzn

@vzn також потрібно було реалізувати шару? Я розумів, що це обмеження означає те, що ми можемо малювати схему вручну, але читабельність не повинна залежати від способу малювання діаграми. Схему TimWolla, безумовно, генерують вручну. Псевдокод здебільшого заснований на Haskell із доданими об’єктами Javascripty.
Джон Дворак

алгоритмічно створена візуалізація мала означати в основному алгоритмічну прошарку, але тепер визнаємо, що її можна було б неоднозначно інтерпретувати. вибачте за відсутність чіткості кристала. чи знаєте ви про будь-який автоматизований макет, який може отримати майже подібні результати, як ваш макет руки?
взн

На жаль, немає. yEd має чудові шари, але він ігнорує орієнтацію. Я ніколи не знайомився з крапкою, і не вважаю його результат дуже приємним. Я думаю, я міг би перевести цей псевдокод у Ruby (легко) і написати власний спеціалізований шаруватий матеріал (не надто важко, але складно), який би експортував схему logisim (це просто XML, і це навіть не gzipped, це досить просто). Чи повинен я (хочу), і чи слід це публікувати як окрему відповідь? Також, чи вважатиметься це ручним дизайном?
Джон Дворак

Усі відповіді хороші, але це виглядає як найелегантніша досі
Digital Trauma

5

2 × 24 НЕ, 2 × 10 + 5 І, 2 × 2 + 5 АБО, 2 × 2 НОР

Це повністю не масштабується. Як і зовсім. Можливо, я спробую це вдосконалити.

Я тестував це на цифри до 30, і це працювало чудово.

Ці 2 великі схеми підраховують кількість активних входів:

  • У верхньому правому куті підраховується кількість бітів з рівною силою (нуль до 4)
  • У лівій нижній частині рахується кількість бітів з непарною потужністю (нуль до 4)

Якщо різниця цих чисел є 0або 3число ділиться на 3. У нижньому правому куті контуру в основному відображає кожну допустима комбінація ( 4,4, 4,1, 3,3, 3,0, 2, 2, 1, 1, 0, 0) або ст.

Маленьке коло посередині - це світлодіод, який увімкнено, якщо число, якщо ділиться на 3, а вимкнено інакше.


вау приємно / швидко! ... plz покладіть посилання на код або встройте його ... також детально, як ви зробили візуалізацію ...?
взн

@vzn Візуалізація була виконана з logisim . Це було побудовано моєю рукою, але загальний алгоритм легко можна виконати і з програмою. Частково це пояснено у відповіді.
TimWolla
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.