提交 78378ce8 authored 作者: Joseph Turian's avatar Joseph Turian

merge

......@@ -108,3 +108,4 @@ TRAC
* Documentation of Klass system
* Package 0.1 documentation, so we are free to update it
* Convert wiki into sphinx or epydoc.
import unittest, os, sys, traceback
def test_root_dir(debugmode=False):
suite = None
filenames = os.listdir('.')
for filename in filenames:
if filename[-3:] == '.py' and filename[0:5] == '_test':
#print >>sys.stderr, 'Loading', modname
modname = filename[0:-3]
try:
module = __import__(modname)
except Exception, e:
print >>sys.stderr, "===================================================="
print >>sys.stderr, "Failed to load %s.py" % modname
print >>sys.stderr, "===================================================="
traceback.print_exc()
print >>sys.stderr, "===================================================="
continue
tests = unittest.TestLoader().loadTestsFromModule(module)
if tests.countTestCases() > 0:
print >>sys.stderr, 'Testing', modname
if suite is None:
suite = tests
else:
suite.addTests(tests)
if debugmode:
suite.debug()
else:
unittest.TextTestRunner(verbosity=1).run(suite)
if __name__ == '__main__':
def printUsage():
print >>sys.stderr, "Bad argument: ",sys.argv
print >>sys.stderr, "only --debug is supported"
sys.exit(1)
debugparam=""
if len(sys.argv)==2:
if sys.argv[1]=="--debug":
debugparam="--debug"
sys.argv.remove(debugparam)
else:
printUsage()
elif len(sys.argv)>2:
printUsage()
if len(sys.argv) >= 2:
cmd = sys.argv[1]
else:
cmd = 'python'
for dir in 'gof compile scalar tensor sparse'.split():
os.system('cd %s; %s autotest.py %s' % (dir, cmd, debugparam))
test_root_dir(debugparam!="")
import unittest, os, sys, traceback
if __name__ == '__main__':
def printUsage():
print >>sys.stderr, "Bad argument: ",sys.argv
print >>sys.stderr, "only --debug is supported"
sys.exit(1)
debugparam=""
if len(sys.argv)==2:
if sys.argv[1]=="--debug":
debugparam="--debug"
sys.argv.remove(debugparam)
else:
printUsage()
elif len(sys.argv)>2:
printUsage()
suite = None
filenames = os.listdir('.')
for filename in filenames:
if filename[-3:] == '.py':
modname = filename[:-3]
if modname in ['__init__', 'autotest']: continue
#print >>sys.stderr, 'Loading', modname
try:
module = __import__(modname)
except Exception, e:
if 'relative import' not in e.message:
print >>sys.stderr, "===================================================="
print >>sys.stderr, "Failed to load module %s" % modname
print >>sys.stderr, "===================================================="
traceback.print_exc()
print >>sys.stderr, "===================================================="
continue
tests = unittest.TestLoader().loadTestsFromModule(module)
if tests.countTestCases() > 0:
print >>sys.stderr, 'Testing', modname
if suite is None:
suite = tests
else:
suite.addTests(tests)
if debugparam:
suite.debug()
else:
unittest.TextTestRunner(verbosity=1).run(suite)
sphinx doesn't like it when this repertory isn't available
sphinx doesn't like it when this repertory isn't available
sphinx doesn't like it when this repertory isn't available
......@@ -194,18 +194,9 @@ Getting Help
If these installation instructions don't work, search the theano-users archive for similar cases. If you don't find a solution, write to theano-users and explain the situation.
.. header:: |THEANO| - README_ - Download_ - Documentation_ - Wiki_ - `Task List`_
.. _README: README.html
.. _Download: README.html#downloading-theano
.. _Documentation: doc/index.html
.. _Wiki: http://pylearn.org/theano
.. _task list: http://lgcm.iro.umontreal.ca/theano/query?status=accepted&status=assigned&status=new&status=reopened&group=milestone&max=200&col=id&col=summary&col=status&col=owner&col=type&col=priority&col=component&col=time&report=9&order=priority
.. |THEANO| image:: http://lgcm.iro.umontreal.ca/theano/chrome/site/theano_logo.png
:target: http://pylearn.org/auto_theano
:alt: THEANO
:align: top
:class: borderless
:width: 60
:height: 18
......@@ -7,20 +7,12 @@
# The list of objects to document. Objects can be named using
# dotted names, module filenames, or package directory names.
# Alases for this option include "objects" and "values".
modules: __init__.py,
[a-z]*.py,
[A-Z]*.py,
gof/__init__.py,
gof/[a-z]*.py,
gof/[A-Z]*.py
modules: theano
# The type of output that should be generated. Should be one
# of: html, text, latex, dvi, ps, pdf.
output: html
# The path to the output directory. May be relative or absolute.
target: html/api/
# An integer indicating how verbose epydoc should be. The default
# value is 0; negative values will supress warnings and errors;
# positive values will give more verbose output.
......@@ -125,9 +117,9 @@ separate-classes: no
# Use this URL prefix to configure the string returned for external API.
#external-api-root: epydoc:http://epydoc.sourceforge.net/api
external-api: wiki doc
external-api-root: wiki:http://lgcm.iro.umontreal.ca/theano/wiki/ doc:http://lgcm.iro.umontreal.ca/auto_theano/doc/
external-api-file: wiki:wiki.idx doc:doc/doc.idx
# external-api: wiki doc
# external-api-root: wiki:http://lgcm.iro.umontreal.ca/theano/wiki/ doc:http://lgcm.iro.umontreal.ca/auto_theano/doc/
# external-api-file: wiki:wiki.idx doc:doc/doc.idx
### Graph options
......
#!/usr/bin/python
# -*- coding: iso-8859-1 -*-
"""An HTML writer supporting link to external documentation.
This module is a frontend for the Docutils_ HTML writer. It allows a document
to reference objects documented in the API documentation generated by
extraction tools such as Doxygen_ or Epydoc_.
.. _Docutils: http://docutils.sourceforge.net/
.. _Doxygen: http://www.doxygen.org/
.. _Epydoc: http://epydoc.sourceforge.net/
"""
# $Id: apirst2html.py 1531 2007-02-18 23:07:25Z dvarrazzo $
__version__ = "$Revision: 1531 $"[11:-2]
__author__ = "Daniele Varrazzo"
__copyright__ = "Copyright (C) 2007 by Daniele Varrazzo"
__docformat__ = 'reStructuredText en'
try:
import locale
locale.setlocale(locale.LC_ALL, '')
except:
pass
# We have to do some path magic to prevent Python from getting
# confused about the difference between the ``epydoc.py`` script, and the
# real ``epydoc`` package. So remove ``sys.path[0]``, which contains the
# directory of the script.
import sys, os.path
# I leave this in place actually, so that I can import pygments_code_block_directive
#script_path = os.path.abspath(sys.path[0])
#sys.path = [p for p in sys.path if os.path.abspath(p) != script_path]
import epydoc.docwriter.xlink as xlink
from docutils.core import publish_cmdline, default_description
try:
# .. code-block:: python should look nice with this
import pygments_code_block_directive
except Exception, e:
print >> sys.stderr, "Failed to import pygments", e
description = ('Generates (X)HTML documents with API documentation links. '
+ default_description)
publish_cmdline(reader=xlink.ApiLinkReader(), writer_name='html',
description=description)
td.linenos { background-color: #f0f0f0; padding-right: 10px; }
span.lineno { background-color: #f0f0f0; padding: 0 5px 0 5px; }
pre { line-height: 125%; }
body { background: #ffffff; }
body .c { color: #808080 } /* Comment */
body .err { color: #F00000; background-color: #F0A0A0 } /* Error */
body .k { color: #008000; font-weight: bold } /* Keyword */
body .o { color: #303030 } /* Operator */
body .cm { color: #808080 } /* Comment.Multiline */
body .cp { color: #507090 } /* Comment.Preproc */
body .c1 { color: #808080 } /* Comment.Single */
body .cs { color: #cc0000; font-weight: bold } /* Comment.Special */
body .gd { color: #A00000 } /* Generic.Deleted */
body .ge { font-style: italic } /* Generic.Emph */
body .gr { color: #FF0000 } /* Generic.Error */
body .gh { color: #000080; font-weight: bold } /* Generic.Heading */
body .gi { color: #00A000 } /* Generic.Inserted */
body .go { color: #808080 } /* Generic.Output */
body .gp { color: #c65d09; font-weight: bold } /* Generic.Prompt */
body .gs { font-weight: bold } /* Generic.Strong */
body .gu { color: #800080; font-weight: bold } /* Generic.Subheading */
body .gt { color: #0040D0 } /* Generic.Traceback */
body .kc { color: #008000; font-weight: bold } /* Keyword.Constant */
body .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */
body .kp { color: #003080; font-weight: bold } /* Keyword.Pseudo */
body .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */
body .kt { color: #303090; font-weight: bold } /* Keyword.Type */
body .m { color: #6000E0; font-weight: bold } /* Literal.Number */
body .s { background-color: #fff0f0 } /* Literal.String */
body .na { color: #0000C0 } /* Name.Attribute */
body .nb { color: #007020 } /* Name.Builtin */
body .nc { color: #B00060; font-weight: bold } /* Name.Class */
body .no { color: #003060; font-weight: bold } /* Name.Constant */
body .nd { color: #505050; font-weight: bold } /* Name.Decorator */
body .ni { color: #800000; font-weight: bold } /* Name.Entity */
body .ne { color: #F00000; font-weight: bold } /* Name.Exception */
body .nf { color: #0060B0; font-weight: bold } /* Name.Function */
body .nl { color: #907000; font-weight: bold } /* Name.Label */
body .nn { color: #0e84b5; font-weight: bold } /* Name.Namespace */
body .nt { color: #007000 } /* Name.Tag */
body .nv { color: #906030 } /* Name.Variable */
body .ow { color: #000000; font-weight: bold } /* Operator.Word */
body .w { color: #bbbbbb } /* Text.Whitespace */
body .mf { color: #6000E0; font-weight: bold } /* Literal.Number.Float */
body .mh { color: #005080; font-weight: bold } /* Literal.Number.Hex */
body .mi { color: #0000D0; font-weight: bold } /* Literal.Number.Integer */
body .mo { color: #4000E0; font-weight: bold } /* Literal.Number.Oct */
body .sb { background-color: #fff0f0 } /* Literal.String.Backtick */
body .sc { color: #0040D0 } /* Literal.String.Char */
body .sd { color: #D04020 } /* Literal.String.Doc */
body .s2 { background-color: #fff0f0 } /* Literal.String.Double */
body .se { color: #606060; font-weight: bold; background-color: #fff0f0 } /* Literal.String.Escape */
body .sh { background-color: #fff0f0 } /* Literal.String.Heredoc */
body .si { background-color: #e0e0e0 } /* Literal.String.Interpol */
body .sx { color: #D02000; background-color: #fff0f0 } /* Literal.String.Other */
body .sr { color: #000000; background-color: #fff0ff } /* Literal.String.Regex */
body .s1 { background-color: #fff0f0 } /* Literal.String.Single */
body .ss { color: #A06000 } /* Literal.String.Symbol */
body .bp { color: #007020 } /* Name.Builtin.Pseudo */
body .vc { color: #306090 } /* Name.Variable.Class */
body .vg { color: #d07000; font-weight: bold } /* Name.Variable.Global */
body .vi { color: #3030B0 } /* Name.Variable.Instance */
body .il { color: #0000D0; font-weight: bold } /* Literal.Number.Integer.Long */
# -*- coding: utf-8 -*-
#
# theano documentation build configuration file, created by
# sphinx-quickstart on Tue Oct 7 16:34:06 2008.
#
# This file is execfile()d with the current directory set to its containing dir.
#
# The contents of this file are pickled, so don't put values in the namespace
# that aren't pickleable (module imports are okay, they're removed automatically).
#
# All configuration values have a default value; values that are commented out
# serve to show the default value.
import sys, os
# If your extensions are in another directory, add it here. If the directory
# is relative to the documentation root, use os.path.abspath to make it
# absolute, like shown here.
#sys.path.append(os.path.abspath('some/directory'))
# General configuration
# ---------------------
# Add any Sphinx extension module names here, as strings. They can be extensions
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
extensions = ['sphinx.ext.autodoc', 'ext']
# Add any paths that contain templates here, relative to this directory.
templates_path = ['.templates']
# The suffix of source filenames.
source_suffix = '.txt'
# The master toctree document.
master_doc = 'index'
# General substitutions.
project = 'theano'
copyright = '2008, LISA lab'
# The default replacements for |version| and |release|, also used in various
# other places throughout the built documents.
#
# The short X.Y version.
version = '0.1'
# The full version, including alpha/beta/rc tags.
release = '0.1'
# There are two options for replacing |today|: either, you set today to some
# non-false value, then it is used:
#today = ''
# Else, today_fmt is used as the format for a strftime call.
today_fmt = '%B %d, %Y'
# List of documents that shouldn't be included in the build.
#unused_docs = []
# List of directories, relative to source directories, that shouldn't be searched
# for source files.
#exclude_dirs = []
# The reST default role (used for this markup: `text`) to use for all documents.
#default_role = None
# If true, '()' will be appended to :func: etc. cross-reference text.
#add_function_parentheses = True
# If true, the current module name will be prepended to all description
# unit titles (such as .. function::).
#add_module_names = True
# If true, sectionauthor and moduleauthor directives will be shown in the
# output. They are ignored by default.
#show_authors = False
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'sphinx'
# Options for HTML output
# -----------------------
# The style sheet to use for HTML and HTML Help pages. A file of that name
# must exist either in Sphinx' static/ path, or in one of the custom paths
# given in html_static_path.
html_style = 'default.css'
# The name for this set of Sphinx documents. If None, it defaults to
# "<project> v<release> documentation".
#html_title = None
# A shorter title for the navigation bar. Default is the same as html_title.
#html_short_title = None
# The name of an image file (within the static path) to place at the top of
# the sidebar.
#html_logo = None
# The name of an image file (within the static path) to use as favicon of the
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
# pixels large.
#html_favicon = None
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['.static']
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
# using the given strftime format.
html_last_updated_fmt = '%b %d, %Y'
# If true, SmartyPants will be used to convert quotes and dashes to
# typographically correct entities.
#html_use_smartypants = True
# Custom sidebar templates, maps document names to template names.
#html_sidebars = {}
# Additional templates that should be rendered to pages, maps page names to
# template names.
#html_additional_pages = {}
# If false, no module index is generated.
#html_use_modindex = True
# If false, no index is generated.
#html_use_index = True
# If true, the index is split into individual pages for each letter.
#html_split_index = False
# If true, the reST sources are included in the HTML build as _sources/<name>.
#html_copy_source = True
# If true, an OpenSearch description file will be output, and all pages will
# contain a <link> tag referring to it. The value of this option must be the
# base URL from which the finished HTML is served.
#html_use_opensearch = ''
# If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml").
#html_file_suffix = ''
# Output file base name for HTML help builder.
htmlhelp_basename = 'theanodoc'
# Options for LaTeX output
# ------------------------
# The paper size ('letter' or 'a4').
#latex_paper_size = 'letter'
# The font size ('10pt', '11pt' or '12pt').
#latex_font_size = '10pt'
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title, author, document class [howto/manual]).
latex_documents = [
('index', 'theano.tex', 'theano Documentation',
'LISA lab', 'manual'),
]
# The name of an image file (relative to this directory) to place at the top of
# the title page.
#latex_logo = None
# For "manual" documents, if this is true, then toplevel headings are parts,
# not chapters.
#latex_use_parts = False
# Additional stuff for the LaTeX preamble.
#latex_preamble = ''
# Documents to append as an appendix to all manuals.
#latex_appendices = []
# If false, no module index is generated.
#latex_use_modindex = True
graph graph.html
tensor graph.html
result graph.html
howto graph.html
oplist oplist.html
......@@ -60,16 +60,6 @@ When you install a package, only the package name can be imported directly. If y
.. _basicnumpy: http://lgcm.iro.umontreal.ca/theano/wiki/BasicNumpy
.. header:: |THEANO| - README_ - Download_ - Documentation_ - Wiki_ - `Task List`_
.. |THEANO| image:: http://lgcm.iro.umontreal.ca/theano/chrome/site/theano_logo.png
:target: http://pylearn.org/auto_theano
:alt: THEANO
:align: top
:class: borderless
:width: 60
:height: 18
.. _README: ../README.html
.. _Download: ../README.html#downloading-theano
.. _Documentation: index.html
......
......@@ -87,16 +87,6 @@ If we had wanted a more brute-force approach to graph construction, we could hav
Note how the call to `Apply` modifies the `owner` and `index` fields of the `Result` s passed as outputs to point to itself and the rank they occupy in the output list. This whole machinery builds a DAG (Directed Acyclic Graph) representing the computation, a graph that theano can compile and optimize.
.. header:: |THEANO| - README_ - Download_ - Documentation_ - Wiki_ - `Task List`_
.. |THEANO| image:: http://lgcm.iro.umontreal.ca/theano/chrome/site/theano_logo.png
:target: http://pylearn.org/auto_theano
:alt: THEANO
:align: top
:class: borderless
:width: 60
:height: 18
.. _README: ../README.html
.. _Download: ../README.html#downloading-theano
.. _Documentation: index.html
......
=====================================
Theano Project Documentation Overview
=====================================
.. toctree::
:glob:
*
Documentation is divided broadly into two kinds: user documentation and
developer documentation.
- `Using Theano` covers how to *use* what is already in the Theano library to
build graphs and evaluate them.
- `Extending Theano` introduces how Theano works and explains how to add new
data and expression types, as well as optimizations to accompany them.
- `Hacking Theano` introduces you to what's under the hood: the compilation
process, the Env, C code generation.
Using Theano
============
- First of all, read the `n00b guide`_. It is a cut-and-paste, tutorial-style intro to what Theano can do.
- Familiarize yourself with the `glossary of terminology`_.
- Join `theano-users`_.
- Learn to use the typelist_, and the oplist_. These are the building blocks
of theano expression graphs.
- Browse through some of the `Howto`_ recipes on the wiki.
.. _Howto:
.. _theano-users: http://groups.google.com/group/theano-users?pli=1
.. _theano-dev: http://groups.google.com/group/theano-dev?pli=1
.. _n00b guide: n00b.html
.. _glossary of terminology: ../api/term-index.html
.. _typelist: typelist.html
.. _oplist: oplist.html
Extending Theano
================
- Read about `How Theano Works <UserAdvanced.html>`__. This introduces the
major interface data structures: Op, Type, Result, Apply.
- How to make a new Op.
- How to make a new Optimization.
- How to make a new data Type.
Hacking Theano
==============
- `Get Started as a Developer <DevStartGuide.html>`__ by setting up mercurial, getting a few accounts,
setting up your environment, and getting some background in mercurial, python,
and numpy.
- Join `theano-dev`_ to participate in development discussion.
- Pick a task from the `task list`_, or suggest one on `theano-users`_.
Features/ideas are generally discussed on `theano-users`_. Technical
discussions of how to actually implement something should be on
`theano-dev`_.
- Browse `Theano's API <../api/>`__.
- Keep an eye on the `Mercurial Changelog <http://pylearn.org/hg/theano>`__.
- Send us your work as a patch to `theano-dev`_ or commit directly to the trunk.
.. _theano-dev: http://groups.google.com/group/theano-dev?pli=1
.. _task list: http://lgcm.iro.umontreal.ca/theano/query?status=accepted&status=assigned&status=new&status=reopened&group=milestone&max=200&col=id&col=summary&col=status&col=owner&col=type&col=priority&col=component&col=time&report=9&order=priority
.. _reStructuredText: http://docutils.sourceforge.net/rst.html
......@@ -237,16 +237,6 @@ code. The question is how to automatically extract the source files and inline
them into this documentation.*
.. header:: |THEANO| - README_ - Download_ - Documentation_ - Wiki_ - `Task List`_
.. |THEANO| image:: http://lgcm.iro.umontreal.ca/theano/chrome/site/theano_logo.png
:target: http://pylearn.org/auto_theano
:alt: THEANO
:align: top
:class: borderless
:width: 60
:height: 18
.. _README: ../README.html
.. _Download: ../README.html#downloading-theano
.. _Documentation: index.html
......
import sys
import re
import os
from docutils import nodes, utils
from docutils.parsers.rst import roles
import epydoc.docwriter.xlink as xlink
def role_fn(name, rawtext, text, lineno, inliner,
options={}, content=[]):
node = nodes.reference(rawtext, text, refuri = "http://pylearn.org/theano/wiki/%s" % text)
return [node], []
_TARGET_RE = re.compile(r'^(.*?)\s*<(?:URI:|URL:)?([^<>]+)>$')
def create_api_role(name, problematic):
"""
Create and register a new role to create links for an API documentation.
Create a role called `name`, which will use the URL resolver registered as
``name`` in `api_register` to create a link for an object.
:Parameters:
`name` : `str`
name of the role to create.
`problematic` : `bool`
if True, the registered role will create problematic nodes in
case of failed references. If False, a warning will be raised
anyway, but the output will appear as an ordinary literal.
"""
def resolve_api_name(n, rawtext, text, lineno, inliner,
options={}, content=[]):
# Check if there's separate text & targets
m = _TARGET_RE.match(text)
if m: text, target = m.groups()
else: target = text
# node in monotype font
text = utils.unescape(text)
node = nodes.literal(rawtext, text, **options)
# Get the resolver from the register and create an url from it.
try:
url = xlink.api_register[name].get_url(target)
except IndexError, exc:
msg = inliner.reporter.warning(str(exc), line=lineno)
if problematic:
prb = inliner.problematic(rawtext, text, msg)
return [prb], [msg]
else:
return [node], []
if url is not None:
node = nodes.reference(rawtext, '', node, refuri=url, **options)
return [node], []
roles.register_local_role(name, resolve_api_name)
def setup(app):
try:
xlink.set_api_file('api', os.path.join(app.outdir, 'api', 'api-objects.txt'))
xlink.set_api_root('api', os.path.join('..', 'api', ''))
#xlink.create_api_role('api', True)
create_api_role('api', True)
except IOError:
print >>sys.stderr, 'WARNING: Could not find api file! API links will not work.'
app.add_role("wiki", role_fn)
.. header:: |THEANO| - README_ - Download_ - Documentation_ - Wiki_ - `Task List`_
.. |THEANO| image:: http://lgcm.iro.umontreal.ca/theano/chrome/site/theano_logo.png
:target: http://pylearn.org/auto_theano
:alt: THEANO
:align: top
:class: borderless
:width: 60
:height: 18
.. _README: ../README.html
.. _Download: ../README.html#downloading-theano
.. _Documentation: index.html
.. _Wiki: http://pylearn.org/theano
.. _task list: http://lgcm.iro.umontreal.ca/theano/query?status=accepted&status=assigned&status=new&status=reopened&group=milestone&max=200&col=id&col=summary&col=status&col=owner&col=type&col=priority&col=component&col=time&report=9&order=priority
=====================================
Theano Project Documentation Overview
=====================================
Documentation is divided broadly into two kinds: user documentation and
developer documentation.
======
Theano
======
- `Using Theano` covers how to *use* what is already in the Theano library to
build graphs and evaluate them.
.. toctree::
:maxdepth: 2
- `Extending Theano` introduces how Theano works and explains how to add new
data and expression types, as well as optimizations to accompany them.
README
doc/index
- `Hacking Theano` introduces you to what's under the hood: the compilation
process, the Env, C code generation.
-------------------------------------------------------------------
A python library for manipulating and evaluating matrix expressions
-------------------------------------------------------------------
Theano is a library in Python, built to evaluate complicated
expressions (especially matrix-valued ones) as quickly as possible.
It was written at LISA_ to explore techniques for machine learning.
Our project uses the name to honour the ancient Greek mathematician.
Using Theano
============
--------------------------------------------------------------------------------
- First of all, read the `n00b guide`_. It is a cut-and-paste, tutorial-style intro to what Theano can do.
.. _not in the normal sense: :wiki:`WhatIsTheano`
- Familiarize yourself with the `glossary of terminology`_.
Overview
========
- Join `theano-users`_.
**To get up & running quickly** see README_.
- Learn to use the typelist_, and the oplist_. These are the building blocks
of theano expression graphs.
All **documentation** can be reached from the `Theano Project Documentation Overview`_.
- Browse through some of the `Howto`_ recipes on the wiki.
As developers of an open source project, we rely on **feedback** for
determining what features to implement, and what documentation needs to be
improved. The best forum for feedback is the theano-users_ mailing list.
.. _Howto:
.. _theano-users: http://groups.google.com/group/theano-users?pli=1
.. _theano-dev: http://groups.google.com/group/theano-dev?pli=1
.. _n00b guide: n00b.html
.. _glossary of terminology: ../api/term-index.html
.. _typelist: typelist.html
.. _oplist: oplist.html
Extending Theano
================
All **discussion** about theano also takes place on the theano-users_ mailing list.
- Read about `How Theano Works <UserAdvanced.html>`__. This introduces the
major interface data structures: Op, Type, Result, Apply.
If you find a **bug**, please file a `bug report`_ or send email to
the theano-users_ mailing list. **Patch** submissions should be
sent to theano-dev_.
- How to make a new Op.
We welcome all kinds of **contributions**. Our `task list`_ is
full of interesting ideas awaiting a champion. If you have any
questions regarding how to extend Theano, please feel free to ask on
the Theano-dev_ mailing list.
- How to make a new Optimization.
Theano is in active development and should be considered **experimental**.
APIs are subject to change at any time.
- How to make a new data Type.
Hacking Theano
==============
Download
========
- `Get Started as a Developer <DevStartGuide.html>`__ by setting up mercurial, getting a few accounts,
setting up your environment, and getting some background in mercurial, python,
and numpy.
We recommend that you use the `latest snapshot`_,
Better yet, use `mercurial`_ to keep your installation fresh.
The snapshots usually contain *more features* and *fewer bugs* than the
"official" releases |---| they're not only for developers!
- Join `theano-dev`_ to participate in development discussion.
- Pick a task from the `task list`_, or suggest one on `theano-users`_.
Features/ideas are generally discussed on `theano-users`_. Technical
discussions of how to actually implement something should be on
`theano-dev`_.
Indices and tables
==================
- Browse `Theano's API <../api/>`__.
* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`
- Keep an eye on the `Mercurial Changelog <http://pylearn.org/hg/theano>`__.
- Send us your work as a patch to `theano-dev`_ or commit directly to the trunk.
.. |---| unicode:: U+02014 .. em dash
:trim:
.. _latest snapshot: http://pylearn.org/hg/theano/archive/tip.tar.gz
.. _bug report: http://lgcm.iro.umontreal.ca/theano/newticket
.. _theano-users: http://groups.google.com/group/theano-users?pli=1
.. _theano-dev: http://groups.google.com/group/theano-dev?pli=1
.. _reStructuredText: rst.html
.. _task list: http://lgcm.iro.umontreal.ca/theano/query?status=accepted&status=assigned&status=new&status=reopened&group=milestone&max=200&col=id&col=summary&col=status&col=owner&col=type&col=priority&col=component&col=time&report=9&order=priority
.. _reStructuredText: http://docutils.sourceforge.net/rst.html
.. header:: |THEANO| - README_ - Download_ - Documentation_ - Wiki_ - `Task List`_
.. |THEANO| image:: http://lgcm.iro.umontreal.ca/theano/chrome/site/theano_logo.png
:target: http://pylearn.org/auto_theano
:alt: THEANO
:align: top
:class: borderless
:width: 60
:height: 18
.. _README: ../README.html
.. _Download: ../README.html#downloading-theano
.. _Documentation: index.html
.. _Wiki: http://pylearn.org/theano
.. _README: README.html
.. _Quick-Start: README.html#quick-start
.. _Theano Project Documentation Overview: doc/index.html
.. _Mercurial: http://www.selenic.com/mercurial/wiki/
.. _docutils: http://docutils.sourceforge.net
.. _epydoc: http://epydoc.sourceforge.net/
.. _scipy: http://scipy.org/
.. _Python: http://www.python.org/
.. _TRAC: http://trac.edgewall.org/
.. _task list: http://lgcm.iro.umontreal.ca/theano/query?status=accepted&status=assigned&status=new&status=reopened&group=milestone&max=200&col=id&col=summary&col=status&col=owner&col=type&col=priority&col=component&col=time&report=9&order=priority
.. _LISA: http://www.iro.umontreal.ca/rubrique.php3?id_rubrique=27
#!/usr/bin/python
# :Author: a Pygments author|contributor; Felix Wiemann; Guenter Milde
# :Date: $Date: 2007-06-13 12:20:42 +0200 (Wed, 13 Jun 2007) $
# :Copyright: This module has been placed in the public domain.
#
# This is a merge of `Using Pygments in ReST documents`_ from the pygments_
# documentation, and a `proof of concept`_ by Felix Wiemann.
#
# ========== ===========================================================
# 2007-06-01 Removed redundancy from class values.
# 2007-06-04 Merge of successive tokens of same type
# (code taken from pygments.formatters.others).
# 2007-06-05 Separate docutils formatter script
# Use pygments' CSS class names (like the html formatter)
# allowing the use of pygments-produced style sheets.
# 2007-06-07 Merge in the formatting of the parsed tokens
# (misnamed as docutils_formatter) as class DocutilsInterface
# 2007-06-08 Failsave implementation (fallback to a standard literal block
# if pygments not found)
# ========== ===========================================================
#
# ::
"""Define and register a code-block directive using pygments
"""
# Requirements
# ------------
# ::
from docutils import nodes
from docutils.parsers.rst import directives
try:
import pygments
from pygments import highlight
from pygments.lexers import get_lexer_by_name
from pygments.formatters.html import _get_ttype_class
from pygments.styles import get_style_by_name
from pygments.lexers import PythonLexer
from pygments.formatters import HtmlFormatter
# Customisation
# -------------
#
# Do not insert inline nodes for the following tokens.
# (You could add e.g. Token.Punctuation like ``['', 'p']``.) ::
unstyled_tokens = ['']
# DocutilsInterface
# -----------------
#
# This interface class combines code from
# pygments.formatters.html and pygments.formatters.others.
#
# It does not require anything of docutils and could also become a part of
# pygments::
class DocutilsInterface(object):
"""Parse `code` string and yield "classified" tokens.
Arguments
code -- string of source code to parse
language -- formal language the code is written in.
Merge subsequent tokens of the same token-type.
Yields the tokens as ``(ttype_class, value)`` tuples,
where ttype_class is taken from pygments.token.STANDARD_TYPES and
corresponds to the class argument used in pygments html output.
"""
def __init__(self, code, language):
self.code = code
self.language = language
def lex(self):
# Get lexer for language (use text as fallback)
try:
lexer = get_lexer_by_name(self.language)
except ValueError:
# info: "no pygments lexer for %s, using 'text'"%self.language
lexer = get_lexer_by_name('text')
return pygments.lex(self.code, lexer)
def join(self, tokens):
"""join subsequent tokens of same token-type
"""
tokens = iter(tokens)
(lasttype, lastval) = tokens.next()
for ttype, value in tokens:
if ttype is lasttype:
lastval += value
else:
yield(lasttype, lastval)
(lasttype, lastval) = (ttype, value)
yield(lasttype, lastval)
def __iter__(self):
"""parse code string and yield "clasified" tokens
"""
try:
tokens = self.lex()
except IOError:
print "INFO: Pygments lexer not found, using fallback"
# TODO: write message to INFO
yield ('', self.code)
return
for ttype, value in self.join(tokens):
yield (_get_ttype_class(ttype), value)
# code_block_directive
# --------------------
# ::
def code_block_directive(name, arguments, options, content, lineno,
content_offset, block_text, state, state_machine):
"""parse and classify content of a code_block
"""
language = arguments[0]
# create a literal block element and set class argument
if 0:
code_block = nodes.literal_block(classes=["code-block", language])
code_block += nodes.raw('<b>hello</b> one', 'hello two')
else:
code_block = nodes.literal_block(classes=["code-block", language])
# parse content with pygments and add to code_block element
for cls, value in DocutilsInterface(u'\n'.join(content), language):
if cls in unstyled_tokens:
# insert as Text to decrease the verbosity of the output.
code_block += nodes.Text(value, value)
else:
code_block += nodes.inline(value, value, classes=[cls])
if 0:
v = highlight(u'\n'.join(content), PythonLexer(),
HtmlFormatter(style='colorful', full=True, cssfile='blah.css'))
print help(nodes.Inline)
return [code_block]
# Register Directive
# ------------------
# ::
code_block_directive.arguments = (1, 0, 1)
code_block_directive.content = 1
directives.register_directive('code-block', code_block_directive)
# .. _doctutils: http://docutils.sf.net/
# .. _pygments: http://pygments.org/
# .. _Using Pygments in ReST documents: http://pygments.org/docs/rstdirective/
# .. _proof of concept:
# http://article.gmane.org/gmane.text.docutils.user/3689
#
# Test output
# -----------
#
# If called from the command line, call the docutils publisher to render the
# input::
except ImportError:
print >> sys.stderr, "Failed to import pygments"
pass
if __name__ == '__main__':
from docutils.core import publish_cmdline, default_description
description = "code-block directive test output" + default_description
try:
import locale
locale.setlocale(locale.LC_ALL, '')
except:
pass
# Uncomment the desired output format:
publish_cmdline(writer_name='pseudoxml', description=description)
# publish_cmdline(writer_name='xml', description=description)
# publish_cmdline(writer_name='html', description=description)
# publish_cmdline(writer_name='latex', description=description)
# publish_cmdline(writer_name='newlatex2e', description=description)
/*
* :Author: Your Name
* :Contact: Your Email Address
* :Copyright: This stylesheet has been placed in the public domain.
*
* Stylesheet for use with Docutils. [Optionally place a more
* detailed description here.]
* */
@import url(html4css1.css); /* for basic rst stuff */
@import url(colorful.css); /* for source highlighting */
/* Your customizations go here. For example: */
/*
h1, h2, h3, h4, h5, h6, p.topic-title {
font-family: sans-serif }
*/
# TODO:
# Get all graphs to work!
[epydoc] # Epydoc section marker (required by ConfigParser)
# The list of objects to document. Objects can be named using
# dotted names, module filenames, or package directory names.
# Alases for this option include "objects" and "values".
modules: *.py, gof/*.py, theano/*.py, theano/gof/*.py, joseph/*.py, pylearn/*.py
# The type of output that should be generated. Should be one
# of: html, text, latex, dvi, ps, pdf.
output: html
# The path to the output directory. May be relative or absolute.
target: html/
# An integer indicating how verbose epydoc should be. The default
# value is 0; negative values will supress warnings and errors;
# positive values will give more verbose output.
verbosity: 1
# A boolean value indicating that Epydoc should show a tracaback
# in case of unexpected error. By default don't show tracebacks
debug: 0
# If True, don't try to use colors or cursor control when doing
# textual output. The default False assumes a rich text prompt
simple-term: 0
### Generation options
# The default markup language for docstrings, for modules that do
# not define __docformat__. Defaults to epytext.
docformat: epytext
# Whether or not parsing should be used to examine objects.
parse: yes
# Whether or not introspection should be used to examine objects.
introspect: yes
# Don't examine in any way the modules whose dotted name match this
# regular expression pattern.
#exclude
# Don't perform introspection on the modules whose dotted name match this
# regular expression pattern.
#exclude-introspect
# Don't perform parsing on the modules whose dotted name match this
# regular expression pattern.
#exclude-parse
# The format for showing inheritance objects.
# It should be one of: 'grouped', 'listed', 'included'.
inheritance: grouped
# Whether or not to inclue private variables. (Even if included,
# private variables will be hidden by default.)
private: yes
# Whether or not to list each module's imports.
imports: yes
# Whether or not to include syntax highlighted source code in
# the output (HTML only).
sourcecode: yes
# Whether or not to includea a page with Epydoc log, containing
# effective option at the time of generation and the reported logs.
include-log: yes
### Output options
# The documented project's name.
name: Theano
# The CSS stylesheet for HTML output. Can be the name of a builtin
# stylesheet, or the name of a file.
css: white
# The documented project's URL.
url: http://lgcm.iro.umontreal.ca/theano/
# HTML code for the project link in the navigation bar. If left
# unspecified, the project link will be generated based on the
# project's name and URL.
#link: <a href="somewhere">My Cool Project</a>
# The "top" page for the documentation. Can be a URL, the name
# of a module or class, or one of the special names "trees.html",
# "indices.html", or "help.html"
#top: os.path
# An alternative help file. The named file should contain the
# body of an HTML file; navigation bars will be added to it.
#help: my_helpfile.html
# Whether or not to include a frames-based table of contents.
#frames: yes
frames: no
# Whether each class should be listed in its own section when
# generating LaTeX or PDF output.
separate-classes: no
### API linking options
# Define a new API document. A new interpreted text role
# will be created
#external-api: epydoc
# Use the records in this file to resolve objects in the API named NAME.
#external-api-file: epydoc:api-objects.txt
# Use this URL prefix to configure the string returned for external API.
#external-api-root: epydoc:http://epydoc.sourceforge.net/api
### EXTERNAL WIKI REFERENCES
external-api: wiki
external-api-root: wiki:http://lgcm.iro.umontreal.ca/theano/wiki/
# this works when epydoc is run from the parent directory of this file
external-api-file: wiki:theano/wiki.idx
### Graph options
# The list of graph types that should be automatically included
# in the output. Graphs are generated using the Graphviz "dot"
# executable. Graph types include: "classtree", "callgraph",
# "umlclass". Use "all" to include all graph types
#graph: classtree
# The path to the Graphviz "dot" executable, used to generate
# graphs.
dotpath: /usr/bin/dot
# The name of one or more pstat files (generated by the profile
# or hotshot module). These are used to generate call graphs.
#pstat: autotest.pstat
# Specify the font used to generate Graphviz graphs.
# (e.g., helvetica or times).
graph-font: Helvetica
# Specify the font size used to generate Graphviz graphs.
graph-font-size: 10
### Return value options
# The condition upon which Epydoc should exit with a non-zero
# exit status. Possible values are error, warning, docstring_warning
#fail-on: error
#!/bin/sh
#python -m profile -o autotest.pstat autotest.py
epydoc --config epydoc-fast
#!/bin/sh
python -m profile -o autotest.pstat autotest.py
epydoc --config epydoc
import sys
sys.path.insert(0, '..')
import theano
from theano import tensor as T
from theano.sandbox import nnet_ops
from theano.sandbox import module
import numpy as N
class LogisticRegressionN(module.FancyModule):
class __instance_type__(module.FancyModuleInstance):
def initialize(self, n_in, n_out):
#self.component is the LogisticRegressionTemplate instance that built this guy.
self.w = N.random.randn(n_in, n_out)
self.b = N.random.randn( n_out)
self.lr = 0.01
def __init__(self, x = None, targ = None):
super(LogisticRegressionN, self).__init__() #boilerplate
self.x = x if x is not None else T.matrix()
self.targ = targ if targ is not None else T.lvector()
self.w = module.Member(T.matrix()) #automatically names
self.b = module.Member(T.vector()) #automatically names
self.lr = module.Member(T.dscalar()) #provides an external interface to change it
#and makes it an implicit input to any Method you build.
self.params = [self.w, self.b]
xent, y = nnet_ops.crossentropy_softmax_1hot(
T.dot(self.x, self.w) + self.b, self.targ)
gparams = T.grad(xent, self.params)
self.update = module.Method([self.x, self.targ], xent,
updates = dict((p, p - self.lr * g) for p, g in zip(self.params, gparams)))
self.apply = module.Method([self.x], T.argmax(T.dot(self.x, self.w) + self.b, axis=1))
class LogisticRegression2(module.FancyModule):
class __instance_type__(module.FancyModuleInstance):
def initialize(self, n_in):
#self.component is the LogisticRegressionTemplate instance that built this guy.
self.w = N.random.randn(n_in,1)
self.b = N.random.randn(1)
self.lr = 0.01
def __init__(self, x = None, targ = None):
super(LogisticRegression2, self).__init__() #boilerplate
self.x = x if x is not None else T.matrix()
self.targ = targ if targ is not None else T.lvector()
self.w = module.Member(T.dmatrix()) #automatically names
self.b = module.Member(T.dvector()) #automatically names
self.lr = module.Member(T.dscalar()) #provides an external interface to change it
#and makes it an implicit input to any Method you build.
self.params = [self.w, self.b]
y = nnet_ops.sigmoid(T.dot(self.x, self.w))
xent_elem = self.targ * T.log(y) - (1.0 - self.targ) *T.log(1.0 - y)
xent = T.sum(xent_elem)
gparams = T.grad(xent, self.params)
self.update = module.Method([self.x, self.targ], [xent, self.w, gparams[0]],
updates = dict((p, p - self.lr * g) for p, g in zip(self.params, gparams)))
self.apply = module.Method([self.x], T.argmax(T.dot(self.x, self.w) + self.b, axis=1))
if __name__ == '__main__':
lr = LogisticRegression2().make(10, mode='FAST_COMPILE')
data_x = N.random.randn(10, 10)
data_y = (N.random.randn(10) > 0)
print lr.params
print lr.w.shape
for i in xrange(10):
xe = lr.update(data_x, data_y)
print N.sum(xe), lr.w.shape
from gen_oplist import print_title, print_hline
if __name__ == '__main__':
print_title("Type List", "~", "~")
print "*THIS PAGE IS A PLACEHOLDER: WRITEME*"
print ""
print_hline()
print ""
print ".. contents::"
print ""
print_title("Type Classes", '=')
print "- scalar.Scalar\n"
print "- tensor.Tensor\n"
print "- sparse.Sparse\n"
print_title("Type Instances", '=')
print "- scalar.int8\n"
print "- tensor.lvector\n"
print "- sparse.??\n"
print ""
for line in open("doc/header.txt"):
print line[:-1]
差异被折叠。
import unittest
from type import *
# todo: test generic
if __name__ == '__main__':
unittest.main()
import unittest, os, sys, traceback
if __name__ == '__main__':
def printUsage():
print >>sys.stderr, "Bad argument: ",sys.argv
print >>sys.stderr, "only --debug is supported"
sys.exit(1)
debugparam=""
if len(sys.argv)==2:
if sys.argv[1]=="--debug":
debugparam="--debug"
sys.argv.remove(debugparam)
else:
printUsage()
elif len(sys.argv)>2:
printUsage()
suite = None
filenames = os.listdir('.')
for filename in filenames:
if filename[-3:] == '.py':
modname = filename[:-3]
if modname in ['__init__', 'autotest']: continue
#print >>sys.stderr, 'Loading', modname
try:
module = __import__(modname)
except Exception, e:
print >>sys.stderr, "===================================================="
print >>sys.stderr, "Failed to load module %s" % modname
print >>sys.stderr, "===================================================="
traceback.print_exc()
print >>sys.stderr, "===================================================="
continue
tests = unittest.TestLoader().loadTestsFromModule(module)
if tests.countTestCases() > 0:
print >>sys.stderr, 'Testing', modname
if suite is None:
suite = tests
else:
suite.addTests(tests)
if debugparam:
suite.debug()
else:
unittest.TextTestRunner(verbosity=1).run(suite)
======
Theano
======
-------------------------------------------------------------------
A python library for manipulating and evaluating matrix expressions
-------------------------------------------------------------------
Theano is a library in Python, built to evaluate complicated
expressions (especially matrix-valued ones) as quickly as possible.
It was written at LISA_ to explore techniques for machine learning.
Our project uses the name to honour the ancient Greek mathematician.
--------------------------------------------------------------------------------
.. _not in the normal sense: :wiki:`WhatIsTheano`
Overview
========
**To get up & running quickly** see README_.
All **documentation** can be reached from the `Theano Project Documentation Overview`_.
As developers of an open source project, we rely on **feedback** for
determining what features to implement, and what documentation needs to be
improved. The best forum for feedback is the theano-users_ mailing list.
All **discussion** about theano also takes place on the theano-users_ mailing list.
If you find a **bug**, please file a `bug report`_ or send email to
the theano-users_ mailing list. **Patch** submissions should be
sent to theano-dev_.
We welcome all kinds of **contributions**. Our `task list`_ is
full of interesting ideas awaiting a champion. If you have any
questions regarding how to extend Theano, please feel free to ask on
the Theano-dev_ mailing list.
Theano is in active development and should be considered **experimental**.
APIs are subject to change at any time.
Download
========
We recommend that you use the `latest snapshot`_,
Better yet, use `mercurial`_ to keep your installation fresh.
The snapshots usually contain *more features* and *fewer bugs* than the
"official" releases |---| they're not only for developers!
.. class:: credits
Project by Mercurial_ and TRAC_.
Powered by Python_ and SciPy_.
Coded at the LISA_ lab.
.. class:: hidden
Google should index the mailing lists:
`theano-users <http://groups.google.com/group/theano-users?pli=1>`__,
and
`theano-dev <http://groups.google.com/group/theano-dev?pli=1>`__.
.. |---| unicode:: U+02014 .. em dash
:trim:
.. _latest snapshot: http://pylearn.org/hg/theano/archive/tip.tar.gz
.. _bug report: http://lgcm.iro.umontreal.ca/theano/newticket
.. _theano-users: http://groups.google.com/group/theano-users?pli=1
.. _theano-dev: http://groups.google.com/group/theano-dev?pli=1
.. _reStructuredText: rst.html
.. _task list: http://lgcm.iro.umontreal.ca/theano/query?status=accepted&status=assigned&status=new&status=reopened&group=milestone&max=200&col=id&col=summary&col=status&col=owner&col=type&col=priority&col=component&col=time&report=9&order=priority
.. _README: README.html
.. _Quick-Start: README.html#quick-start
.. _Theano Project Documentation Overview: doc/index.html
.. _Mercurial: http://www.selenic.com/mercurial/wiki/
.. _docutils: http://docutils.sourceforge.net
.. _epydoc: http://epydoc.sourceforge.net/
.. _scipy: http://scipy.org/
.. _Python: http://www.python.org/
.. _TRAC: http://trac.edgewall.org/
.. _LISA: http://www.iro.umontreal.ca/rubrique.php3?id_rubrique=27
.. |TRAC| image:: http://www.edgewall.org/gfx/trac_logo.png
:target: http://www.edgewall.org/
:alt: Trac Logo
:align: middle
:class: borderless
:width: 193
:height: 32
.. |Python| image:: python.png
:alt: Python Logo
:align: middle
:class: borderless
:width: 193
:height: 32
.. |LISA| image:: http://www.iro.umontreal.ca/images/neurone_chip2.jpg
:target: http://www.iro.umontreal.ca/rubrique.php3?id_rubrique=27
:width: 193
:height: 32
:alt: LISA Logo
:align: middle
:class: borderless
.. header:: |THEANO| - README_ - Download_ - Documentation_ - Wiki_ - `Task List`_
.. _Download: README.html#downloading-theano
.. _Documentation: doc/index.html
.. _Wiki: http://pylearn.org/theano
.. |THEANO| image:: http://lgcm.iro.umontreal.ca/theano/chrome/site/theano_logo.png
:target: http://pylearn.org/auto_theano
:alt: THEANO
:align: top
:class: borderless
:width: 60
:height: 18
..
Local Variables:
mode: indented-text
indent-tabs-mode: nil
sentence-end-double-space: t
fill-column: 70
End:
#!/bin/bash
mkdir -p html/api && mkdir -p html/doc
# this builds some stuff or something... basically makes the rest work properly
# for a reason I don't understand. -JB 20080924
python __init__.py
#runs if you called $./local.build_html.sh epydoc
if [ " $1" != " rst" ]; then
./epydoc --config local.epydoc
fi
#runs if you called $./local.build_html.sh rst
if [ " $1" != " epydoc" ]; then
APIRST2HTML=doc/apirst2html.py
EPYDOC_ARGS='--external-api=api --external-api-file=api:html/api/api-objects.txt --external-api-root=api:../api/ --link-stylesheet'
# install the stylesheets
HTML4CSS1='/usr/lib/python2.5/site-packages/docutils/writers/html4css1/html4css1.css'
cp $HTML4CSS1 html/html4css1.css
cp doc/colorful.css html/colorful.css
cp doc/style.css html/style.css
#generate the index & readme files
echo "$APIRST2HTML $EPYDOC_ARGS index.txt html/index.html..."
$APIRST2HTML -stg $EPYDOC_ARGS --stylesheet=style.css index.txt html/index.html
echo "$APIRST2HTML $EPYDOC_ARGS README.txt html/README.html..."
$APIRST2HTML -stg $EPYDOC_ARGS --stylesheet=style.css README.txt html/README.html
#generate the oplist in ReST format
echo "gen oplist..."
python gen_oplist.py > doc/oplist.txt
python gen_typelist.py > doc/typelist.txt
#generate html files for all the ReST documents in doc/
echo "gen doc/*.txt..."
for RST in doc/*.txt; do
BASENAME=$(basename $RST .txt)
echo "gen doc/$BASENAME.txt..."
$APIRST2HTML -stg $EPYDOC_ARGS --stylesheet=../style.css doc/$BASENAME.txt html/doc/$BASENAME.html
done
fi
差异被折叠。
## PENDING REWRITE OF opt.py
import unittest, os, sys, traceback
if __name__ == '__main__':
def printUsage():
print >>sys.stderr, "Bad argument: ",sys.argv
print >>sys.stderr, "only --debug is supported"
sys.exit(1)
debugparam=""
if len(sys.argv)==2:
if sys.argv[1]=="--debug":
debugparam="--debug"
sys.argv.remove(debugparam)
else:
printUsage()
elif len(sys.argv)>2:
printUsage()
suite = None
filenames = os.listdir('.')
for filename in filenames:
if filename[-3:] == '.py':
modname = filename[:-3]
if modname in ['__init__', 'autotest']: continue
#print >>sys.stderr, 'Loading', modname
try:
module = __import__(modname)
except Exception, e:
if 'relative import' not in e.message:
print >>sys.stderr, "===================================================="
print >>sys.stderr, "Failed to load module %s" % modname
print >>sys.stderr, "===================================================="
traceback.print_exc()
print >>sys.stderr, "===================================================="
continue
tests = unittest.TestLoader().loadTestsFromModule(module)
if tests.countTestCases() > 0:
print >>sys.stderr, 'Testing', modname
if suite is None:
suite = tests
else:
suite.addTests(tests)
if debugparam:
suite.debug()
else:
unittest.TextTestRunner(verbosity=1).run(suite)
# TODO: everything?
#!/usr/bin/python
#
# Call the command line interface for Epydoc.
#
# Make sure that we don't get confused between an epydoc.py script and
# the real epydoc package.
import sys, os.path, inspect
if os.path.exists(os.path.join(sys.path[0], 'epydoc.py')):
del sys.path[0]
import sys
import os
import inspect
from epydoc import docintrospecter
from epydoc.apidoc import RoutineDoc
......@@ -55,10 +49,62 @@ def Op_to_RoutineDoc(op, routine_doc, module_name=None):
return routine_doc
docintrospecter.register_introspecter(
lambda value: getattr(value, '__epydoc_asRoutine', False),
Op_to_RoutineDoc,
priority=-1)
lambda value: getattr(value, '__epydoc_asRoutine', False),
Op_to_RoutineDoc,
priority=-1)
import getopt
from collections import defaultdict
if __name__ == '__main__':
throot = "/".join(sys.path[0].split("/")[:-1])
options = defaultdict(bool)
options.update(dict([x, y or True] for x, y in getopt.getopt(sys.argv[1:], 'o:', ['epydoc', 'rst', 'help'])[0]))
if options['--help']:
print 'Usage: %s [OPTIONS]' % sys.argv[0]
print ' -o <dir>: output the html files in the specified dir'
print ' --rst: only compile the doc (requires sphinx)'
print ' --epydoc: only compile the api documentation (requires epydoc)'
print ' --help: this help'
sys.exit(0)
options['--all'] = not (bool(options['--epydoc']) ^ bool(options['--rst']))
import gen_oplist
print 'Generating oplist...'
gen_oplist.print_file(open('%s/doc/doc/oplist.txt' % throot, 'w'))
print 'oplist done!'
import gen_typelist
print 'Generating typelist...'
gen_typelist.print_file(open('%s/doc/doc/typelist.txt' % throot, 'w'))
print 'typelist done!'
def mkdir(path):
try:
os.mkdir(path)
except OSError:
pass
outdir = options['-o'] or (throot + '/html')
mkdir(outdir)
os.chdir(outdir)
mkdir("doc")
mkdir("api")
if options['--all'] or options['--epydoc']:
from epydoc.cli import cli
sys.path[0:0] = throot
sys.argv[:] = ['', '--config', '%s/doc/api/epydoc.conf' % throot, '-o', 'api']
cli()
# os.system("epydoc --config doc/api/epydoc.conf -o html/api")
if options['--all'] or options['--rst']:
import sphinx
sys.path[0:0] = [os.path.join(throot, 'doc')]
sphinx.main(['', '-E', os.path.join(throot, 'doc'), '.'])
from epydoc.cli import cli
cli()
"""script to generate doc/oplist.txt, which compiles to :doc:`oplist`. """
__docformat__ = "restructuredtext en"
import sys
import gof
import sys, os
theano_path = os.path.realpath("%s/.." % sys.path[0])
sys.path[0:0] = [theano_path]
def print_title(title_string, under_char, over_char=''):
from theano import gof
def print_title(file, title_string, under_char, over_char=''):
l = len(title_string)
if over_char:
print over_char * l
print >>file, over_char * l
print title_string
print >>file, title_string
if under_char:
print under_char * l
print >>file, under_char * l
print ""
print >>file, ""
def print_hline():
print '-' * 80
def print_hline(file):
print >>file, '-' * 80
class Entry:
"""Structure for generating the oplist file"""
......@@ -29,9 +32,9 @@ class Entry:
def __init__(self, symbol, name, current_module):
self.symbol = symbol
self.name = name
self.module = symbol.__module__ #current_module.__name__ # symbol.__module__
self.module = symbol.__module__ # current_module.__name__ # symbol.__module__
self.docstring = symbol.__doc__
self.tags = ['module:%s' % current_module.__name__] + getattr(symbol, '__oplist_tags', [])
self.tags = ['%s' % current_module.__name__] + getattr(symbol, '__oplist_tags', [])
def mini_desc(self, maxlen=50):
"""Return a short description of the op"""
......@@ -73,7 +76,7 @@ class Entry:
else:
return "%s ..."% chomp(self.docstring[:maxlen-minmax])
apilink = property(lambda self: ":api:`%s.%s`"% (self.module, self.name))
apilink = property(lambda self: ":api:`%s <%s.%s>`"% (self.name, self.module, self.name))
"""Return the ReST link into the epydoc of this symbol"""
class EntryOp(Entry):
......@@ -94,15 +97,25 @@ class EntryConstructor(Entry):
Entry.__init__(self, symbol, name, module)
def search_entries(module_list):
ops = []
constructors = []
def search_entries(module_list, ops = None, constructors = None, seen = None):
if ops is None: ops = []
if constructors is None: constructors = []
if seen is None: seen = set()
modules = []
for module in module_list:
symbol_name_list = [s for s in dir(module) if not s[0] == '_']
for symbol_name in symbol_name_list:
symbol = getattr(module, symbol_name)
try:
if symbol in seen:
continue
seen.add(symbol)
except TypeError:
pass
if type(symbol) == type(module): # module
modules.append(symbol)
try:
ops.append(EntryOp(symbol, symbol_name, module))
except TypeError:
......@@ -111,56 +124,68 @@ def search_entries(module_list):
except TypeError:
pass
for symbol in modules:
search_entries([symbol], ops, constructors, seen)
return ops, constructors
def print_entries(ops, constructors):
def print_entries(file, ops, constructors):
tags = {}
for o in ops + constructors:
for t in o.tags:
tags.setdefault(t, []).append(o)
for t in tags:
print_title(t, '=')
print_title(file, t, '=')
tagged_ops = [op for op in tags[t] if isinstance(op, EntryOp)]
if len(tagged_ops):
print_title('Op Classes', '-')
print_title(file, 'Op Classes', '-')
for op in tagged_ops:
print "- %s" % op.apilink
print " %s" % op.mini_desc()
print ""
print >>file, "- %s" % op.apilink
print >>file, " %s" % op.mini_desc()
print >>file, ""
tagged_ops = [op for op in tags[t] if isinstance(op, EntryConstructor)]
if len(tagged_ops):
print_title('Op Constructors', '-')
print_title(file, 'Op Constructors', '-')
for op in tagged_ops:
print "- %s" % op.apilink
print " %s" % op.mini_desc()
print ""
print >>file, "- %s" % op.apilink
print >>file, " %s" % op.mini_desc()
print >>file, ""
if __name__ == "__main__":
"""Generate the op list"""
import scalar, sparse, tensor
def print_file(file):
print_title("Op List", "~", "~")
print """
print_title(file, "Op List", "~", "~")
print >>file, """
This page lists the `Op Classes` and `constructors` that are provided by the Theano library.
`Op Classes` drive from :api:`Op`, whereas `constructors` are typically `Op Class` instances, but may be true Python functions.
In the future, this list may distinguish `constructors` that are Op instances from true Python functions.
"""
print_hline()
print ""
print ".. contents:: "
print ""
print_hline(file)
print >>file, ""
print >>file, ".. contents:: "
print >>file, ""
ops, constructors = search_entries([theano])
print_entries(file, ops, constructors)
print >>file, ""
ops, constructors = search_entries([scalar, sparse, tensor])
import theano
if __name__ == "__main__":
"""Generate the op list"""
print_entries(ops, constructors)
if len(sys.argv) >= 2:
file = open(sys.argv[1], 'w')
else:
file = sys.stdout
print ""
print_file(file)
for line in open("doc/header.txt"):
print line[:-1]
from gen_oplist import print_title, print_hline
def print_file(file):
print_title(file, "Type List", "~", "~")
print >>file, "*THIS PAGE IS A PLACEHOLDER: WRITEME*"
print >>file, ""
print_hline(file)
print >>file, ""
print >>file, ".. contents::"
print >>file, ""
print_title(file, "Type Classes", '=')
print >>file, "- scalar.Scalar\n"
print >>file, "- tensor.Tensor\n"
print >>file, "- sparse.Sparse\n"
print_title(file, "Type Instances", '=')
print >>file, "- scalar.int8\n"
print >>file, "- tensor.lvector\n"
print >>file, "- sparse.??\n"
print >>file, ""
if __name__ == '__main__':
if len(sys.argv) >= 2:
file = open(sys.argv[1], 'w')
else:
file = sys.stdout
print_file(file)
from ez_setup import use_setuptools
use_setuptools()
from setuptools import setup, find_packages, #Extension, Library
setup(name="Theano",
version="0.1",
description="Theano",
long_description="""Machine learning toolkit""",
author="LISA",
author_email="lisa@iro.umontreal.ca",
packages=find_packages(exclude='tests'),
#scripts=['pygmy/audio/calc_feat.py'],
)
import unittest, os, sys, traceback
if __name__ == '__main__':
def printUsage():
print >>sys.stderr, "Bad argument: ",sys.argv
print >>sys.stderr, "only --debug is supported"
sys.exit(1)
debugparam=""
if len(sys.argv)==2:
if sys.argv[1]=="--debug":
debugparam="--debug"
sys.argv.remove(debugparam)
else:
printUsage()
elif len(sys.argv)>2:
printUsage()
suite = None
filenames = os.listdir('.')
for filename in filenames:
if filename[-3:] == '.py':
modname = filename[:-3]
if modname in ['__init__', 'autotest']: continue
#print >>sys.stderr, 'Loading', modname
try:
module = __import__(modname)
except Exception, e:
if 'relative import' not in e.message:
print >>sys.stderr, "===================================================="
print >>sys.stderr, "Failed to load module %s" % modname
print >>sys.stderr, "===================================================="
traceback.print_exc()
print >>sys.stderr, "===================================================="
continue
tests = unittest.TestLoader().loadTestsFromModule(module)
if tests.countTestCases() > 0:
print >>sys.stderr, 'Testing', modname
if suite is None:
suite = tests
else:
suite.addTests(tests)
if debugparam:
suite.debug()
else:
unittest.TextTestRunner(verbosity=1).run(suite)
import unittest, os, sys, traceback
if __name__ == '__main__':
def printUsage():
print >>sys.stderr, "Bad argument: ",sys.argv
print >>sys.stderr, "only --debug is supported"
sys.exit(1)
debugparam=""
if len(sys.argv)==2:
if sys.argv[1]=="--debug":
debugparam="--debug"
sys.argv.remove(debugparam)
else:
printUsage()
elif len(sys.argv)>2:
printUsage()
suite = None
filenames = os.listdir('.')
for filename in filenames:
if filename[-3:] == '.py':
modname = filename[:-3]
if modname in ['__init__', 'autotest']: continue
#print >>sys.stderr, 'Loading', modname
try:
module = __import__(modname)
except Exception, e:
if 'relative import' not in e.message:
print >>sys.stderr, "===================================================="
print >>sys.stderr, "Failed to load module %s" % modname
print >>sys.stderr, "===================================================="
traceback.print_exc()
print >>sys.stderr, "===================================================="
continue
tests = unittest.TestLoader().loadTestsFromModule(module)
if tests.countTestCases() > 0:
print >>sys.stderr, 'Testing', modname
if suite is None:
suite = tests
else:
suite.addTests(tests)
if debugparam:
suite.debug()
else:
unittest.TextTestRunner(verbosity=1).run(suite)
......@@ -258,9 +258,9 @@ class Function(object):
# Check if inputs are missing or if inputs were set more than once
for c in self.input_storage:
if c.required and not c.provided:
raise TypeError("Missing required input: %s" % self.inv_finder[c].result)
raise TypeError("Missing required input: %s" % getattr(self.inv_finder[c], 'result', self.inv_finder[c]))
if c.provided > 1:
raise TypeError("Multiple values for input: %s" % self.inv_finder[c].result)
raise TypeError("Multiple values for input: %s" % getattr(self.inv_finder[c], 'result', self.inv_finder[c]))
# Do the actual work
self.fn()
outputs = [x.data for x in self.output_storage]
......@@ -351,6 +351,7 @@ class SanityCheckFunction(Function):
### FunctionMaker
###
NODEFAULT = ['NODEFAULT']
class FunctionMaker(object):
@staticmethod
......@@ -404,6 +405,7 @@ class FunctionMaker(object):
in the graph from the inputs to the outputs
"""
# Handle the case where inputs and/or outputs is a single Result (not in a list)
unpack_single = False
if not isinstance(outputs, (list, tuple)):
......@@ -414,7 +416,7 @@ class FunctionMaker(object):
# Wrap them in In or Out instances if needed.
inputs, outputs = map(self.wrap_in, inputs), map(self.wrap_out, outputs)
_inputs = gof.graph.inputs([o.result for o in outputs])
_inputs = gof.graph.inputs([o.result for o in outputs] + [i.update for i in inputs if getattr(i, 'update', False)])
indices = [[input] + self.expand_in(input, _inputs) for input in inputs]
expanded_inputs = reduce(list.__add__, [list(z) for x, y, z in indices], [])
......@@ -482,7 +484,17 @@ class FunctionMaker(object):
# one storage unit. The indices and subinputs lists represent which
# of the kit's inputs are active in this graph, so we make as many
# storage units as needed
input_storage += [[None] for i in indices]
if isinstance(default, (list, tuple)) \
and all(isinstance(x, gof.Container) for x in default):
if len(default) == len(indices):
input_storage += [x.storage for x in default]
elif len(default) > len(indices):
input_storage += [default[i].storage for i in indices]
else:
raise ValueError('Not enough storage for SymbolicInputKit', input, indices, default)
default = NODEFAULT
else:
input_storage += [[None] for i in indices]
else:
# Normal case: one new, independent storage unit
input_storage.append([None])
......@@ -496,6 +508,8 @@ class FunctionMaker(object):
# Even though a SymbolicInputKit represents more than one input,
# we still only have one entry for the defaults list.
if isinstance(input, SymbolicInputKit):
if default is NODEFAULT:
_defaults.append((False, False, None))
if default is None:
_defaults.append((True, True, None))
else:
......@@ -548,16 +562,22 @@ copy_reg.pickle(slice, _pickle_slice)
__checkers = []
def check_equal(x, y):
for checker in __checkers:
try:
return checker(x, y)
except:
continue
return x == y
#raise Exception('No checker for equality between %s and %s' % (x, y))
def register_checker(checker):
__checkers.insert(0, checker)
def check_equal_numpy(x, y):
"""
Returns True iff x and y are equal (checks the dtype and
shape if x and y are numpy.ndarray instances).
"""
if isinstance(x, numpy.ndarray) and isinstance(y, numpy.ndarray):
return x.dtype == y.dtype and x.shape == y.shape and numpy.any(abs(x - y) < 1e-10)
else:
return x == y
def function(inputs, outputs, mode='FAST_RUN', accept_inplace = False):
"""
......@@ -663,7 +683,7 @@ def function(inputs, outputs, mode='FAST_RUN', accept_inplace = False):
for default in defaults]
makers = [FunctionMaker(inputs, outputs, m, accept_inplace = accept_inplace) for m in mode[1:]]
fns = [maker.create(dup_defaults(), trustme = True) for maker in makers]
builder = partial(SanityCheckFunction, fns, check_equal_numpy)
builder = partial(SanityCheckFunction, fns, check_equal)
maker1 = FunctionMaker(inputs, outputs, mode[0], accept_inplace = accept_inplace, function_builder = builder)
fn = maker1.create(defaults)
else:
......
......@@ -99,6 +99,8 @@ class SymbolicInputKit(object):
except ValueError:
pass
ret.sort()
if not ret:
return [[], []]
return zip(*ret)
......
......@@ -19,53 +19,7 @@ import graph
import link
import utils
def set_compiledir(path=None):
"""Set the directory into which theano will compile code objects
@param path: an absolute path or relative path. An argument of None will
trigger one of two default paths: firstly an environment variable called
'THEANO_COMPILEDIR' will be sought; failing that, an architecture-specific
directory will be chosen within $HOME/.theano.
@type path: string or None
@return: None
@note: This function will create the path (recursively) as a folder if it
is not present, not readable, or not writable. New folders will be created
with mode 0700.
"""
# N.B. The path is stored as an attribute of this function
if path is None:
# we need to set the default, which can come from one of two places
if os.getenv('THEANO_COMPILEDIR'):
path = os.getenv('THEANO_COMPILEDIR')
else:
platform_id = platform.platform() + '-' + platform.processor()
platform_id = re.sub("[\(\)\s]+", "_", platform_id)
path = os.path.join(os.getenv('HOME'), '.theano', 'compiledir_'+platform_id)
if not os.access(path, os.R_OK | os.W_OK):
os.makedirs(path, 7<<6) #read-write-execute for this user only
# PROBLEM: sometimes the first approach based on os.system('touch')
# returned -1 for an unknown reason; the alternate approach here worked
# in all cases... it was weird.
open(os.path.join(path, '__init__.py'), 'w').close()
set_compiledir.compiledir = path
def get_compiledir():
"""Return the directory where theano code objects should be compiled
@rtype: string
"""
if not hasattr(set_compiledir, 'compiledir'):
set_compiledir()
return set_compiledir.compiledir
from compiledir import *
class CodeBlock:
"""WRITEME
......
import os
import platform
import re
def set_compiledir(path=None):
"""Set the directory into which theano will compile code objects
@param path: an absolute path or relative path. An argument of None will
trigger one of two default paths: firstly an environment variable called
'THEANO_COMPILEDIR' will be sought; failing that, an architecture-specific
directory will be chosen within $HOME/.theano.
@type path: string or None
@return: None
@note: This function will create the path (recursively) as a folder if it
is not present, not readable, or not writable. New folders will be created
with mode 0700.
"""
# N.B. The path is stored as an attribute of this function
if path is None:
# we need to set the default, which can come from one of two places
if os.getenv('THEANO_COMPILEDIR'):
path = os.getenv('THEANO_COMPILEDIR')
else:
platform_id = platform.platform() + '-' + platform.processor()
platform_id = re.sub("[\(\)\s]+", "_", platform_id)
path = os.path.join(os.getenv('HOME'), '.theano', 'compiledir_'+platform_id)
if not os.access(path, os.R_OK | os.W_OK):
os.makedirs(path, 7<<6) #read-write-execute for this user only
# PROBLEM: sometimes the first approach based on os.system('touch')
# returned -1 for an unknown reason; the alternate approach here worked
# in all cases... it was weird.
open(os.path.join(path, '__init__.py'), 'w').close()
set_compiledir.compiledir = path
def get_compiledir():
"""Return the directory where theano code objects should be compiled
@rtype: string
"""
if not hasattr(set_compiledir, 'compiledir'):
set_compiledir()
return set_compiledir.compiledir
from compiledir import *
import sys
try:
sys.path.append(get_compiledir())
from cutils_ext import *
except ImportError:
......@@ -27,6 +33,5 @@ except ImportError:
fun =weave.ext_tools.ext_function('run_cthunk', single_runner, ['cthunk'])
fun.customize.add_extra_compile_arg('--permissive')
mod.add_function(fun)
mod.compile()
mod.compile(location = get_compiledir())
from cutils_ext import *
......@@ -111,7 +111,19 @@ class Linker(object):
class Container(object):
"""WRITEME
"""
def __init__(self, r, storage, readonly = False, strict = False, name = None):
"""WRITEME
:Parameters:
`r`:
`storage`:
`readonly`:
`strict`:
`name`:
"""
if not isinstance(storage, list) or not len(storage) >= 1:
raise TypeError("storage must be a list of length at least one")
#self.r = r
......
import unittest
from link import PerformLinker, Profiler
from cc import *
from type import Type
from graph import Result, Apply, Constant
from op import Op
import env
import toolbox
from theano.gof.link import PerformLinker, Profiler
from theano.gof.cc import *
from theano.gof.type import Type
from theano.gof.graph import Result, Apply, Constant
from theano.gof.op import Op
from theano.gof import env
from theano.gof import toolbox
def as_result(x):
assert isinstance(x, Result)
......@@ -135,77 +135,76 @@ def Env(inputs, outputs):
return e
class _test_CLinker(unittest.TestCase):
def test_straightforward(self):
x, y, z = inputs()
e = add(mul(add(x, y), div(x, y)), sub(sub(x, y), z))
lnk = CLinker().accept(Env([x, y, z], [e]))
fn = lnk.make_function()
self.failUnless(fn(2.0, 2.0, 2.0) == 2.0)
# def test_orphan(self):
# x, y, z = inputs()
# z = Constant(tdouble, 4.12345678)
# e = add(mul(add(x, y), div(x, y)), sub(sub(x, y), z))
# lnk = CLinker(Env([x, y], [e]))
# fn = lnk.make_function()
# self.failUnless(abs(fn(2.0, 2.0) + 0.12345678) < 1e-9)
# print lnk.code_gen()
# self.failUnless("4.12345678" not in lnk.code_gen()) # we do not expect the number to be inlined
def test_literal_inlining(self):
x, y, z = inputs()
z = Constant(tdouble, 4.12345678)
e = add(mul(add(x, y), div(x, y)), sub(sub(x, y), z))
lnk = CLinker().accept(Env([x, y], [e]))
fn = lnk.make_function()
self.failUnless(abs(fn(2.0, 2.0) + 0.12345678) < 1e-9)
self.failUnless("4.12345678" in lnk.code_gen()) # we expect the number to be inlined
def test_single_node(self):
x, y, z = inputs()
node = add.make_node(x, y)
lnk = CLinker().accept(Env(node.inputs, node.outputs))
fn = lnk.make_function()
self.failUnless(fn(2.0, 7.0) == 9)
def test_dups(self):
# Testing that duplicate inputs are allowed.
x, y, z = inputs()
e = add(x, x)
lnk = CLinker().accept(Env([x, x], [e]))
fn = lnk.make_function()
self.failUnless(fn(2.0, 2.0) == 4)
# note: for now the behavior of fn(2.0, 7.0) is undefined
def test_dups_inner(self):
# Testing that duplicates are allowed inside the graph
x, y, z = inputs()
e = add(mul(y, y), add(x, z))
lnk = CLinker().accept(Env([x, y, z], [e]))
fn = lnk.make_function()
self.failUnless(fn(1.0, 2.0, 3.0) == 8.0)
################
# Test CLinker #
################
def test_clinker_straightforward():
x, y, z = inputs()
e = add(mul(add(x, y), div(x, y)), sub(sub(x, y), z))
lnk = CLinker().accept(Env([x, y, z], [e]))
fn = lnk.make_function()
assert fn(2.0, 2.0, 2.0) == 2.0
def test_clinker_literal_inlining():
x, y, z = inputs()
z = Constant(tdouble, 4.12345678)
e = add(mul(add(x, y), div(x, y)), sub(sub(x, y), z))
lnk = CLinker().accept(Env([x, y], [e]))
fn = lnk.make_function()
assert abs(fn(2.0, 2.0) + 0.12345678) < 1e-9
code = lnk.code_gen()
print "=== Code generated ==="
print code
assert "4.12345678" in code # we expect the number to be inlined
def test_clinker_single_node():
x, y, z = inputs()
node = add.make_node(x, y)
lnk = CLinker().accept(Env(node.inputs, node.outputs))
fn = lnk.make_function()
assert fn(2.0, 7.0) == 9
def test_clinker_dups():
# Testing that duplicate inputs are allowed.
x, y, z = inputs()
e = add(x, x)
lnk = CLinker().accept(Env([x, x], [e]))
fn = lnk.make_function()
assert fn(2.0, 2.0) == 4
# note: for now the behavior of fn(2.0, 7.0) is undefined
def test_clinker_dups_inner():
# Testing that duplicates are allowed inside the graph
x, y, z = inputs()
e = add(mul(y, y), add(x, z))
lnk = CLinker().accept(Env([x, y, z], [e]))
fn = lnk.make_function()
assert fn(1.0, 2.0, 3.0) == 8.0
class _test_OpWiseCLinker(unittest.TestCase):
######################
# Test OpWiseCLinker #
######################
def test_opwiseclinker_straightforward():
x, y, z = inputs()
e = add(mul(add(x, y), div(x, y)), sub(sub(x, y), z))
lnk = OpWiseCLinker().accept(Env([x, y, z], [e]))
fn = lnk.make_function()
assert fn(2.0, 2.0, 2.0) == 2.0
def test_opwiseclinker_constant():
x, y, z = inputs()
x = Constant(tdouble, 7.2, name = 'x')
e = add(mul(x, y), mul(y, z))
lnk = OpWiseCLinker().accept(Env([y, z], [e]))
fn = lnk.make_function()
res = fn(1.5, 3.0)
assert res == 15.3
def test_straightforward(self):
x, y, z = inputs()
e = add(mul(add(x, y), div(x, y)), sub(sub(x, y), z))
lnk = OpWiseCLinker().accept(Env([x, y, z], [e]))
fn = lnk.make_function()
self.failUnless(fn(2.0, 2.0, 2.0) == 2.0)
def test_constant(self):
x, y, z = inputs()
x = Constant(tdouble, 7.2, name = 'x')
e = add(mul(x, y), mul(y, z))
lnk = OpWiseCLinker().accept(Env([y, z], [e]))
fn = lnk.make_function()
res = fn(1.5, 3.0)
self.failUnless(res == 15.3, res)
class MyExc(Exception):
......@@ -215,49 +214,34 @@ def _my_checker(x, y):
raise MyExc("Output mismatch.", {'performlinker': x[0], 'clinker': y[0]})
class _test_DualLinker(unittest.TestCase):
def test_straightforward(self):
x, y, z = inputs()
e = add(mul(x, y), mul(y, z)) # add and mul are correct in C and in Python
lnk = DualLinker(checker = _my_checker).accept(Env([x, y, z], [e]))
fn = lnk.make_function()
res = fn(7.2, 1.5, 3.0)
self.failUnless(res == 15.3, res)
def test_mismatch(self):
x, y, z = inputs()
e = sub(mul(x, y), mul(y, z)) # sub is correct in C but erroneous in Python
g = Env([x, y, z], [e])
lnk = DualLinker(checker = _my_checker).accept(g)
fn = lnk.make_function()
self.failUnless(CLinker().accept(g).make_function()(1.0, 2.0, 3.0) == -4.0) # good
self.failUnless(OpWiseCLinker().accept(g).make_function()(1.0, 2.0, 3.0) == -4.0) # good
self.failUnless(PerformLinker().accept(g).make_function()(1.0, 2.0, 3.0) == -10.0) # (purposely) wrong
try:
# this runs OpWiseCLinker and PerformLinker in parallel and feeds
# results of matching operations to _my_checker to verify that they
# are the same.
res = fn(1.0, 2.0, 3.0)
self.fail()
except MyExc, e:
pass
else:
self.fail()
# def test_orphan(self):
# x, y, z = inputs()
# x = Constant(tdouble, 7.2, name = 'x')
# e = add(mul(x, y), mul(y, z)) # add and mul are correct in C and in Python
# lnk = DualLinker(Env([y, z], [e]), checker = _my_checker)
# fn = lnk.make_function()
# res = fn(1.5, 3.0)
# self.failUnless(res == 15.3, res)
if __name__ == '__main__':
unittest.main()
###################
# Test DualLinker #
###################
def test_duallinker_straightforward():
x, y, z = inputs()
e = add(mul(x, y), mul(y, z)) # add and mul are correct in C and in Python
lnk = DualLinker(checker = _my_checker).accept(Env([x, y, z], [e]))
fn = lnk.make_function()
res = fn(7.2, 1.5, 3.0)
assert res == 15.3
def test_duallinker_mismatch():
x, y, z = inputs()
e = sub(mul(x, y), mul(y, z)) # sub is correct in C but erroneous in Python
g = Env([x, y, z], [e])
lnk = DualLinker(checker = _my_checker).accept(g)
fn = lnk.make_function()
assert CLinker().accept(g).make_function()(1.0, 2.0, 3.0) == -4.0 # good
assert OpWiseCLinker().accept(g).make_function()(1.0, 2.0, 3.0) == -4.0 # good
assert PerformLinker().accept(g).make_function()(1.0, 2.0, 3.0) == -10.0 # (purposely) wrong
try:
# this runs OpWiseCLinker and PerformLinker in parallel and feeds
# results of matching operations to _my_checker to verify that they
# are the same.
res = fn(1.0, 2.0, 3.0)
raise Exception("An exception should have been raised here!")
except MyExc, e:
pass
import unittest
from theano.gof.type import Type
from theano.gof import graph
from theano.gof.graph import Result, Apply
from theano.gof.op import Op
from theano.gof.opt import *
from theano.gof import destroyhandler
from theano.gof.env import Env, InconsistencyError
from theano.gof.toolbox import ReplaceValidate
from copy import copy
PatternOptimizer = lambda p1, p2, ign=True: OpKeyOptimizer(PatternSub(p1, p2), ignore_newtrees=ign)
OpSubOptimizer = lambda op1, op2, fail=keep_going, ign=True: TopoOptimizer(OpSub(op1, op2), ignore_newtrees=ign, failure_callback = fail)
def as_result(x):
assert isinstance(x, Result)
return x
class MyType(Type):
def filter(self, data):
return data
def __eq__(self, other):
return isinstance(other, MyType)
def MyResult(name):
return Result(MyType(), None, None, name = name)
def MyValue(data):
return graph.Value(MyType(), data = data)
class MyOp(Op):
def __init__(self, nin, name, vmap = {}, dmap = {}, nout = 1, tolerate_same = []):
self.nin = nin
self.nout = nout
self.name = name
self.destroy_map = dmap
self.view_map = vmap
self.tolerate_same = tolerate_same
def make_node(self, *inputs):
assert len(inputs) == self.nin
inputs = map(as_result, inputs)
for input in inputs:
if not isinstance(input.type, MyType):
raise Exception("Error 1")
outputs = [MyResult(self.name + "_R") for i in xrange(self.nout)]
return Apply(self, inputs, outputs)
def __str__(self):
return self.name
sigmoid = MyOp(1, 'Sigmoid')
transpose_view = MyOp(1, 'TransposeView', vmap = {0: [0]})
add = MyOp(2, 'Add')
add_in_place = MyOp(2, 'AddInPlace', dmap = {0: [0]})
add_in_place_2 = MyOp(2, 'AddInPlace', dmap = {0: [0]}, tolerate_same = [(0, 1)])
dot = MyOp(2, 'Dot')
def inputs():
x = MyResult('x')
y = MyResult('y')
z = MyResult('z')
return x, y, z
_Env = Env
def Env(inputs, outputs, validate = True):
e = _Env(inputs, outputs)
e.extend(destroyhandler.DestroyHandler())
e.extend(ReplaceValidate())
if validate:
e.validate()
return e
class FailureWatch:
# when passed to OpSubOptimizer or PatternOptimizer, counts the number of failures
def __init__(self):
self.failures = 0
def __call__(self, exc, nav, pairs):
assert isinstance(exc, InconsistencyError)
self.failures += 1
def consistent(g):
print "Testing consistent:", g
try:
assert g.consistent()
except AssertionError:
print "Test failed! The graph was marked as NOT consistent."
raise
print "Test OK"
def inconsistent(g):
print "Testing NOT consistent:", g
try:
assert not g.consistent()
except AssertionError:
print "Test failed! The graph was marked as consistent."
raise
print "Test OK"
#################
# Test protocol #
#################
def test_misc():
x, y, z = inputs()
e = transpose_view(transpose_view(transpose_view(transpose_view(x))))
g = Env([x,y,z], [e])
consistent(g)
chk = g.checkpoint()
PatternOptimizer((transpose_view, (transpose_view, 'x')), 'x').optimize(g)
assert str(g) == "[x]"
new_e = add(x,y)
g.replace_validate(x, new_e)
assert str(g) == "[Add(x, y)]"
g.replace(new_e, dot(add_in_place(x,y), transpose_view(x)))
assert str(g) == "[Dot(AddInPlace(x, y), TransposeView(x))]"
inconsistent(g)
g.revert(chk)
consistent(g)
assert str(g) == "[TransposeView(TransposeView(TransposeView(TransposeView(x))))]"
######################
# Test protocol skip #
######################
def test_aliased_inputs_replacement():
x, y, z = inputs()
tv = transpose_view(x)
tvv = transpose_view(tv)
sx = sigmoid(x)
e = add_in_place(x, tv)
g = Env([x, y], [e], False)
inconsistent(g)
g.replace(tv, sx)
consistent(g)
g.replace(sx, tv)
inconsistent(g)
g.replace(tv, tvv)
inconsistent(g)
g.replace(tv, sx)
consistent(g)
def test_indestructible():
x, y, z = inputs()
x.tag.indestructible = True
x = copy(x)
assert x.tag.indestructible # checking if indestructible survives the copy!
e = add_in_place(x, y)
g = Env([x,y,z], [e], False)
inconsistent(g)
g.replace_validate(e, add(x, y))
consistent(g)
def test_usage_loop_through_views_2():
x, y, z = inputs()
e0 = transpose_view(transpose_view(sigmoid(x)))
e = dot(add_in_place(x,y), transpose_view(e0))
g = Env([x,y,z], [e])
consistent(g) # because sigmoid can do the copy
g.replace(e0, x)
inconsistent(g) # we cut off the path to the sigmoid
def test_destroyers_loop():
# AddInPlace(x, y) and AddInPlace(y, x) should not coexist
x, y, z = inputs()
e1 = add(x, y)
e2 = add(y, x)
g = Env([x,y,z], [e1, e2])
chk = g.checkpoint()
consistent(g)
g.replace_validate(e1, add_in_place(x, y))
consistent(g)
try:
g.replace_validate(e2, add_in_place(y, x))
raise Exception("Shouldn't have reached this point.")
except InconsistencyError:
pass
consistent(g)
g.revert(chk)
g.replace_validate(e2, add_in_place(y, x))
consistent(g)
try:
g.replace_validate(e1, add_in_place(x, y))
raise Exception("Shouldn't have reached this point.")
except InconsistencyError:
pass
consistent(g)
########
# Misc #
########
def test_aliased_inputs():
x, y, z = inputs()
e = add_in_place(x, x)
g = Env([x], [e], False)
inconsistent(g)
def test_aliased_inputs2():
x, y, z = inputs()
e = add_in_place(x, transpose_view(x))
g = Env([x], [e], False)
inconsistent(g)
def test_aliased_inputs_tolerate():
x, y, z = inputs()
e = add_in_place_2(x, x)
g = Env([x], [e], False)
consistent(g)
def test_aliased_inputs_tolerate2():
x, y, z = inputs()
e = add_in_place_2(x, transpose_view(x))
g = Env([x], [e], False)
inconsistent(g)
def test_indestructible_through_views():
x, y, z = inputs()
x.tag.indestructible = True
tv = transpose_view(x)
e = add_in_place(tv, y)
g = Env([x,y,z], [e], False)
inconsistent(g)
g.replace_validate(tv, sigmoid(x))
consistent(g)
def test_indirect():
x, y, z = inputs()
e0 = add_in_place(x, y)
e = dot(sigmoid(e0), transpose_view(x))
g = Env([x,y,z], [e], False)
inconsistent(g)
new_e0 = add(x, y)
g.replace(e0, new_e0)
consistent(g)
g.replace(new_e0, add_in_place(x, y))
inconsistent(g)
def test_indirect_2():
x, y, z = inputs()
e0 = transpose_view(x)
e = dot(sigmoid(add_in_place(x, y)), e0)
g = Env([x,y,z], [e], False)
inconsistent(g)
new_e0 = add(e0, y)
g.replace(e0, new_e0)
consistent(g)
def test_long_destroyers_loop():
x, y, z = inputs()
e = dot(dot(add_in_place(x,y), add_in_place(y,z)), add(z,x))
g = Env([x,y,z], [e])
consistent(g)
OpSubOptimizer(add, add_in_place).optimize(g)
consistent(g)
assert str(g) != "[Dot(Dot(AddInPlace(x, y), AddInPlace(y, z)), AddInPlace(z, x))]" # we don't want to see that!
e2 = dot(dot(add_in_place(x,y), add_in_place(y,z)), add_in_place(z,x))
try:
g2 = Env(*graph.clone([x,y,z], [e2]))
raise Exception("Shouldn't have reached this point.")
except InconsistencyError:
pass
def test_misc_2():
x, y, z = inputs()
tv = transpose_view(x)
e = add_in_place(x, tv)
g = Env([x,y], [e], False)
inconsistent(g)
g.replace(tv, x)
inconsistent(g)
def test_multi_destroyers():
x, y, z = inputs()
e = add(add_in_place(x, y), add_in_place(x, y))
try:
g = Env([x,y,z], [e])
raise Exception("Shouldn't have reached this point.")
except InconsistencyError, e:
pass
def test_multi_destroyers_through_views():
x, y, z = inputs()
e = dot(add(transpose_view(z), y), add(z, x))
g = Env([x,y,z], [e])
consistent(g)
fail = FailureWatch()
OpSubOptimizer(add, add_in_place, fail).optimize(g)
consistent(g)
assert fail.failures == 1 # should have succeeded once and failed once
def test_repair_destroy_path():
x, y, z = inputs()
e1 = transpose_view(transpose_view(x))
e2 = transpose_view(transpose_view(e1))
e3 = add_in_place(e2, y)
e4 = add_in_place(e1, z)
g = Env([x,y,z], [e3, e4], False)
inconsistent(g)
g.replace(e2, transpose_view(x))
inconsistent(g)
def test_usage_loop():
x, y, z = inputs()
g = Env([x,y,z], [dot(add_in_place(x, z), x)], False)
inconsistent(g)
OpSubOptimizer(add_in_place, add).optimize(g) # replace add_in_place with add
consistent(g)
def test_usage_loop_through_views():
x, y, z = inputs()
aip = add_in_place(x, y)
e = dot(aip, transpose_view(x))
g = Env([x,y,z], [e], False)
inconsistent(g)
g.replace_validate(aip, add(x, z))
consistent(g)
def test_usage_loop_insert_views():
x, y, z = inputs()
e = dot(add_in_place(x, add(y, z)), sigmoid(sigmoid(sigmoid(sigmoid(sigmoid(x))))))
g = Env([x,y,z], [e])
consistent(g)
fail = FailureWatch()
OpSubOptimizer(sigmoid, transpose_view, fail).optimize(g)
consistent(g)
assert fail.failures == 1 # it must keep one sigmoid in the long sigmoid chain
def test_value_repl():
x, y, z = inputs()
sy = sigmoid(y)
e = add_in_place(x, sy)
g = Env([x,y], [e], False)
consistent(g)
g.replace(sy, MyValue("abc"))
consistent(g)
def test_value_repl_2():
x, y, z = inputs()
sy = sigmoid(y)
e = add_in_place(x, sy)
g = Env([x,y], [e], False)
consistent(g)
g.replace(sy, transpose_view(MyValue("abc")))
consistent(g)
from collections import deque
import unittest
from graph import *
from theano.gof.graph import *
from op import Op
from type import Type
from graph import Result
if 1:
testcase = unittest.TestCase
else:
testcase = object
realtestcase = unittest.TestCase
from theano.gof.op import Op
from theano.gof.type import Type
from theano.gof.graph import Result
def as_result(x):
......@@ -55,75 +47,31 @@ class MyOp(Op):
MyOp = MyOp()
##########
# inputs #
##########
# class MyResult(Result):
# def __init__(self, thingy):
# self.thingy = thingy
# Result.__init__(self, role = None )
# self.data = [self.thingy]
# def __eq__(self, other):
# return self.same_properties(other)
# def same_properties(self, other):
# return isinstance(other, MyResult) and other.thingy == self.thingy
# def __str__(self):
# return str(self.thingy)
# def __repr__(self):
# return str(self.thingy)
class TestInputs:
# class MyOp(Op):
# def __init__(self, *inputs):
# for input in inputs:
# if not isinstance(input, MyResult):
# raise Exception("Error 1")
# self.inputs = inputs
# self.outputs = [MyResult(sum([input.thingy for input in inputs]))]
class _test_inputs(testcase):
def test_straightforward(self):
def test_inputs(self):
r1, r2 = MyResult(1), MyResult(2)
node = MyOp.make_node(r1, r2)
assert inputs(node.outputs) == [r1, r2]
def test_deep(self):
def test_inputs_deep(self):
r1, r2, r5 = MyResult(1), MyResult(2), MyResult(5)
node = MyOp.make_node(r1, r2)
node2 = MyOp.make_node(node.outputs[0], r5)
i = inputs(node2.outputs)
self.failUnless(i == [r1, r2, r5], i)
# def test_unreached_inputs(self):
# r1, r2, r5 = MyResult(1), MyResult(2), MyResult(5)
# op = MyOp(r1, r2)
# op2 = MyOp(op.outputs[0], r5)
# try:
# # function doesn't raise if we put False instead of True
# ro = results_and_orphans([r1, r2, op2.outputs[0]], op.outputs, True)
# except Exception, e:
# if e[0] is results_and_orphans.E_unreached:
# return
# self.fail()
# class _test_orphans(testcase):
# def test_straightforward(self):
# r1, r2, r5 = MyResult(1), MyResult(2), MyResult(5)
# node = MyOp.make_node(r1, r2)
# node2 = MyOp.make_node(node.outputs[0], r5)
# orph = orphans([r1, r2], node2.outputs)
# self.failUnless(orph == [r5], orph)
assert i == [r1, r2, r5], i
#############
# as_string #
#############
class _test_as_string(testcase):
class X:
leaf_formatter = lambda self, leaf: str(leaf.type)
node_formatter = lambda self, node, argstrings: "%s(%s)" % (node.op,
......@@ -133,19 +81,22 @@ class _test_as_string(testcase):
return as_string(inputs, outputs,
leaf_formatter = self.leaf_formatter,
node_formatter = self.node_formatter)
class TestStr(X):
def test_straightforward(self):
def test_as_string(self):
r1, r2 = MyResult(1), MyResult(2)
node = MyOp.make_node(r1, r2)
s = self.str([r1, r2], node.outputs)
self.failUnless(s == ["MyOp(R1, R2)"], s)
assert s == ["MyOp(R1, R2)"]
def test_deep(self):
def test_as_string_deep(self):
r1, r2, r5 = MyResult(1), MyResult(2), MyResult(5)
node = MyOp.make_node(r1, r2)
node2 = MyOp.make_node(node.outputs[0], r5)
s = self.str([r1, r2, r5], node2.outputs)
self.failUnless(s == ["MyOp(MyOp(R1, R2), R5)"], s)
assert s == ["MyOp(MyOp(R1, R2), R5)"]
def test_multiple_references(self):
r1, r2, r5 = MyResult(1), MyResult(2), MyResult(5)
......@@ -161,16 +112,11 @@ class _test_as_string(testcase):
assert self.str(node2.inputs, node2.outputs) == ["MyOp(R3, R3)"]
class _test_clone(testcase):
leaf_formatter = lambda self, leaf: str(leaf.type)
node_formatter = lambda self, node, argstrings: "%s(%s)" % (node.op,
", ".join(argstrings))
#########
# clone #
#########
def str(self, inputs, outputs):
return as_string(inputs, outputs,
leaf_formatter = self.leaf_formatter,
node_formatter = self.node_formatter)
class TestClone(X):
def test_accurate(self):
r1, r2 = MyResult(1), MyResult(2)
......@@ -198,6 +144,11 @@ class _test_clone(testcase):
assert self.str(inputs(new_node.outputs), new_node.outputs) == ["MyOp(R7, R8)"]
assert self.str(inputs(node.outputs), node.outputs) == ["MyOp(MyOp(R1, R2), R5)"]
############
# toposort #
############
def prenode(obj):
if isinstance(obj, Result):
if obj.owner:
......@@ -205,79 +156,64 @@ def prenode(obj):
if isinstance(obj, Apply):
return obj.inputs
class _test_toposort(testcase):
def test0(self):
class TestToposort:
def test_0(self):
"""Test a simple graph"""
r1, r2, r5 = MyResult(1), MyResult(2), MyResult(5)
o = MyOp.make_node(r1, r2)
o2 = MyOp.make_node(o.outputs[0], r5)
all = general_toposort(o2.outputs, prenode)
self.failUnless(all == [r5, r2, r1, o, o.outputs[0], o2, o2.outputs[0]], all)
assert all == [r5, r2, r1, o, o.outputs[0], o2, o2.outputs[0]]
all = io_toposort([r5], o2.outputs)
self.failUnless(all == [o, o2], all)
assert all == [o, o2]
def test1(self):
def test_1(self):
"""Test a graph with double dependencies"""
r1, r2, r5 = MyResult(1), MyResult(2), MyResult(5)
o = MyOp.make_node(r1, r1)
o2 = MyOp.make_node(o.outputs[0], r5)
all = general_toposort(o2.outputs, prenode)
self.failUnless(all == [r5, r1, o, o.outputs[0], o2, o2.outputs[0]], all)
assert all == [r5, r1, o, o.outputs[0], o2, o2.outputs[0]]
def test2(self):
def test_2(self):
"""Test a graph where the inputs have owners"""
r1, r2, r5 = MyResult(1), MyResult(2), MyResult(5)
o = MyOp.make_node(r1, r1)
r2b = o.outputs[0]
o2 = MyOp.make_node(r2b, r2b)
all = io_toposort([r2b], o2.outputs)
self.failUnless(all == [o2], all)
assert all == [o2]
o2 = MyOp.make_node(r2b, r5)
all = io_toposort([r2b], o2.outputs)
self.failUnless(all == [o2], all)
assert all == [o2]
def test3(self):
def test_3(self):
"""Test a graph which is not connected"""
r1, r2, r3, r4 = MyResult(1), MyResult(2), MyResult(3), MyResult(4)
o0 = MyOp.make_node(r1, r2)
o1 = MyOp.make_node(r3, r4)
all = io_toposort([r1, r2, r3, r4], o0.outputs + o1.outputs)
self.failUnless(all == [o1,o0], all)
assert all == [o1,o0]
def test4(self):
def test_4(self):
"""Test inputs and outputs mixed together in a chain graph"""
r1, r2, r3, r4 = MyResult(1), MyResult(2), MyResult(3), MyResult(4)
o0 = MyOp.make_node(r1, r2)
o1 = MyOp.make_node(o0.outputs[0], r1)
all = io_toposort([r1, o0.outputs[0]], [o0.outputs[0], o1.outputs[0]])
self.failUnless(all == [o1], all)
assert all == [o1]
def test5(self):
def test_5(self):
"""Test when outputs have clients"""
r1, r2, r3, r4 = MyResult(1), MyResult(2), MyResult(3), MyResult(4)
o0 = MyOp.make_node(r1, r2)
o1 = MyOp.make_node(o0.outputs[0], r4)
all = io_toposort([], o0.outputs)
self.failUnless(all == [o0], all)
if __name__ == '__main__':
if 1:
#run all tests
unittest.main()
elif 1:
#load some TestCase classes
suite = unittest.TestLoader()
suite = suite.loadTestsFromTestCase(_test_toposort)
assert all == [o0]
#run just some of them
unittest.TextTestRunner(verbosity=2).run(suite)
else:
#run just a single test
_test_toposort('test0').debug()
from theano.gof import graph
from theano.gof.graph import Result, Apply, Constant
from theano.gof.type import Type
from theano.gof.op import Op
from theano.gof import env
from theano.gof import toolbox
import unittest
import graph
from graph import Result, Apply, Constant
from type import Type
from op import Op
import env
import toolbox
from link import *
from theano.gof.link import *
#from _test_result import Double
......@@ -78,7 +75,7 @@ def Env(inputs, outputs):
return e
class _test_PerformLinker(unittest.TestCase):
class TestPerformLinker:
def test_thunk(self):
x, y, z = inputs()
......@@ -105,14 +102,14 @@ class _test_PerformLinker(unittest.TestCase):
def test_input_output_same(self):
x, y, z = inputs()
fn = perform_linker(Env([x], [x])).make_function()
self.failUnless(1.0 is fn(1.0))
assert 1.0 is fn(1.0)
def test_input_dependency0(self):
x, y, z = inputs()
a,d = add(x,y), div(x,y)
e = mul(a,d)
fn = perform_linker(Env(*graph.clone([x, y, a], [e]))).make_function()
self.failUnless(fn(1.0,2.0,9.0) == 4.5)
assert fn(1.0,2.0,9.0) == 4.5
def test_skiphole(self):
x,y,z = inputs()
......@@ -120,14 +117,16 @@ class _test_PerformLinker(unittest.TestCase):
r = raise_err(a)
e = add(r,a)
fn = perform_linker(Env(*graph.clone([x, y,r], [e]))).make_function()
self.failUnless(fn(1.0,2.0,4.5) == 7.5)
assert fn(1.0,2.0,4.5) == 7.5
def wrap_linker(env, linkers, wrapper):
lnk = WrapLinker(linkers, wrapper).accept(env)
return lnk
class _test_WrapLinker(unittest.TestCase):
def test0(self):
class TestWrapLinker:
def test_0(self):
nodes = []
def wrap(i, node, th):
nodes.append(node.op)
......@@ -138,10 +137,10 @@ class _test_WrapLinker(unittest.TestCase):
i[0].data = 1
i[1].data = 2
fn()
self.failUnless(nodes == [div, add, mul], nodes)
self.failUnless(o[0].data is None)
assert nodes == [div, add, mul]
assert o[0].data is None
def test1(self):
def test_1(self):
nodes = []
def wrap(i, node, th):
nodes.append(node.op)
......@@ -153,44 +152,8 @@ class _test_WrapLinker(unittest.TestCase):
i[0].data = 1
i[1].data = 2
fn()
self.failUnless(nodes == [div, add, mul], nodes)
self.failUnless(o[0].data == 1.5, o[0].data)
# def test_disconnected_input_output(self):
# x,y,z = inputs()
# a = add(x,y)
# a.data = 3.0 # simulate orphan calculation
# fn = perform_linker(env([z], [a])).make_function(inplace=True)
# self.failUnless(fn(1.0) == 3.0)
# self.failUnless(fn(2.0) == 3.0)
# def test_thunk_inplace(self):
# x, y, z = inputs()
# e = mul(add(x, y), div(x, y))
# fn, i, o = perform_linker(Env([x, y, z], [e])).make_thunk(True)
# fn()
# assert e.data == 1.5
# def test_thunk_not_inplace(self):
# x, y, z = inputs()
# e = mul(add(x, y), div(x, y))
# fn, i, o = perform_linker(env([x, y, z], [e])).make_thunk(False)
# fn()
# assert o[0].data == 1.5
# assert e.data != 1.5
# def test_function(self):
# x, y, z = inputs()
# e = mul(add(x, y), div(x, y))
# fn = perform_linker(env([x, y, z], [e])).make_function()
# assert fn(1.0, 2.0, 3.0) == 1.5
# assert e.data != 1.5 # not inplace
if __name__ == '__main__':
unittest.main()
assert nodes == [div, add, mul]
assert o[0].data == 1.5
......
import unittest
from copy import copy
from op import *
from type import Type, Generic
from graph import Apply, Result
from theano.gof.op import *
from theano.gof.type import Type, Generic
from theano.gof.graph import Apply, Result
def as_result(x):
assert isinstance(x, Result)
......@@ -38,7 +37,7 @@ class MyOp(Op):
MyOp = MyOp()
class _test_Op(unittest.TestCase):
class TestOp:
# Sanity tests
def test_sanity_0(self):
......
import unittest
from type import Type
from graph import Result, Apply, Constant
from op import Op
from opt import *
from env import Env
from toolbox import *
from theano.gof.type import Type
from theano.gof.graph import Result, Apply, Constant
from theano.gof.op import Op
from theano.gof.opt import *
from theano.gof.env import Env
from theano.gof.toolbox import *
def as_result(x):
......@@ -73,7 +71,7 @@ def inputs():
PatternOptimizer = lambda p1, p2, ign=False: OpKeyOptimizer(PatternSub(p1, p2), ignore_newtrees=ign)
TopoPatternOptimizer = lambda p1, p2, ign=True: TopoOptimizer(PatternSub(p1, p2), ignore_newtrees=ign)
class _test_PatternOptimizer(unittest.TestCase):
class TestPatternOptimizer:
def test_replace_output(self):
# replacing the whole graph
......@@ -250,7 +248,7 @@ class _test_PatternOptimizer(unittest.TestCase):
OpSubOptimizer = lambda op1, op2: TopoOptimizer(OpSub(op1, op2))
OpSubOptimizer = lambda op1, op2: OpKeyOptimizer(OpSub(op1, op2))
class _test_OpSubOptimizer(unittest.TestCase):
class TestOpSubOptimizer:
def test_straightforward(self):
x, y, z = inputs()
......@@ -267,7 +265,7 @@ class _test_OpSubOptimizer(unittest.TestCase):
assert str(g) == "[Op1(Op2(x), Op4(y), Op4(z))]"
class _test_MergeOptimizer(unittest.TestCase):
class TestMergeOptimizer:
def test_straightforward(self):
x, y, z = inputs()
......@@ -330,42 +328,6 @@ class _test_MergeOptimizer(unittest.TestCase):
g = Env([x, y, z], [e1])
MergeOptimizer().optimize(g)
strg = str(g)
self.failUnless(strg == '[Op1(y, y)]' or strg == '[Op1(z, z)]', strg)
# def test_identical_constant_args_with_destroymap(self):
# x, y, z = inputs()
# y.data = 2.0
# y.constant = False
# z.data = 2.0
# z.constant = True
# e1 = op_d(y, z)
# g = env([x, y, z], [e1])
# MergeOptimizer().optimize(g)
# strg = str(g)
# self.failUnless(strg == '[OpD(y, z)]', strg)
# def test_merge_with_destroyer_1(self):
# x, y, z = inputs()
# e1 = op_d(op1(x,y), y)
# e2 = op_d(op1(x,y), z)
# g = env([x, y, z], [e1,e2])
# MergeOptimizer().optimize(g)
# strg = str(g)
# self.failUnless(strg == '[OpD(Op1(x, y), y), OpD(Op1(x, y), z)]', strg)
# def test_merge_with_destroyer_2(self):
# x, y, z = inputs()
# e1 = op_d(op1(x,y), z)
# e2 = op_d(op1(x,y), z)
# g = env([x, y, z], [e1,e2])
# MergeOptimizer().optimize(g)
# strg = str(g)
# self.failUnless(strg == '[*1 -> OpD(Op1(x, y), z), *1]', strg)
if __name__ == '__main__':
unittest.main()
assert strg == '[Op1(y, y)]' or strg == '[Op1(z, z)]'
import unittest
from theano.gof.graph import Result, Apply
from theano.gof.type import Type
from theano.gof.op import Op
from graph import Result, Apply
from type import Type
from op import Op
from env import Env, InconsistencyError
from toolbox import *
from theano.gof.env import Env, InconsistencyError
from theano.gof.toolbox import *
def as_result(x):
......@@ -63,22 +61,8 @@ def inputs():
return x, y, z
# class _test_EquivTool(unittest.TestCase):
# def test_straightforward(self):
# x, y, z = inputs()
# sx = sigmoid(x)
# e = add(sx, sigmoid(y))
# g = Env([x, y, z], [e])
# g.extend(EquivTool(g))
# assert hasattr(g, 'equiv')
# assert g.equiv(sx) is sx
# g.replace(sx, dot(x, z))
# assert g.equiv(sx) is not sx
# assert g.equiv(sx).owner.op is dot
class _test_NodeFinder(unittest.TestCase):
class TestNodeFinder:
def test_straightforward(self):
x, y, z = inputs()
......@@ -89,7 +73,7 @@ class _test_NodeFinder(unittest.TestCase):
assert hasattr(g, 'get_nodes')
for type, num in ((add, 3), (sigmoid, 3), (dot, 2)):
if not len([x for x in g.get_nodes(type)]) == num:
self.fail((type, num))
raise Exception("Expected: %i times %s" % (num, type))
new_e0 = add(y, z)
assert e0.owner in g.get_nodes(dot)
assert new_e0.owner not in g.get_nodes(add)
......@@ -98,21 +82,7 @@ class _test_NodeFinder(unittest.TestCase):
assert new_e0.owner in g.get_nodes(add)
for type, num in ((add, 4), (sigmoid, 3), (dot, 1)):
if not len([x for x in g.get_nodes(type)]) == num:
self.fail((type, num))
# def test_robustness(self):
# # this test used to make sense to have, but it doesn't work like that anymore
# x, y, z = inputs()
# e = add(add(sigmoid(x), sigmoid(sigmoid(z))), dot(add(x, y), dot(y, z)))
# g = Env([x, y, z], [e])
# g.extend(NodeFinder())
# gen = g.get_nodes(sigmoid) # I want to get Sigmoid instances
# g.replace(e, add(x, y)) # but here I prune them all
# assert len([x for x in gen]) == 0 # the generator should not yield them
raise Exception("Expected: %i times %s" % (num, type))
if __name__ == '__main__':
unittest.main()
from theano.gof.type import *
# todo: test generic
差异被折叠。
......@@ -213,6 +213,8 @@ class PPrinter:
def process(self, r, pstate = None):
if pstate is None:
pstate = PrinterState(pprinter = self)
elif isinstance(pstate, dict):
pstate = PrinterState(pprinter = self, **pstate)
for condition, printer in self.printers:
if condition(pstate, r):
return printer.process(r, pstate)
......@@ -227,17 +229,39 @@ class PPrinter:
cp.assign(condition, printer)
return cp
def process_graph(self, inputs, outputs):
strings = ["inputs: " + ", ".join(map(str, inputs))]
def process_graph(self, inputs, outputs, updates = {}, display_inputs = False):
if not isinstance(inputs, (list, tuple)): inputs = [inputs]
if not isinstance(outputs, (list, tuple)): outputs = [outputs]
current = None
if display_inputs:
strings = [(0, "inputs: " + ", ".join(map(str, list(inputs) + updates.keys())))]
else:
strings = []
pprinter = self.clone_assign(lambda pstate, r: r.name is not None and r is not current,
LeafPrinter())
for node in gof.graph.io_toposort(inputs, outputs):
inv_updates = dict((b, a) for (a, b) in updates.iteritems())
i = 1
for node in gof.graph.io_toposort(list(inputs) + updates.keys(),
list(outputs) + updates.values()):
for output in node.outputs:
if output in inv_updates:
name = str(inv_updates[output])
strings.append((i + 1000, "%s <- %s" % (name, pprinter.process(output))))
i += 1
if output.name is not None or output in outputs:
name = 'outputs[%i]' % outputs.index(output) if output.name is None else output.name
name = 'out[%i]' % outputs.index(output) if output.name is None else output.name
current = output
strings.append("%s = %s" % (name, pprinter.process(output)))
return "\n".join(strings)
try:
idx = 2000 + outputs.index(output)
except ValueError:
idx = i
if len(outputs) == 1 and outputs[0] is output:
strings.append((idx, "return %s" % pprinter.process(output)))
else:
strings.append((idx, "%s = %s" % (name, pprinter.process(output))))
i += 1
strings.sort()
return "\n".join(s[1] for s in strings)
......@@ -261,6 +285,8 @@ psub = OperatorPrinter('-', -2, 'left')
pdot = OperatorPrinter(special['middle_dot'], -1, 'left')
psum = OperatorPrinter(special['big_sigma']+' ', -2, 'left')
from ..tensor import inplace as I
def pprinter():
pp = PPrinter()
pp.assign(lambda pstate, r: True, DefaultPrinter())
......@@ -276,17 +302,21 @@ def pprinter():
pp.assign(T.tensor_copy, IgnorePrinter())
pp.assign(T.log, FunctionPrinter('log'))
pp.assign(T.tanh, FunctionPrinter('tanh'))
pp.assign(T.transpose_inplace, MemberPrinter('T'))
pp.assign(T._abs, PatternPrinter(('|%(0)s|', -1000)))
pp.assign(I.transpose_inplace, MemberPrinter('T'))
pp.assign(T.abs_, PatternPrinter(('|%(0)s|', -1000)))
pp.assign(T.sgn, FunctionPrinter('sgn'))
pp.assign(lambda pstate, r: r.owner and isinstance(r.owner.op, T.Filler) and r.owner.op.value == 0, FunctionPrinter('seros'))
pp.assign(lambda pstate, r: r.owner and isinstance(r.owner.op, T.Filler) and r.owner.op.value == 1, FunctionPrinter('ones'))
pp.assign(lambda pstate, r: r.owner and isinstance(r.owner.op, T.Subtensor), SubtensorPrinter())
pp.assign(T.shape, MemberPrinter('shape'))
pp.assign(T.fill, FunctionPrinter('fill'))
pp.assign(T.vertical_stack, FunctionPrinter('vstack'))
pp.assign(lambda pstate, r: r.owner and isinstance(r.owner.op, T.MakeVector), MakeVectorPrinter())
#pp.assign(T.vertical_stack, FunctionPrinter('vstack'))
#pp.assign(lambda pstate, r: r.owner and isinstance(r.owner.op, T.MakeVector), MakeVectorPrinter())
return pp
pp = pprinter()
pp2 = pprinter()
pp2.assign(lambda pstate, r: hasattr(pstate, 'target') and pstate.target is not r and r.name is not None,
LeafPrinter())
差异被折叠。
差异被折叠。
差异被折叠。
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论