SingleCellTK is an R based package, allowing users to run analysis in system command-line, R console, and R Shiny user interface. To get your machine fully equipped with singleCellTK, you must have R (>=4.0) pre-installed.
See more details on how to install R
Additionally, singleCellTK wraps a number of useful toolkits, where some of them are Python based. To enable this part of functionality, users need to get Python (v3.x) and a set of Python packages built. The fast pip
command can be used to easily install all the required dependencies as shown below:
pip install scipy numpy astroid six scrublet scanpy bbknn scanorama louvain leidenalg
See more details for setting up Python Environment for singleCellTK
With R successfully installed, users can now install singleCellTK to your local system. For quick start, Bioconductor users can directly install our released version with the following command:
if (!requireNamespace("BiocManager", quietly = TRUE))
install.packages("BiocManager")
BiocManager::install("singleCellTK")
See more details about custom installation of singleCellTK
For users who would like to perform console interactive analysis, we strongly suggest that you have RStudio installed.
Users can go to R Official Site to choose the preferred installer.
On the site, users will need to first specify a CRAN mirror. CRAN is a network of servers around the world that store approved R dependencies. Specifying a mirror that is the nearest to you helps minimize network load.
Linux, Windows and MacOS users will be able to find the corresponding installer at the top of the page after choosing a mirror.
Our latest stable release is available on BioConductor. BioConductor is a distribution platform for biology-related packages. The page for singleCellTK can be found here.
Run the following command in R console to install singleCellTK from Bioconductor:
if (!requireNamespace("BiocManager", quietly = TRUE))
install.packages("BiocManager")
BiocManager::install("singleCellTK")
We regularly push new updates to our source code on our Github development branch.
The simplest way to install the development version is by running the following command:
if (!requireNamespace("devtools", quietly = TRUE)) {
install.packages("devtools")
}
devtools::install_github("compbiomed/singleCellTK@devel")
Meanwhile, the source code for the stable releases can be downloaded from here.
To install from source code, you need to first download the tarball file (ending with .tar.gz
), which is a compressed file for the whole directory. Then in R console, run the following command:
# REPLACE {PATH} with the path you place the downloaded tarball file
# REPLACE {VERSION} with the version number in the filename
install.packages("{PATH}/singleCellTK_{VERSION}.tar.gz", repos = NULL)
singleCellTK can successfully be loaded without a Python installation. However, some parts of the toolkit require a live Python environment. For example, the quality control and batch correction sections utilize Python packages, tools and dependencies.
If you do not have Python installed previously and do not plan to use it later, we have prepared a simple command to minimize the workload for the ease of the users. After installing singleCellTK in your R console run the following command:
library(singleCellTK)
sctkPythonInstallConda()
### Alternatively
# sctkPythonInstallVirtualEnv()
If you would like to start to work with Python or are already an experienced Python user, here we skip the approach to the Python installation. If you have a standalone Python installation, it is not necessary to run the command above because it is likely to create a redundant Miniconda copy in your machine. For the list of dependencies that are required, please refer to the pip
command at the top of this page, and you can also replace pip
with conda
.
If you would like to work in a Python virtual environment (“venv”) or a Conda environment, and have already created one, please run the environment selecting function in R console before starting to analyze your data. See the general Python environment instructions below to activate the Python environment to use with the toolkit.
If you ran sctkPythonInstallConda()
(or sctkPythonInstallVirtualEnv()
) directly, or have created your own singleCellTK specific environment (or venv), it is important that you activate the environment before starting to perform any analysis in the toolkit. Otherwise, the toolkit may not be able to properly locate the required dependencies and may result in unexpected behavior or crashes.
### For Python venv user
selectSCTKVirtualEnvironment("{NAME of your VENV}")
### For conda environment user
selectSCTKConda("{NAME of your VENV}")
For the majority of users, the commands above will install the latest version of the singleCellTK without any errors.
Rarely, you may encounter an error due to previously installed versions of some packages that are required for the singleCellTK. If you encounter an error during installation, use the commands below to check the version of Bioconductor that is installed:
if (!requireNamespace("BiocManager", quietly=TRUE))
install.packages("BiocManager")
BiocManager::version()
If the version number is not 3.6 or higher, you must upgrade Bioconductor to install the toolkit:
BiocManager::install()
After you install Bioconductor 3.6 or higher, you should be able to install the toolkit. If you still encounter an error, ensure your Bioconductor packages are up to date by running the following command.
BiocManager::valid()
If the command above does not return TRUE
, run the following command to update your R packages:
BiocManager::install()
Then, try to install the toolkit again.
singleCellTK adopts reticulate to connect R with Python. If the specific functions in singleCellTK, which require Python dependencies, do not properly start to run after you have installed the dependencies or restart the R session, please try to specify the correct Python executable/binary file in a new R session (where “new” means no Python or reticulate related operations have been performed).
library(reticulate)
use_python("{PATH to the correct Python exexutable/binary file}")
You can always use reticulate::py_config()
to check what specific Python version you are using and what other versions are available. py_config()
configures the R-to-Python connection at once, so you will have to restart the R session if you need to change the configuration with use_python()
after you have the check done.
If you still encounter an error, please open an issue at our GitHub repository and we’d be happy to help.
To contribute to singleCellTK, follow these steps:
Note: Development of the singleCellTK is done using the latest version of R.
git clone https://github.com/{username}/singleCellTK.git
You can then make your changes and test your code using the Rstudio build tools. There is a lot of information about building packages available here: http://r-pkgs.had.co.nz/.
Information about building shiny packages is available here: http://shiny.rstudio.com/tutorial/.
When you are ready to upload your changes, commit them locally, push them to your forked repo, and make a pull request to the compbiomed singleCellTK repository.
Report bugs and request features on our GitHub issue tracker.
Join us on slack!


There are a few different ways to plot in Julia (including calling PyPlot).
Here we'll show you how to use Plots.jl
.
using Pkg; Pkg.add("Plots")
using Plots
One of the advantages to Plots.jl
is that it allows you to seamlessly change backends. In this notebook, we'll try out the gr()
and plotlyjs()
backends.
In the name of scientific inquiry, let's use this notebook to examine the relationship between the global temperature and the number of pirates between roughly 1860 and 2000.
globaltemperatures = [14.4, 14.5, 14.8, 15.2, 15.5, 15.8]
numpirates = [45000, 20000, 15000, 5000, 400, 17]
To get plotting, let's load the GR backend
gr()
and now we can use commands like plot
and scatter
to generate plots.
plot(numpirates, globaltemperatures, label="line")
scatter!(numpirates, globaltemperatures, label="points")
The !
at the end of the scatter!
function name makes scatter!
a mutating function, indicating that the scattered points will be added onto the pre-existing plot.
In contrast, see what happens when you replace scatter!
in the above with the non-mutating function scatter
.
Next, let's update this plot with the xlabel!
, ylabel!
, and title!
commands to add more information to our plot.
xlabel!("Number of Pirates [Approximate]")
ylabel!("Global Temperature (C)")
title!("Influence of pirate population on global warming")
This still doesn't look quite right. The number of pirates has decreased since 1860, so reading the plot from left to right is like looking backwards in time rather than forwards. Let's flip the x axis to better see how pirate populations have caused global temperatures to change over time!
xflip!()
And there we have it!
Note: We've had some confusion about this exercise. :) This is a joke about how people often conflate correlation and causation.
Without changing syntax, we can create this plot with the unicodeplots()
backend
using Pkg; Pkg.add("UnicodePlots")
unicodeplots()
plot(numpirates, globaltemperatures, label="line")
scatter!(numpirates, globaltemperatures, label="points")
xlabel!("Number of Pirates [Approximate]")
ylabel!("Global Temperature (C)")
title!("Influence of pirate population on global warming")
And notice how this second plot differs from the first!


