|
|
(One intermediate revision by one other user not shown) |
Line 1: |
Line 1: |
| In [[computer science]], specifically [[formal language]]s, '''convolution''' (sometimes referred to as '''zip''') is a function which maps a [[tuple]] of [[sequence]]s into a [[sequence]] of [[tuple]]s.
| | Furniture Finisher Foster Sanderford from Burk's Falls, has numerous pursuits which include ghost hunting, diet and compose music. Discovers the charm in visiting places across the entire world, of late only coming back from Itsukushima Shinto Shrine. |
| | |
| == Example ==
| |
| Given the three words ''and'', ''fish'' and ''be'' where |''and''| is 3, |''fish''| is 4 and |''be''| is 2. Let <math>\ell</math> denote the longest word which is ''fish''; <math>\ell = 4</math>. The convolution of ''and'', ''fish'', ''be'' is then 4 tuples of elements:
| |
| | |
| : <math> (a,f,b)(n,i,e)(d,s,\#)(\#,h,\#)</math>
| |
| | |
| where ''#'' is a symbol not in the original alphabet. In [[Haskell (programming language)|Haskell]] which truncates to shortest sequence <math>\underline{\ell}</math>, where <math>\underline{\ell} = 2</math>:
| |
| | |
| <source lang="haskell">
| |
| zip3 "and" "fish" "be"
| |
| -- [('a','f','b'),('n','i','e')]
| |
| </source>
| |
| | |
| == Definition ==
| |
| Let Σ be an alphabet, # a symbol not in Σ.
| |
| | |
| Let ''x''<sub>1</sub>''x''<sub>2</sub>... ''x''<sub>|''x''|</sub>, ''y''<sub>1</sub>''y''<sub>2</sub>... ''y''<sub>|''y''|</sub>, ''z''<sub>1</sub>''z''<sub>2</sub>... ''z''<sub>|''z''|</sub>, ... be ''n'' [[word (mathematics)|words]] (i.e. finite [[sequence]]s) of elements of Σ. Let <math>\ell</math> denote the length of the longest word, i.e. the maximum of |''x''|, |''y''|, |''z''|, ... .
| |
| | |
| The convolution of these words is a finite sequence of ''n''-tuples of elements of (Σ ∪ {#}), i.e. an element of <math>((\Sigma\cup\{\# \})^n)^*</math>:
| |
| | |
| :<math> (x_1,y_1,\ldots)(x_2,y_2,\ldots)\ldots(x_\ell,y_\ell,\ldots)</math>,
| |
| | |
| where for any index ''i'' > |''w''|, the ''w<sub>i''</sub> is #.
| |
| | |
| The convolution of ''x, y, z, ...'' is denoted conv( ''x, y, z, ...''), zip( ''x, y, z, ...'') or ''x'' ⋆ ''y'' ⋆ ''z'' ⋆ ...
| |
| | |
| The inverse to convolution is sometimes denoted unzip.
| |
| | |
| A variation of the convolution operation is defined by:
| |
| | |
| :<math> (x_1,y_1,\ldots)(x_2,y_2,\ldots)\ldots(x_{\underline{\ell}},y_{\underline{\ell}},\ldots)</math>
| |
|
| |
| where <math>\underline{\ell}</math> is the ''minimum'' length of the input words. It avoids the use of an adjoined element <math>\#</math>, but destroys information about elements of the input sequences beyond <math>\underline{\ell}</math>.
| |
| | |
| == In programming languages ==
| |
| Convolution [[Subroutine|functions]] are often available in [[programming language]]s, often referred to as <tt>zip</tt>. In [[Lisp (programming language)|Lisp]]-dialects one can simply <tt>[[Map (higher-order function)|map]]</tt> the desired function over the desired lists, <tt>map</tt> is [[Variadic function|variadic]] in Lisp so it can take an arbitrary amount of lists as argument. An example from [[Clojure]]:<ref>[http://clojuredocs.org/clojure_core/1.2.0/clojure.core/map map] from ClojureDocs</ref>
| |
| | |
| <source lang="clojure">
| |
| ;; `nums' contains an infinite list of numbers (0 1 2 3 ...)
| |
| (def nums (range))
| |
| (def tens [10 20 30])
| |
| (def firstname "Alice")
| |
| | |
| ;; To convolve (0 1 2 3 ...) and [10 20 30] into a vector, invoke `map vector' on them; same with list
| |
| (map vector nums tens) ; ⇒ ([1 10] [2 20] [3 30])
| |
| (map list nums tens) ; ⇒ ((1 10) (2 20) (3 30))
| |
| (map str nums tens) ; ⇒ ("110" "220" "330")
| |
| | |
| ;; `map' truncates to the shortest sequence; note missing \c and \e from "Alice"
| |
| (map vector nums tens firstname) ; ⇒ ([1 10 \A] [2 20 \l] [3 30 \i])
| |
| (map str nums tens firstname) ; ⇒ ("110A" "220l" "330i")
| |
| | |
| ;; To unzip, apply `map vector' or `map list'
| |
| (apply map list (map vector nums tens firstname))
| |
| ;; ⇒ ((0 1 2) (10 20 30) (\A \l \i))
| |
| </source>
| |
| | |
| In [[Common Lisp]]:
| |
| <source lang="lisp">
| |
| (defparameter nums '(1 2 3))
| |
| (defparameter tens '(10 20 30))
| |
| (defparameter firstname "Alice")
| |
| | |
| (mapcar #'list nums tens)
| |
| ;; ⇒ ((1 10) (2 20) (3 30))
| |
| | |
| (mapcar #'list nums tens (coerce firstname 'list))
| |
| ;; ⇒ ((1 10 #\A) (2 20 #\l) (3 30 #\i)) — truncates on shortest list
| |
| | |
| ;; Unzips
| |
| (apply #'mapcar #'list (mapcar #'list nums tens (coerce firstname 'list)))
| |
| ;; ⇒ ((1 2 3) (10 20 30) (#\A #\l #\i))
| |
| </source>
| |
| | |
| Languages such as [[Python (programming language)|Python]] provide a <tt>zip()</tt> function, older version (Python 2.*) allowed mapping <tt>None</tt> over lists to get a similar effect.<ref name="pydocs">[http://docs.python.org/library/functions.html#map map(function, iterable, ...)] from section Built-in Functions from Python v2.7.2 documentation</ref> <tt>zip()</tt> in conjunction with the <tt>*</tt> operator unzips a list:<ref name="pydocs"/>
| |
| <source lang="python">
| |
| nums = [1, 2, 3]
| |
| tens = [10, 20, 30]
| |
| firstname = 'Alice'
| |
| | |
| zipped = zip(nums, tens)
| |
| zipped
| |
| # ⇒ [(1, 10), (2, 20), (3, 30)] — zip
| |
| | |
| zip(*zipped)
| |
| # ⇒ [(1, 2, 3), (10, 20, 30)] — unzip
| |
| | |
| zipped2 = zip(nums, tens, list(firstname))
| |
| zipped2
| |
| # ⇒ [(1, 10, 'A'), (2, 20, 'l'), (3, 30, 'i')] — zip, truncates on shortest
| |
| zip(*zipped2)
| |
| # ⇒ [(1, 2, 3), (10, 20, 30), ('A', 'l', 'i')] — unzip
| |
| | |
| # mapping with `None' doesn't truncate; deprecated in Python 3.*
| |
| map(None,nums, tens, list(firstname))
| |
| # ⇒ [(1, 10, 'A'), (2, 20, 'l'), (3, 30, 'i'), (None, None, 'c'), (None, None, 'e')]
| |
| </source>
| |
| | |
| [[Haskell (programming language)|Haskell]] has a method of convolving sequences but requires a specific function for each [[arity]] (<tt>zip</tt> for two sequences, <tt>zip3</tt> for three etc.),<ref>[http://hackage.haskell.org/packages/archive/base/latest/doc/html/Prelude.html#v:zip zip :: <nowiki>[a] -> [b] -> [(a, b)]</nowiki>] from Prelude, Basic libraries</ref> similarly the functions <tt>unzip</tt> and <tt>unzip3</tt> are available for unzipping:
| |
| <source lang="haskell">
| |
| -- nums contains an infinite list of numbers [1, 2, 3,...]
| |
| nums = [1..]
| |
| tens = [10, 20, 30]
| |
| firstname = "Alice"
| |
| | |
| zip nums tens
| |
| -- ⇒ [(1,10),(2,20),(3,30)] — zip, truncates infinite list
| |
| unzip $ zip nums tens
| |
| -- ⇒ ([1,2,3],[10,20,30]) — unzip
| |
| | |
| zip3 nums tens firstname
| |
| -- ⇒ [(1,10,'A'),(2,20,'l'),(3,30,'i')] — zip, truncates
| |
| unzip3 $ zip3 nums tens firstname
| |
| -- ⇒ ([1,2,3],[10,20,30],"Ali") — unzip
| |
| </source>
| |
| | |
| ==Language comparison==
| |
| List of languages by support of convolution:
| |
| | |
| {| class="wikitable"
| |
| |+ Zip in various languages
| |
| ! Language !! Zip !! Zip 3 lists !! Zip ''n'' lists !! Notes
| |
| |-
| |
| | [[Clojure]]
| |
| | <tt>(map list ''list1'' ''list2'')<br/> (map vector ''list1'' ''list2'') </tt>
| |
| | <tt>(map vector ''list1'' ''list2'' ''list3'')<br/> (map vector ''list1'' ''list2'' ''list3'') </tt>
| |
| | <tt>(map list ''list1'' … ''listn'')<br/> (map vector ''list1'' … ''listn'') </tt>
| |
| | Stops after the length of the shortest list.
| |
| |-
| |
| | [[Common Lisp]]
| |
| | <tt>(mapcar #'list ''list1'' ''list2'')</tt>
| |
| | <tt>(mapcar #'list ''list1'' ''list2'' ''list3'')</tt>
| |
| | <tt>(mapcar #'list ''list1'' ... ''listn'')</tt>
| |
| | Stops after the length of the shortest list.
| |
| |-
| |
| | [[Haskell (programming language)|Haskell]]
| |
| | <tt>zip ''list1'' ''list2''</tt>
| |
| | <tt>zip3 ''list1'' ''list2'' ''list3''</tt>
| |
| | <tt>zip''n'' ''list1'' … ''listn''</tt>
| |
| | <tt>zipn</tt> for ''n'' > 3 is available in the module ''Data.List''. Stops after the shortest list ends.
| |
| |-
| |
| | [[Python (programming language)|Python]]
| |
| | <tt>zip(''list1'', ''list2'')</tt>
| |
| | <tt>zip(''list1'', ''list2'', ''list3'')</tt>
| |
| | <tt>zip(''list1'', …, ''listn'')</tt>
| |
| | <tt>''zip()''</tt> and <tt>''map()''</tt> (3.x) stops after the shortest list ends, whereas <tt>''map()''</tt> (2.x) and <tt>''itertools.zip_longest()''</tt> (3.x) extends the shorter lists with <tt>''None''</tt> items
| |
| |-
| |
| | [[Ruby (programming language)|Ruby]]
| |
| | <tt>''list1''.zip(''list2'')</tt>
| |
| | <tt>''list1''.zip(''list2'', ''list3'')</tt>
| |
| | <tt>''list1''.zip(''list1'', .., ''listn'')</tt>
| |
| | When the list being executed upon (list1) is shorter than the lists being zipped the resulting list is the length of list1. If list1 is longer nil values are used to fill the missing values<ref>http://www.ruby-doc.org/core-2.0/Array.html#method-i-zip</ref>
| |
| |}
| |
| | |
| {| class="wikitable"
| |
| |+ Unzip in various languages
| |
| ! Language !! Unzip !! Unzip 3 tuples !! Unzip ''n'' tuples !! Notes
| |
| |-
| |
| | [[Clojure]]
| |
| | <tt>(apply map vector ''convlist'')</tt>
| |
| | <tt>(apply map vector ''convlist'')</tt>
| |
| | <tt>(apply map vector ''convlist'')</tt>
| |
| |
| |
| |-
| |
| | [[Common Lisp]]
| |
| | <tt>(apply #'mapcar #'list ''convlist'')</tt>
| |
| | <tt>(apply #'mapcar #'list ''convlist'')</tt>
| |
| | <tt>(apply #'mapcar #'list ''convlist'')</tt>
| |
| |
| |
| |-
| |
| | [[Haskell (programming language)|Haskell]]
| |
| | <tt>unzip ''convlist''</tt>
| |
| | <tt>unzip3 ''convlist''</tt>
| |
| | <tt>unzip''n'' ''convlist''</tt>
| |
| | <tt>unzipn</tt> for ''n'' > 3 is available in the module <tt>''Data.List''.</tt>
| |
| |-
| |
| | [[Python (programming language)|Python]]
| |
| | <tt>zip(*''convvlist'')</tt>
| |
| | <tt>zip(*''convvlist'')</tt>
| |
| | <tt>zip(*''convvlist'')</tt>
| |
| |
| |
| |}
| |
| | |
| == See also ==
| |
| * [[Map (higher-order function)]]
| |
| | |
| ==References==
| |
| <references/>
| |
| | |
| {{PlanetMath attribution|id=5734|title=convolution}}
| |
| | |
| [[Category:Formal languages]]
| |
| [[Category:Articles with example Haskell code]]
| |
| [[Category:Articles with example Lisp code]]
| |
| [[Category:Articles with example Clojure code]]
| |
| [[Category:Articles with example Python code]]
| |