David Barragán Merino / @bameda
#FFF8E7 at
Kaleidos.net
Grouchy Smurf at
Taiga.io
bameda on GitHub
@bameda on Twitter
Slides: https://bameda.github.io/python-functional-101-t3chfest2018/index.html
Repo: https://github.com/bameda/python-functional-101-t3chfest2018
In computer science, functional programming is a programming paradigma style of building the structure and elements of computer programs—that treats computation as the evaluation of mathematical functions and avoids changing-state and mutable data. It is a declarative programming paradigm, which means programming is done with expressions or declarations instead of statements. (...) can make it much easier to understand and predict the behavior of a program, which is one of the key motivations for the development of functional programming.
Functional programming
from Wikipedia
Calculate partially invalid string with operation.
input = "23+45++++2++5++32++100"
Actions that change state from initial state to resultI => Imperative style => HOW?
input = "23+45++++2++5++32++100"
res = 0
for t in input.split("+"):
if t:
res += int(t)
print(res)
["23", "45", "", "", "", "2", "", "5", "", "32", "", "100"], 0
"23", 0
"45", 23
"2", 68
"5", 70
"32", 75
"100", 107
207
Apply rules, restrictions, transformation (and compositions) => Declarative style => WHAT
input = "23+45++++2++5++32++100"
from functools import reduce
from operator import add
res = reduce(add, map(int, filter(bool, input.split("+"))))
print(res)
["23", "45", "", "", "", "2", "", "5", "", "32", "", "100"]
["23", "45", "2", "5", "32", "100"]
[23, 45, 2, 5, 32, 100]
207
values = ['rock', 'paper', 'scissors']
combs = []
for x in values:
for y in values:
if x != y:
combs.append((x, y))
print(combs)
[('rock', 'paper'), ('rock', 'scissors'), ('paper', 'rock'),
('paper', 'scissors'), ('scissors', 'rock'), ('scissors', 'paper')]
values = ['rock', 'paper', 'scissors']
combs = [(x, y) for x in values for y in values if x != y]
print(combs)
[('rock', 'paper'), ('rock', 'scissors'), ('paper', 'rock'),
('paper', 'scissors'), ('scissors', 'rock'), ('scissors', 'paper')]
Are you sure you can not do it better?
iterable: An object capable of returning its members one at a time. Examples of iterables include all sequence types (such as list, str, and tuple) and some non-sequence types like dict, file objects, and objects of any classes you define with an__iter__()
method or__getitem__
(...) When an iterable object is passed as an argument to the built-in functioniter()
, it returns an iterator for the object. This iterator is good for one pass over the set of values.
for n in [1, 2, 3]:
print (n)
1
2
3
for l in "abc":
print (l)
a
b
c
file = open("to_pdf.sh", "r")
for line in file:
print(line)
#!/bin/bash
node node_modules/decktape/decktape.js --no-sandbox reveal "http://localhost:8000" slides.pdf
__iter__:This method is called when an iterator is required for a container. This method should return a new iterator object that can iterate over all the objects in the container. For mappings, it should iterate over the keys of the container.
iterator: An object representing a stream of data. Repeated calls to the iterator’s__next__()
method (or passing it to the built-in functionnext()
) return successive items in the stream. When no more data are available aStopIteration
exception is raised instead. At this point, the iterator object is exhausted and any further calls to its__next__()
method just raiseStopIteration
again. Iterators are required to have an__iter__()
method that returns the iterator object itself so every iterator is also iterable and may be used in most places where other iterables are accepted.
class yrange:
def __init__(self, n):
self.i = 0
self.n = n
def __iter__(self):
return self
def __next__(self):
if self.i < self.n:
i = self.i
self.i += 1
return i
else:
raise StopIteration()
y = yrange(3)
print(next(y))
print(next(y))
print(next(y))
print(next(y))
0
1
2
---------------------------------------------------------------------------
StopIteration Traceback (most recent call last)
<ipython-input-49-c97cadfde7e4> in <module>()
3 print(next(y))
4 print(next(y))
----> 5 print(next(y))
<ipython-input-45-79e514da8e3b> in __next__(self)
13 return i
14 else:
---> 15 raise StopIteration()
StopIteration:
for n in yrange(3):
print(n)
0
1
2
def my_for(iterable):
it = iter(iterable)
while True:
try:
print(next(it))
except StopIteration:
break
my_for(yrange(3))
0
1
2
Iterator is good for one pass over the set of values.
y = yrange(5)
print(tuple(y))
print(tuple(y))
(0, 1, 2, 3, 4)
()
generator A function which returns a generator iterator. It looks like a normal function except that it containsyield
expressions for producing a series of values usable in a for-loop or that can be retrieved one at a time with thenext()
function.
generator iterator An object created by a generator function.
def my_generator():
yield 1
yield 2
yield 3
g = my_generator()
print(g)
print(next(g))
print(next(g))
print(next(g))
print(next(g))
<generator object my_generator at 0x7ff9ec48fc50>
1
2
3
---------------------------------------------------------------------------
StopIteration Traceback (most recent call last)
<ipython-input-55-567ce73dea18> in <module>()
4 print(next(g))
5 print(next(g))
----> 6 print(next(g))
StopIteration:
def count(stop):
"""Return all numbers <= stop."""
numbers = []
n = 0
while n <= stop:
numbers.append(n)
n += 1
return numbers
print(count(10))
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
print(count(1e18))
===================================================================
| Kernel restarting |
| |
| The kernel appears to have died. It will restart automatically. |
===================================================================
def count():
n = 0
while True:
yield n
n +=1
counter = count()
print(next(counter))
print(next(counter))
print(next(counter))
print(next(counter))
0
1
2
3
for num in count():
print(num)
# zZzZzZzZz...
Let's go back to the previous example...
values = ['rock', 'paper', 'tijer ']
combs = ((x, y) for x in values for y in values if x != y)
print(combs)
<generator object <genexpr> at 0x7ff9ec545468>
next(combs)
('rock', 'paper')
next(combs)
('rock', 'scissors')
__ite __()
or __getitem__()
method.__next__()
.yield
), returning a generator.
If you need mutch more, read "Generator Tricks for Systems Programmers" by David M. Beazley
and some Python Enhancement Proposals PEP 288
, PEP 325
, PEP 342
and PEP 380.
This module implements a number of iterator building blocks inspired by constructs from APL, Haskell, and SML. Each has been recast in a form suitable for Python.
The module standardizes a core set of fast, memory efficient tools that are useful by themselves or in combination. Together, they form an “iterator algebra” making it possible to construct specialized tools succinctly and efficiently in pure Python.
count()
, cycle()
, repeat()
accumulate()
, chain()
, chain.from_iterable()
, compress()
, dropwhile()
, filterfalse()
, groupby()
, islice()
, starmap()
, takewhile()
, tee()
, zip_longest()
product()
, permutations()
, combinations()
, combinations_with_replacement()
See itertools doc.
Let's implement a very basic string compression function using the counts of repeated characters.
For example:
compress("sssdddddxxaaaaaa")
"s3d5x2a6"
...without itertools
def compress(word):
result = []
current = word[0]
counter = 1
for letter in word[1:]:
if letter == current:
# We're still in the same group
counter += 1
else:
# We need to start a new group
result += [current, str(counter)]
current = letter # start a new group
counter = 1
result += [current, str(counter)]
return "".join(result)
compress("sssdddddxxaaaaaa")
"s3d5x2a6"
...with itertools
itertools.groupby(iterable, key=None)
None
, key defaults to an identity function and returns the element unchanged. Generally, the iterable needs to already be sorted on the same key function.
def compress(word):
return ''.join(f"{key}{len(tuple(group))}"
for key, group in itertools.groupby(word))
compress("sssdddddxxaaaaaa")
"s3d5x2a6"
If we roll four six-sided dices, what are their posible outcomes?
...without itertools
def product(first, second, third, fourth):
"""A generator of the Cartesian product of four iterables."""
for w in first:
for x in second:
for y in third:
for z in fourth:
yield (w, x, y, z)
dice = range(1, 7)
len(tuple(product(dice, dice, dice, dice)))
1296
...with itertools
itertools.product(*iterables, repeat=1)
repeat
keyword argument. For example, product(A, repeat=4)
means the same as product(A, A, A, A)
.
import itertools
dice = range(1, 7)
len(tuple(itertools.product(dice, repeat=4)))
1296
...and in how many outcomes they add up to 6?
tuple(filter(lambda x: sum(x) == 6,
itertools.product(dice, repeat=4)))
((1, 1, 1, 3), (1, 1, 2, 2), (1, 1, 3, 1), (1, 2, 1, 2), (1, 2, 2, 1),
(1, 3, 1, 1), (2, 1, 1, 2), (2, 1, 2, 1), (2, 2, 1, 1), (3, 1, 1, 1))
To know more about irtertools see
Kung Fu at Dawn with Itertools
by Víctor Terrón (@pyctor)
at EuroPython 2016
Video EN / Video ES / Repo [CC BY-SA 2.0]
lambda: An anonymous inline function consisting of a single expression which is evaluated when the function is called. The syntax to create a lambda function is lambda [arguments]: expression
expression: A piece of syntax which can be evaluated to some value. In other words, an expression is an accumulation of expression elements like literals, names, attribute access, operators or function calls which all return a value.
sum_numbers = lambda x, y: x+y
print(sum_numbers)
<function <lambda> at 0x7f0aef3d9ea0>
sum_numbers(1, 4)
5
even_or_odd = lambda x: "even" if x % 2 == 0 else "odd"
print(f"1 is {even_or_odd(1)}")
print(f"4 is {even_or_odd(4)}")
print(f"22 is {even_or_odd(22)}")
print(f"1479 is {even_or_odd(1479)}")
1 is odd
4 is even
22 is even
1479 is odd
In mathematics and computer science, a higher-order function(also functional, functional form or functor)is a function that takes one or more functions as arguments or return a function.
Higher-order function
from Wikipedia
def twice(f):
return lambda x: f(f(x))
plus_three = lambda x: x + 3
twice_plus_three = twice(plus_three)
twice_plus_three(10)
16
Python comes with some higher-order functions
map(function, iterable, ...)
see itertools.starmap()
.
tuple(map(lambda x, y: (x,y), (1, 2, 3, 4), ('a', 'b', 'c', 'd')))
((1, 'a'), (2, 'b'), (3, 'c'), (4, 'd'))
filter(function, iterable)
filter(function, iterable)
is equivalent to the generator expression (item for item in iterable if function(item))
if function is not None
and (item for item in iterable if item)
if function is None
.
itertools.filterfalse()
for the complementary function that returns elements of iterable for which function returns false.
tuple(filter(lambda x: x % 2 == 0, [1, 2, 3, 4, 5, 15, 17, 32, 1986]))
(2, 4, 32, 1986)
sorted(iterable, *, key=None, reverse=False)
key
specifies a function of one argument that is used to extract a comparison key from each list element: key=str.lower
. The default value is None (compare the elements directly).
reverse
is a boolean value. If set to True
, then the list elements are sorted as if each comparison were reversed.
sorted()
function is guaranteed to be stable. A sort is stable if it guarantees not to change the relative order of elements that compare equal — this is helpful for sorting in multiple passes (for example, sort by department, then by salary grade).
from collections import namedtuple
Student = namedtuple('Student', ('name', 'age', 'grade'))
students = (
Student("María", 21, 'C'),
Student("Pedro", 22, 'B'),
Student("Rosa", age=21, grade='A')
)
sorted(students, key=lambda s: s.age)
[Student(name='María', age=21, grade='C'),
Student(name='Rosa', age=21, grade='A'),
Student(name='Pedro', age=22, grade='B')]
from operator import attrgetter
sorted(students, key=attrgetter('age', 'grade'))
[Student(name='Rosa', age=21, grade='A'),
Student(name='María', age=21, grade='C'),
Student(name='Pedro', age=22, grade='B')]
The functools module is for higher-order functions: functions that act on or return other functions. In general, any callable object can be treated as a function for the purposes of this module.
See functools doc.
functools.reduce(function, iterable[, initializer])
reduce(lambda x, y: x+y, [1, 2, 3, 4, 5])
calculates ((((1+2)+3)+4)+5)
. The left argument, x, is the accumulated value and the right argument, y, is the update value from the sequence. If the optional initializer is present, it is placed before the items of the sequence in the calculation, and serves as a default when the sequence is empty. If initializer is not given and sequence contains only one item, the first item is returned.
import functools
functools.reduce(lambda x, y: x * y, range(1, 11))
@functools.lru_cache(maxsize=128, typed=False)
maxsize
is set to None
, the LRU feature is disabled and the cache can grow without bound. The LRU feature performs best when maxsize is a power-of-two. If typed
is set to true
, function arguments of different types will be cached separately.
import functools
@functools.lru_cache()
def get_heavy_func(param):
print(f"Multiply (param={param} by 3")
return param * 3
print(get_heavy_func(1))
Multiply 1 by 3
3
print(get_heavy_func(2))
Multiply 2 by 3
6
print(get_heavy_func(1))
3
print(get_heavy_func(2))
6
class MultiplierMaker:
def __init__(self, n):
self.n = n
def multiplier(self, x):
return self.n * x
times3 = MultiplierMaker(3)
times5 = MultiplierMaker(5)
print(times3.multiplier(9))
27
print(times5.multiplier(3))
15
print(times5.multiplier(times3.multiplier(2)))
30
A closure is a function evaluated in an environment that contains
one or more variables dependent on another environment.
In programming languages, a closure (also lexical closure or function closure) is a technique for implementing lexically scoped name binding in a language with first-class functions. Operationally, a closure is a record storing a function together with an environment. The environment is a mapping associating each free variable of the function (variables that are used locally, but defined in an enclosing scope) with the value or reference to which the name was bound when the closure was created. A closure—unlike a plain function—allows the function to access those captured variables through the closure's copies of their values or references, even when the function is invoked outside their scope.
Closure (computer programming)
from Wikipedia
def make_multiplier_of(n):
def multiplier(x):
return x * n
return multiplier
times3 = make_multiplier_of(3)
times5 = make_multiplier_of(5)
print(times3(9))
27
print(times5(3))
15
print(times5(times3(2)))
30
print(make_multiplier_of.__closure__)
None
print(times3.__closure__[0].cell_contents)
3
Decorators are “wrappers”, which means that they let you execute code before
and after the function they decorate without modifying the function itself.
A decorator is a function that takes in another function and returns another function.
The best exaplanation about decorators in Python is here
def bold(fn):
def wrapped():
return f"**{fn()}**"
return wrapped
def italic(fn):
def wrapped():
return f"_{fn()}_"
return wrapped
def hello():
return "hello world"
print(bold(italic(hello))())
**_hello world_**
@bold
@italic
def hello():
return "hello world"
print(hello())
**_hello world_**
There is a small problem with decorated functions and their metadata
@bold
def hello():
"""Print hello message"""
return "hello world"
print(hello.__name__)
wrapped
print(hello.__doc__)
None
import functools
def bold(fn):
@functools.wraps(fn)
def wrapped():
return f"*{fn()}*"
return wrapped
@bold
def hello():
"""Print hello message"""
return "hello world"
print(hello.__name__)
hello
print(hello.__doc__)
Print hello message
from functools import wraps
def md_tag(tag):
def factory(func):
@wraps(func)
def decorator(msg):
return f"{tag}{func(msg)}{tag}"
return decorator
return factory
@md_tag("**")
@md_tag("_")
def message(msg):
"""Return a text message"""
return msg
print(message("Hello T3chFest"))
**_Hello T3chFest_**
print(message.__name__)
message
print(message.__doc__)
Return a text message
papply: (((a × b) → c) × a) → (b → c) = λ(f, x). λy. f (x, y)
The process of fixing a number of arguments to a function, producing another function of smaller arity.
Partial application
from Wikipedia
def log(level, msg):
print(f"[{level}]: {msg}")
def debug(msg):
log("debug", msg)
log("debug", "Start doing something")
log("debug", "Continue with something else")
debug("Finished. Procastinate")
[debug]: Start doing something
[debug]: Continue with something else
[debug]: Finished. Procastinate
from functools import partial
def log(level, msg):
print(f"[{level}]: {msg}")
debug = partial(log, "debug")
debug("Start doing something")
debug("Continue with something else")
debug("Procastinate")
[debug]: Start doing something
[debug]: Continue with something else
[debug]: Procastinate
[info]: End
info = partial(log, "info")
warn = partial(log, "warning")
error = partial(log, "error")
from django.http import HttpResponse
JsonResponse = lambda content, *args, **kwargs: HttpResponse(
json.dumps(content),
content_type="application/json",
*args,
**kwargs
)
JsonOKResponse = partial(JsonResponse, status=200)
JsonBadRequestResponse = partial(JsonResponse, status=400)
JsonCreatedResponse = partial(JsonResponse, status=201)
JsonNotAllowedResponse = partial(JsonResponse, status=405)
from django.core.mail import send_mail
email_admin = partial(send_email<EMAIL_ADDRESS>email_general_it = partial(send_email<EMAIL_ADDRESS>email_marketing = partial(send_email<EMAIL_ADDRESS>email_sales = partial(send_email<EMAIL_ADDRESS># (...)
# In our services
if thing_is_broken():
email_admin(subject="It's brokened!", body='Fix it!')
# (...)
if sales_people():
email_sales(subject="sales stuff", body="business, business, business!")
curry: ((a × b) → c) → (a → (b → c)) = λf. λx. λy. f (x, y)
The technique of transforming a function that takes multiple arguments in such a way that it can be called as a chain of functions each with a single argument.
Partial application
from Wikipedia
def curry(fn):
def curried(*args, **kwargs):
return curry(partial(fn, *args, **kwargs)) if args or kwargs else fn()
return curried
@curry
def accumulator(*args):
return sum(args)
acc = accumulator(10)
acc = acc(12)(15)(22)
acc = acc(1)(1)
print(acc())
61
currencies = {
'GBP': 0.879700,
'JPY': 131.259995,
'EUR': 1.0,
'USD': 1.223200
}
@curry
def exchange(from_currency, to_currency, amount):
return amount * currencies[to_currency] / currencies[from_currency]
from_eur = exchange('EUR')
from_gbp = exchange('GBP')
from_eur_to_gbp = from_eur('GBP')
from_eur_to_usd = from_eur('USD')
from_gbp_to_eur = from_gbp('EUR')
print(from_eur_to_gbp(100.0)())
print(from_gbp_to_eur(87.97)())
print(from_eur_to_usd(10.0)())
87.97
100.0
12.232000000000001
I recently posted an entry in my Python History blog on the origins of Python's functional features. A side remark about not supporting tail recursion elimination (TRE) immediately sparked several comments about what a pity it is that Python doesn't do this, including links to recent blog entries by others trying to "prove" that TRE can be added to Python easily. So let me defend my position (which is that I don't want TRE in the language). If you want a short answer, it's simply unpythonic. Here's the long answer: (...)
Tail Recursion elimination
Posted by Guido van Rossum on April 22, 2009
import sys
sys.getrecursionlimit()
3000
def fib(n, sum):
return sum if not n else fib(n-1, sum+n)
fib(3500, 0)
<ipython-input-117-6cb630841faa> in fib(n, sum)
1 def fib(n, sum):
----> 2 return sum if not n else fib(n-1, sum+n)
3
4 fib(3500, 0)
RecursionError: maximum recursion depth exceeded
def fib(n):
a, b = 0, 1
for i in range(n):
yield a
a, b = b, a + b
tuple(fib(3500))
More resources at Awesome Functional Python.
...and
Follow the Zen of Python (PEP 20)
import this


[( #{registrationAlmostComplete} )]
[( #{confirmYourEmail} )] [( ${confirmationLink} )]
[( #{ignoreIfYouDidntSignUp} )]


--- layout: page pageid: contact show_flyout: false title: "Contact" description: "Contact Ted Serbinski." ---
Each week, I receive 1000s of emails. I try my best to respond, but usually, I just don't have the time to respond to every message. I do read every message and appreciate you taking the time to send me a thought.
Due to time constraints, I'll only respond to those messages that are a good match for my interests and schedule.
I appreciate your understanding!
Use the form below to send me a concise message. The limited message size ensures clarity with a specific ask. Also, read my 5 tips for writing a great email.
You can also try me on Twitter. The brevity and openness of that platform can make for great conversations. Tweet at @tedserbinski.


Applications are invited for the following programmes.
Click on the programme to download.
Application can be made on-line by entering all the particulars including marks along with on-line payment through the Net banking/Credit card/Debit card. Application can also be downloaded, duly filled and submitted along with demand draft in favor of "The Principal, PSG College of Technology" payable at Coimbatore. The duly filled in application along with demand draft (Cost is mentioned in the applications) can be submitted in person or shall be sent through post to “The Principal, PSG College of Technology, Post Box No. 1611, Peelamedu, Coimbatore - 641 004, Tamil Nadu, INDIA" and should reach on or before the last dates. Based on merit the students will be intimated & called for counselling / Online test /interview cum admission.
If you require further assistance, please contact the college office.
More Info Click on the programme to download the application.
Click on "Apply Online" for online submission.
Filled Application should reach on or before the dates mentioned below.
Please feel free to contact us if you require further assistance


Viktor Arvidsson injury update: Nashville Predators forward out 4-6 weeks
by Sammi SilberNashville Predators forward Viktor Arvidsson is expected to be out 4-6 weeks with a lower-body injury, the team announced Sunday.
Arvidsson was injured in the first period of Saturday's game against the St. Louis Blues, when he was cross-checked into the Blues' net by defenseman Robert Bortuzzo. He fell after hitting his head on the crossbar. As the 26-year-old tried to get up, Bortuzzo delivered another check to Arvidsson's back, knocking him down again before goaltender Jordan Binnington delivered another hit to the forward.
MORE: Bortuzzo suspended four games for hits on Arvidsson
Arvidsson skated off in pain and did not return to game action. Despite hitting his head on the play, the injury — which remains undisclosed — does not involve the upper body.
Bortuzzo was given a hearing on Sunday and received a four-game suspension for his actions.
In 22 games for Nashville this season, Arvidsson has six goals and 15 points.


Lecture Notes
a. Additional Resources
b. What is Big O
c. O(n)
d. O(1)
e. O(n^2)
f. Memoization
g. Fibonacci Numbers
h. Space Complexity
i. O(log n)
j. Determining Big O
k. The 3 Main Rules of Big O
If you found these notes helpful and want to show appreciation to the author, coffee donations are much loved.
Computing Big O Notes - Lambda
These notes are based off of Beej’s previous recording for CS13, which condenses the usual 4 hours of lecture down to 3.
The notes also pull from this simple overview of Big O Notation
Big O Breakdown of Data Structures and Sorting Algorithms
** Also included in this repo is a copy of Grokking’s Algorithms in PDF format. Big O Notation
begins on page 10.
Big O Notation is a way to determine how efficient a function is, based on run time and space requirements. It evaluates based on the worst case scenario of the function.
Big O Notation is a good indicator of how well an algorithm will scale.
Even if the function might run efficiently in some instances (small item list), it will evaluate based on the worst possible set of inputs. That does not mean an algorithm can’t or shouldn’t be used in some scenarios - it’s just important to consider, especially when building for scale.
Big O is considered the worst case evaluation while Big Theta is finds the average case.
When we discuss Big O, we’re evaluating as if on a graph (see BigO Graph.png file in repo folder). It’s essentially like graphing the time it takes to run the function with different sized inputs (an array of 1 item, 2 items, 3 items, etc).
The line that is shown on the graph displays the trend of that algorithm’s efficiency when handling small to large inputs.
O(n)
, called Order of N
or O of N
, refers to linear time
. Linear time means that for every additional item in the function’s input, that many operations are computed. 1 input? 1 operation. 10 inputs? 10 operations. The time complexity grows linearly with the number of inputs.
On the graph image, that is depicted by the green line of n
.
A good example of O(n) would be something like this:
def item_in_list(check_item, the_list):
for item in the_list:
if check_item == item:
return True
return False
This function receives an item and a list of items. It will pass over each individual item in the list to see if it matches with the given item. Because each item is being compared individually, the run time of this algorithm depends on how many items are in the_list. If it’s short, it will be fast. If it’s a long list, the run time will be much longer.
O(1)
, called Order of 1
, refers to Constant Time
. This means that no matter how large the input is, it will always take the same amount of time to run.
On the graph image, this is depicted by the pink line of 1
.
An example of O(1) is:
def is_none(item):
return item is None
No matter how many inputs are in item
that we give this function, the run time will always be the same - the time it takes to return None
.
It cannot run faster, but it also cannot run slower. Constant time is considered the best case scenario for a function because it cannot grow despite the complexity of the inputs.
O(n^2)
, called Order of n squared
, indicates that for every input item (n), we have to do that number squared (n^2 or n*n) operations. This is still considered proportional to the size of the input data set, just squared.
As you can imagine, that run time can become very slow, very quickly. If there are only 2 inputs, that would mean 4 operations. But if we have just 8 inputs, that’s already 64 operations being computed.
On the graph image, this is depicted by the red line of n^2
.
A common example of O(n^2) run time is a nested for loop (though that does not always indicate n squared time, so consider each one carefully).
An example might be:
def all_combinations(the_list)
results = []
for item in the_list:
for inner_item in the_list:
results.append((item, inner_item))
return results
This function matches each item within the_list with every other item in the_list. Therefore, if the_list = [1,2,3], it would output [(1,1), (1,2), (1,3), (2,1), (2,2), (2,3), (3,1), (3,2), (3,3)] - an output of 9 items, despite only 3 being in the input (n^2).
O(n^2) taps into Combinatorics (the mathematical study of combinations of things and counting) - but not every algorithm does, despite the common conception that most do.
Learn more about Combinatorics
Discrete Math is the basis of a lot of Computer Science (if you’re looking for further learning). Algebra, geometry and trigonometry are common if you’re planning to go into graphics. If you like 3D graphics, Linear Algebra is a good field of additional study too.
Memoization
is an optimization technique that speeds up a program or algorithm by storing the results of previous function calls in a cache, to easily access the result if the same call is made again. (This only works if, given the same input, the output is always the same.)
A cache
is a way of storing data that typically takes extensive computing, to speed it up. It’s less complete and durable than a database, so it typically only stores a subset of data. Browsers also use caching to load web pages faster, by not having to fetch and render data completely each time you re-visit a webpage. It’s a way we also store user preferences.
Memoization is best used when you notice that your algorithm is making the same calculations repeatedly. A good example is when solving the Fibonacci sequence. By storing previous results, the algorithm becomes much faster (rather than having to compute the same result each time).
Another way we might use memoization is by storing square roots, sin and cosine computations within a table when the function is created, to speed up the runtime (and add to the table when new outputs are run).
If you realize a function is being called often and the run time is slow, that’s a good sign that memoization would help speed it up.
If a database is being frequently queried for one or two types of input, and the table typically stays the same, to speed up the backend, we might opt to save those values and send them more quickly - rather than querying the database every time.
We can practice solving using dynamic programming techniques with the Fibonacci sequence.
In math, the Fibonacci sequence is numbers in order, where each number is the sum of the two preceding one, starting from 0 and 1.
F0 = 0
F1 = 1
F2 = 1 (0 + 1)
F3 = 2 (1 + 1)
F4 = 3 (2 + 1)
And so on.
0 and 1 are our base cases.
A basic way of writing it might look like this:
fib(0) = 0
fib(1) = 1
fib(n) = fib(n-1) + fib(n-2)
So let’s define the function and call it recursively:
def fib(n):
if n == 0:
return 0
if n == 1:
return 1
return fib(n-1) + fib(n-2)
for i in range(10):
print(fib(i))
This works and outputs the first 10 Fibonacci number.
Recursive solutions work and can make sense. But if we try to run it for range(30), our terminal will drastically slow down, due to the poor run time of this algorithm.
This is an example of…
O(2^n)
, called Order of 2 to the nth
, is exponential
time - for each additional input, the operations computed grow exponentially.
On the graph image, this is depicted by the dark orange line of 2^n
.
The standard Fibonacci calculation is a good example of this type of function, though we could optimize it to reduce the run time.
The basic solution could also be called a “naive” solution - it’s simple and brute force but doesn’t take into account larger inputs or scalability.
So how can we improve the Fibonacci sequence?
First, let’s consider why our current solution is not ideal. If we want to find fib(8), the function is recursively trying to solve:
fib(8) = fib(7) + fib(6)
fib(7) = fib(6) + fib(5)
fib(6) = fib(5) + fib(4)
fib(4) = fib(3) + fib(2)
We’re finding fib(n) multiple times for each higher integer - despite having already calculated it once before.
Instead, we could use a memoization (top down) solution, as well as an iterative (bottom up) solution. Both will improve our run time.
If we store values that were previously calculated in a table, we can instead just reference that memory in the table for duplicate calls. This uses a cache.
For our memoization (top down) solution, we’ll initialize a cache that will store calculated Fibonacci numbers. We’ll start with the two base cases of 0 and 1.
Then in our fib() function, if n is not currently in the cache, we’ll calculate it and store it. If it is in there, we’ll simply return the existing stored result.
cache = {}
def fib(n):
if n not in cache:
cache[n] = fib(n-1) + fib(n-2)
return cache[n]
cache[0] = 0
cache[1] = 1
for i in range(10):
print(fib(i))
As the function is run more and more, the cache will contain more and more stored Fibonacci numbers, making it faster to return results because it does not have to re-calculate each number, every time.
If we print the cache after this, it will look like:
{0: 0, 1: 1, 2: 1, 3: 2, 4: 3, 5: 5, 6: 8, 7: 13, 8: 21, 9: 34}
Every Fibonacci number in the range(10) was calculated and stored for future quick access.
This solution has O(n)
runtime.
Let’s now try computing bottom up, or iteratively, for an optimized solution that is not recursive. Usually an algorithm is either recursive or iterative.
We’ll start with our base cases and work our way up from that, by setting a base case of 0 and base case of 1. Then within a for loop, that runs to n-1 (because we want to have the range up to n, not including n), we’ll re-assign p0 and p1 to the next set of numbers up, to build to the next Fibonacci number.
def fib_iter(n):
if n == 0:
return 0
if n == 1:
return 1
p0 = 0
p1 = 1
for i in range(n-1):
next = p0 + p1
p0 = p1
p1 = next
return next
for i in range(10):
print(f'{i}: {fib_iter(i)}')
This solution builds up from the base cases, to store the outputs as the input increases. Rather than having to re-calculate the same value multiple times when working from the top down, building from the bottom up ensures that each number only needs to be calculated once.
The expected output would be:
0: 0
1: 1
2: 1
3: 2
4: 3
5: 5
6: 8
7: 13
8: 21
9: 34
(If we had left the algorithm at for i in range(n):
, it would have been outputting one number ahead of what it should have, because it would have initially set 2 to output 2 instead of 1 –> 2:2, 3:3, 4:5, 5:8, etc..)
So when we discuss scalability with algorithms, we’re really asking: How much longer does it take to calculate n+1 elements than n elements?
With the memoization and iterative optimized solutions, the algorithm becomes much more efficient, finding fib(1000) relatively quickly. With the O(2^n) brute force solution, fib(1000) is never output because the run time will stall out.
When our software or algorithmic solutions have to scale to large inputs, it’s critical to consider these Big O Notation concepts when deciding what type of algorithm or solution to use.
If our input will always be small, then using a brute force solution may be okay. It may not ever affect our user’s experience or output.
But in most cases, the code we write may need to handle an unknown future number of inputs, which means we want to write optimized algorithms to prevent future issues.
Space complexity refers to the amount of space used by an algorithm - O(n), linear, is using 10 units per 10 inputs. Memoization uses O(n) space complexity, wheras the iterative solution has constant space complexity: O(1).
We can analyze an algorithm for both space and time complexity.
If two algorithms are the same time complexity and memory usage is also important, we might opt for the iterative solution as the better choice. There may be different reasons to prioritize time and/or space complexity.
** Keep in mind:
when solving an algorithm problem (or whiteboard problem), finding any solution is the first and more important step. Optimizing is the next step. If you’re struggling to find an “elegant” or “optimized” solution, simply brute force first. Then openly find ways to optimize. Pre-mature optimization is not always ideal or necessary, as it typically increases the complexity of the code which makes it difficult to maintain and prone to bugs. Not every problem is worth those issues.
For example, if we knew we’d never need to find fib() greater than input 4, then optimizing is unnecessary. If we think it would grow to fib(100), then that’s a great reason to optimize.
Hash tables
(cache) takes up more space and are more complicated than lists, but they provide speed.
O(log n)
, called log time
, indicates a logarithmic run time function, of log base 2 (so, sometimes seen as O(log2n) ).
If we have n elements, it will take the log of n * inputs to run the calculations - it will take logn of time units. If we have 1 unit, that will take (roughly) 0 time units to run. If it were linear (O(n)), 10 units would take 10 times units - but with O(log n), 10 units would only take 3 time units. At 100 units, it will take only 6 time units.
Essentially, with log n, the choice of which next element to perform an action on is broken into a few possibilities, but only one is chosen. Typically, if each step involves halving the remaining number of units, that indicates O(log n).
For example, when searching in a phone book: if we are looking for “Smith” and open the phone book at random to “McDonald”, we intuitively understand that the data set we should next look at is not before McDonald but after. We mentally broke the phone book into two data sets - before M and after M. Based on comparison, we know that Smith is going to be found after M. The next data set we choose to look at is based on a break point chosen in our first whole data set.
On the graph image, this is depicted by the dark blue line of O(log2n)
.
O(log n) is faster than O(n), but its true speed advantage grows as the input items grow in number. The more inputs, the faster it is than O(n).
A good example of O(log n) is binary search
. With the binary search algorithm, a data set is halved on each iteration, and compares the median to the target value.
Because the number of inputs is halved repeatedly, doubling the size of the input data has little effect on its run time. Unlike O(n), which would continue to double with double the input data, O(log n) only becomes slightly slower. This makes O(log n) and binary search extremely efficient when dealing with large data sets.
If we were searching a phone book and used this example, what is the run time?
phonebook = ['Aaron', 'Angela', 'Andrew', 'Banana', 'Beej', 'Cameron', 'Cindy', 'Cynthia']
def name_in_phonebook(to_find):
for name in phonebook:
if name == to_find:
return True
return False
print(name_in_phonebook("Beej"))
This example is O(n) - it’s linear time. The run time will scale with the size of the phone book. While some names will be found faster than others (like Aaron, which is at the start of the list), we still calculate Big O based on the worst case scenario, or Big Theta based on the average case scenario.
On average, this search will take roughly half the number of inputs in time units. In the worst case, it will take as long as the number of inputs in time units. So, for our Big O evaluation, this runs with linear time.
Remember, Big Theta evaluation would also depend on if this function is being given an ordered list or not. If the list was not alphabetized, that may change the average time it takes to find the name.
We could optimize this if we know the list is organized by using binary search, to search the ordered list the same way a person would, by splitting the phone book into segments to narrow down our items as we search. By cutting the space in half each time, we would have an algorithm that is O(log n).
What if we looped through the index letters until we find a matching start letter with the name we’re searching for, and then loop through the values in the phone book that start with that letter?
Since we’re looping through the index of existing letters, it’s still O(n) because the time increases with the number of starting letters in the phone book. While it will max at 26 units of time, and grow only based on the values it then loops through with that starting letter, it is still O(n).
Although that method has two loops, they aren’t nested. It’s simply one loop that follows once the logic of the first loop is completed.
But wait - isn’t that actually O(2n)?
If O(n) of the first loop + O(n) of the second loop, wouldn’t that equate to O(2n)?
Yes - but when evaluating algorithms, we typically do not care about the integer in front of n in any linear time label. There are more advanced cases where it matters but in general, we care about the shape of the graphed line. For this example, whether O(n) or O(2n), the line will still be linear in shape, so we just refer to it as O(n).
What if we used a linear search to get to the right starting letter index (B) and then used Binary Search to find “Beej” within the B name?
O(n) + O(log n) = ?
If we provide some imaginary time units based on n growing in size…
If n=1,000: 1,000 + 10 = 1,010
If n=1,000,000: 1,000,000 + 20 = 1,000,020
Because O(n) is slower than O(log n), and Big O evaluates based on the worst case scenario, we would still evaluate this algorithm as O(n), because if n becomes extremely large (like 1000), the time complexity is still 1000.
O(n) will dominate the shape of the graphed line, because its larger time complexity dominates the overall time complexity of this algorithm. So we would consider it O(n) despite it including an O(log n) process too.
In short: When adding different Big O notations, evaluate based on the one that has the worst time complexity, aka the one whose time output will affect the overall run time the most.
What if we want to find out the time complexity of a function without looking at its source code? For example, when Python runs a search on a dictionary, how do we know how efficient it is and what method it’s using?
We could time the results and plot them, to see the shape of the trend line. This would require vast dictionaries with thousands or millions of items to see the way it handles large data sets.
When we want to evaluate an alogrithm for time complexity, there are two questions we’ll ask:
For a given number n, what is the maximum number of times the loop runs?
For a given number n, how many time units is it going to take to process?
Let’s take a look at this basic algorithm that finds the square root of the given number, and prints each whole number up to that square root.
import math
def foo(n):
sq_root = int(math.sqrt(n))
for i in range(0, sq_root):
print(i, sq_root)
If we print out a list of the given number (n) and the length of the output (meaning the number of times the algorithm loops), we can get a better idea of the relationship between the input and loop:
n sqrt(n)
1 1
2 1
3 1
4 2
5 2
6 2
7 2
8 2
9 3
10 3
11 3
12 3
Looking at this, it’s apparent that this algorithm is not linear because as the input grows, the loops do not increase similarly.
But it doesn’t exactly fit any of the other Big O Notations we’ve discussed either. So what would we describe this as?
 The graph shows the most common ones, but any could exist within the graph as well.
For example, an accurate description of this square root algorithm might be O(sqrt(n))
which is a valid time complexity. It’s a square root of n process. As n increases, the amount of time it takes to process this algorithm will increase by the square root of n.
As a programmer, when you write an algorithm like this, mentally you should be considering, “As n increases, it won’t loop through the entire range up to n, but instead it will loop through to the square root of n, which indicates this is a square root process.”
Just because it has a for loop does not mean it is O(n) - it’s how the loop processes that matters for the time complexity.
Let’s try another one.
def bar(n):
s = 0
for i in range(n):
for j in range(n):
s += i * j
return s
This has a nested for loop - so given number of n, what is the maximum number of times each loop runs?
We would assume this is O(n^2)
because of the nested for loop, but let’s adjust the function a little to print the number of times we loop through the i loop and j loop, to be certain:
def bar(n):
s = 0
i_count = []
j_count = []
for i in range(n):
i_count.append(i)
for j in range(n):
j_count.append(j)
s += i * j
return f's: {s}, i count: {len(i_count)}, j count: {len(j_count)}'
If we run print(bar(5))
, the terminal prints:
s: 100, i count: 5, j count: 25
Showing that the algorithm does in fact loop through n^2 times (5 * 5 = 25, and the j loop runs 25 times).
When you see a nested loop, it’s important to always stay alert to the problem that O(n^2)
can become slow very quickly. If the expected inputs will be large, that’s a good case for optimization.
Keep in mind, not all nested loops are O(n^2) though.
If we modify the previous loop to:
def baz(n):
s = 0
for i in range(n):
for j in range(int(math.sqrt(n))):
s += i * j
return s
What is the time complexity now?
Since we’re only running the inner loop O(sqrt(n))
times, does that change the time complexity to O(sqrt(n))
?
Again, let’s expand this algorithm out to see how many loops are running by printing a count for each:
def baz_expanded(n):
s = 0
i_count = []
j_count = []
for i in range(n):
i_count.append(i)
for j in range(int(math.sqrt(n))):
j_count.append(j)
s += i * j
return f's: {s}, i count: {len(i_count)}, j count: {len(j_count)}'
print(baz_expanded(25))
The terminal prints out:
s: 3000, i count: 25, j count: 125
If this algorithm were still O(n^2), the j count
would be 625.
O(n) * O(sqrt(n))
= O(n * sqrt(n))
= O(n sqrt n)
O(n) * O(sqrt(n)) = O(n * sqrt(n)) =
O(n sqrt n)
Let’s try another example:
def frotz(n):
s = 0
for i in range(n):
for j in range(2*n):
s += i * j
return s
What is the time complexity of this algorithm?
Before running it with printed counters, let’s consider…
The first loop runs for i in range(n)
which gives it O(n)
.
The second loop runs for j in range(2*n)
which gives it O(2*n)
.
The first loop runs for i in range(n)
which gives it O(n). The second loop runs for j in range(2*n)
which gives it O(2*n). But it’s also a nested for loop which means the time complexity is O(n^2) because the inner loop is not being limited.
n * 2n in this algorithm equates to 2 * n^2, or two times n squared.
Again we can expanded it out and print counters to see exactly how many times each loop runs:
def frotz_expanded(n):
s = 0
i_count = []
j_count = []
for i in range(n):
i_count.append(i)
for j in range(2*n):
j_count.append(j)
s += i * j
return f's: {s}, i count: {len(i_count)}, j count: {len(j_count)}'
print(frotz_expanded(5))
This prints out in the terminal:
s: 450, i count: 5, j count: 50
n = 5
n^2 = 25
2 * n^2 = 50
This algorithm does in fact have the time complexity of O(2 * n^2)
, as shown by the final loop count of 50, the exact output expected of O(2 * n^2) when the input is 5.
But remember that constants in Big O are dropped, so we would simplify this to O(n^2) process.
Despite this version taking twice as long as the simplified version, the shape of the curve is what we care about, not the exact time of the worst case scenario. Although the curve of this algorithm (O(2 * n^2)
)might be steeper than just O(n^2)
, the shape of the line is the same.
Constants don’t change the shape of the curve, only how steep it is. There is no number you can multiply n^2 by to change how the line bends, so although there are better and worse case scenarios within O(n^2) type algorithms, they are evaluated as equal in time complexity.
- Discard the constant
- The bigger Big O Notation dominates (less efficient wins)
- We’re interested in what happens with large values of
n
because some processes can be deceptively efficient with small values, but that doesn’t account for scalability.
For our last example, let’s try to figure out how many times each loop runs without running the algorithm first:
def booley(x):
sum = 0
for i in range(0, 1463):
i += sum
for j in range(0,x):
for k in range(x, x+15):
sum +=1
If we break this apart line by line, we can determine the time complexity of each loop individually and then determine how they relate to one another.
for i in range(0, 1463)
indicates constant time O(1)
because no matter how small or large x is, the time for calculating this will remain constant, even through i += sum
happens on each loop.
for j in range(0,x)
indicates linear time O(n)
because it will grow linearly depending on how large or small x is.
for k in range(x, x + 15)
indicates O(15)
or O(1) because it is a nested for loop that will run exactly 15 times, no matter how big or small x is. The range will always be from x to x+15.
Because all these loops are nested, we would multiply them together:
O(1) * O(n) * O(15) =
O(n)
Despite two nested loops, this algorithm has a linear run time of O(n)
.
When there are nested loops, we mutiply their time complexities to reach a final result; when the loops run independently (one after another completes), we add them together instead.
One more example:
def bogey(array):
print(array[1])
midpoint = len(array) // 2
for i in range(0, midpoint):
print(array[i])
for _ in range(1000):
print('hi')
len(array) // 2
is integer division that says the length of the array divided by two.
Let’s break it down, line by line:
print(array[1])
= O(1)
midpoint = len(array) // 2
= O(1)
for i in range(0, midpoint)
= O(n)
print(array[1])
= O(1)
for _ in range(1000)
= O(1)
print('hi')
= O(1)
When we combine these:
O(1) + O(1) + ( O(n) * O(1) ) + ( O(1) * O(1) )
Which combines down to:
O(1) + O(1) + O(n) + O(1) =
O(n)
Again, this algorithm evaluates down to a linear time complexity O(n).


Judge receives medical report showing Maina is fit to stand trial
by Bolanle OlabimtanA medical report the National Correctional Service (NCS) presented to a federal high court in Abuja on Monday showed that Abdulrasheed Maina, former chairman of the Pension Reforms Task Force (PRTF), is fit to stand trial.
Maina had been using ill health as an excuse to delay his trial.
On November 5, Okon Abang, the presiding judge, ordered the deputy comptroller of the NCS in charge of medicals and welfare to ascertain the true health status of the defendant.
Maina, who is standing trial on allegations of money laundering, has frequently appeared in court with the aid of walking sick.
He was wheeled into the court on November 7. On November 21, Francis Orasanye, his lawyer, informed the court that his client was bleeding from his nose.
However, at the resumed trial on Monday, M.S. Abubakar, the prosecution counsel, informed the court that Economic and Financial Crimes Commission (EFCC) on November 20, 2019, received a comprehensive report on Maina’s medical status from the prison service.
He said in the report signed by Remi Ojo, an assistant comptroller general (medical) of the service, only stated that Maina, 45 years old, has slight malaria and high blood pressure.
The report said Maina was suffering from high blood pressure but it has been brought under control.
“Maina vital organs are working normal. He is fit to stand trial.”
Consequently, Okon Abang, the judge, ordered the prosecution to serve the defence team with the report.


This section describes the changes and improvements between different versions of Varnish, and what upgrading between the different versions entail.
VTC
Changes in Varnish 5.1
Enter search terms or a module, class or function name.


We don't just know how the top search engines work; some of our team members have worked at the top tech companies to build them. onPeak focuses on crafting content to cater to the user experience. Simple, seamless and sleek is our motto, and we will ensure your customers can find you.
Your main concern with your business, should be running your business. Bookkeeping is a universal problem for many entrepreneurs but it doesn't have to be. onPeak offers bookkeeping services, as well as internal accounting to aid with planning and increased profit.
onPeak believes that the medium is the message, but the message still matters. We can help you manage inbound channels and ensure your writing meets the highest standard. Whether this is through blogging or the generation of media, onPeak can help.
We're extremely selective with who we work with at onPeak Consulting, and that's one of the reasons for our success. Usually we operate strictly on a referral basis, but if you have an interesting project feel free to send it our way!
Based in Canada, we've had the opportunity to work with domestic clients as well as international ones. We specialize in driving traffic to your business through improving marketing channels, or working deeper at the planning level. We aim to help small business succeed, and can aid in accounting, marketing, design and planning roles. As a boutique agency, we can devote resouces to all aspects of your business.


« CSS « CSS Reference
The
inherit
value is allowed on every CSS property. It causes the element for which it is specified to take the Computed value
of the property from its parent element.
For inherited properties, this reinforces the default behavior, and is only needed to override another rule. For example:
/* make second-level headers green */ h2 { color: green; } /* ...but leave those in the sidebar alone so they use their parent's color */ #sidebar h2 { color: inherit; }
Note that in this example the h2
elements inside the sidebar might be different colors. For example, if one of them were the child of a div matched by the rule
div#current { color: blue; }
it would be blue.
For non-inherited properties, this specifies a behavior that typically makes relatively little sense.
Inheritance is always from the parent element in the document tree, even when the parent element is not the containing block.
| Specification | Status | Comment |
|---|---|---|
| CSS Values and Units Level 3 | Working Draft | No significant change from CSS Level 2 (Revision 1) |
| CSS Level 2 (Revision 1) | Recommendation |
| Browser | Lowest Version |
|---|---|
| Internet Explorer | 8.0 |
| Firefox (Gecko) | 1.0 (1.0) |
| Opera | 4.0-7.0 |
| Safari (WebKit) | 1.0 (85) |


CARBS: joint spectrophotometric fitting with dense_basis and grizli¶
Contribute¶
Issue Tracker: https://github.com/kartheikiyer/dense_basis/issues Source Code: https://github.com/kartheikiyer/dense_basis Support If you are having issues, please let me know at<EMAIL_ADDRESS>License & Attribution¶
Copyright 2020 CANUCS team.
dense_basis is being developed by Kartheik Iyer in a public GitHub repository. The source code is made available under the terms of the MIT license.
grizli is being developed by Gabe Brammer in a public GitHub repository. The source code is made available under the terms of the MIT license.
If you make use of this code, please cite [include relevant citation].


Panasonic Center / LDL Design
- Curated by 韩爽 - HAN Shuang
- about 4 hours
Interior Design · Hangzhou, China
- version="1.0" encoding="UTF-8"? Architects: LDL Design
- AreaArea of this architecture projectArea: 1300.0 m2
- version="1.0" encoding="UTF-8"?YearCompletion year of this architecture project Year: 2019
- version="1.0" encoding="UTF-8"?PhotographsPhotographs: Yi Wang
- version="1.0" encoding="UTF-8"?ManufacturersBrands with products used in this architecture project Manufacturers: Panasonic, Shaw, Tikkurila, Timbertimes
- Lead Architects Juan Liu, Leo Yin
- Design team Guiyuan Liu, Yifa Shi
- Project Director Leon Zhang, Leo Yin
More Specs Less Specs
Text description provided by the architects. Panasonic Center Hangzhou is the third flagship store in the world after Osaka and Tokyo. Adjacent to the West Lake, it is located in Block B, Jiebai City Outlets, West Lake Business District. Panasonic Center, as an experience flagship store, unlike other flagship stores mainly specializing in offline sales, it is more focused on offline experience and interactive display in close range, so that consumers could obtain a more intuitive understanding of the products and brand itself, thus updating the image of the century-old Panasonic brand in their heart. In this regard, after a close discussion with the project team of Panasonic, the design team decided to start from several directions within the extremely limited design time, so as to realize the business goals set by Hangzhou Panasonic Flagship Store.
Time
Panasonic is a century Japanese company
Panasonic is a century-old Japanese company and time-honored precipitation has become one of the characteristics of Panasonic. In order to leave the imprints of time in the flagship store, the design team searched for the answer from the traditional Japanese architecture, and finally chose the representative traditional Japanese elements of square panes, which, after being refined, became more symbolic. After combining with the “scale sense” of traditional Japanese architecture, the building facade of the flagship store was re-constructed, allowing the abstract “time” to be visualized.
In the center of 2F, the design team introduced the concept of traditional Japanese courtyard and combined with modern design techniques to create a modern atrium atmosphere for the entire 2F. It is this series of design techniques that make the combination of tradition and modernity just to the point in a natural manner. In addition, in the flagship store, some time-imprinted “items” were also considered by the design team at the beginning of the design, such as Panasonic’s most classic historical products and the “Capsule Toys” derived from these products.
Space
Panasonic Center Hangzhou consists of two floors, with a usable indoor area of 1,033 square meters. Among them, hundreds of exhibited products and a large number of future activities were available for the design team as subjects. Therefore, in terms of the thinking direction, designers had been aimed at creating an efficient space that can be used flexibly in the future. After sorting out the space for many times, the design team chose “Panasonic Light Theatre” as the spatial theme for 1F and divided the forms of theatre, most of which were set as flexible display space to correspond to the theme, and flexibly displayed and constructed by the Panasonic project team in accordance with the theme of its own products.
In addition, the design team opened up the narrow main entrance to the original building facade, creating a transitional space between indoor and outdoor to ease the adverse conditions of being too close to the intersection, and specially set up barrier-free ramps to facilitate consumers. Moreover, a cafe area was set up in Wushan Road adjacent to the future pedestrian street in Hangzhou. At the same time, the curtain wall facing the street is opened, and an open bar and an outer booth were set to extend the indoor space to the outdoor. Inside it, the overall circular space and the highly layered arc-shaped LED wall soften the visiting line and the space, making the space more “dramatic”.
Located in the circular space, a spiral staircase connects 1F and 2F as a link. Meanwhile, a barrier-free elevator is specially set between the core cylinder of the staircase to provide more convenient services for consumers. Different from 1F, 2F serves as the exhibition of living space with a spatial theme of “Panasonic Light Life House”. Therefore, the design team referred to the rectangular grid planning of traditional Japanese streets for layout, forming a microscopic scene of Japanese downtown streets. Therefore, after consumers climb up the spiral staircase to 2F, they will see the exhibition area of featured products with the Japanese courtyard as the element. The difference in form strengthens its spatial contrast with 1F.
Other functions such as “Beauty”, “Light Catering” and “Cooking” are all centered on this, just like the layout of traditional Japanese downtown streets. Centered on “the courtyard”, the space is interconnected with each other, and the unity between materials and color tones makes the entire 2F a richer but not messy space. Therefore, when commercial activities or live broadcasts are carried out in any block of 2F, there will be no conflict between different spaces; instead, it will better set off the activity by contrast, making it more exciting and more active.
Life
Life is a philosophy, and a comfortable and beautiful life could heal people and give them hope. Designers not only give full consideration from the perspectives of vision and space, but also pay great attention to the creation of the environment and atmosphere so that Panasonic Center Hangzhou could have an atmosphere of life. All the small objects and plants in the space are arranged to make consumers feel the beautiful and relaxed life atmosphere in this experience flagship store with the purpose of conveying the brand spirit of Panasonic: “A Better Life A Better World”.


A sorting algorithm:
Compare items 1 and 2; swap them if necessary
Compare 2 and 3; swap if necessary; then 1 and 2 again;
Compare 3 and 4, then 2 and 3, then 1 and 2;
etc.


"The Man in the Iron Mask" - The Sword is Mightier than the Pen by Homer Yen (c) 1998
TMITIM does a couple of smart things to ensure that potential movie-goers will at least think about seeing this film. First, it's a story that soothes us with the familiarity of Aramis, Athos, Porthos and D'artagnan - the legendary four Musketeers. Little introduction is needed about these men, and we can quickly jump into the story. Louis XIII, the great King whose throne the Musketeers served, has died and has now been succeeded by his arrogant and cruel heir, Louis XIV (Leonardo DiCaprio). The original three Musketeers have now retired from service and now live relatively quiet lives. D'artagnan, still an active Musketeer, is now Captain of the young king's bodyguards.
Louis XIV is not a well-liked King. His selfish actions result in deep resentment by the people. He is the target of numerous assassination attempts. He is also greatly disliked by the retired Musketeers, who believe that this is a leader truly unworthy of a Musketeer's devotion. However, their ire for the king puts them at odds with D'artagnan, who has sworn an oath to protect the king with his life. Nonetheless, the original three know that France will never prosper unless a change is made. A bold plan is devised, and it's success rests on the Man in the Iron Mask, a mysterious figure that was imprisoned years ago and almost forgotten. The three Musketeers must first devise a way to free him and then execute their plan. If they succeed, they could alter the future of France. But, their biggest obstacle is D'artagnan.
The other attractive element is that the film puts together an all-star ensemble. Co-starring Jeremy Irons, John Malkovich, Gerard Depardieu, and Gabriel Byrne as the Musketeers, it has tremendous international star power and mass appeal.
Yet, despite all these positive points, the story never comes close to reaching the legendary status of the Musketeers. One thing that was unsettling was listening to the actors lines. At times, they spoke using the 'Dialect of Infinite Wisdom' (where one speaks so slowly as if to simulate awesome intelligence), which was void of any conviction or passion. At other times, the banter was so tongue-in-cheek that it seemed to purposely anchor itself in swashbuckling commercialism rather than dramatic greatness. Still, at other times, the dialogue seemed so forced that actors looked like they were straining not to look or sound foolish.
Written by Randall Wallace, the same person that wrote "Braveheart", I really expected a powerful drama that would explore the rift between D'artagnan and the Musketeers; the motivating nature behind the young king; or even the possibilities that present itself when an impostor with ambitions of sheep-tending assumes the almighty throne. Yet it seemed content on just being an action-adventure film about old heroes that reunite to bring back an era that had been forgotten.
I felt that a potentially great film was squandered. TMITIM is an uneven production that was glorious at some points but unfocused at others. I did, however, enjoy Gabriel Byrnes as D'artagnan, who desparately tried to find a balance between his oath to the king and his ability to live up to the code of the Musketeers. And the climactic ending is a rousing finish that shows how good this film could have been. But for much of this film, we needed a fifth Musketeer. His name could have been Pathos!
Grade: B-
The review above was posted to the
rec.arts.movies.reviews newsgroup (de.rec.film.kritiken for German reviews).
The Internet Movie Database accepts no responsibility for the contents of the
review and has no editorial control. Unless stated otherwise, the copyright
belongs to the author.
Please direct comments/criticisms of the review to relevant newsgroups.
Broken URLs inthe reviews are the responsibility of the author.
The formatting of the review is likely to differ from the original due
to ASCII to HTML conversion.
Related links: index of all rec.arts.movies.reviews reviews


My Skills
HTML5
Python
Android
Previous Work
Banking App
A bank management web app
Client Testimonials
Yash Katara
Founder: Java Bank
"Sagar is an excellent partner to work with."
Yash Dadwani
Founder: Java Bank
"Sagar is an excellent partner to work with."
Nishkarsh Goyal
Founder: Java Bank
"Sagar is an excellent partner to work with."


By default, when the dateWindow
or updateOptions
of a chart is changed programmatically by a call to updateOptions
the zoomed flags (isZoomed
) are changed. This is the same
as manually zooming in using the mouse.
Sometimes it may be desirable to change the display of the chart by
manipulating the dateWindow
and valueRange
options but without changing the zoomed flags, for example where manual
zooming is still required but where it is also desired that the zoomed
flags drive display elements, but only for manual zooming.
In this case isZoomedIgnoreProgrammaticZoom
may be specified along with
either the dateWindow
or valueRange
values to
updateOptions
and the zoomed flags will remain unaffected.
The chart below may be manipulated to change the updateOptions
using the Max and Min Y axis buttons and the dateWindow
by using the Max and Min X axis buttons.
Toggle the check box below to determine the difference in operation of the zoom flags when the date and value windows of the chart are changed using the arrows underneath.
Do not change zoom flags (isZoomedIgnoreProgrammaticZoom
)
Max Y Axis:
Min Y Axis:
Min X Axis:
Max X Axis:
Zoomed: False
Zoomed X: False
Zoomed Y: False


FACE OF RHOSYFACEBEAT 2021
Register
Login
CONTACT
Visit Our Studio Today
© 2020 Copyright: RHOSAY FACEBEAT, All right reserved. Privacy and Legal Policies


home
Browse Job
Contact
Log in
Post a Job
MENU
home
Browse Job
Contact
Student Profile
Please fill the following information
select
Enrolled
Unrolled
Student Status
select
Enrolled
Unrolled
Select program
CIT
Bussiness Management
Marketing
Agriculture
Program Enrolled For
Select program
CIT
Bussiness Management
Marketing
Agriculture
Upload Resume
Upload Cover Letter
Submit


starship init --help- Print the starship integration code for the specified shell:
starship init bash|elvish|fish|ion|powershell|tcsh|zsh- Append the `starship` integration code to `~/.bashrc`:
starship init bash >> ~/.bashrc- Append the `starship` integration code to `~/.zshrc`:
starship init zsh >> ~/.zshrc


C programmers:
your program name must be: prob04.exe
JAVA
programmers: your program name must be: prob04.class
Task
Description
Many persons are familiar
with the Roman numerals for relatively small numbers.
The symbols ``I", ``V", ``X", ``L", and ``C" represent
the decimal values 1, 5, 10, 50, and 100 respectively.
To represent other values, these symbols, and multiples
where necessary, are concatenated, with the
smaller-valued symbols written further to the right.
For example, the number 3 is represented as ``III", and
the value 73 is represented as ``LXXIII". The
exceptions to this rule occur for numbers having units
values of 4 or 9, and for tens values of 40 or 90.
For these cases, the Roman numeral representations are
``IV" (4), ``IX" (9), ``XL" (40), and ``XC" (90).
So the Roman numeral representations for 24, 39, 44, 49,
and 94 are ``XXIV", ``XXXIX", ``XLIV", ``XLIX", and ``XCIV",
respectively.
The input will consist of
a sequence of integers in the range 1 to 100.
You are to write a program
that prompts the user to enter a positive integer and
responds by printing out the equivalent Roman Numeral.
The program should terminate when the user enters 0.
Program Input
/ Output
Enter a number:
1
The Roman Numeral for 1 is I
Enter a number:
2
The Roman Numeral for 1 is II
Enter a number:
1
The Roman Numeral for 1 is I
Enter a number:
20
The Roman Numeral for 20 is XX
Enter a number:
99
The Roman Numeral for 99 is IC
Enter a number:
0
|


GUILTY PLEA REPORTED IN SMUGGLING OF CHINESE INTO N.J.
NEWARK, N.J. _ Intensifying their investigation of the smuggling
of Chinese immigrants into the United States, a federal prosecutor
said Tuesday that one of the crew members of a smuggling ship that
ran aground in New Jersey had pleaded guilty to conspiracy charges
and another was expected to plead guilty later this week.
At the same time, the prosecutor, Carolyn Murray, an assistant
U.S. attorney in New Jersey, said that the 23 Chinese immigrants
who arrived aboard that smuggling ship and have since been detained
by the authorities as witnesses in the federal investigation would
probably be released on bond soon. Beginning next week, the federal
government plans to take depositions from some of the 23 in a
process that should take several weeks, and at its conclusion, will
allow the immigrants to be released.
``The whole purpose of the depositions is to keep the amount of
time they spend in custody as witnesses to a minimum,'' Ms. Murray
said after a calendar conference with defense lawyers before Judge
Dickinson Debevoise in U.S. District Court here. So far, the
illegal immigrants have been detained for more than two months.
Tuesday's proceeding was not a formal hearing; it was more a
matter of legal necessity to coordinate schedules and logistics as
the summer winds down. Even so, the conference hinted at how the
government is proceeding with its investigation into the smuggling
of illegal immigrants, and what lies ahead for the principal
players involved.
The federal government is investigating the events surrounding
the evening of May 30, when a power boat carrying the illegal
immigrants ran aground in a soupy fog in the affluent town of Bay
Head, N.J., some eight miles north of the intended destination,
Belmar, N.J.
The case attracted additional attention, no doubt, because of
its parallels with the case of Golden Venture, a larger ship that
was carrying 286 illegal Chinese immigrants when it sputtered to a
halt in Queens in 1993. There was cruel coincidence, too: The name
of the powerboat in this case was the Oops II.
Last month, the federal government indicted six men in a
conspiracy to smuggle the 23 Chinese men into the United States.
The six were accused of participating in an international smuggling
operation that solicited as much as $40,000 apiece from anyone
interested in being taken from Fujian province in southern China
via South America to the United States.
Five of the six are being held without bail in New Jersey jails;
the other, Charng Seon Choi, is still at large. One man facing
smuggling charges, Kim Jong Che, has said that he was born in Korea
but lives in Venezuela, while the backgrounds and residences of the
other defendants remain unclear.
But last week, another of the six, Cho Yang Nam, pleaded guilty
to one conspiracy charge, acknowledging that he plotted with
unnamed others to smuggle the Chinese immigrants, according to
court documents. He has since agreed to cooperate with
investigators, which could pare his sentence from its maximum of 10
years in jail and a $250,000 fine, the documents show.
Cho's guilty plea was not disclosed until Tuesday, however,
because of case strategy, Ms. Murray said. Another man accused of
smuggling, Nam Jick Cho of Bayside, Queens, may plead guilty this
week, she said.
Neither of the Chos _ who prosecutors say are not believed to be
related _ appeared in court Tuesday. But the other three accused
men in custody _ Che, Piao Zhen Jia and Jiang Yong Zhu _ did show
up in the courtroom, looking stone-faced while listening to a
translator. The trial is scheduled to being on Nov. 17.
As for the illegal immigrants, they were first held in an
Immigration and Naturalization Service detention center in
Elizabeth, N.J. Most were released in mid-July on bond by two
immigration judges, only to be immediately rearrested by federal
authorities as witnesses in the federal investigation.
For now, the 23 men remain in government custody, most in the
Passaic County Jail. But some of the men briefly escaped the
loneliness of being imprisoned in a foreign land when they were
reunited last month with several relatives who appeared in
immigration court in Elizabeth to offer testimony to support the
men's release on bond.
Now, the prospect of reunions lasting more than a few minutes,
and occurring outside of a courtroom, looms larger. Within a week
or so, federal prosecutors are expected to whittle the list of 23
to about 10 or so men from whom they plan to take videotaped
depositions.
Those who are not deposed presumably will be released
immediately; those who are formally questioned will be released
after their depositions, assuming no further legal complications,
Ms. Murray said.
Of course, the men still face deportation hearings by the INS.
But most have filed for political asylum.


Grocer
Cart
(0)
×
Sections
Produce
Deli
Frozen
Groceries
Produce
Onions
$1.11
Add to cart
Tomatoes
$1.56
Add to cart
Carrots
$2.88
Add to cart
Deli
Cold Cuts
$1.47
Add to cart
Frozen
Orange Juice
$2.52
Add to cart
Ice Cream
$14.08
Add to cart
Pizza
$16.61
Add to cart


OpenAPI Tree Pots
Example spec
Version: 1.0.0
BasePath:/v2
All rights reserved
http://apache.org/licenses/LICENSE-2.0.html
Access
[ Jump to Models ]
Table of Contents
(op199)
Return type
Example data
Content-Type: application/json
{
"firstName" : "firstName",
"lastName" : "lastName",
"id" : 0
}
Produces
This API call produces the following media types according to the request header;
the media type will be conveyed by the response header.
Responses
200
a pet to be returned
SomeObject
default
Unexpected error
ErrorModel
Update an existing pet (getCase1)
Return type
Example data
Content-Type: application/json
{
"name" : "name",
"active" : true,
"id" : 0
}
Produces
This API call produces the following media types according to the request header;
the media type will be conveyed by the response header.
Responses
200
Ok
ItemWithBoolean
(getPolymorphic)
Return type
Example data
Content-Type: application/json
{
"firstName" : "firstName",
"lastName" : "lastName",
"id" : 0
}
Produces
This API call produces the following media types according to the request header;
the media type will be conveyed by the response header.
Responses
200
a pet to be returned
SomeObject
Codegen (issue7754)
Return type
Example data
Content-Type: application/json
{
"Long2" : 6,
"Long1" : 0
}
Produces
This API call produces the following media types according to the request header;
the media type will be conveyed by the response header.
Responses
200
Ok
LongModel
(op708)
Query parameters
bar (optional)
Query Parameter — default: foobar
Responses
default
successful operation
(op75)
Return type
Example data
Content-Type: application/json
{ }
Produces
This API call produces the following media types according to the request header;
the media type will be conveyed by the response header.
Responses
200
Ok
ObjWithEnums
(pull66)
Consumes
This API call consumes the following media types via the request header:
Request body
Responses
200
Ok
[ Jump to Methods ]
Table of Contents
Element
-
Enum2WithCustomName
-
EnumInArrayOfArray
-
EnumWithCustomName
-
ErrorModel
-
Int2Enum
-
IntEnum
-
ItemWithBoolean
-
Leave
-
Leave_allOf
-
Long2Enum
-
LongEnum
-
LongEnumWithCustomName
-
LongModel
-
Node
-
Node_allOf
-
ObjWithEnums
-
SomeObject
-
String2Enum
-
StringEnum
-
Task
-
Weather
-
p1 (optional)
p2 (optional)
p3 (optional)
statusCode (optional)
Integer http status code format: int32
statusDescription (optional)
String http status reason phrase
errorMessage (optional)
id (optional)
active (optional)
name (optional)
id (optional)
type
value (optional)
Long1 (optional)
Long2 (optional)
id (optional)
type
childrenIds (optional)
IProp (optional)
LProp (optional)
SProp (optional)
IProp2 (optional)
LProp2 (optional)
SProp2 (optional)
Custom (optional)
id (optional)
firstName (optional)
lastName (optional)
status (optional)
OPEN
CLOSED


{% extends "base.html" %} {% block title %}About{% endblock %} {% block head %} {{ super() }} {% endblock %} {% set active_page = "about" %} {% block content %}
With all the discussion taking place about curated feeds, I thought it would be nice to at least have the alternative to get access to my subscribed channels in an unfiltered way.
This was the idea that triggered the creation of allmysubs.video. With this project, I try to stay as transparent, as I possibly can. The sources are open on GitHub, the app currently only requires reading permissions of your YouTube account (otherwise, the subscribed channels cannot be read).
The functionality is very limited right now: For every channel, that you have subscribed to, it reads the information of the five latest video and presents this list in chronological order. That's all.
If you like the idea, you probably have as many ideas how and what to build on this foundation, as I do. Please, join the discussion and leave some Feedback.
Thanks to my friends Defender833 and Istani for their support, ideas and early testing.
If you want to support me, consider joining the development and watch some of my videos. Thanks, Andreas
SUBSCRIBE


Youth found murdered in Ambattur
Search on for youth from Odisha who worked at the unit
by Special CorrespondentA 27-year-old youth was murdered at a manufacturing unit in Ambattur Industrial Estate on Friday.
The police have launced a manhunt to nab two suspects from Odisha, who worked at the unit owned by the father of the deceased.
S. Anandan runs the unit for moulding iron material. His son, A. Prabakaran, left his house in Vyasarpadi early on Friday, and did not return. His mobile phone was switched off. Mr. Anandan then got to the unit, and found its door open.
 Initial investigation revealed that a few workers from Odisha were the last to be seen with him.
The police suspect that they had a quarrel with Prabakaran, which may have led to the murder.


Firestorm is an ORM for firestore which can be used with Typescript.
This library currently only supports the client Firebase SDK.
Firestorm relies on using Typescript's
experimental decorators
for defining your models. Please ensure you have the following in your tsconfig.json
(ES5 is minimum target):
{
"compilerOptions": {
"target": "ES5",
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
}
}
$ npm install firebase-firestorm
In this section, we will walk you through an example of how a basic blogging database might look using posts, comments and authors.
Call firestorm.initialize(firestore, options?)
as soon as you initialize
your firestore app. See intialization options
for more information about intiailizing firestorm.
import * as firestorm from 'firebase-firestorm';
...
const firestore = firebase.initializeApp(...).firestore();
firestorm.initialize(firestore, /* options */);
...
Here we have a class representing a posts
collection. Entity classes are
typically non-pluralized as they represent a single document from that
collection. To define a root collection you must:
Entity
class.@rootCollection(opts: ICollectionConfig)
.@field(opts: IFieldConfig)
.import { Entity, rootCollection, field } from 'firebase-firestorm';
@rootCollection({
name: 'posts',
})
export default class Post extends Entity {
@field({ name: 'title' })
title!: string;
@field({ name: 'content' })
content!: string;
}
Each of your models, whether they represent a root collection or subcollection must extend from the
Entity
class provided.
Now we want documents in the posts
collection to have a subcollection
of comments
. First, we need to create a class for the comments. Notice
how we do not annotate the class with @rootCollection
.
import { Entity, rootCollection, field } from 'firebase-firestorm';
export default class Comment extends Entity {
@field({ name: 'content' })
content!: string;
@field({ name: 'by' })
by!: string;
}
Back in the Post
class, we can add Comment
as a subcollection using the @subCollection(opts: ISubcollectionConfig)
decorator.
import { Entity, ICollection, rootCollection, field } from 'firebase-firestorm';
import Comment from './Comment';
@rootCollection({
name: 'posts',
})
export default class Post extends Entity {
@subCollection({
name: 'comments',
entity: Comment, // we must define the entity class due to limitations in Typescript's reflection capabilities. Progress should be made on this issue in future releases.
})
comments!: ICollection<Comment>;
...
}
Finally we want documents in the posts
collection to reference an author in
an authors
collection (another root collection). First, we define the Author
entity:
import { Entity, rootCollection, field } from 'firebase-firestorm';
@rootCollection({
name: 'authors',
})
export default class Author extends Entity {
@field({ name: 'name' })
name!: string;
}
Then we can add an Author
reference to the Post
entity using the @documentRef(opts: IDocumentRefConfig)
decorator:
import { Entity, ICollection, IDocumentRef, rootCollection, field } from 'firebase-firestorm';
import Author from './Author';
@rootCollection({
name: 'posts',
})
export default class Post extends Entity {
@documentRef({
name: 'author',
entity: Author, // we must define the entity class due to limitations in Typescript's reflection capabilities. Progress should be made on this issue in future releases.
})
author!: IDocumentRef<Author>;
...
}
Now we've built our model, we're ready to start querying. Calling
Collection(entity : IEntity)
will return a list of methods use can
use to manipulate the data.
const post = Collection(Post).get('post-1').then((post : Post) => {
console.log(post);
});
In our example Comment
is a subcollection of Post
. You can get
subcollections from a retrieved document, or a document reference.
// Comment subcollection from document.
const post = Collection(Post).get('post-1').then((post : Post) => {
const commentCollection = post.collection(Comment);
});
// Comment subcollection from document ref.
const postRef = Collection(Post).doc('post-1');
const commentCollection = postRef.collection(Comment);
// Finds all comments from commentCollection.
const commentsSnap = await commentCollection.find();
Calling query()
on a collection will allow you to build queries in a similar fashion to the standard Firestore SDK. You can build a query by chaining together methods, and finally calling the get()
method to fetch the result. Omitting filters after the query()
method will return all results from a collection.
// Build the query.
const query = Collection(Post)
.query()
.where('title', '==', 'Example Title');
// Fetch and manipulate the result.
query.get().then((snapshot) => {
const post = snapshot.docs;
...
});
const post = new Post();
post.id = 'post-1'; // id is optional, if it is not defined it will be generated by firestore.
post.title = 'Untitled';
let savedPost : Post;
Collection(Post).create(post).then((_savedPost : Post) => {
savedPost = _savedPost;
});
const post = new Post();
post.id = 'post-1'; // id is required.
post.title = 'Untitled';
let savedPost : Post;
Collection(Post).update(post).then((_savedPost: Post) => {
savedPost = _savedPost;
});
Collection(Post).remove('post-id').then(...);
You can set up listeners for changes on either a single document, or a group of documents for a query. This is done a similar way to the standard Firebase SDK.
You can attach a listener to a single document reference by using the onSnapshot(callback)
method.
Collection(Post).doc('post-id').onSnapshot(
(snapshot): DocumentSnapshot<Post> => {
const post: Post = snapshot.doc;
}
);
...
The callback function will executed once with the initial snapshot payload, and then for any subsequent updates to that document.
You can attach a listener to a group of documents in a collection by using the onSnapshot(callback)
method on a collection query.
Collection(Post).query().onSnapshot(
(snapshot): QuerySnapshot<Post> => {
const posts: Post[] = snapshot.docs;
}
);
// or
Collection(Post)
.query()
.where('title', '==', 'Example Title')
.onSnapshot(
(snapshot): QuerySnapshot<Post> => {
const posts: Post[] = snapshot.docs;
}
);
The callback function will executed once with the initial snapshot payload, and then for any subsequent updates to that query. As per the Firebase SDK, you call see the document changes in each snapshot using the snapshot.docChanges()
method.
An instance of entity maybe contain properties such as
subcollections which you do not wish to include if, for example,
you are building a REST API. Calling the toData()
method on
an instance of an entity will produce a plain JSON object
containing just primitive data, nested JSON objects, and
document reference which have already been retrieved using
the .get()
method. For example:
import { Collection } from 'firebase-firestorm';
import Author from './Author';
import Post from './Post';
Collection(Post).get('post-1').then((post: Post) => {
console.log(post.toData());
/*
Output:
{
id: ...,
title: ...,
content: ...
}
*/
post.author.get().then((author: Author) => {
console.log(post.toData());
/*
Output:
{
id: ...,
title: ...,
content: ...,
author: {
id: ...,
name: ...
}
}
*/
});
});
Firestore documents can contain arrays of strings, numbers, objects,
etc. Defining arrays in Firestorm is as simple as assigning properties
as array types in your Entity
files. For example:
class Example extends Entity {
@field({ name: 'example_property_1' })
property1!: string[];
@field({ name: 'example_property_2' })
property2!: IDocumentRef<AnotherEntity>[];
}
Firestore documents can contains nested objects (or maps). For a nested
object, you need to create a new class to represent that object, and add
a property with that class in your Entity
, wrapped with the @map
decorator.
class Example extends Entity {
@map({ name: 'nested_object' })
nestedObject!: Nested;
}
class Nested {
@field({ name: 'nested_property' })
nestedProperty!: string;
}
And then to use this entity:
const nested = new Nested();
nested.nestedProperty = 'test';
const example = new Example();
example.nestedObject = nested;
Important: If your is nested data is an array you must provide the 'entity' option in the configuration.
class Nested {
@map({ name: 'nested_array', entity: Nested })
nestedObject: Nested[];
}
Geopoints store locational data and can be used as fields. We have a wrapper class for firestore's GeoPoint which basically serves the same functionality.
class Example extends Entity {
@geoPoint({
name: 'geopoint_property',
})
geopoint!: IGeoPoint;
}
And then to assign a GeoPoint:
const example = new Example();
example.geopoint = new Geopoint(latitude, longitude);
You can represent date & time data in your Entity
files. Like geopoints,
our timestamp representation is essentially a wrapper of firestore's. You
can set the options for the field to updateOnWrite
which uses the server
timestamp when creating or updating documents, or updateOnCreate
or updateOnUpdate
.
class Example extends Entity {
@timestamp({
name: 'timestamp_property',
updateOnWrite: true,
})
timestamp!: ITimestamp;
}
firestorm.intialize({ ...opts : IFireormConfig })
can be called
with the following options:
| Option | Description | Type |
|---|---|---|
fieldConversion |
Providing this option will convert Entity propertity names into firestore collection names so you don't need to provide the name option in @field() decorators. To view available values please check out the docs. |
enum FieldConversionType |
All files for root collections, subcollections and nested maps must have a unique class name due to the way the metadata storage hooks everything up. We're currently looking for a way to resolve this issue.
Make sure fields such as geopoints, timestamps and document
reference's have the I
infront of the type, e.g. IDocumentRef
,
ITimestamp
, IGeoPoint
.
If you would like to help resolve these issues, feel free to make a a pull request.
cd firebase-firestorm
npm install
The testing script looks for *.spec.ts
files in the src
and test
directory.
npm test
Please report any bugs you have found submitting an issue to our Github repository, after ensuring the issue doesn't already exist. Alternatively, you can make a pull request with a fix.
If you would like to help add or a feature or fix a bug, you can do so by making a pull request. The project uses Conventional Commits, so please make sure you follow the spec when making PRs. You must also include relevant tests.
Generated using TypeDoc


✎ Edit
Photo:
Description:
"
"
on
Location:
Features:
Reviews:
[+
Add Review
]
👍
👎
said:
❝
❞
Reviewed on


Breaking Benjamin is an American rock band from Wilkes-Barre, Pennsylvania, consisting of Benjamin Burnley, Aaron Fink, Mark Klepaski and Chad Szeliga. The band has released four albums to date. The group is currently on hiatus due to frontman Benjamin Burnley's recurring illnesses and is unable to tour for the time being.


For this section the batch size was fixed to TODO. The model was then trained for TODO epochs with learning rate linearly increasing from TODO to TODO over the entire length of this training. At each iteration (i.e, each batch), TODO points were selected randomly from the training set and the loss was calculated and stored (without propagating any gradients for these points). This was repeated for TODO different random initializations of the model. For analysis, we ignored learning rates at or greater than the lowest learning rate that caused network explosion (NaNs) in any of the trials.
Prior to starting the sweep for each model, the model was "warmed up" to reduce the bias toward the beginning where improvements are faster. The model was warmed up for TODO samples with a fixed learning rate of TODO and batch size of TODO.
After this process, there was a trial dimension, x dimension (learning rates), and y dimension which was transformed to 1/(loss+1). The trial dimension was coalesced using LogSumExp. The result was then smoothed with a Savitzky-Golay filter with window size TODO and polynomial order 1 (a linear convolution). The derivative of 1/(loss+1) with respect to learning rate of this smoothed filter was approximated as described here. This result was again smoothed with the same linear convolution. Then the smallest set of intervals in which within each interval the derivative was strictly positive was calculated, such that every point where the derivative was positive was in one of the intervals in this set. From there, the widest interval was determined. If this interval had long tails, i.e., if it was possible to reduce the interval width without correspondingly impacting the integral of the derivative over the interval, this was done (see range_finder.py for details).
After this process, it was concluded that learning rates between TODO and TODO were reasonable for the given batch size.
For this section, it was assumed that a good learning rate for a batch size of TODO is TODO. Further, it was assumed that multiplying the batch size by any factor requires multiplying the learning rate by the same factor. The model was trained for TODO epochs with batch size linearly increasing from TODO to TODO. The batch size for each iteration was selected based on the number of preceeding points, i.e., if there were 10 points total and the range of batch sizes was (1, 2, 3, 4, 5) then the batch sizes would be distributed to the points as (1, 1, 2, 2, 3, 3, 4, 4, 5, 5) and then the actual batches would be (1, 1, 2, 3) for the first epoch. The leftover points at the end of training (not at the end of each epoch) were clipped.
After each iteration (ie. each batch), TODO points were selected randomly from the training set and the loss was calculated and stored (without propagating any gradients for these points). This was repeated for TODO different random initializations of the model. After this process, where-ever there were batch sizes with multiple values (as in the above example there were multiple batches with size 1), the loss for that batch size was taken as the mean over each of the losses collected after a batch with that size.
After this process, there was a trial dimension, x dimension (batch sizes), and y dimension which was transformed to 1/(loss+1). A good range for batch sizes was selected at this point using almost the same technique as for learning rate at this stage. The only difference is that the derivative of the LSE was not smoothed as it was not found to be necessary. The result was that good batch sizes fall between TODO and TODO.
The mean of this range, TODO, was selected.
From this range, TODO points were selected from a distribution biased toward a higher derivative of inverse loss relative to batch size (i.e., a batch size with derivative 2r was twice as likely to be picked as one with derivative r for all real values r). The points selected were TODO. For each selected point, TODO trials were performed over different random initializations of the model, each for TODO epochs. This corresponded precisely to one cycle of the learning rate. After training, the loss for the model on the entire training set was computed. The LogSumExp over the trial dimension of the final 1/(loss+1) of each of the batch sizes was computed, and the best of them was selected. This corresponded to a batch size of TODO.
The final learning rate was simply the learning rate found in the initial sweep modified to account for the new batch size linearly. Hence, the final learning rate range was from TODO to TODO
For this section the batch size was fixed to TODO, the value from the batch size sweep. The model was then trained for TODO epochs with learning rate linearly increasing from TODO to TODO over the entire length of this training. The range was adjusted based on the new batch size, such that we maintain the same ratio of learning rate to batch size. At each iteration (i.e, each batch), TODO points were selected randomly from the training set and the loss was calculated and stored (without propagating any gradients for these points). This was repeated for TODO different random initializations of the model.
Prior to starting the sweep for each model, the model was "warmed up" to reduce the bias toward the beginning where improvements are faster. The model was warmed up for TODO samples with a fixed learning rate of TODO and batch size of TODO.
After this process, there was a trial dimension, x dimension (learning rates), and y dimension which was transformed to 1/(loss+1). The trial dimension was coalesced using LogSumExp. The result was then smoothed with a Savitzky-Golay filter with window size TODO and polynomial order 1 (a linear convolution). The derivative of 1/(loss+1) with respect to learning rate of this smoothed filter was approximated as described here. Then the smallest set of intervals in which within each interval the derivative was strictly positive was calculated, such that every point where the derivative was positive was in one of the intervals in this set. From there, the widest interval was determined. If this interval had long tails, i.e., if it was possible to reduce the interval width without correspondingly impacting the integral of the derivative over the interval, this was done (see range_finder.py for details).
After this process, it was concluded that learning rates between TODO and TODO were reasonable for the given batch size.
Training was performed using minibatched SGD without momentum or dampening. Learning rate oscillated linearly, starting at TODO and increasing to TODO at the start of epoch TODO and then decreasing back to TODO at the start of cycle TODO. The batch size was fixed to TODO. A total of TODO trials were performed. On the training set, after training, the highest performance was TODO and the lowest loss was TODO, while on average performance was TODO±TODO and loss was TODO±TODO. On the validation set, after training, the highest performance was TODO and the lowest loss was TODO, while on average performance was TODO±TODO and loss was TODO±TODO.
Average values are presented as mean ± standard deviation.