Connect to VERGE server via JSON-RPC.
Bases: builtins.object
A VERGEConnection object defines a connection to a verge server. It is a thin wrapper around a JSON-RPC API connection.
Arguments to constructor:
Safely copies wallet.dat to destination, which can be a directory or a path with filename.
Arguments: - destination – directory or path with filename to backup wallet to.
Creates a raw transaction spending given inputs (a list of dictionaries, each containing a transaction id and an output number), sending to given address(es).
Returns hex-encoded raw transaction.
Example usage: >>> conn.createrawtransaction(
- [{“txid”: “a9d4599e15b53f3eb531608ddb31f48c695c3d0b3538a6bda871e8b34f2f430c”,
- “vout”: 0}],
{“DkZBYBiq6DNoQEKakpMJegyDbw2YiNQnHT”:50})
Arguments:
inputs – A list of {“txid”: txid, “vout”: n} dictionaries.
they are to be paid.
Produces a human-readable JSON object for a raw transaction.
Arguments:
Returns the private key belonging to <address>.
Arguments:
Returns the account associated with the given address.
Arguments:
Returns the current verge address for receiving payments to an account.
Arguments:
Returns the list of addresses for the given account.
Arguments:
Get the current balance, either for an account or the total server balance.
Arguments: - account – If this parameter is specified, returns the balance in the account. - minconf – Minimum number of confirmations required for transferred balance.
Returns information about the given block hash.
Returns the number of blocks in the longest block chain.
Returns hash of block in best-block-chain at index.
| Parameters: | index – index ob the block |
|---|
Returns the block number of the latest block in the longest block chain. Deprecated. Use getblockcount instead.
Returns the number of connections to other nodes.
Returns the proof-of-work difficulty as a multiple of the minimum difficulty.
Returns True or False, depending on whether generation is enabled.
Returns a recent hashes per second performance measurement while generating.
Returns an ServerInfo object containing various state info.
Returns an MiningInfo object containing various mining state info.
Returns a new verge address for receiving payments.
Arguments:
Get transaction raw info
Arguments:
Returns the total amount received by addresses with an account in transactions with at least a certain number of confirmations.
Arguments:
Returns the total amount received by a verge address in transactions with at least a certain number of confirmations.
Arguments:
Get detailed information about transaction
Arguments:
Returns details about an unspent transaction output (UTXO)
Arguments:
Get work for remote mining, or submit result. If data is specified, the server tries to solve the block using the provided data and returns True if it was successful. If not, the function returns formatted hash data (WorkItem) to work on.
Arguments:
import private key <privkey> to account [acct], optionally rescanning blockchain .
Arguments:
Fills the keypool, requires wallet passphrase to be set.
Returns a list of account names.
Arguments:
Returns a list of accounts.
Each account is represented with a AccountInfo object.
Arguments:
Returns a list of addresses.
Each address is represented with a AddressInfo object.
Arguments:
Returns a list of the last transactions for an account.
Each transaction is represented with a TransactionInfo object.
Arguments:
all accounts if None.
count – Number of transactions to return.
from_ – Skip the first <from_> transactions.
address – Receive address to consider
Returns a list of unspent transaction inputs in the wallet.
Arguments:
Move from one account in your wallet to another.
Arguments:
Sends amount from account’s balance to vergeaddress. This method will fail if there is less than amount verges with minconf confirmations in the account’s balance (unless account is the empty-string-named default account; it behaves like the sendtoaddress method). Returns transaction ID on success.
Arguments:
Sends specified amounts from account’s balance to vergeaddresses. This method will fail if there is less than total amount verges with minconf confirmations in the account’s balance (unless account is the empty-string-named default account; Returns transaction ID on success.
Arguments:
Sends amount from the server’s available balance to vergeaddress.
Arguments:
Sets the account associated with the given address.
Arguments:
Enable or disable generation (mining) of coins.
Arguments:
Sign messages, returns the signature
| Parameters: |
|
|---|---|
| Return type: | unicode |
Sign inputs for raw transaction (serialized, hex-encoded).
Arguments:
hexstring – A hex string of the transaction to sign.
{“txid”: txid, “vout”: n, “scriptPubKey”: hex, “redeemScript”: hex}, representing previous transaction outputs that this transaction depends on but may not yet be in the block chain.
keys that, if given, will be the only keys used to sign the transaction.
Stop verge server.
Validate a verge address and return information for it.
The information is represented by a AddressValidation object.
Arguments: – Address to validate.
Verify a signed message
| Parameters: |
|
|---|---|
| Return type: | bool |
Removes the wallet encryption key from memory, locking the wallet. After calling this method, you will need to call walletpassphrase again before being able to call any methods which require the wallet to be unlocked.
Stores the wallet decryption key in memory for <timeout> seconds.
passphrase – The wallet passphrase.
(by keeping the passphrase in memory).
return False.
Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.
Arguments:
return False.


Hessian inversion failed. Hessian reset to the identify matrix I.
NonLinearSystem: J inversion failed. J reset to identity matrix I.
No estimated parameters added to … panel estimation
Each new objective resets Parameter::DoNotConstrain to FALSE. User must reset it after adding additional objectives.
X in … not the same length as Psi. Load is doing nothing.
File "+fname+"."+EXT+" not found. Load is doing nothing.
Object stored in "+fname+" is of class "+otype+". Current object is "+classname(this)+"
Object Label in "+fname+" is "+inL+", which is not the same as "+L+"
X in "+fname+"."+EXT+" not the same length as Psi. Load is doing nothing.
"+L+" NvfuncTerms, length of return vfunc(), not initialized. Set to 1.
Using default objective which equals 0.0. Your derived objective should provide a replacement for vfunc().


Man charged in connection with schoolboy Brooklyn Colbert’s murder
by By David RaleighGardaí have charged a man in connection with the murder of Limerick schoolboy Brooklyn Colbert.
The man, aged in his late 20s, was charged tonight and will appear before Limerick District Court tomorrow morning.
Brooklyn (aged 11) was found with multiple injuries last Sunday night in a house in Ballynanty on the north side of Limerick city.
Gardaí said that, “for operational reasons” they were not releasing details of how he died.
Speaking earlier tonight, Fr Donal McNamara of St Munchin’s Parish, said the whole of Limerick was praying for the boy’s parents and extended family.
“He was an only child and it must be shattering for his family. The sadness is palpable around the north side of Limerick city, and all over really,” Fr McNamara said.
“Everybody is so hurt and so upset over the whole thing. It’s horrendous, an awful tragedy. My thoughts and prayers are with the young lad’s family.”
“The people of the north side are so loving and welcoming and they are all so hurt over this. I’m thinking of the boy and his family and I’m praying with them in spirit.”
A private wake took place at the boy’s family home tonight.
His funeral mass takes place 11am tomorrow, at St Saviour’s Church, Glentworth Street, Limerick, with burial afterwards in the nearby Mount St Oliver Cemetery.
READ MORE
Victim's rights campaigner says Kriegel family's words were 'the most important' she's heard


--- layout: post title: Andreas Lloyd on Two Bits date: 2008-12-01 23:05:24.000000000 -08:00 categories: - reading circles tags: [] status: publish type: post published: true meta: _edit_last: '1' author: login: ckelty email<EMAIL_ADDRESS>display_name: ckelty first_name: Christopher last_name: Kelty excerpt: !ruby/object:Hpricot::Doc options: {} ---
Andreas Lloyd has an excellent review of Two Bits on his blog.
I particularly appreciate this because Andreas' work is on the Ubuntu project, and his observations of that project will be very important to understanding the ongoing process of maintaining Free Software. Since my book ends about the time Ubuntu emerged, it's nice to know others are continuing to ask questions like Andreas'.


"""
Boolean algebra module for SymPy
"""
from __future__ import print_function, division
from collections import defaultdict
from itertools import combinations, product
from sympy.core.basic import Basic
from sympy.core.cache import cacheit
from sympy.core.numbers import Number
from sympy.core.operations import LatticeOp
from sympy.core.function import Application, Derivative
from sympy.core.compatibility import ordered, range, with_metaclass, as_int
from sympy.core.sympify import converter, _sympify, sympify
from sympy.core.singleton import Singleton, S
class Boolean(Basic):
"""A boolean object is an object for which logic operations make sense."""
__slots__ = []
def __and__(self, other):
"""Overloading for & operator"""
return And(self, other)
__rand__ = __and__
def __or__(self, other):
"""Overloading for |"""
return Or(self, other)
__ror__ = __or__
def __invert__(self):
"""Overloading for ~"""
return Not(self)
def __rshift__(self, other):
"""Overloading for >>"""
return Implies(self, other)
def __lshift__(self, other):
"""Overloading for <<"""
return Implies(other, self)
__rrshift__ = __lshift__
__rlshift__ = __rshift__
def __xor__(self, other):
return Xor(self, other)
__rxor__ = __xor__
def equals(self, other):
"""
Returns True if the given formulas have the same truth table.
For two formulas to be equal they must have the same literals.
Examples
========
>>> from sympy.abc import A, B, C
>>> from sympy.logic.boolalg import And, Or, Not
>>> (A >> B).equals(~B >> ~A)
True
>>> Not(And(A, B, C)).equals(And(Not(A), Not(B), Not(C)))
False
>>> Not(And(A, Not(A))).equals(Or(B, Not(B)))
False
"""
from sympy.logic.inference import satisfiable
from sympy.core.relational import Relational
if self.has(Relational) or other.has(Relational):
raise NotImplementedError('handling of relationals')
return self.atoms() == other.atoms() and \
not satisfiable(Not(Equivalent(self, other)))
class BooleanAtom(Boolean):
"""
Base class of BooleanTrue and BooleanFalse.
"""
is_Boolean = True
_op_priority = 11 # higher than Expr
@property
def canonical(self):
return self
def _noop(self, other=None):
raise TypeError('BooleanAtom not allowed in this context.')
__add__ = _noop
__radd__ = _noop
__sub__ = _noop
__rsub__ = _noop
__mul__ = _noop
__rmul__ = _noop
__pow__ = _noop
__rpow__ = _noop
__rdiv__ = _noop
__truediv__ = _noop
__div__ = _noop
__rtruediv__ = _noop
__mod__ = _noop
__rmod__ = _noop
_eval_power = _noop
[docs]class BooleanTrue(with_metaclass(Singleton, BooleanAtom)):
"""
SymPy version of True, a singleton that can be accessed via S.true.
This is the SymPy version of True, for use in the logic module. The
primary advantage of using true instead of True is that shorthand boolean
operations like ~ and >> will work as expected on this class, whereas with
True they act bitwise on 1. Functions in the logic module will return this
class when they evaluate to true.
Notes
=====
There is liable to be some confusion as to when ``True`` should
be used and when ``S.true`` should be used in various contexts
throughout SymPy. An important thing to remember is that
``sympify(True)`` returns ``S.true``. This means that for the most
part, you can just use ``True`` and it will automatically be converted
to ``S.true`` when necessary, similar to how you can generally use 1
instead of ``S.One``.
The rule of thumb is:
"If the boolean in question can be replaced by an arbitrary symbolic
``Boolean``, like ``Or(x, y)`` or ``x > 1``, use ``S.true``.
Otherwise, use ``True``"
In other words, use ``S.true`` only on those contexts where the
boolean is being used as a symbolic representation of truth.
For example, if the object ends up in the ``.args`` of any expression,
then it must necessarily be ``S.true`` instead of ``True``, as
elements of ``.args`` must be ``Basic``. On the other hand,
``==`` is not a symbolic operation in SymPy, since it always returns
``True`` or ``False``, and does so in terms of structural equality
rather than mathematical, so it should return ``True``. The assumptions
system should use ``True`` and ``False``. Aside from not satisfying
the above rule of thumb, the
assumptions system uses a three-valued logic (``True``, ``False``, ``None``),
whereas ``S.true`` and ``S.false`` represent a two-valued logic. When in
doubt, use ``True``.
"``S.true == True is True``."
While "``S.true is True``" is ``False``, "``S.true == True``"
is ``True``, so if there is any doubt over whether a function or
expression will return ``S.true`` or ``True``, just use ``==``
instead of ``is`` to do the comparison, and it will work in either
case. Finally, for boolean flags, it's better to just use ``if x``
instead of ``if x is True``. To quote PEP 8:
Don't compare boolean values to ``True`` or ``False``
using ``==``.
* Yes: ``if greeting:``
* No: ``if greeting == True:``
* Worse: ``if greeting is True:``
Examples
========
>>> from sympy import sympify, true, Or
>>> sympify(True)
True
>>> ~true
False
>>> ~True
-2
>>> Or(True, False)
True
See Also
========
sympy.logic.boolalg.BooleanFalse
"""
def __nonzero__(self):
return True
__bool__ = __nonzero__
def __hash__(self):
return hash(True)
def as_set(self):
"""
Rewrite logic operators and relationals in terms of real sets.
Examples
========
>>> from sympy import true
>>> true.as_set()
UniversalSet()
"""
return S.UniversalSet
[docs]class BooleanFalse(with_metaclass(Singleton, BooleanAtom)):
"""
SymPy version of False, a singleton that can be accessed via S.false.
This is the SymPy version of False, for use in the logic module. The
primary advantage of using false instead of False is that shorthand boolean
operations like ~ and >> will work as expected on this class, whereas with
False they act bitwise on 0. Functions in the logic module will return this
class when they evaluate to false.
Notes
======
See note in :py:class`sympy.logic.boolalg.BooleanTrue`
Examples
========
>>> from sympy import sympify, false, Or, true
>>> sympify(False)
False
>>> false >> false
True
>>> False >> False
0
>>> Or(True, False)
True
See Also
========
sympy.logic.boolalg.BooleanTrue
"""
def __nonzero__(self):
return False
__bool__ = __nonzero__
def __hash__(self):
return hash(False)
def as_set(self):
"""
Rewrite logic operators and relationals in terms of real sets.
Examples
========
>>> from sympy import false
>>> false.as_set()
EmptySet()
"""
from sympy.sets.sets import EmptySet
return EmptySet()
true = BooleanTrue()
false = BooleanFalse()
# We want S.true and S.false to work, rather than S.BooleanTrue and
# S.BooleanFalse, but making the class and instance names the same causes some
# major issues (like the inability to import the class directly from this
# file).
S.true = true
S.false = false
converter[bool] = lambda x: S.true if x else S.false
class BooleanFunction(Application, Boolean):
"""Boolean function is a function that lives in a boolean space
It is used as base class for And, Or, Not, etc.
"""
is_Boolean = True
def _eval_simplify(self, ratio, measure):
return simplify_logic(self)
def to_nnf(self, simplify=True):
return self._to_nnf(*self.args, simplify=simplify)
@classmethod
def _to_nnf(cls, *args, **kwargs):
simplify = kwargs.get('simplify', True)
argset = set([])
for arg in args:
if not is_literal(arg):
arg = arg.to_nnf(simplify)
if simplify:
if isinstance(arg, cls):
arg = arg.args
else:
arg = (arg,)
for a in arg:
if Not(a) in argset:
return cls.zero
argset.add(a)
else:
argset.add(arg)
return cls(*argset)
[docs]class And(LatticeOp, BooleanFunction):
"""
Logical AND function.
It evaluates its arguments in order, giving False immediately
if any of them are False, and True if they are all True.
Examples
========
>>> from sympy.core import symbols
>>> from sympy.abc import x, y
>>> from sympy.logic.boolalg import And
>>> x & y
And(x, y)
Notes
=====
The ``&`` operator is provided as a convenience, but note that its use
here is different from its normal use in Python, which is bitwise
and. Hence, ``And(a, b)`` and ``a & b`` will return different things if
``a`` and ``b`` are integers.
>>> And(x, y).subs(x, 1)
y
"""
zero = false
identity = true
nargs = None
@classmethod
def _new_args_filter(cls, args):
newargs = []
rel = []
for x in reversed(list(args)):
if isinstance(x, Number) or x in (0, 1):
newargs.append(True if x else False)
continue
if x.is_Relational:
c = x.canonical
if c in rel:
continue
nc = (~c).canonical
if any(r == nc for r in rel):
return [S.false]
rel.append(c)
newargs.append(x)
return LatticeOp._new_args_filter(newargs, And)
def as_set(self):
"""
Rewrite logic operators and relationals in terms of real sets.
Examples
========
>>> from sympy import And, Symbol
>>> x = Symbol('x', real=True)
>>> And(x<2, x>-2).as_set()
(-2, 2)
"""
from sympy.sets.sets import Intersection
if len(self.free_symbols) == 1:
return Intersection(*[arg.as_set() for arg in self.args])
else:
raise NotImplementedError("Sorry, And.as_set has not yet been"
" implemented for multivariate"
" expressions")
[docs]class Or(LatticeOp, BooleanFunction):
"""
Logical OR function
It evaluates its arguments in order, giving True immediately
if any of them are True, and False if they are all False.
Examples
========
>>> from sympy.core import symbols
>>> from sympy.abc import x, y
>>> from sympy.logic.boolalg import Or
>>> x | y
Or(x, y)
Notes
=====
The ``|`` operator is provided as a convenience, but note that its use
here is different from its normal use in Python, which is bitwise
or. Hence, ``Or(a, b)`` and ``a | b`` will return different things if
``a`` and ``b`` are integers.
>>> Or(x, y).subs(x, 0)
y
"""
zero = true
identity = false
@classmethod
def _new_args_filter(cls, args):
newargs = []
rel = []
for x in args:
if isinstance(x, Number) or x in (0, 1):
newargs.append(True if x else False)
continue
if x.is_Relational:
c = x.canonical
if c in rel:
continue
nc = (~c).canonical
if any(r == nc for r in rel):
return [S.true]
rel.append(c)
newargs.append(x)
return LatticeOp._new_args_filter(newargs, Or)
def as_set(self):
"""
Rewrite logic operators and relationals in terms of real sets.
Examples
========
>>> from sympy import Or, Symbol
>>> x = Symbol('x', real=True)
>>> Or(x>2, x<-2).as_set()
(-oo, -2) U (2, oo)
"""
from sympy.sets.sets import Union
if len(self.free_symbols) == 1:
return Union(*[arg.as_set() for arg in self.args])
else:
raise NotImplementedError("Sorry, Or.as_set has not yet been"
" implemented for multivariate"
" expressions")
[docs]class Not(BooleanFunction):
"""
Logical Not function (negation)
Returns True if the statement is False
Returns False if the statement is True
Examples
========
>>> from sympy.logic.boolalg import Not, And, Or
>>> from sympy.abc import x, A, B
>>> Not(True)
False
>>> Not(False)
True
>>> Not(And(True, False))
True
>>> Not(Or(True, False))
False
>>> Not(And(And(True, x), Or(x, False)))
Not(x)
>>> ~x
Not(x)
>>> Not(And(Or(A, B), Or(~A, ~B)))
Not(And(Or(A, B), Or(Not(A), Not(B))))
Notes
=====
- The ``~`` operator is provided as a convenience, but note that its use
here is different from its normal use in Python, which is bitwise
not. In particular, ``~a`` and ``Not(a)`` will be different if ``a`` is
an integer. Furthermore, since bools in Python subclass from ``int``,
``~True`` is the same as ``~1`` which is ``-2``, which has a boolean
value of True. To avoid this issue, use the SymPy boolean types
``true`` and ``false``.
>>> from sympy import true
>>> ~True
-2
>>> ~true
False
"""
is_Not = True
@classmethod
def eval(cls, arg):
from sympy import (
Equality, GreaterThan, LessThan,
StrictGreaterThan, StrictLessThan, Unequality)
if isinstance(arg, Number) or arg in (True, False):
return false if arg else true
if arg.is_Not:
return arg.args[0]
# Simplify Relational objects.
if isinstance(arg, Equality):
return Unequality(*arg.args)
if isinstance(arg, Unequality):
return Equality(*arg.args)
if isinstance(arg, StrictLessThan):
return GreaterThan(*arg.args)
if isinstance(arg, StrictGreaterThan):
return LessThan(*arg.args)
if isinstance(arg, LessThan):
return StrictGreaterThan(*arg.args)
if isinstance(arg, GreaterThan):
return StrictLessThan(*arg.args)
def as_set(self):
"""
Rewrite logic operators and relationals in terms of real sets.
Examples
========
>>> from sympy import Not, Symbol
>>> x = Symbol('x', real=True)
>>> Not(x>0).as_set()
(-oo, 0]
"""
if len(self.free_symbols) == 1:
return self.args[0].as_set().complement(S.Reals)
else:
raise NotImplementedError("Sorry, Not.as_set has not yet been"
" implemented for mutivariate"
" expressions")
def to_nnf(self, simplify=True):
if is_literal(self):
return self
expr = self.args[0]
func, args = expr.func, expr.args
if func == And:
return Or._to_nnf(*[~arg for arg in args], simplify=simplify)
if func == Or:
return And._to_nnf(*[~arg for arg in args], simplify=simplify)
if func == Implies:
a, b = args
return And._to_nnf(a, ~b, simplify=simplify)
if func == Equivalent:
return And._to_nnf(Or(*args), Or(*[~arg for arg in args]), simplify=simplify)
if func == Xor:
result = []
for i in range(1, len(args)+1, 2):
for neg in combinations(args, i):
clause = [~s if s in neg else s for s in args]
result.append(Or(*clause))
return And._to_nnf(*result, simplify=simplify)
if func == ITE:
a, b, c = args
return And._to_nnf(Or(a, ~c), Or(~a, ~b), simplify=simplify)
raise ValueError("Illegal operator %s in expression" % func)
[docs]class Xor(BooleanFunction):
"""
Logical XOR (exclusive OR) function.
Returns True if an odd number of the arguments are True and the rest are
False.
Returns False if an even number of the arguments are True and the rest are
False.
Examples
========
>>> from sympy.logic.boolalg import Xor
>>> from sympy import symbols
>>> x, y = symbols('x y')
>>> Xor(True, False)
True
>>> Xor(True, True)
False
>>> Xor(True, False, True, True, False)
True
>>> Xor(True, False, True, False)
False
>>> x ^ y
Xor(x, y)
Notes
=====
The ``^`` operator is provided as a convenience, but note that its use
here is different from its normal use in Python, which is bitwise xor. In
particular, ``a ^ b`` and ``Xor(a, b)`` will be different if ``a`` and
``b`` are integers.
>>> Xor(x, y).subs(y, 0)
x
"""
def __new__(cls, *args, **kwargs):
argset = set([])
obj = super(Xor, cls).__new__(cls, *args, **kwargs)
for arg in obj._args:
if isinstance(arg, Number) or arg in (True, False):
if arg:
arg = true
else:
continue
if isinstance(arg, Xor):
for a in arg.args:
argset.remove(a) if a in argset else argset.add(a)
elif arg in argset:
argset.remove(arg)
else:
argset.add(arg)
rel = [(r, r.canonical, (~r).canonical) for r in argset if r.is_Relational]
odd = False # is number of complimentary pairs odd? start 0 -> False
remove = []
for i, (r, c, nc) in enumerate(rel):
for j in range(i + 1, len(rel)):
rj, cj = rel[j][:2]
if cj == nc:
odd = ~odd
break
elif cj == c:
break
else:
continue
remove.append((r, rj))
if odd:
argset.remove(true) if true in argset else argset.add(true)
for a, b in remove:
argset.remove(a)
argset.remove(b)
if len(argset) == 0:
return false
elif len(argset) == 1:
return argset.pop()
elif True in argset:
argset.remove(True)
return Not(Xor(*argset))
else:
obj._args = tuple(ordered(argset))
obj._argset = frozenset(argset)
return obj
@property
@cacheit
def args(self):
return tuple(ordered(self._argset))
def to_nnf(self, simplify=True):
args = []
for i in range(0, len(self.args)+1, 2):
for neg in combinations(self.args, i):
clause = [~s if s in neg else s for s in self.args]
args.append(Or(*clause))
return And._to_nnf(*args, simplify=simplify)
[docs]class Nand(BooleanFunction):
"""
Logical NAND function.
It evaluates its arguments in order, giving True immediately if any
of them are False, and False if they are all True.
Returns True if any of the arguments are False
Returns False if all arguments are True
Examples
========
>>> from sympy.logic.boolalg import Nand
>>> from sympy import symbols
>>> x, y = symbols('x y')
>>> Nand(False, True)
True
>>> Nand(True, True)
False
>>> Nand(x, y)
Not(And(x, y))
"""
@classmethod
def eval(cls, *args):
return Not(And(*args))
[docs]class Nor(BooleanFunction):
"""
Logical NOR function.
It evaluates its arguments in order, giving False immediately if any
of them are True, and True if they are all False.
Returns False if any argument is True
Returns True if all arguments are False
Examples
========
>>> from sympy.logic.boolalg import Nor
>>> from sympy import symbols
>>> x, y = symbols('x y')
>>> Nor(True, False)
False
>>> Nor(True, True)
False
>>> Nor(False, True)
False
>>> Nor(False, False)
True
>>> Nor(x, y)
Not(Or(x, y))
"""
@classmethod
def eval(cls, *args):
return Not(Or(*args))
[docs]class Implies(BooleanFunction):
"""
Logical implication.
A implies B is equivalent to !A v B
Accepts two Boolean arguments; A and B.
Returns False if A is True and B is False
Returns True otherwise.
Examples
========
>>> from sympy.logic.boolalg import Implies
>>> from sympy import symbols
>>> x, y = symbols('x y')
>>> Implies(True, False)
False
>>> Implies(False, False)
True
>>> Implies(True, True)
True
>>> Implies(False, True)
True
>>> x >> y
Implies(x, y)
>>> y << x
Implies(x, y)
Notes
=====
The ``>>`` and ``<<`` operators are provided as a convenience, but note
that their use here is different from their normal use in Python, which is
bit shifts. Hence, ``Implies(a, b)`` and ``a >> b`` will return different
things if ``a`` and ``b`` are integers. In particular, since Python
considers ``True`` and ``False`` to be integers, ``True >> True`` will be
the same as ``1 >> 1``, i.e., 0, which has a truth value of False. To
avoid this issue, use the SymPy objects ``true`` and ``false``.
>>> from sympy import true, false
>>> True >> False
1
>>> true >> false
False
"""
@classmethod
def eval(cls, *args):
try:
newargs = []
for x in args:
if isinstance(x, Number) or x in (0, 1):
newargs.append(True if x else False)
else:
newargs.append(x)
A, B = newargs
except ValueError:
raise ValueError(
"%d operand(s) used for an Implies "
"(pairs are required): %s" % (len(args), str(args)))
if A == True or A == False or B == True or B == False:
return Or(Not(A), B)
elif A == B:
return S.true
elif A.is_Relational and B.is_Relational:
if A.canonical == B.canonical:
return S.true
if (~A).canonical == B.canonical:
return B
else:
return Basic.__new__(cls, *args)
def to_nnf(self, simplify=True):
a, b = self.args
return Or._to_nnf(~a, b, simplify=simplify)
[docs]class Equivalent(BooleanFunction):
"""
Equivalence relation.
Equivalent(A, B) is True iff A and B are both True or both False
Returns True if all of the arguments are logically equivalent.
Returns False otherwise.
Examples
========
>>> from sympy.logic.boolalg import Equivalent, And
>>> from sympy.abc import x, y
>>> Equivalent(False, False, False)
True
>>> Equivalent(True, False, False)
False
>>> Equivalent(x, And(x, True))
True
"""
def __new__(cls, *args, **options):
from sympy.core.relational import Relational
args = [_sympify(arg) for arg in args]
argset = set(args)
for x in args:
if isinstance(x, Number) or x in [True, False]: # Includes 0, 1
argset.discard(x)
argset.add(True if x else False)
rel = []
for r in argset:
if isinstance(r, Relational):
rel.append((r, r.canonical, (~r).canonical))
remove = []
for i, (r, c, nc) in enumerate(rel):
for j in range(i + 1, len(rel)):
rj, cj = rel[j][:2]
if cj == nc:
return false
elif cj == c:
remove.append((r, rj))
break
for a, b in remove:
argset.remove(a)
argset.remove(b)
argset.add(True)
if len(argset) <= 1:
return true
if True in argset:
argset.discard(True)
return And(*argset)
if False in argset:
argset.discard(False)
return And(*[~arg for arg in argset])
_args = frozenset(argset)
obj = super(Equivalent, cls).__new__(cls, _args)
obj._argset = _args
return obj
@property
@cacheit
def args(self):
return tuple(ordered(self._argset))
def to_nnf(self, simplify=True):
args = []
for a, b in zip(self.args, self.args[1:]):
args.append(Or(~a, b))
args.append(Or(~self.args[-1], self.args[0]))
return And._to_nnf(*args, simplify=simplify)
[docs]class ITE(BooleanFunction):
"""
If then else clause.
ITE(A, B, C) evaluates and returns the result of B if A is true
else it returns the result of C
Examples
========
>>> from sympy.logic.boolalg import ITE, And, Xor, Or
>>> from sympy.abc import x, y, z
>>> ITE(True, False, True)
False
>>> ITE(Or(True, False), And(True, True), Xor(True, True))
True
>>> ITE(x, y, z)
ITE(x, y, z)
>>> ITE(True, x, y)
x
>>> ITE(False, x, y)
y
>>> ITE(x, y, y)
y
"""
@classmethod
def eval(cls, *args):
try:
a, b, c = args
except ValueError:
raise ValueError("ITE expects exactly 3 arguments")
if a == True:
return b
if a == False:
return c
if b == c:
return b
def to_nnf(self, simplify=True):
a, b, c = self.args
return And._to_nnf(Or(~a, b), Or(a, c), simplify=simplify)
def _eval_derivative(self, x):
return self.func(self.args[0], *[a.diff(x) for a in self.args[1:]])
# the diff method below is copied from Expr class
def diff(self, *symbols, **assumptions):
new_symbols = list(map(sympify, symbols)) # e.g. x, 2, y, z
assumptions.setdefault("evaluate", True)
return Derivative(self, *new_symbols, **assumptions)
### end class definitions. Some useful methods
def conjuncts(expr):
"""Return a list of the conjuncts in the expr s.
Examples
========
>>> from sympy.logic.boolalg import conjuncts
>>> from sympy.abc import A, B
>>> conjuncts(A & B)
frozenset([A, B])
>>> conjuncts(A | B)
frozenset([Or(A, B)])
"""
return And.make_args(expr)
def disjuncts(expr):
"""Return a list of the disjuncts in the sentence s.
Examples
========
>>> from sympy.logic.boolalg import disjuncts
>>> from sympy.abc import A, B
>>> disjuncts(A | B)
frozenset([A, B])
>>> disjuncts(A & B)
frozenset([And(A, B)])
"""
return Or.make_args(expr)
def distribute_and_over_or(expr):
"""
Given a sentence s consisting of conjunctions and disjunctions
of literals, return an equivalent sentence in CNF.
Examples
========
>>> from sympy.logic.boolalg import distribute_and_over_or, And, Or, Not
>>> from sympy.abc import A, B, C
>>> distribute_and_over_or(Or(A, And(Not(B), Not(C))))
And(Or(A, Not(B)), Or(A, Not(C)))
"""
return _distribute((expr, And, Or))
def distribute_or_over_and(expr):
"""
Given a sentence s consisting of conjunctions and disjunctions
of literals, return an equivalent sentence in DNF.
Note that the output is NOT simplified.
Examples
========
>>> from sympy.logic.boolalg import distribute_or_over_and, And, Or, Not
>>> from sympy.abc import A, B, C
>>> distribute_or_over_and(And(Or(Not(A), B), C))
Or(And(B, C), And(C, Not(A)))
"""
return _distribute((expr, Or, And))
def _distribute(info):
"""
Distributes info[1] over info[2] with respect to info[0].
"""
if info[0].func is info[2]:
for arg in info[0].args:
if arg.func is info[1]:
conj = arg
break
else:
return info[0]
rest = info[2](*[a for a in info[0].args if a is not conj])
return info[1](*list(map(_distribute,
[(info[2](c, rest), info[1], info[2]) for c in conj.args])))
elif info[0].func is info[1]:
return info[1](*list(map(_distribute,
[(x, info[1], info[2]) for x in info[0].args])))
else:
return info[0]
def to_nnf(expr, simplify=True):
"""
Converts expr to Negation Normal Form.
A logical expression is in Negation Normal Form (NNF) if it
contains only And, Or and Not, and Not is applied only to literals.
If simpify is True, the result contains no redundant clauses.
Examples
========
>>> from sympy.abc import A, B, C, D
>>> from sympy.logic.boolalg import Not, Equivalent, to_nnf
>>> to_nnf(Not((~A & ~B) | (C & D)))
And(Or(A, B), Or(Not(C), Not(D)))
>>> to_nnf(Equivalent(A >> B, B >> A))
And(Or(A, And(A, Not(B)), Not(B)), Or(And(B, Not(A)), B, Not(A)))
"""
if is_nnf(expr, simplify):
return expr
return expr.to_nnf(simplify)
[docs]def to_cnf(expr, simplify=False):
"""
Convert a propositional logical sentence s to conjunctive normal form.
That is, of the form ((A | ~B | ...) & (B | C | ...) & ...)
If simplify is True, the expr is evaluated to its simplest CNF form.
Examples
========
>>> from sympy.logic.boolalg import to_cnf
>>> from sympy.abc import A, B, D
>>> to_cnf(~(A | B) | D)
And(Or(D, Not(A)), Or(D, Not(B)))
>>> to_cnf((A | B) & (A | ~A), True)
Or(A, B)
"""
expr = sympify(expr)
if not isinstance(expr, BooleanFunction):
return expr
if simplify:
return simplify_logic(expr, 'cnf', True)
# Don't convert unless we have to
if is_cnf(expr):
return expr
expr = eliminate_implications(expr)
return distribute_and_over_or(expr)
[docs]def to_dnf(expr, simplify=False):
"""
Convert a propositional logical sentence s to disjunctive normal form.
That is, of the form ((A & ~B & ...) | (B & C & ...) | ...)
If simplify is True, the expr is evaluated to its simplest DNF form.
Examples
========
>>> from sympy.logic.boolalg import to_dnf
>>> from sympy.abc import A, B, C
>>> to_dnf(B & (A | C))
Or(And(A, B), And(B, C))
>>> to_dnf((A & B) | (A & ~B) | (B & C) | (~B & C), True)
Or(A, C)
"""
expr = sympify(expr)
if not isinstance(expr, BooleanFunction):
return expr
if simplify:
return simplify_logic(expr, 'dnf', True)
# Don't convert unless we have to
if is_dnf(expr):
return expr
expr = eliminate_implications(expr)
return distribute_or_over_and(expr)
def is_nnf(expr, simplified=True):
"""
Checks if expr is in Negation Normal Form.
A logical expression is in Negation Normal Form (NNF) if it
contains only And, Or and Not, and Not is applied only to literals.
If simpified is True, checks if result contains no redundant clauses.
Examples
========
>>> from sympy.abc import A, B, C
>>> from sympy.logic.boolalg import Not, is_nnf
>>> is_nnf(A & B | ~C)
True
>>> is_nnf((A | ~A) & (B | C))
False
>>> is_nnf((A | ~A) & (B | C), False)
True
>>> is_nnf(Not(A & B) | C)
False
>>> is_nnf((A >> B) & (B >> A))
False
"""
expr = sympify(expr)
if is_literal(expr):
return True
stack = [expr]
while stack:
expr = stack.pop()
if expr.func in (And, Or):
if simplified:
args = expr.args
for arg in args:
if Not(arg) in args:
return False
stack.extend(expr.args)
elif not is_literal(expr):
return False
return True
[docs]def is_cnf(expr):
"""
Test whether or not an expression is in conjunctive normal form.
Examples
========
>>> from sympy.logic.boolalg import is_cnf
>>> from sympy.abc import A, B, C
>>> is_cnf(A | B | C)
True
>>> is_cnf(A & B & C)
True
>>> is_cnf((A & B) | C)
False
"""
return _is_form(expr, And, Or)
[docs]def is_dnf(expr):
"""
Test whether or not an expression is in disjunctive normal form.
Examples
========
>>> from sympy.logic.boolalg import is_dnf
>>> from sympy.abc import A, B, C
>>> is_dnf(A | B | C)
True
>>> is_dnf(A & B & C)
True
>>> is_dnf((A & B) | C)
True
>>> is_dnf(A & (B | C))
False
"""
return _is_form(expr, Or, And)
def _is_form(expr, function1, function2):
"""
Test whether or not an expression is of the required form.
"""
expr = sympify(expr)
# Special case of an Atom
if expr.is_Atom:
return True
# Special case of a single expression of function2
if expr.func is function2:
for lit in expr.args:
if lit.func is Not:
if not lit.args[0].is_Atom:
return False
else:
if not lit.is_Atom:
return False
return True
# Special case of a single negation
if expr.func is Not:
if not expr.args[0].is_Atom:
return False
if expr.func is not function1:
return False
for cls in expr.args:
if cls.is_Atom:
continue
if cls.func is Not:
if not cls.args[0].is_Atom:
return False
elif cls.func is not function2:
return False
for lit in cls.args:
if lit.func is Not:
if not lit.args[0].is_Atom:
return False
else:
if not lit.is_Atom:
return False
return True
def eliminate_implications(expr):
"""
Change >>, <<, and Equivalent into &, |, and ~. That is, return an
expression that is equivalent to s, but has only &, |, and ~ as logical
operators.
Examples
========
>>> from sympy.logic.boolalg import Implies, Equivalent, \
eliminate_implications
>>> from sympy.abc import A, B, C
>>> eliminate_implications(Implies(A, B))
Or(B, Not(A))
>>> eliminate_implications(Equivalent(A, B))
And(Or(A, Not(B)), Or(B, Not(A)))
>>> eliminate_implications(Equivalent(A, B, C))
And(Or(A, Not(C)), Or(B, Not(A)), Or(C, Not(B)))
"""
return to_nnf(expr)
def is_literal(expr):
"""
Returns True if expr is a literal, else False.
Examples
========
>>> from sympy import Or, Q
>>> from sympy.abc import A, B
>>> from sympy.logic.boolalg import is_literal
>>> is_literal(A)
True
>>> is_literal(~A)
True
>>> is_literal(Q.zero(A))
True
>>> is_literal(A + B)
True
>>> is_literal(Or(A, B))
False
"""
if isinstance(expr, Not):
return not isinstance(expr.args[0], BooleanFunction)
else:
return not isinstance(expr, BooleanFunction)
def to_int_repr(clauses, symbols):
"""
Takes clauses in CNF format and puts them into an integer representation.
Examples
========
>>> from sympy.logic.boolalg import to_int_repr
>>> from sympy.abc import x, y
>>> to_int_repr([x | y, y], [x, y]) == [set([1, 2]), set([2])]
True
"""
# Convert the symbol list into a dict
symbols = dict(list(zip(symbols, list(range(1, len(symbols) + 1)))))
def append_symbol(arg, symbols):
if arg.func is Not:
return -symbols[arg.args[0]]
else:
return symbols[arg]
return [set(append_symbol(arg, symbols) for arg in Or.make_args(c))
for c in clauses]
def term_to_integer(term):
"""
Return an integer corresponding to the base-2 digits given by ``term``.
Parameters
==========
term : a string or list of ones and zeros
Examples
========
>>> from sympy.logic.boolalg import term_to_integer
>>> term_to_integer([1, 0, 0])
4
>>> term_to_integer('100')
4
"""
return int(''.join(list(map(str, list(term)))), 2)
def integer_to_term(k, n_bits=None):
"""
Return a list of the base-2 digits in the integer, ``k``.
Parameters
==========
k : int
n_bits : int
If ``n_bits`` is given and the number of digits in the binary
representation of ``k`` is smaller than ``n_bits`` then left-pad the
list with 0s.
Examples
========
>>> from sympy.logic.boolalg import integer_to_term
>>> integer_to_term(4)
[1, 0, 0]
>>> integer_to_term(4, 6)
[0, 0, 0, 1, 0, 0]
"""
s = '{0:0{1}b}'.format(abs(as_int(k)), as_int(abs(n_bits or 0)))
return list(map(int, s))
def truth_table(expr, variables, input=True):
"""
Return a generator of all possible configurations of the input variables,
and the result of the boolean expression for those values.
Parameters
==========
expr : string or boolean expression
variables : list of variables
input : boolean (default True)
indicates whether to return the input combinations.
Examples
========
>>> from sympy.logic.boolalg import truth_table
>>> from sympy.abc import x,y
>>> table = truth_table(x >> y, [x, y])
>>> for t in table:
... print('{0} -> {1}'.format(*t))
[0, 0] -> True
[0, 1] -> True
[1, 0] -> False
[1, 1] -> True
>>> table = truth_table(x | y, [x, y])
>>> list(table)
[([0, 0], False), ([0, 1], True), ([1, 0], True), ([1, 1], True)]
If input is false, truth_table returns only a list of truth values.
In this case, the corresponding input values of variables can be
deduced from the index of a given output.
>>> from sympy.logic.boolalg import integer_to_term
>>> vars = [y, x]
>>> values = truth_table(x >> y, vars, input=False)
>>> values = list(values)
>>> values
[True, False, True, True]
>>> for i, value in enumerate(values):
... print('{0} -> {1}'.format(list(zip(
... vars, integer_to_term(i, len(vars)))), value))
[(y, 0), (x, 0)] -> True
[(y, 0), (x, 1)] -> False
[(y, 1), (x, 0)] -> True
[(y, 1), (x, 1)] -> True
"""
variables = [sympify(v) for v in variables]
expr = sympify(expr)
if not isinstance(expr, BooleanFunction) and not is_literal(expr):
return
table = product([0, 1], repeat=len(variables))
for term in table:
term = list(term)
value = expr.xreplace(dict(zip(variables, term)))
if input:
yield term, value
else:
yield value
def _check_pair(minterm1, minterm2):
"""
Checks if a pair of minterms differs by only one bit. If yes, returns
index, else returns -1.
"""
index = -1
for x, (i, j) in enumerate(zip(minterm1, minterm2)):
if i != j:
if index == -1:
index = x
else:
return -1
return index
def _convert_to_varsSOP(minterm, variables):
"""
Converts a term in the expansion of a function from binary to it's
variable form (for SOP).
"""
temp = []
for i, m in enumerate(minterm):
if m == 0:
temp.append(Not(variables[i]))
elif m == 1:
temp.append(variables[i])
else:
pass # ignore the 3s
return And(*temp)
def _convert_to_varsPOS(maxterm, variables):
"""
Converts a term in the expansion of a function from binary to it's
variable form (for POS).
"""
temp = []
for i, m in enumerate(maxterm):
if m == 1:
temp.append(Not(variables[i]))
elif m == 0:
temp.append(variables[i])
else:
pass # ignore the 3s
return Or(*temp)
def _simplified_pairs(terms):
"""
Reduces a set of minterms, if possible, to a simplified set of minterms
with one less variable in the terms using QM method.
"""
simplified_terms = []
todo = list(range(len(terms)))
for i, ti in enumerate(terms[:-1]):
for j_i, tj in enumerate(terms[(i + 1):]):
index = _check_pair(ti, tj)
if index != -1:
todo[i] = todo[j_i + i + 1] = None
newterm = ti[:]
newterm[index] = 3
if newterm not in simplified_terms:
simplified_terms.append(newterm)
simplified_terms.extend(
[terms[i] for i in [_ for _ in todo if _ is not None]])
return simplified_terms
def _compare_term(minterm, term):
"""
Return True if a binary term is satisfied by the given term. Used
for recognizing prime implicants.
"""
for i, x in enumerate(term):
if x != 3 and x != minterm[i]:
return False
return True
def _rem_redundancy(l1, terms):
"""
After the truth table has been sufficiently simplified, use the prime
implicant table method to recognize and eliminate redundant pairs,
and return the essential arguments.
"""
essential = []
for x in terms:
temporary = []
for y in l1:
if _compare_term(x, y):
temporary.append(y)
if len(temporary) == 1:
if temporary[0] not in essential:
essential.append(temporary[0])
for x in terms:
for y in essential:
if _compare_term(x, y):
break
else:
for z in l1:
if _compare_term(x, z):
if z not in essential:
essential.append(z)
break
return essential
def _find_predicates(expr):
"""Helper to find logical predicates in BooleanFunctions.
A logical predicate is defined here as anything within a BooleanFunction
that is not a BooleanFunction itself.
"""
if not isinstance(expr, BooleanFunction):
return {expr}
return set().union(*(_find_predicates(i) for i in expr.args))
[docs]def simplify_logic(expr, form=None, deep=True):
"""
This function simplifies a boolean function to its simplified version
in SOP or POS form. The return type is an Or or And object in SymPy.
Parameters
==========
expr : string or boolean expression
form : string ('cnf' or 'dnf') or None (default).
If 'cnf' or 'dnf', the simplest expression in the corresponding
normal form is returned; if None, the answer is returned
according to the form with fewest args (in CNF by default).
deep : boolean (default True)
indicates whether to recursively simplify any
non-boolean functions contained within the input.
Examples
========
>>> from sympy.logic import simplify_logic
>>> from sympy.abc import x, y, z
>>> from sympy import S
>>> b = (~x & ~y & ~z) | ( ~x & ~y & z)
>>> simplify_logic(b)
And(Not(x), Not(y))
>>> S(b)
Or(And(Not(x), Not(y), Not(z)), And(Not(x), Not(y), z))
>>> simplify_logic(_)
And(Not(x), Not(y))
"""
if form == 'cnf' or form == 'dnf' or form is None:
expr = sympify(expr)
if not isinstance(expr, BooleanFunction):
return expr
variables = _find_predicates(expr)
truthtable = []
for t in product([0, 1], repeat=len(variables)):
t = list(t)
if expr.xreplace(dict(zip(variables, t))) == True:
truthtable.append(t)
if deep:
from sympy.simplify.simplify import simplify
variables = [simplify(v) for v in variables]
if form == 'dnf' or \
(form is None and len(truthtable) >= (2 ** (len(variables) - 1))):
return SOPform(variables, truthtable)
elif form == 'cnf' or form is None:
return POSform(variables, truthtable)
else:
raise ValueError("form can be cnf or dnf only")
def _finger(eq):
"""
Assign a 5-item fingerprint to each symbol in the equation:
[
# of times it appeared as a Symbol,
# of times it appeared as a Not(symbol),
# of times it appeared as a Symbol in an And or Or,
# of times it appeared as a Not(Symbol) in an And or Or,
sum of the number of arguments with which it appeared,
counting Symbol as 1 and Not(Symbol) as 2
]
>>> from sympy.logic.boolalg import _finger as finger
>>> from sympy import And, Or, Not
>>> from sympy.abc import a, b, x, y
>>> eq = Or(And(Not(y), a), And(Not(y), b), And(x, y))
>>> dict(finger(eq))
{(0, 0, 1, 0, 2): [x], (0, 0, 1, 0, 3): [a, b], (0, 0, 1, 2, 8): [y]}
So y and x have unique fingerprints, but a and b do not.
"""
f = eq.free_symbols
d = dict(list(zip(f, [[0] * 5 for fi in f])))
for a in eq.args:
if a.is_Symbol:
d[a][0] += 1
elif a.is_Not:
d[a.args[0]][1] += 1
else:
o = len(a.args) + sum(ai.func is Not for ai in a.args)
for ai in a.args:
if ai.is_Symbol:
d[ai][2] += 1
d[ai][-1] += o
else:
d[ai.args[0]][3] += 1
d[ai.args[0]][-1] += o
inv = defaultdict(list)
for k, v in ordered(iter(d.items())):
inv[tuple(v)].append(k)
return inv
[docs]def bool_map(bool1, bool2):
"""
Return the simplified version of bool1, and the mapping of variables
that makes the two expressions bool1 and bool2 represent the same
logical behaviour for some correspondence between the variables
of each.
If more than one mappings of this sort exist, one of them
is returned.
For example, And(x, y) is logically equivalent to And(a, b) for
the mapping {x: a, y:b} or {x: b, y:a}.
If no such mapping exists, return False.
Examples
========
>>> from sympy import SOPform, bool_map, Or, And, Not, Xor
>>> from sympy.abc import w, x, y, z, a, b, c, d
>>> function1 = SOPform([x, z, y],[[1, 0, 1], [0, 0, 1]])
>>> function2 = SOPform([a, b, c],[[1, 0, 1], [1, 0, 0]])
>>> bool_map(function1, function2)
(And(Not(z), y), {y: a, z: b})
The results are not necessarily unique, but they are canonical. Here,
``(w, z)`` could be ``(a, d)`` or ``(d, a)``:
>>> eq = Or(And(Not(y), w), And(Not(y), z), And(x, y))
>>> eq2 = Or(And(Not(c), a), And(Not(c), d), And(b, c))
>>> bool_map(eq, eq2)
(Or(And(Not(y), w), And(Not(y), z), And(x, y)), {w: a, x: b, y: c, z: d})
>>> eq = And(Xor(a, b), c, And(c,d))
>>> bool_map(eq, eq.subs(c, x))
(And(Or(Not(a), Not(b)), Or(a, b), c, d), {a: a, b: b, c: d, d: x})
"""
def match(function1, function2):
"""Return the mapping that equates variables between two
simplified boolean expressions if possible.
By "simplified" we mean that a function has been denested
and is either an And (or an Or) whose arguments are either
symbols (x), negated symbols (Not(x)), or Or (or an And) whose
arguments are only symbols or negated symbols. For example,
And(x, Not(y), Or(w, Not(z))).
Basic.match is not robust enough (see issue 4835) so this is
a workaround that is valid for simplified boolean expressions
"""
# do some quick checks
if function1.__class__ != function2.__class__:
return None
if len(function1.args) != len(function2.args):
return None
if function1.is_Symbol:
return {function1: function2}
# get the fingerprint dictionaries
f1 = _finger(function1)
f2 = _finger(function2)
# more quick checks
if len(f1) != len(f2):
return False
# assemble the match dictionary if possible
matchdict = {}
for k in f1.keys():
if k not in f2:
return False
if len(f1[k]) != len(f2[k]):
return False
for i, x in enumerate(f1[k]):
matchdict[x] = f2[k][i]
return matchdict
a = simplify_logic(bool1)
b = simplify_logic(bool2)
m = match(a, b)
if m:
return a, m
return m is not None


198 incredible moments from the Western Morning News Business Awards
The brightest minds in business came together at Plymouth Pavilions to revel in their success - here's another look back through all of the glittering occasion's finest moments
23 Nov 2019, 18:37 by Miles O'Leary
The Western Morning News Business Awards 2019 held at Plymouth Pavilions. Pictured: DM Orthotics
The Western Morning News Business Awards 2019 held at Plymouth Pavilions. Pictured: Finalist - Plessey Semiconductors Ltd
The Western Morning News Business Awards 2019 held at Plymouth Pavilions. Pictured: Finalist - Ultrabeam Hydrographic
The Western Morning News Business Awards 2019 held at Plymouth Pavilions. Pictured: Silverstream
The Western Morning News Business Awards 2019 held at Plymouth Pavilions. Pictured: Silverstream
The Western Morning News Business Awards 2019 held at Plymouth Pavilions. Pictured: SunGift Energy
The Western Morning News Business Awards 2019 held at Plymouth Pavilions. Pictured: The finalists
The Western Morning News Business Awards 2019 held at Plymouth Pavilions. Pictured: Callestick Farm
The Western Morning News Business Awards 2019 held at Plymouth Pavilions. Pictured: Joe Turnbull
The Western Morning News Business Awards 2019 held at Plymouth Pavilions. Pictured: Forthglade Food Ltd
The Western Morning News Business Awards 2019 held at Plymouth Pavilions. Pictured: Callestick Farm
The Western Morning News Business Awards 2019 held at Plymouth Pavilions. Pictured: The finalists
The Western Morning News Business Awards 2019 held at Plymouth Pavilions. Pictured: Ultrabeam Hydrographic
The Western Morning News Business Awards 2019 held at Plymouth Pavilions. Pictured: Finalist - Ultrabeam Hydrographic
The Western Morning News Business Awards 2019 held at Plymouth Pavilions
The Western Morning News Business Awards 2019 held at Plymouth Pavilions
The Western Morning News Business Awards 2019 held at Plymouth Pavilions
The Western Morning News Business Awards 2019 held at Plymouth Pavilions
The Western Morning News Business Awards 2019 held at Plymouth Pavilions
The Western Morning News Business Awards 2019 held at Plymouth Pavilions
The Western Morning News Business Awards 2019 held at Plymouth Pavilions
The Western Morning News Business Awards 2019 held at Plymouth Pavilions
The Western Morning News Business Awards 2019 held at Plymouth Pavilions
The Western Morning News Business Awards 2019 held at Plymouth Pavilions
The Western Morning News Business Awards 2019 held at Plymouth Pavilions
The Western Morning News Business Awards 2019 held at Plymouth Pavilions
The Western Morning News Business Awards 2019 held at Plymouth Pavilions
The Western Morning News Business Awards 2019 held at Plymouth Pavilions
The Western Morning News Business Awards 2019 held at Plymouth Pavilions
The Western Morning News Business Awards 2019 held at Plymouth Pavilions
The Western Morning News Business Awards 2019 held at Plymouth Pavilions
The Western Morning News Business Awards 2019 held at Plymouth Pavilions
The Western Morning News Business Awards 2019 held at Plymouth Pavilions
Winner of Innovative Business of the Year, Ultrabeam Hydrographic. Pictured with Judi Spiers and Bill Martin. Presenter/sponsor: Openreach (Matthew Galley). Western Morning News Business Awards 2019 at the Plymouth Pavilions, Thursday 21st November 2019. Picture: Matt Gilley.
Winner of Micro Business of the Year, Bird Sunglasses. Pictured with Judi Spiers and Bill Martin. Western Morning News Business Awards 2019 at the Plymouth Pavilions, Thursday 21st November 2019. Picture: Matt Gilley.
Winner of Exporter of the Year, Ideal Foods Ltd. Pictured with Judi Spiers and Bill Martin. Presenter/sponsor: Optimus (Mark Russell). Western Morning News Business Awards 2019 at the Plymouth Pavilions, Thursday 21st November 2019. Picture: Matt Gilley.
Winner of Best Start-Up, Ultrabeam Hydrophic. Pictured with Judi Spiers and Bill Martin. Western Morning News Business Awards 2019 at the Plymouth Pavilions, Thursday 21st November 2019. Picture: Matt Gilley.
Winner of Communication Award, C-Council - Together for Families. Pictured with Judi Spiers and Bill Martin. Presenter/sponsor: Livewest (Paul Crawford). Western Morning News Business Awards 2019 at the Plymouth Pavilions, Thursday 21st November 2019. Picture: Matt Gilley.
Winner of Customer Service, The Five Bells Inn. Pictured with Judi Spiers and Bill Martin. Western Morning News Business Awards 2019 at the Plymouth Pavilions, Thursday 21st November 2019. Picture: Matt Gilley.
Winner of Exporter of the Year, Ideal Foods Ltd walk to the stage to collect their award. Western Morning News Business Awards 2019 at the Plymouth Pavilions, Thursday 21st November 2019. Picture: Matt Gilley.
Winner of Apprenticeships Development Award, BluescreenIT. Pictured with Judi Spiers and Bill Martin. Presenter/sponsor: Cornwall College (Jayne Wyckett). Western Morning News Business Awards 2019 at the Plymouth Pavilions, Thursday 21st November 2019. Picture: Matt Gilley.
Western Morning News Business Awards 2019 at the Plymouth Pavilions, Thursday 21st November 2019. Picture: Matt Gilley.
Winner of Family Business of the Year, Callestick Farm. Pictured with Judi Spiers and Bill Martin. Western Morning News Business Awards 2019 at the Plymouth Pavilions, Thursday 21st November 2019. Picture: Matt Gilley.
Winner of Customer Service, The Five Bells Inn. Pictured with Judi Spiers and Bill Martin. Western Morning News Business Awards 2019 at the Plymouth Pavilions, Thursday 21st November 2019. Picture: Matt Gilley.
Winner of Business of the Year, Rittal-CSM Ltd. Western Morning News Business Awards 2019 at the Plymouth Pavilions, Thursday 21st November 2019. Picture: Matt Gilley.
Winner of Young Business Person of the Year Harry Solomon Pictured with Judi Spiers and Bill Martin. Presenter/sponsor: Natwest (Chris Preston). Western Morning News Business Awards 2019 at the Plymouth Pavilions, Thursday 21st November 2019. Picture: Matt Gilley.
Western Morning News Business Awards 2019 at the Plymouth Pavilions, Thursday 21st November 2019. Picture: Matt Gilley.
Winner of Best Tech or Creative Business, Sungift Energy. Pictured with Judi Spiers and Bill Martin. Presenter/sponsor: Cornwall Chamber (Kim Conchie). Western Morning News Business Awards 2019 at the Plymouth Pavilions, Thursday 21st November 2019. Picture: Matt Gilley.
Western Morning News Business Awards 2019 at the Plymouth Pavilions, Thursday 21st November 2019. Picture: Matt Gilley.
Winner of Business of the Year, Rittal-CSM Ltd. Western Morning News Business Awards 2019 at the Plymouth Pavilions, Thursday 21st November 2019. Picture: Matt Gilley.
Winner of Lifetime Achievement Award, James Saughton-St.Austell. Western Morning News Business Awards 2019 at the Plymouth Pavilions, Thursday 21st November 2019. Picture: Matt Gilley.
Winner of Lifetime Achievement Award, James Saughton-St.Austell. Western Morning News Business Awards 2019 at the Plymouth Pavilions, Thursday 21st November 2019. Picture: Matt Gilley.
Winner of Business of the Year, Rittal-CSM Ltd. Pictured with Judi Spiers and Bill Martin. Presenter/sponsored: Computech (Garry Thompson). Western Morning News Business Awards 2019 at the Plymouth Pavilions, Thursday 21st November 2019. Picture: Matt Gilley.
Winner of Manufacturer of the Year, Rittal-CSM Ltd. Pictured with Judi Spiers and Bill Martin. Presenter/sponsor: Foot Anstey (Dickon Court). Western Morning News Business Awards 2019 at the Plymouth Pavilions, Thursday 21st November 2019. Picture: Matt Gilley.
Auctioneer James Morrish taking bids during the charity auction. Western Morning News Business Awards 2019 at the Plymouth Pavilions, Thursday 21st November 2019. Picture: Matt Gilley.
Winner of Business of the Year, Rittal-CSM Ltd. Western Morning News Business Awards 2019 at the Plymouth Pavilions, Thursday 21st November 2019. Picture: Matt Gilley.
Western Morning News Business Awards 2019 at the Plymouth Pavilions, Thursday 21st November 2019. Picture: Matt Gilley.
Winner of Business of the Year, Rittal-CSM Ltd. Western Morning News Business Awards 2019 at the Plymouth Pavilions, Thursday 21st November 2019. Picture: Matt Gilley.
Winner of Business of the Year, Rittal-CSM Ltd. Pictured with Judi Spiers and Bill Martin. Presenter/sponsored: Computech (Garry Thompson). Western Morning News Business Awards 2019 at the Plymouth Pavilions, Thursday 21st November 2019. Picture: Matt Gilley.
Winner of Corporate Social Responsibility Award, Total Energy Solutions Limited. Pictured with Judi Spiers and Bill Martin. Presenter/sponsor: Pavilions (Sarah Phillips). Western Morning News Business Awards 2019 at the Plymouth Pavilions, Thursday 21st November 2019. Picture: Matt Gilley.
Auctioneer James Morrish taking bids during the charity auction. Western Morning News Business Awards 2019 at the Plymouth Pavilions, Thursday 21st November 2019. Picture: Matt Gilley.
Winner of Business of the Year, Rittal-CSM Ltd. Western Morning News Business Awards 2019 at the Plymouth Pavilions, Thursday 21st November 2019. Picture: Matt Gilley.
Winner of Best Tech or Creative Business, Sungift Energy. Pictured with Judi Spiers and Bill Martin. Presenter/sponsor: Cornwall Chamber (Kim Conchie). Western Morning News Business Awards 2019 at the Plymouth Pavilions, Thursday 21st November 2019. Picture: Matt Gilley.
Winner of Lifetime Achievement Award, James Saughton-St.Austell. Pictured with Judi Spiers and Bill Martin. Presenter/sponsored: Browne Jacobson (Julia Green). Western Morning News Business Awards 2019 at the Plymouth Pavilions, Thursday 21st November 2019. Picture: Matt Gilley.
Winner of Business of the Year, Rittal-CSM Ltd. Western Morning News Business Awards 2019 at the Plymouth Pavilions, Thursday 21st November 2019. Picture: Matt Gilley.
Winner of Small Business of the Year, GRE Ltd. Pictured with Judi Spiers and Bill Martin. Presenter/sponsor: Natwest (Chris Preston). Western Morning News Business Awards 2019 at the Plymouth Pavilions, Thursday 21st November 2019. Picture: Matt Gilley.
A signed Ant Middleton book is auctioned for charity. Western Morning News Business Awards 2019 at the Plymouth Pavilions, Thursday 21st November 2019. Picture: Matt Gilley.
Western Morning News Business Awards 2019 at the Plymouth Pavilions, Thursday 21st November 2019. Picture: Matt Gilley.
Western Morning News Business Awards 2019 at the Plymouth Pavilions, Thursday 21st November 2019. Picture: Matt Gilley.
Michael Spiers gift voucher is sold during the charity auction. Western Morning News Business Awards 2019 at the Plymouth Pavilions, Thursday 21st November 2019. Picture: Matt Gilley.
Penny Cross, Edd Moore and Erin Black. Western Morning News Business Awards 2019 at the Plymouth Pavilions, Thursday 21st November 2019. Picture: Matt Gilley.
Western Morning News Business Awards 2019 at the Plymouth Pavilions, Thursday 21st November 2019. Picture: Matt Gilley.
Auctioneer James Morrish taking bids during the charity auction. Western Morning News Business Awards 2019 at the Plymouth Pavilions, Thursday 21st November 2019. Picture: Matt Gilley.
Western Morning News Business Awards 2019 at the Plymouth Pavilions, Thursday 21st November 2019. Picture: Matt Gilley.
Western Morning News Business Awards 2019 at the Plymouth Pavilions, Thursday 21st November 2019. Picture: Matt Gilley.
Western Morning News Business Awards 2019 at the Plymouth Pavilions, Thursday 21st November 2019. Picture: Matt Gilley.
Western Morning News Business Awards 2019 at the Plymouth Pavilions, Thursday 21st November 2019. Picture: Matt Gilley.
Western Morning News Business Awards 2019 at the Plymouth Pavilions, Thursday 21st November 2019. Picture: Matt Gilley.
Western Morning News Business Awards 2019 at the Plymouth Pavilions, Thursday 21st November 2019. Picture: Matt Gilley.
The Western Morning News Business Awards 2019 held at Plymouth Pavilions
The Western Morning News Business Awards 2019 held at Plymouth Pavilions
The Western Morning News Business Awards 2019 held at Plymouth Pavilions
The Western Morning News Business Awards 2019 held at Plymouth Pavilions
The Western Morning News Business Awards 2019 held at Plymouth Pavilions
The Western Morning News Business Awards 2019 held at Plymouth Pavilions
The Western Morning News Business Awards 2019 held at Plymouth Pavilions
The Western Morning News Business Awards 2019 held at Plymouth Pavilions
The Western Morning News Business Awards 2019 held at Plymouth Pavilions
The Western Morning News Business Awards 2019 held at Plymouth Pavilions
The Western Morning News Business Awards 2019 held at Plymouth Pavilions
The Western Morning News Business Awards 2019 held at Plymouth Pavilions
The Western Morning News Business Awards 2019 held at Plymouth Pavilions
The Western Morning News Business Awards 2019 held at Plymouth Pavilions
The Western Morning News Business Awards 2019 held at Plymouth Pavilions
The Western Morning News Business Awards 2019 held at Plymouth Pavilions
The Western Morning News Business Awards 2019 held at Plymouth Pavilions
The Western Morning News Business Awards 2019 held at Plymouth Pavilions
The Western Morning News Business Awards 2019 held at Plymouth Pavilions
The Western Morning News Business Awards 2019 held at Plymouth Pavilions
The Western Morning News Business Awards 2019 held at Plymouth Pavilions
The Western Morning News Business Awards 2019 held at Plymouth Pavilions
The Western Morning News Business Awards 2019 held at Plymouth Pavilions
The Western Morning News Business Awards 2019 held at Plymouth Pavilions
The Western Morning News Business Awards 2019 held at Plymouth Pavilions
The Western Morning News Business Awards 2019 held at Plymouth Pavilions
The Western Morning News Business Awards 2019 held at Plymouth Pavilions
The Western Morning News Business Awards 2019 held at Plymouth Pavilions
The Western Morning News Business Awards 2019 held at Plymouth Pavilions
The Western Morning News Business Awards 2019 held at Plymouth Pavilions
The Western Morning News Business Awards 2019 held at Plymouth Pavilions
The Western Morning News Business Awards 2019 held at Plymouth Pavilions
The Western Morning News Business Awards 2019 held at Plymouth Pavilions
The Western Morning News Business Awards 2019 held at Plymouth Pavilions
The Western Morning News Business Awards 2019 held at Plymouth Pavilions
The Western Morning News Business Awards 2019 held at Plymouth Pavilions
The Western Morning News Business Awards 2019 held at Plymouth Pavilions
The Western Morning News Business Awards 2019 held at Plymouth Pavilions
The Western Morning News Business Awards 2019 held at Plymouth Pavilions
The Western Morning News Business Awards 2019 held at Plymouth Pavilions
The Western Morning News Business Awards 2019 held at Plymouth Pavilions
The Western Morning News Business Awards 2019 held at Plymouth Pavilions
The Western Morning News Business Awards 2019 held at Plymouth Pavilions
The Western Morning News Business Awards 2019 held at Plymouth Pavilions
The Western Morning News Business Awards 2019 held at Plymouth Pavilions
The Western Morning News Business Awards 2019 held at Plymouth Pavilions
The Western Morning News Business Awards 2019 held at Plymouth Pavilions
The Western Morning News Business Awards 2019 held at Plymouth Pavilions
The Western Morning News Business Awards 2019 held at Plymouth Pavilions
The Western Morning News Business Awards 2019 held at Plymouth Pavilions
The Western Morning News Business Awards 2019 held at Plymouth Pavilions
The Western Morning News Business Awards 2019 held at Plymouth Pavilions
The Western Morning News Business Awards 2019 held at Plymouth Pavilions
The Western Morning News Business Awards 2019 held at Plymouth Pavilions
The Western Morning News Business Awards 2019 held at Plymouth Pavilions
The Western Morning News Business Awards 2019 held at Plymouth Pavilions
The Western Morning News Business Awards 2019 held at Plymouth Pavilions
The Western Morning News Business Awards 2019 held at Plymouth Pavilions
The Western Morning News Business Awards 2019 held at Plymouth Pavilions
The Western Morning News Business Awards 2019 held at Plymouth Pavilions
The Western Morning News Business Awards 2019 held at Plymouth Pavilions
The Western Morning News Business Awards 2019 held at Plymouth Pavilions
The Western Morning News Business Awards 2019 held at Plymouth Pavilions
The Western Morning News Business Awards 2019 held at Plymouth Pavilions
The Western Morning News Business Awards 2019 held at Plymouth Pavilions
The Western Morning News Business Awards 2019 held at Plymouth Pavilions
The Western Morning News Business Awards 2019 held at Plymouth Pavilions
The Western Morning News Business Awards 2019 held at Plymouth Pavilions
The Western Morning News Business Awards 2019 held at Plymouth Pavilions
The Western Morning News Business Awards 2019 held at Plymouth Pavilions
The Western Morning News Business Awards 2019 held at Plymouth Pavilions
The Western Morning News Business Awards 2019 held at Plymouth Pavilions
The Western Morning News Business Awards 2019 held at Plymouth Pavilions
The Western Morning News Business Awards 2019 held at Plymouth Pavilions
The Western Morning News Business Awards 2019 held at Plymouth Pavilions
The Western Morning News Business Awards 2019 held at Plymouth Pavilions
The Western Morning News Business Awards 2019 held at Plymouth Pavilions
The Western Morning News Business Awards 2019 held at Plymouth Pavilions
The Western Morning News Business Awards 2019 held at Plymouth Pavilions
The Western Morning News Business Awards 2019 held at Plymouth Pavilions
The Western Morning News Business Awards 2019 held at Plymouth Pavilions
The Western Morning News Business Awards 2019 held at Plymouth Pavilions. Pictured: David Webb
The Western Morning News Business Awards 2019 held at Plymouth Pavilions. Pictured: David Webb
The Western Morning News Business Awards 2019 held at Plymouth Pavilions. Pictured: David Webb
The Western Morning News Business Awards 2019 held at Plymouth Pavilions
The Western Morning News Business Awards 2019 held at Plymouth Pavilions
The Western Morning News Business Awards 2019 held at Plymouth Pavilions. Pictured: The finalists - Best Business Start Up - Moo Music - Lisa Clark
The Western Morning News Business Awards 2019 held at Plymouth Pavilions
The Western Morning News Business Awards 2019 held at Plymouth Pavilions. Pictured: Matt Chorley
The Western Morning News Business Awards 2019 held at Plymouth Pavilions. Pictured: Obedair LTD
The Western Morning News Business Awards 2019 held at Plymouth Pavilions
The Western Morning News Business Awards 2019 held at Plymouth Pavilions. Pictured: Matt Chorley
The Western Morning News Business Awards 2019 held at Plymouth Pavilions. Pictured: Ultrabeam Hydrographic
The Western Morning News Business Awards 2019 held at Plymouth Pavilions. Pictured: Finalists, Tara Leader, - The Dartmoor Skincare Company
The Western Morning News Business Awards 2019 held at Plymouth Pavilions. Pictured: Finalist - Ekopod
The Western Morning News Business Awards 2019 held at Plymouth Pavilions. Pictured: Matt Chorley
The Western Morning News Business Awards 2019 held at Plymouth Pavilions. Pictured: Highly Commended - Rittal -CSM Ltd
The Western Morning News Business Awards 2019 held at Plymouth Pavilions. Pictured: Matt Chorley
The Western Morning News Business Awards 2019 held at Plymouth Pavilions. Pictured: The finalists
The Western Morning News Business Awards 2019 held at Plymouth Pavilions. Pictured: Finalist - Livewest
The Western Morning News Business Awards 2019 held at Plymouth Pavilions. Pictured: Highly Commended - Just Enough Brave
The Western Morning News Business Awards 2019 held at Plymouth Pavilions. Pictured: Finalist - The Brownston Gallery
The Western Morning News Business Awards 2019 held at Plymouth Pavilions. Pictured: Finalist TDA
The Western Morning News Business Awards 2019 held at Plymouth Pavilions. Pictured: Finalist - GM Coachwork
The Western Morning News Business Awards 2019 held at Plymouth Pavilions. Pictured: Devon Contract Waste
The Western Morning News Business Awards 2019 held at Plymouth Pavilions. Pictured: The finalists
The Western Morning News Business Awards 2019 held at Plymouth Pavilions. Pictured: Finalist - Putnam Health Co Ltd
The Western Morning News Business Awards 2019 held at Plymouth Pavilions. Pictured: Finalist - Bovey Castle
The Western Morning News Business Awards 2019 held at Plymouth Pavilions. Pictured: Moments Cafe and Community Hub
The Western Morning News Business Awards 2019 held at Plymouth Pavilions. Pictured: The finalists
The Western Morning News Business Awards 2019 held at Plymouth Pavilions. Pictured: Finalist - Tamar Performance Centre
The Western Morning News Business Awards 2019 held at Plymouth Pavilions. Pictured: The finalists
The Western Morning News Business Awards 2019 held at Plymouth Pavilions. Pictured: Finalist- GRE Ltd
The Western Morning News Business Awards 2019 held at Plymouth Pavilions. Pictured: The finalists
The Western Morning News Business Awards 2019 held at Plymouth Pavilions. Pictured: CATERED LIMITED
The Western Morning News Business Awards 2019 held at Plymouth Pavilions. Pictured: Finalist - Optimus Performance Marketing
The Western Morning News Business Awards 2019 held at Plymouth Pavilions. Pictured: Nexus Open Systems
The Western Morning News Business Awards 2019 held at Plymouth Pavilions. Pictured: SunGift Energy
The Western Morning News Business Awards 2019 held at Plymouth Pavilions. Pictured: Moo Music - Lisa Clark


Weather Information:
City Name:
Zip Code:
Get Forecast
City:
Temperature (F):
Max Temperature (F):
Min Temperature (F):
Pressure (millibars):
Humidity (%):
Post Form:
Input:
Name:
Age:
Weight:
Http Bin Submit
Response:
Name:
Age:
Weight:


Link to the structural features of TATA-binding proteins
Transcription initiation is one of the key regulatory steps in the control of gene expression: initiating transcription at the correct promoter at the correct time is essential for executing the correct biological process. The transcription of eukaryotic genes requires one of three RNA polymerases: Pol I, Pol II, or Pol III. However, none of these RNA polymerases can initiate transcription on its own, instead requiring the aid of different sets of transcription factors. The TATA-box binding protein (TBP) is required for the accurate initiation of transcription by all three transcription factors from promoters with or without a TATA-box, associating with a variety of different transcription factors.
TBP has been explored most thoroughly for its association with Pol II, which is required for the transcription of protein-encoding genes into mRNA. Pol II associates with a host of other factors, including the general transcription factors TFIIA, TFIIB, TFIID, TFIIE, TFIIF, and TFIIH, to form huge multi-subunit pre-initiation complexes on the core DNA promoters (TATA box) at the mRNA start sites. To form these initiation complexes, TBP associates with distinct sets of TBP-associated factors (TAF), which enable the accurate initiation of transcription using specific RNA polymerases. For example, Pol II transcription can involve TFIID in which TBP associates with 13 to 14 different TAFs, or B-TFIID in which TBP associates with BTAF1. These associations can be highly specific. For example, the association of TBP with an unprocessed form of TFIIA in the TBP-TFIIA-containing complex (TAC) is specific for undifferentiated stem cells.


LXRANDR(1) http://LXDE.org LXRANDR(1) NAME lxrandr - a GTK+2 interface to XRandR for LXDE desktop. SYNOPSIS lxrandr DESCRIPTION This manual page documents briefly the lxrandr command. lxrandr is a program that change the resolution and frequency of the monitor using a simple interface. AUTHOR This manual page was written by paulliu<EMAIL_ADDRESS>for the Debian system (but may be used by others). Permission is granted to copy, distribute and/or modify this document under the terms of the GNU General Public License, Version 2 any later version published by the Free Software Foundation. On Debian systems, the complete text of the GNU General Public License can be found in /usr/share/common-licenses/GPL. AUTHOR Ying-Chun Liu Author. COPYRIGHT Copyright © 2008 paulliu http://LXDE.org March 2, 2008 LXRANDR(1)


Domain names are the name of a website, for example the domain name of Google’s website would be “www.google.com”. You can buy domain names online from various websites, such as GoDaddy, Bluehost and etc. These are the things people can type into their search bar in the browser to go to a specific website. They are linked to something called an IP Address.
ICANN stands for Internet Corporation for Assigned Names and Numbers. While it has “Internet” in the name it is not a company that controls the Internet. This is a non-profit organization that makes sure the DNS (Domain Name System) which is like the Yellow Pages of the internet is in order, and coordinates to make sure it runs smoothly.
We use domain names because they allow us to remember the name of websites, and not have to remember the complicated IP addresses of a website.
In the picture "ICANN Example" we can see that ICANN is not a domain name registry but an entity that oversees them. It allows them to coordinate different domain name and registries so there are no overlaps in the domain names and that there is no confusion with which IP addresses belongs to which Domain name.


Free Code Camp Ashburn
- Learning Code
- Building Projects
- Creating Community
Get Started
The single fastest way to connect with us on is Flock!
Step 1: Join Flock
Flock is a slack-alternative and the premier medium where FCCA Members keep in touch!
Channels:
- Announcements - Important channel-wide announcements from the admins!
- General - Make new friends by chatting about coding, events, and related topics!
- Resources & Local Events - Share your best finds for great resources and cool events!
- Daily-Log - Daily coding is a powerful habit. Strengthen this habit by typing 1 sentence about what you coded today!
Step 2: Attend Events
Starbucks @ One Loundoun
44735 Thorndike St, Ashburn, VA 20147
Come hang out with us for code, coffee, and socializing!
Stay for as little or as long as you like!
Where will you be?
- There's tons of parking behind starbucks
- Look for the freeCodeCamp Ashburn sign
- Meeting schedule: Friday 5pm, Saturday 12pm, or Sunday 12pm
- Subject to change according to member's schedule
- Check on Flock for the most updated information
What do I bring?
Have a laptop with an IDE installed
A coding language you want to work on
A friendly, collaborative spirit
Step 3: Build Projects
Want to contribute to projects for our group or start something?
Talk with Tim or Juan on Flock or at events!
Recommended Tools: Git, Github, Gyazo, Flock.
Here are planned ideas for the future:
- Convert title on website to FCC font
- Change color scheme of whole website to match FCC scheme
- Style the buttons on FCCA
- Add video banner to top
- Add transitions/autoscroll buttons to site
- Add pictures for members
- User submitted events with formspree
- RSVP app (ReactJS Project)
- The next event banner app (ReactJS Project)
- Search members function app (ReactJS Project)
- Convert whole site (ReactJS Project)
About
We are a local, organized group of aspiring developers who strive to learn by working together.
We code together at Starbucks on the weekend and go to web development events. We communicate through an app
called Flock.
Goals:
- Tackle challenges from Free Code Camp
- Pair up with others to work at hangouts
- Build projects for FCC Ashburn Group
Scopes:
- Mostly Front-End Development
- Focused on HTML, CSS, JavaScript
- Other frameworks welcomed
- Focus: JavaScript, ES6, ReactJS
- Hobbies: Coding, Traveling, Backpacking
- Focus: JavaScript, ReactJS, ES6+, CSS
- Hobbies: Biking, Playing Guitar, Coding
- Focus: Javascript, ES6, ReactJS, SCSS
- Hobbies: Salsa dancing, Soccer, Coding


All of Microsoft’s X019 Inside Xbox livestream announcements
by Steve WrightLots announced today.
Microsoft’s X019 event is in full swing and we’ve all the big announcements from the Inside Xbox livestream that’s accompanied it.
Strap in, everyone — there’s a lot to cover!
- Project xCloud preview adds more than 50 new games
- Project xCloud heads to PC, “other devices” in 2020
- Project xCloud heads to Canada, India, Japan in 2020
- Everwild is the newest IP to come from Microsoft’s Rare
- Sea of Thieves The Seabound Soul coming next week
- DONTNOD’s Tell Me Why will feature a transgender protagonist
- Halo Reach Master Chief Collection release date set for 3 December
- 50 new games were just announced for Xbox Game Pass
- Grounded is a first-person, co-op survival game from Obsidian
What from the above has you most excited?
Steve Wright attended X019 in London, England as a guest of Microsoft. Travel and accomodation were supplied by Microsoft.


The following is an aimless journey through a degenerate form of Ruby, in an effort to learn a bit more about functional programming, simplicity, and API design.
Suppose that the only way we have to organize code in Ruby is to make lambdas, and the only way we have to structure data are arrays:
1 2 3 4 5 6 7 8 |
|
This is the most bare-bones essence of functional programming: all we have is functions. Let’s write some real-ish code this way and see how far we get before it starts becoming painful.
Suppose we want to manipulate a database of people, and someone has provided us a few functions to interact with a data store. We want to use these to add a UI and some validations.
Here’s how we interact with our data store:
1 2 3 4 |
|
First, we need to be able to add a person to our database, along with some validations. We’ll get this data from user input (we can assume that puts
and gets
are built-ins that work as expected):
1 2 3 4 5 6 7 8 |
|
We need a function to do our validations and add a person to the database. What might it look like? It should accept the attributes of a person and return either an id (on successfully validation and insertion), or an error message, representing what went wrong. Since we don’t have exceptions or hashes - just arrays - we’re going to have to get creative.
Let’s create a convention in our system that every business logic methods returns an array of size 2. The first element is the return value on success, and the second element is an error message on failure. The presence or absence of data in one of these slots indicates the result.
Now that we’ve sorted out what we accept as arguments and what we’re going to return, let’s write our function:
1 2 3 4 5 6 7 8 9 |
|
If you aren’t familiar with String()
, it is a function that coalesces nil to the empty string, so we don’t have to check for both.
With this function, what we’d like to do is call it in a loop until the user has provided correct input, like so:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
|
Of course, we never said anything about while
loops :) Suppose we don’t have them.
Loops are just functions (called recursively)
To loop, we simply wrap our code in a function and call it recursively until we achieve the desired result.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
|
We can envision that our code is going to have a lot of if result[1] == nil
in it, so let’s wrap it in a function.
The great thing about functions is that they allow us to re-use structure, as opposed to logic. The structure here is
checking for an error and doing one thing on success and another on error.
1 2 3 4 5 6 7 |
|
Now, our get_new_person
function abstracts away the error handling:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
|
Notice what the use of handle_result
allows us to explicitly name variables, instead of using Array de-referencing. Not only can we name error_message
, but, using Ruby’s
array-extraction syntax, we can “explode” our person array into its attributes via the ((id,name,birthdate,gender))
syntax.
So far, so good. This code is probably a bit weird looking, but it’s not terribly verbose, or complex.
Clean code uses more functions.
One thing that might seem odd is that our person has no real structure or formal definition. We simply have an array, and a convention that the first element is the name, second element is birthdate, etc. Our domain is pretty simple as-is, but let’s suppose we want to add a new field: title. What happens to our code when we do this?
Our database team delivers new versions of insert_person
and update_person
to us:
1 2 |
|
We then have to update our add_person
method:
1 2 3 4 5 6 7 8 9 10 |
|
And, since we use these extractions in get_new_person
, that has to change, too. Ugh:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
|
This is the very definition of high-coupling. get_new_person
really shouldn’t care about the particular fields of a person; it
should simply read them in, and then pass them to add_person
. Let’s see if we can make that happen by extracting some of this code into new functions.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
|
We’ve now abstracted the way in which we store a person into two functions: read_person_from_user
and person_id
. At this
point, get_new_person
will not need to change if we add more fields to a person.
If you’re confused about the use of *
in this code, here’s a brief explanation: *
allows us to treat an array as a list of arguments and vice versa. In person_id
, we
use the parameter list *_,id
, which tells Ruby to place all arguments to the function, save the last, into the variable _
(so-named because we don’t care about its value),
and place the last argument in the variable id
. This only works in Ruby 1.9; in 1.8 only the last argument of a function may use the *
syntax. Further, when we call
add_person
, we use the *
on the results of read_person_from_user
. Since read_person_from_user
returns an array, we want to treat that array as if it were an argument
list, since add_person
accepts explicit arguments. The *
does that for us. Nice!
Back to our code, you’ll note that we still have coupling between read_person_from_user
and person_id
. They both are intimate with how we store a person in an array.
Further, if we added new features to actually do something with our people database, we can envision more methods coupled to this array-based format.
We need some sort of data structure.
Data structures are just functions
In non-degenerate Ruby, we’d probably make a class at this point, or at least us a Hash
, but we don’t have access to those
here. Can we make a real data structure just using functions? It turns out we can, if we create a function that treats its first argument as an attribute of our data
structure:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
new_person
acts like a constructor, but instead of returning an object (which don’t exist for us), we return a function that, when called, can tell us the values of the
various attributes of our person. We explicitly itemize the possible attributes, so we have a fairly firm definition of what the type of a person is.
Compare this to a class that does the same thing:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
Interesting. The size of these two bits of code is more or less the same, but the class-based version is full of special forms. Special Forms are essentially magic provided by the language or runtime. To understand this code, you need to know:
- what
class
means - that calling
new
on the class’s name calls theinitialize
methods - what methods are
- that prepending
@
to a variable makes it private to the class’ instance - the difference between a class and an instance
- what
attr_reader
does
Compared to our functional version, all you need to know is:
- how to define a function
- how to invoke a function
Like I said, I find this interesting. We have two ways of writing essentially the same code, and one way requires you to have a lot more special knowledge than the other.
OK, now that we have a real data structure, let’s rework our code to use it, instead of arrays:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
|
add_person
is a bit noisier, due to the syntax of getting an attribute, but we can now add new fields very easily and keep things structured.
Object-orientation is just functions
We can also add derived fields. Suppose we want a saluation for the person that uses their title? We can make that an attribute of the person:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
|
Heck, we can create full-on OO-style methods if we wanted to:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
|
While we’re at it, let’s add inheritance! Suppose we have an employee that is a person, but with an employee id number:
1 2 3 4 5 6 7 |
|
We’ve created classes, objects, and inheritance, all with just functions, and in just a few lines of code.
In a sense, an object in an OO language is a set of functions that have access to a shared set of data. It’s not hard to see why adding an object system to a functional language is considered trivial by those knoweldgable in functional languages. It’s certainly a lot easier than adding functions to an object-oriented language!
Although the syntax for accessing attributes is a bit clunky, I’m not feeling a ton of pain by not having classes. Classes seem almost like syntactic sugar at this point, rather than some radical concept.
One thing that seems problematic is mutation. Look at how verbose add_person
is. It calls insert_person
to put our person into the database, and
gets an ID back. We then have to create an entirely new person just to set the ID. In classic OO, we’d just do person.id = id
.
Is mutable state what’s nice about this construct? I’d argue that its compactness is what’s nice, and the fact that this compactness is implemented via mutable state is just incidental. Unless we are in a severely memory-starved environment, with terrible garbage collection, we aren’t going to be concerned about making new objects. We are going to be annoyed by the needless repetition of building new objects from scratch. Since we already know how to add functions to our, er, function, let’s add one to bring back this compact syntax.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
|
Now, add_person
is even simpler:
1 2 3 4 5 6 7 8 9 10 |
|
It’s not quite as clean as person.id = id
, but it’s terse enough that it’s still readable, and the code is better for it.
Namespaces are just functions
What I’m really missing is namespaces. If you’ve done any C programming, you know that your code becomes littered with functions that have complex prefixes to avoid name-clashes. We could certainly do that here, but it would be nice to have proper namespacing, like we get via modules in Ruby or object literals in JavaScript. We’d like to add this without adding a feature to our language. The simplest way to do that is to implement some sort of map. We can already get explicit attributes of a data structure, so we just need a more generic way to do so.
Currently, the only data structure we have is an array, and we don’t have methods, since we don’t have classes. The arrays we have are really tuples, and the only general operations we have are the ability to extract data from them. For example:
1 2 |
|
We can model a map as a list, by treating it as a list with three entires: the key, the value, and the rest of the map. Let’s avoid the “OO style” of making “methods” and just keep it pureful functional:
1 2 3 4 5 6 7 8 9 |
|
We can use it like so:
1 2 3 4 5 |
|
This is enough to namepsace things:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
|
We could certainly replace our new_person
implementation with a map, but it’s nice to have an explicit list of attributes that we support, so we’ll leave new_person
as-is.
One last bit of magic. include
is a nice feature of Ruby; it lets us bring modules into scope to avoid using the namespace. Can we do that here? We can get close:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
|
OK, this might be over the top, but it’s fairly interesting to think of something like include
as just a way to “type less stuff”, and that we can achieve a similar
reduction in “typing stuff” by just using functions.
What have we learned?
With just a few basic language constructs, we can create a fairly usable programming language. We can create bona-fide types, namespaces, and even do object-oriented programming, without any explicit support for these features. And we can do so in more or less the same amount of code that would be required by using Ruby’s built-in support. The syntax is slightly verbose compared to the full-blown Ruby equivalent, but it’s not that bad. We could write real code using this degenerate form of Ruby, and it wouldn’t be too bad.
Does this help us in our everyday work? I think this is a lesson in simplicity. Ruby is fraught with DSLs, abused syntax, and meta-programming, yet we’ve just been able to accomplish a lot without even using classes!  Perhaps you don’t need anything fancy, but can rely on the more straightforward parts of your language.