# Copyright (c) 2021 - present / Neuralmagic, Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""
Code for managing the search and creation of sparsezoo Model and Recipe objects
"""
from typing import List, Union
from sparsezoo.objects.model import Model
from sparsezoo.objects.optimization_recipe import OptimizationRecipe
from sparsezoo.requests import ModelArgs, download_get_request, search_get_request
__all__ = ["Zoo"]
[docs]class Zoo:
"""
Provides static functions for loading and searching SparseZoo models and recipes
"""
[docs] @staticmethod
def load_model(
domain: str,
sub_domain: str,
architecture: str,
sub_architecture: Union[str, None],
framework: str,
repo: str,
dataset: str,
training_scheme: Union[str, None],
optim_name: str,
optim_category: str,
optim_target: Union[str, None],
release_version: Union[str, None] = None,
override_folder_name: Union[str, None] = None,
override_parent_path: Union[str, None] = None,
force_token_refresh: bool = False,
) -> Model:
"""
Obtains a Model with signed files from the model repo
:param domain: The domain of the model the object belongs to;
e.g. cv, nlp
:param sub_domain: The sub domain of the model the object belongs to;
e.g. classification, segmentation
:param architecture: The architecture of the model the object belongs to;
e.g. resnet_v1, mobilenet_v1
:param sub_architecture: The sub architecture (scaling factor) of the model
the object belongs to; e.g. 50, 101, 152
:param framework: The framework the model the object belongs to was trained on;
e.g. pytorch, tensorflow
:param repo: The source repo for the model the object belongs to;
e.g. sparseml, torchvision
:param dataset: The dataset the model the object belongs to was trained on;
e.g. imagenet, cifar10
:param training_scheme: The training scheme used on the model the object
belongs to if any; e.g. augmented
:param optim_name: The name describing the optimization of the model
the object belongs to, e.g. base, pruned, pruned_quant
:param optim_category: The degree of optimization of the model the object
belongs to; e.g. none, conservative (~100% baseline metric),
moderate (>=99% baseline metric), aggressive (<99% baseline metric)
:param optim_target: The deployment target of optimization of the model
the object belongs to; e.g. edge, deepsparse, deepsparse_throughput, gpu
:param release_version: The sparsezoo release version for the model
:param override_folder_name: Override for the name of the folder to save
this file under
:param override_parent_path: Path to override the default save path
for where to save the parent folder for this file under
:param force_token_refresh: True to refresh the auth token, False otherwise
:return: The requested Model instance
"""
args = ModelArgs(
domain=domain,
sub_domain=sub_domain,
architecture=architecture,
sub_architecture=sub_architecture,
framework=framework,
repo=repo,
dataset=dataset,
training_scheme=training_scheme,
optim_name=optim_name,
optim_category=optim_category,
optim_target=optim_target,
release_version=release_version,
)
return Zoo.load_model_from_stub(
args, override_folder_name, override_parent_path, force_token_refresh
)
[docs] @staticmethod
def load_model_from_stub(
stub: Union[str, ModelArgs],
override_folder_name: Union[str, None] = None,
override_parent_path: Union[str, None] = None,
force_token_refresh: bool = False,
) -> Model:
"""
:param stub: the SparseZoo stub path to the model, can be a string path or
ModelArgs object
:param override_folder_name: Override for the name of the folder to save
this file under
:param override_parent_path: Path to override the default save path
for where to save the parent folder for this file under
:param force_token_refresh: True to refresh the auth token, False otherwise
:return: The requested Model instance
"""
response_json = download_get_request(
args=stub,
file_name=None,
force_token_refresh=force_token_refresh,
)
return Model(
**response_json["model"],
override_folder_name=override_folder_name,
override_parent_path=override_parent_path,
)
[docs] @staticmethod
def search_models(
domain: str,
sub_domain: str,
architecture: Union[str, None] = None,
sub_architecture: Union[str, None] = None,
framework: Union[str, None] = None,
repo: Union[str, None] = None,
dataset: Union[str, None] = None,
training_scheme: Union[str, None] = None,
optim_name: Union[str, None] = None,
optim_category: Union[str, None] = None,
optim_target: Union[str, None] = None,
release_version: Union[str, None] = None,
page: int = 1,
page_length: int = 20,
override_folder_name: Union[str, None] = None,
override_parent_path: Union[str, None] = None,
force_token_refresh: bool = False,
) -> List[Model]:
"""
Obtains a list of Models matching the search parameters
:param domain: The domain of the model the object belongs to;
e.g. cv, nlp
:param sub_domain: The sub domain of the model the object belongs to;
e.g. classification, segmentation
:param architecture: The architecture of the model the object belongs to;
e.g. resnet_v1, mobilenet_v1
:param sub_architecture: The sub architecture (scaling factor) of the model
the object belongs to; e.g. 50, 101, 152
:param framework: The framework the model the object belongs to was trained on;
e.g. pytorch, tensorflow
:param repo: The source repo for the model the object belongs to;
e.g. sparseml, torchvision
:param dataset: The dataset the model the object belongs to was trained on;
e.g. imagenet, cifar10
:param training_scheme: The training scheme used on the model the object
belongs to if any; e.g. augmented
:param optim_name: The name describing the optimization of the model
the object belongs to, e.g. base, pruned, pruned_quant
:param optim_category: The degree of optimization of the model the object
belongs to; e.g. none, conservative (~100% baseline metric),
moderate (>=99% baseline metric), aggressive (<99% baseline metric)
:param optim_target: The deployment target of optimization of the model
the object belongs to; e.g. edge, deepsparse, deepsparse_throughput, gpu
:param release_version: The sparsezoo release version for the model
:param page: the page of values to get
:param page_length: the page length of values to get
:param override_folder_name: Override for the name of the folder to save
this file under
:param override_parent_path: Path to override the default save path
for where to save the parent folder for this file under
:param force_token_refresh: True to refresh the auth token, False otherwise
:return: The requested Model instance
"""
args = ModelArgs(
domain=domain,
sub_domain=sub_domain,
architecture=architecture,
sub_architecture=sub_architecture,
framework=framework,
repo=repo,
dataset=dataset,
training_scheme=training_scheme,
optim_name=optim_name,
optim_category=optim_category,
optim_target=optim_target,
release_version=release_version,
)
response_json = search_get_request(
args=args,
page=page,
page_length=page_length,
force_token_refresh=force_token_refresh,
)
return [
Model(
**model,
override_folder_name=override_folder_name,
override_parent_path=override_parent_path,
)
for model in response_json["models"]
]
[docs] @staticmethod
def search_similar_models(
model: Union[Model, str, ModelArgs],
match_domain: bool = True,
match_sub_domain: bool = True,
match_architecture: bool = True,
match_sub_architecture: bool = True,
match_framework: bool = True,
match_repo: bool = True,
match_dataset: bool = True,
match_training_scheme: bool = False,
match_optim_name: bool = False,
match_optim_category: bool = False,
match_optim_target: bool = False,
) -> List[Model]:
"""
Search for similar models to the given one
:param model: The model object, a SparseZoo model stub path, or a ModelArgs
object representing the base model to search similar models of
:param match_domain: True to match similar models to the current
domain of the model the object belongs to; e.g. cv, nlp
:param match_sub_domain: True to match similar models to the current
sub domain of the model the object belongs to;
e.g. classification, segmentation
:param match_architecture: True to match similar models to the current
architecture of the model the object belongs to;
e.g. resnet_v1, mobilenet_v1
:param match_sub_architecture: True to match similar models to the current
sub architecture (scaling factor) of the model
the object belongs to; e.g. 50, 101, 152
:param match_framework: True to match similar models to the current
framework the model the object belongs to was trained on;
e.g. pytorch, tensorflow
:param match_repo: True to match similar models to the current
source repo for the model the object belongs to;
e.g. sparseml, torchvision
:param match_dataset: True to match similar models to the current
dataset the model the object belongs to was trained on;
e.g. imagenet, cifar10
:param match_training_scheme: True to match similar models to the current
training scheme used on the model the object
belongs to if any; e.g. augmented
:param match_optim_name: True to match similar models to the current
name describing the optimization of the model
the object belongs to, e.g. base, pruned, pruned_quant
:param match_optim_category: True to match similar models to the current
degree of optimization of the model the object
belongs to; e.g. none, conservative (~100% baseline metric),
moderate (>=99% baseline metric), aggressive (<99% baseline metric)
:param match_optim_target: True to match similar models to the current
deployment target of optimization of the model
the object belongs to; e.g. edge, deepsparse, deepsparse_throughput, gpu
:return: a list of models matching the given model, if any
"""
if isinstance(model, Model) or isinstance(model, str):
model = Zoo.load_model_from_stub(model)
return Zoo.search_models(
domain=model.domain if match_domain else None,
sub_domain=model.sub_domain if match_sub_domain else None,
architecture=model.architecture if match_architecture else None,
sub_architecture=model.sub_architecture if match_sub_architecture else None,
framework=model.framework if match_framework else None,
repo=model.repo if match_repo else None,
dataset=model.dataset if match_dataset else None,
training_scheme=model.training_scheme if match_training_scheme else None,
optim_name=model.optim_name if match_optim_name else None,
optim_category=model.optim_category if match_optim_category else None,
optim_target=model.optim_target if match_optim_target else None,
)
[docs] @staticmethod
def search_optimized_models(
model: Union[Model, str, ModelArgs],
match_framework: bool = True,
match_repo: bool = True,
match_dataset: bool = True,
match_training_scheme: bool = True,
) -> List[Model]:
"""
Search for different available optimized versions based off of the current model
:param model: The model object, a SparseZoo model stub path, or a ModelArgs
object representing the base model to search different optimizations of
:param match_framework: True to match similar models to the current
framework the model the object belongs to was trained on;
e.g. pytorch, tensorflow
:param match_repo: True to match similar models to the current
source repo for the model the object belongs to;
e.g. sparseml, torchvision
:param match_dataset: True to match similar models to the current
dataset the model the object belongs to was trained on;
e.g. imagenet, cifar10
:param match_training_scheme: True to match similar models to the current
training scheme used on the model the object
belongs to if any; e.g. augmented
:return: the list of matching optimized models, if any
"""
return Zoo.search_similar_models(
model=model,
match_domain=True,
match_sub_domain=True,
match_architecture=True,
match_sub_architecture=True,
match_framework=match_framework,
match_repo=match_repo,
match_dataset=match_dataset,
match_training_scheme=match_training_scheme,
)
[docs] @staticmethod
def search_recipes(
domain: str,
sub_domain: str,
architecture: Union[str, None] = None,
sub_architecture: Union[str, None] = None,
framework: Union[str, None] = None,
repo: Union[str, None] = None,
dataset: Union[str, None] = None,
training_scheme: Union[str, None] = None,
optim_name: Union[str, None] = None,
optim_category: Union[str, None] = None,
optim_target: Union[str, None] = None,
release_version: Union[str, None] = None,
page: int = 1,
page_length: int = 20,
override_folder_name: Union[str, None] = None,
override_parent_path: Union[str, None] = None,
force_token_refresh: bool = False,
) -> List[OptimizationRecipe]:
"""
Obtains a list of Recipes matching the model search parameters
:param domain: The domain of the model the object belongs to;
e.g. cv, nlp
:param sub_domain: The sub domain of the model the object belongs to;
e.g. classification, segmentation
:param architecture: The architecture of the model the object belongs to;
e.g. resnet_v1, mobilenet_v1
:param sub_architecture: The sub architecture (scaling factor) of the model
the object belongs to; e.g. 50, 101, 152
:param framework: The framework the model the object belongs to was trained on;
e.g. pytorch, tensorflow
:param repo: The source repo for the model the object belongs to;
e.g. sparseml, torchvision
:param dataset: The dataset the model the object belongs to was trained on;
e.g. imagenet, cifar10
:param training_scheme: The training scheme used on the model the object
belongs to if any; e.g. augmented
:param optim_name: The name describing the optimization of the model
the object belongs to, e.g. base, pruned, pruned_quant
:param optim_category: The degree of optimization of the model the object
belongs to; e.g. none, conservative (~100% baseline metric),
moderate (>=99% baseline metric), aggressive (<99% baseline metric)
:param optim_target: The deployment target of optimization of the model
the object belongs to; e.g. edge, deepsparse, deepsparse_throughput, gpu
:param release_version: The sparsezoo release version for the model
:param page: the page of values to get
:param page_length: the page length of values to get
:param override_folder_name: Override for the name of the folder to save
this file under
:param override_parent_path: Path to override the default save path
for where to save the parent folder for this file under
:param force_token_refresh: True to refresh the auth token, False otherwise
:return: A list of OptimizationRecipe objects for models that match the given
search parameters
"""
matched_models = Zoo.search_models(
domain,
sub_domain,
architecture=architecture,
sub_architecture=sub_architecture,
framework=framework,
repo=repo,
dataset=dataset,
training_scheme=training_scheme,
optim_name=optim_name,
optim_category=optim_category,
optim_target=optim_target,
release_version=release_version,
page=page,
page_length=page_length,
override_folder_name=override_folder_name,
override_parent_path=override_parent_path,
force_token_refresh=force_token_refresh,
)
return [recipe for model in matched_models for recipe in model.recipes]
[docs] @staticmethod
def search_optimized_recipes(
model: Union[Model, str, ModelArgs],
match_framework: bool = True,
match_repo: bool = True,
match_dataset: bool = True,
match_training_scheme: bool = True,
) -> List[OptimizationRecipe]:
"""
Search for optimized recipes of the given model
:param model: The model object, a SparseZoo stub model path, or a ModelArgs
object representing the base model to search different optimizations of
:param match_framework: True to match similar models to the current
framework the model the object belongs to was trained on;
e.g. pytorch, tensorflow
:param match_repo: True to match similar models to the current
source repo for the model the object belongs to;
e.g. sparseml, torchvision
:param match_dataset: True to match similar models to the current
dataset the model the object belongs to was trained on;
e.g. imagenet, cifar10
:param match_training_scheme: True to match similar models to the current
training scheme used on the model the object
belongs to if any; e.g. augmented
:return: the list of matching optimization recipes, if any
"""
optimized_models = Zoo.search_similar_models(
model=model,
match_domain=True,
match_sub_domain=True,
match_architecture=True,
match_sub_architecture=True,
match_framework=match_framework,
match_repo=match_repo,
match_dataset=match_dataset,
match_training_scheme=match_training_scheme,
)
return [recipe for model in optimized_models for recipe in model.recipes]


Get data on the top rated TV shows. This product uses the TMDb API but is not endorsed or certified by TMDb.


SUBROUTINE ZGELSD( M, N, NRHS, A, LDA, B, LDB, S, RCOND, RANK, $ WORK, LWORK, RWORK, IWORK, INFO ) * * -- LAPACK driver routine (version 3.1) -- * Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. * November 2006 * * .. Scalar Arguments .. INTEGER INFO, LDA, LDB, LWORK, M, N, NRHS, RANK DOUBLE PRECISION RCOND * .. * .. Array Arguments .. INTEGER IWORK( * ) DOUBLE PRECISION RWORK( * ), S( * ) COMPLEX*16 A( LDA, * ), B( LDB, * ), WORK( * ) * .. * * Purpose * ======= * * ZGELSD computes the minimum-norm solution to a real linear least * squares problem: * minimize 2-norm(| b - A*x |) * using the singular value decomposition (SVD) of A. A is an M-by-N * matrix which may be rank-deficient. * * Several right hand side vectors b and solution vectors x can be * handled in a single call; they are stored as the columns of the * M-by-NRHS right hand side matrix B and the N-by-NRHS solution * matrix X. * * The problem is solved in three steps: * (1) Reduce the coefficient matrix A to bidiagonal form with * Householder tranformations, reducing the original problem * into a "bidiagonal least squares problem" (BLS) * (2) Solve the BLS using a divide and conquer approach. * (3) Apply back all the Householder tranformations to solve * the original least squares problem. * * The effective rank of A is determined by treating as zero those * singular values which are less than RCOND times the largest singular * value. * * The divide and conquer algorithm makes very mild assumptions about * floating point arithmetic. It will work on machines with a guard * digit in add/subtract, or on those binary machines without guard * digits which subtract like the Cray X-MP, Cray Y-MP, Cray C-90, or * Cray-2. It could conceivably fail on hexadecimal or decimal machines * without guard digits, but we know of none. * * Arguments * ========= * * M (input) INTEGER * The number of rows of the matrix A. M >= 0. * * N (input) INTEGER * The number of columns of the matrix A. N >= 0. * * NRHS (input) INTEGER * The number of right hand sides, i.e., the number of columns * of the matrices B and X. NRHS >= 0. * * A (input) COMPLEX*16 array, dimension (LDA,N) * On entry, the M-by-N matrix A. * On exit, A has been destroyed. * * LDA (input) INTEGER * The leading dimension of the array A. LDA >= max(1,M). * * B (input/output) COMPLEX*16 array, dimension (LDB,NRHS) * On entry, the M-by-NRHS right hand side matrix B. * On exit, B is overwritten by the N-by-NRHS solution matrix X. * If m >= n and RANK = n, the residual sum-of-squares for * the solution in the i-th column is given by the sum of * squares of the modulus of elements n+1:m in that column. * * LDB (input) INTEGER * The leading dimension of the array B. LDB >= max(1,M,N). * * S (output) DOUBLE PRECISION array, dimension (min(M,N)) * The singular values of A in decreasing order. * The condition number of A in the 2-norm = S(1)/S(min(m,n)). * * RCOND (input) DOUBLE PRECISION * RCOND is used to determine the effective rank of A. * Singular values S(i) <= RCOND*S(1) are treated as zero. * If RCOND < 0, machine precision is used instead. * * RANK (output) INTEGER * The effective rank of A, i.e., the number of singular values * which are greater than RCOND*S(1). * * WORK (workspace/output) COMPLEX*16 array, dimension (MAX(1,LWORK)) * On exit, if INFO = 0, WORK(1) returns the optimal LWORK. * * LWORK (input) INTEGER * The dimension of the array WORK. LWORK must be at least 1. * The exact minimum amount of workspace needed depends on M, * N and NRHS. As long as LWORK is at least * 2*N + N*NRHS * if M is greater than or equal to N or * 2*M + M*NRHS * if M is less than N, the code will execute correctly. * For good performance, LWORK should generally be larger. * * If LWORK = -1, then a workspace query is assumed; the routine * only calculates the optimal size of the array WORK and the * minimum sizes of the arrays RWORK and IWORK, and returns * these values as the first entries of the WORK, RWORK and * IWORK arrays, and no error message related to LWORK is issued * by XERBLA. * * RWORK (workspace) DOUBLE PRECISION array, dimension (MAX(1,LRWORK)) * LRWORK >= * 10*N + 2*N*SMLSIZ + 8*N*NLVL + 3*SMLSIZ*NRHS + * (SMLSIZ+1)**2 * if M is greater than or equal to N or * 10*M + 2*M*SMLSIZ + 8*M*NLVL + 3*SMLSIZ*NRHS + * (SMLSIZ+1)**2 * if M is less than N, the code will execute correctly. * SMLSIZ is returned by ILAENV and is equal to the maximum * size of the subproblems at the bottom of the computation * tree (usually about 25), and * NLVL = MAX( 0, INT( LOG_2( MIN( M,N )/(SMLSIZ+1) ) ) + 1 ) * On exit, if INFO = 0, RWORK(1) returns the minimum LRWORK. * * IWORK (workspace) INTEGER array, dimension (MAX(1,LIWORK)) * LIWORK >= max(1, 3*MINMN*NLVL + 11*MINMN), * where MINMN = MIN( M,N ). * On exit, if INFO = 0, IWORK(1) returns the minimum LIWORK. * * INFO (output) INTEGER * = 0: successful exit * < 0: if INFO = -i, the i-th argument had an illegal value. * > 0: the algorithm for computing the SVD failed to converge; * if INFO = i, i off-diagonal elements of an intermediate * bidiagonal form did not converge to zero. * * Further Details * =============== * * Based on contributions by * Ming Gu and Ren-Cang Li, Computer Science Division, University of * California at Berkeley, USA * Osni Marques, LBNL/NERSC, USA * * ===================================================================== * * .. Parameters .. DOUBLE PRECISION ZERO, ONE, TWO PARAMETER ( ZERO = 0.0D+0, ONE = 1.0D+0, TWO = 2.0D+0 ) COMPLEX*16 CZERO PARAMETER ( CZERO = ( 0.0D+0, 0.0D+0 ) ) * .. * .. Local Scalars .. LOGICAL LQUERY INTEGER IASCL, IBSCL, IE, IL, ITAU, ITAUP, ITAUQ, $ LDWORK, LIWORK, LRWORK, MAXMN, MAXWRK, MINMN, $ MINWRK, MM, MNTHR, NLVL, NRWORK, NWORK, SMLSIZ DOUBLE PRECISION ANRM, BIGNUM, BNRM, EPS, SFMIN, SMLNUM * .. * .. External Subroutines .. EXTERNAL DLABAD, DLASCL, DLASET, XERBLA, ZGEBRD, ZGELQF, $ ZGEQRF, ZLACPY, ZLALSD, ZLASCL, ZLASET, ZUNMBR, $ ZUNMLQ, ZUNMQR * .. * .. External Functions .. INTEGER ILAENV DOUBLE PRECISION DLAMCH, ZLANGE EXTERNAL ILAENV, DLAMCH, ZLANGE * .. * .. Intrinsic Functions .. INTRINSIC INT, LOG, MAX, MIN, DBLE * .. * .. Executable Statements .. * * Test the input arguments. * INFO = 0 MINMN = MIN( M, N ) MAXMN = MAX( M, N ) LQUERY = ( LWORK.EQ.-1 ) IF( M.LT.0 ) THEN INFO = -1 ELSE IF( N.LT.0 ) THEN INFO = -2 ELSE IF( NRHS.LT.0 ) THEN INFO = -3 ELSE IF( LDA.LT.MAX( 1, M ) ) THEN INFO = -5 ELSE IF( LDB.LT.MAX( 1, MAXMN ) ) THEN INFO = -7 END IF * * Compute workspace. * (Note: Comments in the code beginning "Workspace:" describe the * minimal amount of workspace needed at that point in the code, * as well as the preferred amount for good performance. * NB refers to the optimal block size for the immediately * following subroutine, as returned by ILAENV.) * IF( INFO.EQ.0 ) THEN MINWRK = 1 MAXWRK = 1 LIWORK = 1 LRWORK = 1 IF( MINMN.GT.0 ) THEN SMLSIZ = ILAENV( 9, 'ZGELSD', ' ', 0, 0, 0, 0 ) MNTHR = ILAENV( 6, 'ZGELSD', ' ', M, N, NRHS, -1 ) NLVL = MAX( INT( LOG( DBLE( MINMN ) / DBLE( SMLSIZ + 1 ) ) / $ LOG( TWO ) ) + 1, 0 ) LIWORK = 3*MINMN*NLVL + 11*MINMN MM = M IF( M.GE.N .AND. M.GE.MNTHR ) THEN * * Path 1a - overdetermined, with many more rows than * columns. * MM = N MAXWRK = MAX( MAXWRK, N*ILAENV( 1, 'ZGEQRF', ' ', M, N, $ -1, -1 ) ) MAXWRK = MAX( MAXWRK, NRHS*ILAENV( 1, 'ZUNMQR', 'LC', M, $ NRHS, N, -1 ) ) END IF IF( M.GE.N ) THEN * * Path 1 - overdetermined or exactly determined. * LRWORK = 10*N + 2*N*SMLSIZ + 8*N*NLVL + 3*SMLSIZ*NRHS + $ ( SMLSIZ + 1 )**2 MAXWRK = MAX( MAXWRK, 2*N + ( MM + N )*ILAENV( 1, $ 'ZGEBRD', ' ', MM, N, -1, -1 ) ) MAXWRK = MAX( MAXWRK, 2*N + NRHS*ILAENV( 1, 'ZUNMBR', $ 'QLC', MM, NRHS, N, -1 ) ) MAXWRK = MAX( MAXWRK, 2*N + ( N - 1 )*ILAENV( 1, $ 'ZUNMBR', 'PLN', N, NRHS, N, -1 ) ) MAXWRK = MAX( MAXWRK, 2*N + N*NRHS ) MINWRK = MAX( 2*N + MM, 2*N + N*NRHS ) END IF IF( N.GT.M ) THEN LRWORK = 10*M + 2*M*SMLSIZ + 8*M*NLVL + 3*SMLSIZ*NRHS + $ ( SMLSIZ + 1 )**2 IF( N.GE.MNTHR ) THEN * * Path 2a - underdetermined, with many more columns * than rows. * MAXWRK = M + M*ILAENV( 1, 'ZGELQF', ' ', M, N, -1, $ -1 ) MAXWRK = MAX( MAXWRK, M*M + 4*M + 2*M*ILAENV( 1, $ 'ZGEBRD', ' ', M, M, -1, -1 ) ) MAXWRK = MAX( MAXWRK, M*M + 4*M + NRHS*ILAENV( 1, $ 'ZUNMBR', 'QLC', M, NRHS, M, -1 ) ) MAXWRK = MAX( MAXWRK, M*M + 4*M + ( M - 1 )*ILAENV( 1, $ 'ZUNMLQ', 'LC', N, NRHS, M, -1 ) ) IF( NRHS.GT.1 ) THEN MAXWRK = MAX( MAXWRK, M*M + M + M*NRHS ) ELSE MAXWRK = MAX( MAXWRK, M*M + 2*M ) END IF MAXWRK = MAX( MAXWRK, M*M + 4*M + M*NRHS ) ELSE * * Path 2 - underdetermined. * MAXWRK = 2*M + ( N + M )*ILAENV( 1, 'ZGEBRD', ' ', M, $ N, -1, -1 ) MAXWRK = MAX( MAXWRK, 2*M + NRHS*ILAENV( 1, 'ZUNMBR', $ 'QLC', M, NRHS, M, -1 ) ) MAXWRK = MAX( MAXWRK, 2*M + M*ILAENV( 1, 'ZUNMBR', $ 'PLN', N, NRHS, M, -1 ) ) MAXWRK = MAX( MAXWRK, 2*M + M*NRHS ) END IF MINWRK = MAX( 2*M + N, 2*M + M*NRHS ) END IF END IF MINWRK = MIN( MINWRK, MAXWRK ) WORK( 1 ) = MAXWRK IWORK( 1 ) = LIWORK RWORK( 1 ) = LRWORK * IF( LWORK.LT.MINWRK .AND. .NOT.LQUERY ) THEN INFO = -12 END IF END IF * IF( INFO.NE.0 ) THEN CALL XERBLA( 'ZGELSD', -INFO ) RETURN ELSE IF( LQUERY ) THEN RETURN END IF * * Quick return if possible. * IF( M.EQ.0 .OR. N.EQ.0 ) THEN RANK = 0 RETURN END IF * * Get machine parameters. * EPS = DLAMCH( 'P' ) SFMIN = DLAMCH( 'S' ) SMLNUM = SFMIN / EPS BIGNUM = ONE / SMLNUM CALL DLABAD( SMLNUM, BIGNUM ) * * Scale A if max entry outside range [SMLNUM,BIGNUM]. * ANRM = ZLANGE( 'M', M, N, A, LDA, RWORK ) IASCL = 0 IF( ANRM.GT.ZERO .AND. ANRM.LT.SMLNUM ) THEN * * Scale matrix norm up to SMLNUM * CALL ZLASCL( 'G', 0, 0, ANRM, SMLNUM, M, N, A, LDA, INFO ) IASCL = 1 ELSE IF( ANRM.GT.BIGNUM ) THEN * * Scale matrix norm down to BIGNUM. * CALL ZLASCL( 'G', 0, 0, ANRM, BIGNUM, M, N, A, LDA, INFO ) IASCL = 2 ELSE IF( ANRM.EQ.ZERO ) THEN * * Matrix all zero. Return zero solution. * CALL ZLASET( 'F', MAX( M, N ), NRHS, CZERO, CZERO, B, LDB ) CALL DLASET( 'F', MINMN, 1, ZERO, ZERO, S, 1 ) RANK = 0 GO TO 10 END IF * * Scale B if max entry outside range [SMLNUM,BIGNUM]. * BNRM = ZLANGE( 'M', M, NRHS, B, LDB, RWORK ) IBSCL = 0 IF( BNRM.GT.ZERO .AND. BNRM.LT.SMLNUM ) THEN * * Scale matrix norm up to SMLNUM. * CALL ZLASCL( 'G', 0, 0, BNRM, SMLNUM, M, NRHS, B, LDB, INFO ) IBSCL = 1 ELSE IF( BNRM.GT.BIGNUM ) THEN * * Scale matrix norm down to BIGNUM. * CALL ZLASCL( 'G', 0, 0, BNRM, BIGNUM, M, NRHS, B, LDB, INFO ) IBSCL = 2 END IF * * If M < N make sure B(M+1:N,:) = 0 * IF( M.LT.N ) $ CALL ZLASET( 'F', N-M, NRHS, CZERO, CZERO, B( M+1, 1 ), LDB ) * * Overdetermined case. * IF( M.GE.N ) THEN * * Path 1 - overdetermined or exactly determined. * MM = M IF( M.GE.MNTHR ) THEN * * Path 1a - overdetermined, with many more rows than columns * MM = N ITAU = 1 NWORK = ITAU + N * * Compute A=Q*R. * (RWorkspace: need N) * (CWorkspace: need N, prefer N*NB) * CALL ZGEQRF( M, N, A, LDA, WORK( ITAU ), WORK( NWORK ), $ LWORK-NWORK+1, INFO ) * * Multiply B by transpose(Q). * (RWorkspace: need N) * (CWorkspace: need NRHS, prefer NRHS*NB) * CALL ZUNMQR( 'L', 'C', M, NRHS, N, A, LDA, WORK( ITAU ), B, $ LDB, WORK( NWORK ), LWORK-NWORK+1, INFO ) * * Zero out below R. * IF( N.GT.1 ) THEN CALL ZLASET( 'L', N-1, N-1, CZERO, CZERO, A( 2, 1 ), $ LDA ) END IF END IF * ITAUQ = 1 ITAUP = ITAUQ + N NWORK = ITAUP + N IE = 1 NRWORK = IE + N * * Bidiagonalize R in A. * (RWorkspace: need N) * (CWorkspace: need 2*N+MM, prefer 2*N+(MM+N)*NB) * CALL ZGEBRD( MM, N, A, LDA, S, RWORK( IE ), WORK( ITAUQ ), $ WORK( ITAUP ), WORK( NWORK ), LWORK-NWORK+1, $ INFO ) * * Multiply B by transpose of left bidiagonalizing vectors of R. * (CWorkspace: need 2*N+NRHS, prefer 2*N+NRHS*NB) * CALL ZUNMBR( 'Q', 'L', 'C', MM, NRHS, N, A, LDA, WORK( ITAUQ ), $ B, LDB, WORK( NWORK ), LWORK-NWORK+1, INFO ) * * Solve the bidiagonal least squares problem. * CALL ZLALSD( 'U', SMLSIZ, N, NRHS, S, RWORK( IE ), B, LDB, $ RCOND, RANK, WORK( NWORK ), RWORK( NRWORK ), $ IWORK, INFO ) IF( INFO.NE.0 ) THEN GO TO 10 END IF * * Multiply B by right bidiagonalizing vectors of R. * CALL ZUNMBR( 'P', 'L', 'N', N, NRHS, N, A, LDA, WORK( ITAUP ), $ B, LDB, WORK( NWORK ), LWORK-NWORK+1, INFO ) * ELSE IF( N.GE.MNTHR .AND. LWORK.GE.4*M+M*M+ $ MAX( M, 2*M-4, NRHS, N-3*M ) ) THEN * * Path 2a - underdetermined, with many more columns than rows * and sufficient workspace for an efficient algorithm. * LDWORK = M IF( LWORK.GE.MAX( 4*M+M*LDA+MAX( M, 2*M-4, NRHS, N-3*M ), $ M*LDA+M+M*NRHS ) )LDWORK = LDA ITAU = 1 NWORK = M + 1 * * Compute A=L*Q. * (CWorkspace: need 2*M, prefer M+M*NB) * CALL ZGELQF( M, N, A, LDA, WORK( ITAU ), WORK( NWORK ), $ LWORK-NWORK+1, INFO ) IL = NWORK * * Copy L to WORK(IL), zeroing out above its diagonal. * CALL ZLACPY( 'L', M, M, A, LDA, WORK( IL ), LDWORK ) CALL ZLASET( 'U', M-1, M-1, CZERO, CZERO, WORK( IL+LDWORK ), $ LDWORK ) ITAUQ = IL + LDWORK*M ITAUP = ITAUQ + M NWORK = ITAUP + M IE = 1 NRWORK = IE + M * * Bidiagonalize L in WORK(IL). * (RWorkspace: need M) * (CWorkspace: need M*M+4*M, prefer M*M+4*M+2*M*NB) * CALL ZGEBRD( M, M, WORK( IL ), LDWORK, S, RWORK( IE ), $ WORK( ITAUQ ), WORK( ITAUP ), WORK( NWORK ), $ LWORK-NWORK+1, INFO ) * * Multiply B by transpose of left bidiagonalizing vectors of L. * (CWorkspace: need M*M+4*M+NRHS, prefer M*M+4*M+NRHS*NB) * CALL ZUNMBR( 'Q', 'L', 'C', M, NRHS, M, WORK( IL ), LDWORK, $ WORK( ITAUQ ), B, LDB, WORK( NWORK ), $ LWORK-NWORK+1, INFO ) * * Solve the bidiagonal least squares problem. * CALL ZLALSD( 'U', SMLSIZ, M, NRHS, S, RWORK( IE ), B, LDB, $ RCOND, RANK, WORK( NWORK ), RWORK( NRWORK ), $ IWORK, INFO ) IF( INFO.NE.0 ) THEN GO TO 10 END IF * * Multiply B by right bidiagonalizing vectors of L. * CALL ZUNMBR( 'P', 'L', 'N', M, NRHS, M, WORK( IL ), LDWORK, $ WORK( ITAUP ), B, LDB, WORK( NWORK ), $ LWORK-NWORK+1, INFO ) * * Zero out below first M rows of B. * CALL ZLASET( 'F', N-M, NRHS, CZERO, CZERO, B( M+1, 1 ), LDB ) NWORK = ITAU + M * * Multiply transpose(Q) by B. * (CWorkspace: need NRHS, prefer NRHS*NB) * CALL ZUNMLQ( 'L', 'C', N, NRHS, M, A, LDA, WORK( ITAU ), B, $ LDB, WORK( NWORK ), LWORK-NWORK+1, INFO ) * ELSE * * Path 2 - remaining underdetermined cases. * ITAUQ = 1 ITAUP = ITAUQ + M NWORK = ITAUP + M IE = 1 NRWORK = IE + M * * Bidiagonalize A. * (RWorkspace: need M) * (CWorkspace: need 2*M+N, prefer 2*M+(M+N)*NB) * CALL ZGEBRD( M, N, A, LDA, S, RWORK( IE ), WORK( ITAUQ ), $ WORK( ITAUP ), WORK( NWORK ), LWORK-NWORK+1, $ INFO ) * * Multiply B by transpose of left bidiagonalizing vectors. * (CWorkspace: need 2*M+NRHS, prefer 2*M+NRHS*NB) * CALL ZUNMBR( 'Q', 'L', 'C', M, NRHS, N, A, LDA, WORK( ITAUQ ), $ B, LDB, WORK( NWORK ), LWORK-NWORK+1, INFO ) * * Solve the bidiagonal least squares problem. * CALL ZLALSD( 'L', SMLSIZ, M, NRHS, S, RWORK( IE ), B, LDB, $ RCOND, RANK, WORK( NWORK ), RWORK( NRWORK ), $ IWORK, INFO ) IF( INFO.NE.0 ) THEN GO TO 10 END IF * * Multiply B by right bidiagonalizing vectors of A. * CALL ZUNMBR( 'P', 'L', 'N', N, NRHS, M, A, LDA, WORK( ITAUP ), $ B, LDB, WORK( NWORK ), LWORK-NWORK+1, INFO ) * END IF * * Undo scaling. * IF( IASCL.EQ.1 ) THEN CALL ZLASCL( 'G', 0, 0, ANRM, SMLNUM, N, NRHS, B, LDB, INFO ) CALL DLASCL( 'G', 0, 0, SMLNUM, ANRM, MINMN, 1, S, MINMN, $ INFO ) ELSE IF( IASCL.EQ.2 ) THEN CALL ZLASCL( 'G', 0, 0, ANRM, BIGNUM, N, NRHS, B, LDB, INFO ) CALL DLASCL( 'G', 0, 0, BIGNUM, ANRM, MINMN, 1, S, MINMN, $ INFO ) END IF IF( IBSCL.EQ.1 ) THEN CALL ZLASCL( 'G', 0, 0, SMLNUM, BNRM, N, NRHS, B, LDB, INFO ) ELSE IF( IBSCL.EQ.2 ) THEN CALL ZLASCL( 'G', 0, 0, BIGNUM, BNRM, N, NRHS, B, LDB, INFO ) END IF * 10 CONTINUE WORK( 1 ) = MAXWRK IWORK( 1 ) = LIWORK RWORK( 1 ) = LRWORK RETURN * * End of ZGELSD * END


| 1091 | (A) | and þer was schaftis sondirde fułł and many schelde thirllede |
| 1095 | (C) | ¶ Shaftes scheueredde were sone . & scheldes thorow thryllede |
| 1078 | (D) | Shaftis shyverid were sone & sheldis y-thrillid |
| 1058 | (E) | ¶ Schaftes schyuered were soone . & scheldys ythirled |
| 50 | (Ex) | . . . was Thrylled |
| 1116 | (L) | schaftes schedred were sone & scheldes y-þrelled |
| 1029 | (P) | S haftes s. . . |
| 1067 | (U) | ¶ Shaftes shiuerd were sone / and sheldes yhurled |
| 156 | (V) | Shaftes sheuered were sone sheldes were prissed |


# Save network torch.save(network.state_dict(), 'network.torch') # Load network network.load.state_dict(torch.load('network.pytorch'))
Let's represent this sequence 23 450 27 124
Let's represent this sequence 0.3 1.3 0.1 1.3 -0.5 2.3 5.5 -2.5 ... ... ... ... 1.6 0.0 -3.2 8.2
Cho et al. 2014
Remember the temporal credit assignment problem
https://colah.github.io/posts/2015-08-Understanding-LSTMs/
Motivation:
Bahdenau et al. 2015
How to represent meaning in a computer?
CS224n, Stanford 2019
motel = [0 0 0 0 0 0 0 0 0 0 1 0 0 0 0] hotel = [0 0 0 0 0 0 0 1 0 0 0 0 0 0 0]
A word embedding is a distributed and dense representation for each word (generally a dense vector), chosen so that it is similar to vectors of words that appear in similar contexts
Word2vec (Mikolov et al. 2013) was an early framework for learning word vectors
Idea:
http://mccormickml.com/2016/04/19/word2vec-tutorial-the-skip-gram-model/
Mikolov et al. 2013
Van der Oord et al. 2016
Vaswani et al. 2017, Devlin et al. 2017
the man went to [MASK] store [SEP] he bought a gallon [MASK] milk Label = IsNext
the man [MASK] to the store [SEP] penguin [MASK] are flight ##less birds Label = NotNext


Slammed Ford Mustang Mach-E Looks More Pony, Less SUV
by Andrei TutuLadies and gentlemen drivers, I'm sure there are plenty of you who still don't know how to feel about the just-landed Ford Mustang Mach-E. Well, you should know that at least a part of the Internet has decided to treat the electric crossover like a proper Mustang. For one thing, the rendering that brought us here casts the EV in the role of a tuner car.
To be more precise, this pixel work gives us a slammed take on the Mustang Mach-E. The first thing you notice is the microscopic ground clearance. And it does look like the Blue Oval toy has been gifted with air suspension, which means the ground clearance can be varied, so the practical side of the machine hasn't been axed.
Then we have the custom wheels of the electropony. Supplied by Rotiform, the new shoes are enough to draw attention on their own and seem to fit the styling of the machine - pixel tip to digital artist Abimelec Arellano for this image.
Speaking of which, the design of the newcomer is definitely one of its assets - the Mustang badge up front is backed up by the rest of the styling, right up to the iconic taillight design.
Of course, we'll have to wait for the newcomer to hit the market next year before jumping to conclusions on its real-world impact. Meanwhile, as mentioned in the intro, opinions are split. However, it looks like Ford has done the math, determining that the number of purists affected by the use of the "Mustang" name and visual features is considerably smaller than the number of buyers drawn to this proposal.
On a less serious note, we now live in an era when the Ford v Ferrari tale might just get a crossover makeover as soon as the Prancing Horse releases its first SUV, a move expected to take place in the first part of next decade.


Plants are family too! Get to know them better.
1. Introduction
1.1 These terms and conditions shall govern your use of our app.
1.2 By using our website, you accept these terms and conditions in full; accordingly, if you disagree with these terms and conditions or any part of these terms and conditions, you must not use our app.
1.3 If you register with our app, submit any material to our website or use any of our app services, we will ask you to expressly agree to these terms and conditions.
1.4 You must be at least 18 years of age to use our app; by using our app or agreeing to these terms and conditions, you warrant and represent to us that you are at least 18 years of age.
2. Credit
2.1 This document was created using a template from SEQ Legal.
3. Copyright notice
3.1 Copyright (c) 2016 LetUmGrow
3.2 Subject to the express provisions of these terms and conditions:
(a) we, together with our licensors, own and control all the copyright and other intellectual property rights in our app and the material on our app; and
(b) all the copyright and other intellectual property rights in our app and the material on our app are reserved.
4. Licence to use website
4.1 Except as expressly permitted by Section 4.1 or the other provisions of these terms and conditions, you must not download any material from our app or save any such material to your computer.
4.2 You may only use our app for your own personal and business purposes, and you must not use our app for any other purposes.
4.3 Except as expressly permitted by these terms and conditions, you must not edit or otherwise modify any material on our website.
4.4 Unless you own or control the relevant rights in the material, you must not:
(a) republish material from our website (including republication on another website);
(b) sell, rent or sub-license material from our website;
(c) show any material from our website in public;
(d) exploit material from our website for a commercial purpose; or
(e) redistribute material from our website.
4.5 We reserve the right to restrict access to areas of our website, or indeed our whole website, at our discretion; you must not circumvent or bypass, or attempt to circumvent or bypass, any access restriction measures on our website.
5. Acceptable use
5.1 You must not:
(a) use our app in any way or take any action that causes, or may cause, damage to the plants listed in our app;
(b) use our app in any way that is unlawful, illegal, fraudulent or harmful, or in connection with any unlawful, illegal, fraudulent or harmful purpose or activity;
(c) use our app as a means to identify edible plants to consume personally, THIS APP IS FOR INFORMATIONAL USE ONLY;
5.2 You must ensure that all the information you supply to us through our app, or in relation to our app, is true, accurate, current, complete and non-misleading.
6. Registration and accounts
6.1 To be eligible for an account on our app under this Section 6, you must have a current hawaii.edu account.
6.2 You must not allow any other person to use your account to access the app.
6.3 You must notify us in writing immediately if you become aware of any unauthorized use of your account.
6.4 You must not use any other person's account to access the app, unless you have that person's express permission to do so.
7. User login details
7.1 You must keep your password confidential.
7.2 You must notify us in writing immediately if you become aware of any disclosure of your password.
7.3 You are responsible for any activity on our app arising out of any failure to keep your password confidential, and may be held liable for any losses arising out of such a failure.
8. Cancellation and suspension of account
8.1 We may:
(a) suspend your account;
(b) cancel your account; and/or
(c) edit your account details, at any time in our sole discretion without notice or explanation.
9. Limitations and exclusions of liability
9.1 Nothing in these terms and conditions will:
(a) limit or exclude any liability of users for death or personal injury resulting from negligence, WE ARE NOT RESPONSIBLE FOR EFFECTS OF USING OR CONSUMING PLANTS THAT ARE LISTED ON THIS APP;
(b) limit or exclude any liability of users for fraud or fraudulent misrepresentation;
(c) limit any liabilities in any way that is not permitted under applicable law; or
(d) exclude any liabilities that may not be excluded under applicable law.
9.2 To the extent that our website and the information and services on our website are provided free of charge, we will not be liable for any loss or damage of any nature.
9.3 We will not be liable to you in respect of any losses arising out of any event or events beyond our reasonable control.
9.4 We will not be liable to you in respect of any loss or corruption of any data, database or software.
9.5 We will not be liable to you in respect of any special, indirect or consequential loss or damage.
9.6 You accept that we have an interest in limiting the personal liability of our officers and employees and, having regard to that interest, you acknowledge that we are a limited liability entity; you agree that you will not bring any claim personally against our officers or employees in respect of any losses you suffer in connection with the app or these terms and conditions (this will not, of course, limit or exclude the liability of the limited liability entity itself for the acts and omissions of our officers and employees).
10. Breaches of these terms and conditions
10.1 Without prejudice to our other rights under these terms and conditions, if you breach these terms and conditions in any way, or if we reasonably suspect that you have breached these terms and conditions in any way, we may:
(a) send you one or more formal warnings;
(b) temporarily suspend your access to our app;
(c) permanently prohibit you from accessing our app;
(d) block computers using your IP address from accessing our app;
(e) contact any or all of your internet service providers and request that they block your access to our app;
(f) commence legal action against you, whether for breach of contract or otherwise; and/or
(g) suspend or delete your account on our app.
10.2 Where we suspend or prohibit or block your access to our app or a part of our app, you must not take any action to circumvent such suspension or prohibition or blocking (including without limitation creating and/or using a different account).
Looking for a specific plant or want to learn more about a plant that you've seen? Keep track of plants in your garden or view what plants are on your favorite hike with LetUmGrow. Please explore our menu above or click on the following links. The TUTORIAL goes over the general use for this application. The ADD PLANT section allows you to add a plant from your current location or specific location via Latitude/Longitude coordinates. The PLANT MAP displays the location of all added plants on the map, and allows you to add plants not yet identified on the map via clicking on the map. The LIST PLANTS section allows you to view and edit plants in the database and also links to each plant's individual profile. The USER PROFILE allows you to view and edit specific information associated with your account. Interested in Lāʻau Lapaʻau (Hawaiian plant remedies)? Check out some REMEDIES passed down from Kumu Levon Ohai. And the FAQ PAGE answers some of the frequently asked questions that users come across in the LetUmGrow app. Our purpose is to bridge the gaps between people, technology, and nature. We need plants around in order for us to survive so just "LetUmGrow"!


Invoke the WLM_GET_SERVICE_SUBCLASS_STATS_V97 table function again.
If you are using a 9.5 database, you will need to run the WLM_GET_SERVICE_SUBCLASS_STATS table function instead. Since DB2 9.7, this table function has been deprecated and replaced by the WLM_GET_SERVICE_SUBCLASS_STATS_V97 table function. Click on the 'Edit mode' button in the top right panel, and edit the SQL before clicking on 'Run.'
Notice that the LAST_RESET timestamp has been updated and the statistics have been reset.


@()(implicit header: RequestHeader, messages: Messages, pm: PageMeta, wja: WebJarAssets, session: Session) @page { } {
There is beauty in space, and it is orderly. There is no weather, and there is regularity. It is predictable. Everything in space obeys the laws of physics. If you know these laws, and obey them, space will treat you kindly.
Go to Phonebook }


Let the straight line EF fall on the parallel straight lines AB and CD.
I say that it makes the alternate angles AGH and GHD equal, the exterior angle EGB equal to the interior and opposite angle GHD, and the sum of the interior angles on the same side, namely BGH and GHD, equal to two right angles.
If the angle AGH does not equal the angle GHD, then one of them is greater. Let the angle AGH be greater.
Add the angle BGH to each. Therefore the sum of the angles AGH and BGH is greater than the sum of the angles BGH and GHD.
But sum of the angles AGH and BGH equals two right angles. Therefore the sum of the angles BGH and GHD is less than two right angles.
But straight lines produced indefinitely from angles less than two right angles meet. Therefore AB and CD, if produced indefinitely, will meet. But they do not meet, because they are by hypothesis parallel.
Therefore the angle AGH is not unequal to the angle GHD, and therefore equals it.
Again, the angle AGH equals the angle EGB. Therefore the angle EGB also equals the angle GHD.
Add the angle BGH to each. Therefore the sum of the angles EGB and BGH equals the sum of the angles BGH and GHD.
But the sum of the angles EGB and BGH equals two right angles. Therefore the sum of the angles BGH and GHD also equals two right angles.
Therefore a straight line falling on parallel straight lines makes the alternate angles equal to one another, the exterior angle equal to the interior and opposite angle, and the sum of the interior angles on the same side equal to two right angles.
The statement of this proposition includes three parts, one the converse of I.27, the other two the converse of I.28. Like those propositions, this one assumes an ambient plane containing all the three lines.
This is the first proposition which depends on the parallel postulate. As such it does not hold in hyperbolic geometry.
These three geometries can be distinguished by the number of lines parallel to a given line passing through a given point. For elliptic geometry, there is no such parallel line; for Euclidean geometry (which may be called parabolic geometry), there is exactly one; and for hyperbolic geometry, there are infinitely many.
It is not possible to illustrate hyperbolic geometry with correct distances on a flat surface since a flat surface is Euclidean. Poincaré, however, described a useful model of hyperbolic geometry where the “points” in a hyperbolic plane are taken to be points inside a fixed circle (but not the points on the circumference). The “lines” in the hyperbolic plane are the parts of circles orthogonal, that is, at right angles to the fixed circle. And in this model, “angles” in the hyperbolic plane are angles between these arcs, or, more precisely, angles between the tangents to the arcs at the point of intersection. Since “angles” are just angles, this model is called a conformal model. Distances in the hyperbolic plane, however, are not measured by distances along the arcs. There is a more complicated relation between distances so that near the edge of the fixed circle a very short arc models a very long “line.”
| Once this model is accepted, it is easy to see why there are
infinitely many “lines” parallel to a given “line” through a given
“point.” That is just that there are infinitely many circles
orthogonal to the fixed circle which don’t intersect the given
circle orthogonal to the fixed circle but do pass through the given
point.
In the diagram, AB is a “line” in the hyperbolic plane, that is, a circle orthogonal to the circumference of the shaded disk which represents the hyperbolic plane. A “point” C lies in that plane. Two “lines” are shown passing through C, one gets close to the line AB in the direction of A, the other gets close in the direction of B. But these two “lines” don’t intersect AB since the arcs representing them only intersect on the circumference of the disk, and points on the circumference don’t represent “points” in the hyperbolic plane. |
These two parallel “lines” are called the asymptotic parallels of AB since they approach AB at one end or the other. There are infinitely many parallels between them. (In much of the literature on hyperbolic geometry, the word “parallels” is used for what are called “asymptotic parallels” here, while “nonintersecting lines” is used for what are called “parallels” here.)


STEP BY STEP
Copyright (c) 1997 Christopher Fuchs
This game is played on the following 5x5 square board:
There are enough neutral stones off board (in these diagrams, the white pieces).
- CELL LEVEL - The number of neutral stones on a specific cell.
- Initially, the level of the central cell is five.
- TURN - On each turn, each player must execute two actions by this order:
- First, moves his stone to an orthogonally adjacent valid cell.
- A cell is valid if (a) it is not occupied by the opponent's stone and (b) it has the same level, or one less or one more than the initial moving cell.
- When not ascending, the move may be multiple, i.e., the player may continue moving to orthogonal adjacent valid cells with equal or lower level. When the piece moves up one level, the move sequence stops. At each move, the piece cannot return to its previous cell.
- Second, drops a neutral stone on a cell with only zero or more neutrals, which is orthogonally adjacent to his own stone.
- GOAL - The winner is whoever (a) moves his friendly stone to the central cell, or (b) stalemates the adversary.
- If the game uses a limited number of neutrals, the game is declared a draw if all neutrals are used and either goal is not achieved.
The original game rules also refer L-shape movements but do not explicit more.
Some initial moves Red just placed another neutral at c4 to prevent Black to move there (b4 and c4 now have a difference of two neutrals).
Winning by Stalemate Black moved b4-b3 and dropped a neutral at b2.
He has won because now Red cannot move his piece.
I wish to thank Bernard Wack for sending me information about this game.


Regards,
Sitograph Team
Sitograph Content Management System.
The Sitograph CMS is an online, open source website creation tool.
Sitograph is a set of solutions for any online business.
It is simple and powerful Content Management System for website or online shop.
|


--- layout: post title: The Cost of Being Unique date: '2012-02-23T07:12:27-08:00' tags: tumblr_url: http://alexhwilliams.tumblr.com/post/18130552358/the-cost-of-being-unique ---
http://bit.ly/ArVuIU


Press 'ESC' on your keyboard or click outside of the element!
Put the first element on top of the stack.


PGXNtool is meant to make developing new Postgres extensions for PGXN easier.
Currently, it consists a base Makefile that you can include instead of writing your own, a template META.json, and some test framework. More features will be added over time.
If you find any bugs or have ideas for improvements, please open an issue.
1. Install
This assumes that you’ve already initialized your extension in git.
|
Note
|
The --squash is important!
2. Usage
Typically, you can just create a simple Makefile that does nothing but include base.mk:
include pgxntool/base.mk
3. make targets
These are the make targets that are provided by base.mk
|
Note
|
all the targets normally provided by Postgres PGXS still work. |
3.1. html
This will build any .html files that can be created. See [_Document_Handling].
3.2. test
Runs unit tests via the PGXS installcheck
target. Unlike a simple make installcheck
though, the test
rule has the following prerequisites: clean testdeps install installcheck.  By default it has a single prerequisite, pgtap
, which will attempt to install pgtap from PGXN. This depneds on having the pgxn client installed.
You can add any other dependencies you want by simply adding another testdeps
rule. For example:
testdeps example from test_factory
testdeps: check_control .PHONY: check_control check_control: grep -q "requires = 'pgtap, test_factory'" test_factory_pgtap.control
If you want to over-ride the default dependency on pgtap
you should be able to do that with a makefile override. If you need help with that, please open an issue.
|
Warning
|
It will probably cause problems if you try to create a testdeps rule that has a recipe. Instead of doing that, put the recipe in a separate rule and make that rule a prerequisite of testdeps as show in the example.
|
3.4. results
Because make test
ultimately runs installcheck
, it’s using the Postgres test suite. Unfortunately, that suite is based on running diff
between a raw output file and expected results. I STRONGLY recommend you use pgTap instead! The extra effort of learning pgTap will quickly pay for itself. This example might help get you started.
No matter what method you use, once you know that all your tests are passing correctly, you need to create or update the test output expected files. make results
does that for you.
3.5. tag
make tag
will create a git branch for the current version of your extension, as determined by the META.json file. The reason to do this is so you can always refer to the exact code that went into a released version.
If there’s already a tag for the current version that probably means you forgot to update META.json, so you’ll get an error. If you’re certain you want to over-write the tag, you can do make forcetag
, which removes the existing tag (via make rmtag
) and creates a new one.
|
Warning
|
You will be very unhappy if you forget to update the .control file for your extension! There is an open issue to improve this. |
3.6. dist
make dist
will create a .zip file for your current version that you can upload to PGXN. The file is named after the PGXN name and version (the top-level "name" and "version" attributes in META.json). The .zip file is placed in the parent directory so as not to clutter up your git repo.
|
Note
|
Part of the clean recipe is cleaning up these .zip files. If you accidentally clean before uploading, just run make dist-only .
|
3.7. pgxntool-sync
This rule will pull down the latest released version of PGXNtool via git subtree pull
.
|
Note
|
Your repository must be clean (no modified files) in order to run this. Running this command will produce a git commit of the merge. |
|
Tip
|
There is also a pgxntool-sync-% rule if you need to do more advanced things.
|
4. Document Handling
PGXNtool supports generation and installation of document files. There are several variables and rules that control this behavior.
It is recommended that you commit any generated documentation files (such as HTML generated from Asciidoc) into git. That way users will have these files installed when they install your extension. If any generated files are missing (or out-of-date) during installation, PGXNtool will build them if Asciidoc is present on the system.
4.1. Document Variables
- DOC_DIRS
-
Directories to look for documents in. Defined as
+= doc
. - DOCS
-
PGXS variable. See The DOCS variable below.
- DOCS_HTML
-
Document HTML files. PGXNtool appends `$(ASCIIDOC_HTML) to this variable.
- ASCIIDOC
-
Location of
asciidoc
or equivalent executable. If not set PGXNtool will search for firstasciidoctor
, thenasciidoc
. - ASCIIDOC_EXTS
-
File extensions to consider as Asciidoc. Defined as
+= adoc asciidoc
. - ASCIIDOC_FILES
-
Asciidoc input files. PGXNtool searches each
$(DOC_DIRS)
directory, looking for files with any$(ASCIIDOC_EXTS)
extension. Any files found are added toASCIIDOC_FILES
using+=
. - ASCIIDOC_FLAGS
-
Additional flags to pass to Asciidoc.
- ASCIIDOC_HTML
-
PGXNtool replaces each
$(ASCIIDOC_EXTS)
in$(ASCIIDOC_FILES)
withhtml
. The result is appended toASCIIDOC_HTML
using+=
.
4.2. Document Rules
If Asciidoc is found (or $(ASCIIDOC)
is set), the html
rule will be added as a prerequisite to the install
and installchec
rules.
That will ensure that docs are generated for install and test, but only if Asciidoc is available.
The dist
rule will always depend on html
though, to ensure html files are up-to-date before creating a distribution.
The html
rule simply depends on `$(ASCIIDOC_HTML).
This rule is always present.
For each Asciidoc extension in $(ASCIIDOC_EXTS)
a rule is generated to build a .html file from that extension using $(ASCIIDOC)
.
These rules are generated from ASCIIDOC_template
:
define ASCIIDOC_template
%.html: %.$(1) (1)
ifndef ASCIIDOC
$$(warning Could not find "asciidoc" or "asciidoctor". Add one of them to your PATH,)
$$(warning or set ASCIIDOC to the correct location.)
$$(error Could not build %$$@)
endif # ifndef ASCIIDOC
$$(ASCIIDOC) $$(ASCIIDOC_FLAGS) $$<
endef # define ASCIIDOC_template
-
$(1)
is replaced by the extension.
These rules will always exist, even if $(ASCIIDOC)
isn’t set (ie: if Asciidoc wasn’t found on the system).
These rules will throw an error if they are run if $(ASCIIDOC)
isn’t defined.
On a normal user system that should never happen, because the html
rule won’t be included in install
or installcheck
.
4.3. The DOCS variable
This variable has special meaning to PGXS. See the Postgres documentation for full details.
If DOCS is defined when PGXS is included then rules will be added to install everything defined by $(DOCS) in PREFIX/share/doc/extension
.
|
Note
|
If DOCS is defined but empty some of the PGXS targets will error out.
Because of this, base.mk will forcibly define it to be NULL if it’s empty.
|
PGXNtool appends all files found in all $(DOC_DIRS)
to DOCS
.
5. Copyright
Copyright (c) 2015 Jim Nasby<EMAIL_ADDRESS>PGXNtool is released under a BSD license. Note that it includes JSON.sh, which is released under a MIT license.


Review: Mortal Kombat: Annihilation (1997) Rating: 3.0 stars (out of 4.0) ******************************** Key to rating system: 2.0 stars Debatable 2.5 stars Some people may like it 3.0 stars I liked it 3.5 stars I am biased in favor of the movie 4.0 stars I felt the movie's impact personally or it stood out ********************************* A Movie Review by David Sunga
Directed by: John Leonetti
Screenplay written by: Brent Friedman and Bryce Zabel (original story written by Lawrence Kasanoff, Joshua Wexler, and John Tobias).
Starring: Robin Shou, Taliso Soto, James Remar, Sandra Hess, Lynn "Red" Williams
Ingredients: Other dimensions, fate of the world, martial arts heroes, costumed villains, karate babes
Synopsis: This is not a sentimental movie, a 'date' movie, or a thriller. It's the sequel to ‘Mortal Kombat,' a 1995 movie based on a popular video game. In the original ‘Mortal Kombat' an immortal named Lord Rayden chose three heroes - - nice Hong Kong guy Liu Kang, SWAT team leader Sonya Blade, and movie star Johnny Cage - - to represent the planet earth in a high stakes interdimensional martial arts tournament called Mortal Kombat. Talisa Soto played Kitana, the princess from another dimension who helped the heroes succeed. In this sequel, ‘Mortal Kombat: Annihilation,' no sooner do the victorious heroes return to earth with their friend Princess Kitana than another crisis presents itself. Shao-Kahn, the evil emperor of Outworld, has hatched a plot to kill Lord Rayden and the heroes, and take over the earth by merging it with another dimension. Shao-Kahn kills Johnny, captures Kitana to set a death trap for the heroes, and then sets about destroying the earth with rocket-launching techno-ninjas, a zombified queen, a centaur creature, scorpion monsters, martial arts armies, and evil siblings. Meanwhile the heroes enlist the aid of Sonya Blade's old SWAT team pal Jax, and start kicking booty. Will good triumph over evil?
Opinion: This is the kind of movie that adolescent guys will love. If you liked the first ‘Mortal Kombat,' with it's hyperactive high-kicking male and female leads, you'll like this movie, which emphasizes state-of-the-art special effects, great fight photography, and martial arts choreography, and de-emphasizes a confusing mythic plot. The visual "oomph" emphasis is probably due to that fact that director John Leonetti is best known for photography - - he was the director of photography on ‘The Mask' and on ‘Mortal Kombat,' while his brother Matthew shot ‘Star Trek: First Contact.' ‘Mortal Kombat: Annihilation' uses an eclectic blend of fresh fight choreography from a number of different fighting arts involving plenty of aerial kicks and trampoline-style spinning jumps. The CG (computer generated) characters manage to do decent fight scenes as well. In other words, this movie puts American fight choreography up there with Hong Kong wu shu. For Asian-Americans and for Hollywood, ‘Mortal Kombat: Annihilation' will be a test of how willing the American public is to pay money to view an Asian movie protagonist. Producer Larry Kasanoff, who also produced ‘Terminator 2' is producing this film.
Stars: Robin Shou, the leading man in ‘Mortal Kombat' and ‘Mortal Kombat: Annihiliation' was born in Hong Kong but moved to Los Angeles at age eleven and obtained a degree in civil engineering from CSU Los Angeles. He worked for a year and half as a soil engineer, but eventually moved to Hong Kong, became a movie stuntman, and finally worked his way into playing villains. After nine years of Hong Kong movies, he went to a friend's barbecue in California and met an agent, who suggested that Robin audition for ‘Mortal Kombat.' Robin's martial arts style is wu shu, a cinematic mixture of martial arts forms and dramatic presentation. As a college he became so excited about wushu that he sold his car and skipped a quarter of school to fly to China and study it.
Model-turned-actress Talisa Soto is best known for playing James Bond Girl Lupe Lamora in ‘License to Kill.' To my knowledge she is the first Hispanic Bond Girl.
Reviewed by David Sunga November 21, 1997
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


{% extends "user.base.html" %} {% block content %} {% with nav_bar = nav_bar %}
In order to finishing claiming your acceptance, submit a signed hackbca.com/waiver before March 23rd. Waivers can be scanned and emailed to<EMAIL_ADDRESS>or submitted to BCA's main office.
No waiver, no attendance.
Have a question? Shoot us an email at<EMAIL_ADDRESS>{% elif decision == "accepted" %} {% if current_user.type_account == "hacker" %}In order to claim your acceptance, RSVP and submit a signed hackbca.com/waiver before March 23rd. Waivers can be scanned and emailed to<EMAIL_ADDRESS>or submitted to BCA's main office.
No waiver, no attendance.
Have a question? Shoot us an email at<EMAIL_ADDRESS>{% elif current_user.type_account == "mentor" %}Emails and RSVP forms for mentors will be released shortly.
Have a question? Shoot us an email at<EMAIL_ADDRESS>{% endif %} {% elif decision == "rejected" %}Unfortunately, we don't have enough space to accomodate all of our applicants.
However, there's still a chance you'll be able to come to hackBCA IV so keep checking your email!
Have a question? Shoot us an email at<EMAIL_ADDRESS>Have a question? Shoot us an email at contact@hackbca.com.


Using GVariant
Using GVariant
Overviewback top
The idea of GVariant is inspired by the similar Variant in Windows COM technology.
A GVariant is used to represent arbitrary type of value.
Any value, such as but not limited to, integer, float, pointer, object, reference, can be stored in a GVariant.
The reflection and script binding libraries use GVariant extensively. GVariant is the very core concept in those libraries.
Please bear in mind, GVariant is used in runtime, so it doesn't remember any compile time information, except the fundamental types.
So GVariant is not 100% type safe. To use it correctly, you must know the type it holds.
Also, GVariant is not only for reflection. It's an all purpose variant data type.
Store value to GVariantback top
Any values can be converted to a GVariant implicitly, so you don't need to call GVariant constructor explicitly.
This is why the invoke function in GMetaMethod accepts only GVariant but any value can be passed directly.
The prototype of "invoke" in GMetaMethod is,
GVariant invoke(void * instance, const GVariant & p1, const GVariant & p2, ..., const GVariant & pN);
We can call it as method->invoke(instance, 5, "test", myObject).
Retrieve value from GVariantback top
A GVariant can be converted back to a normal value with the function fromVariant.
Assume v is a GVariant.
int n = fromVariant<int>(v);
Convert v to integer.
string s = fromVariant<char *>(v);
Convert v to C string then assign to a STL string.
MyObject obj = fromVariant<MyObject>(v);
Convert v to MyObject.
If fromVariant finds the GVariant can't be converted to the desired type, an exception GVariantException will be thrown.
To test if a GVariant can be converted to a type, use canFromVariant.
It has the same parameters as fromVariant, but returns a boolean to indicate if the GVariant can be casted.
Store non-copyable object or reference to GVariantback top
Bye default, GVariant requires the value assigned to it copyable.
If the value is a class object, but the copy constructor is private or not implemented, when trying to create GVariant from such value, compiling will fail.
To store non-copyable object or reference to GVariant, use function createVariant.
template <bool CanShadow, typename T>
GVariant createVariant(const T & value, bool allowShadow = false);
The first template parameter, CanShadow, determines if the object copyable.
If CanShadow is false, the object is not copyable.
So to store a non-copyable object, named A, to GVariant v, write like this,
GVariant v = createVariant<false>(A);
Rules to cast from GVariantback top
Rule 1, A GVariant with fundamental value can be casted to any other fundamental.
GVariant v;
v = 1; // integer
fromVariant<double>(v); // OK
Rule 2, A GVariant with pointer value can be casted to any other pointer, even if the pointer dimension is different.
v = (char *)1;
fromVariant<int **>(v); // OK
Rule 3, A GVariant with fundamental value or pointer value can be casted to an object that has constructor to accept the type implicitly.
v = "abc"; // C string, const char *
std::string s = fromVariant<std::string>(v); // OK, because std::string accepts "const char *".
Rule 4, When casting a GVariant with object (T) or object reference (T &) to another object type (U), T and U must be the same type.
Otherwise, the memory may be corrupted.
This is because of GVariant doesn't remember any type information, except the fundamental types.
So when casting to type U, GVariant will always assume that it holds a buffer with sizeof(U) and try to cast the buffer to U.
Rule 5, By default, casting a GVariant to reference-to-const (const T &) will not perform implicit type conversion.
std::string s = "blah";
v = s;
const std::string & rs = fromVariant<const std::string &>(v);
rs will become a reference to v.
The address of rs and v will be the same. &rs == &v
const char * s = "blah";
const std::string & rs = fromVariant<const std::string &>(s);
This doesn't work.
rs will reference to invalid address because s is not std::string.
And the cast will not convert C string to std::string.
To make fromVariant perform the implicit conversion, feed it with a second parameter.
const char * s = "blah";
const std::string & rs = fromVariant<const std::string &, VarantCastCopyConstRef>(s);
This works as if it's a C++ assignment,
const char * s = "blah";
const std::string & rs = s;
A temporary std::string will be create to hold s, then assign it to rs.
Rule 6, Setting a reference to fundamental (such as int &, double &) to variant will cause the value is copied instead of reference.
That's to say, you can't convert such variant back to reference.
int n = 0;
int & r = n;
GVariant v = r;
fromVariant<int &>(v); // faile
However, setting a reference to object (such as MyClass &) to variant will cause the variant references to the object.
MyClass c;
MyClass & r = c;
GVariant v = r;
fromVariant<MyClass &>(v); // ok
In summary, be careful to use reference. Usually you should reference-to-const or pointer instead of reference.
Rule 7, GVariant treats rvalue reference (int &&, MyClass &&, etc) same as lvalue reference.
GVariant memory management and avoid memory leakback top
GVariant manages memory automatically.
And usually a GVariant entity is created on the stack, and passed by value or const reference, then there is no possibility of memory leak.
However, the interface based APIs only accept GVariantData instead of GVariant.
GVariantData is a POD struct and doesn't manage the memory.
So to avoid memory leak, never use GVariantData directly. You should use GVariant.data instead.
For example, to invoke IMetaField::get to get the field value, we should write like this,
GVariant v;
myMetaClass->get(&v.data, instance);
// now v holds the value
// if we need to reuse v again, we should reset it
v = 0;
myMetaClass->get(&v.data, anotherInstance);


Classes as Dependencies
Before diving deeper into the Dependency Injection system, let's upgrade the previous example.
A dict
from the previous example¶
In the previous example, we were returning a dict
from our dependency ("dependable"):
from fastapi import Depends, FastAPI
app = FastAPI()
async def common_parameters(q: str = None, skip: int = 0, limit: int = 100):
return {"q": q, "skip": skip, "limit": limit}
@app.get("/items/")
async def read_items(commons: dict = Depends(common_parameters)):
return commons
@app.get("/users/")
async def read_users(commons: dict = Depends(common_parameters)):
return commons
But then we get a dict
in the parameter commons
of the path operation function.
And we know that editors can't provide a lot of support (like completion) for dict
s, because they can't know their keys and value types.
We can do better...
What makes a dependency¶
Up to now you have seen dependencies declared as functions.
But that's not the only way to declare dependencies (although it would probably be the more common).
The key factor is that a dependency should be a "callable".
A "callable" in Python is anything that Python can "call" like a function.
So, if you have an object something
(that might not be a function) and you can "call" it (execute it) like:
something()
or
something(some_argument, some_keyword_argument="foo")
then it is a "callable".
Classes as dependencies¶
You might notice that to create an instance of a Python class, you use that same syntax.
For example:
class Cat:
def __init__(self, name: str):
self.name = name
fluffy = Cat(name="Mr Fluffy")
In this case, fluffy
is an instance of the class Cat
.
And to create fluffy
, you are "calling" Cat
.
So, a Python class is also a callable.
Then, in FastAPI, you could use a Python class as a dependency.
What FastAPI actually checks is that it is a "callable" (function, class or anything else) and the parameters defined.
If you pass a "callable" as a dependency in FastAPI, it will analyze the parameters for that "callable", and process them in the same way as the parameters for a path operation function. Including sub-dependencies.
That also applies to callables with no parameters at all. The same as it would be for path operation functions with no parameters.
Then, we can change the dependency "dependable" common_parameters
from above to the class CommonQueryParameters
:
from fastapi import Depends, FastAPI
app = FastAPI()
fake_items_db = [{"item_name": "Foo"}, {"item_name": "Bar"}, {"item_name": "Baz"}]
class CommonQueryParams:
def __init__(self, q: str = None, skip: int = 0, limit: int = 100):
self.q = q
self.skip = skip
self.limit = limit
@app.get("/items/")
async def read_items(commons: CommonQueryParams = Depends(CommonQueryParams)):
response = {}
if commons.q:
response.update({"q": commons.q})
items = fake_items_db[commons.skip : commons.skip + commons.limit]
response.update({"items": items})
return response
Pay attention to the __init__
method used to create the instance of the class:
from fastapi import Depends, FastAPI
app = FastAPI()
fake_items_db = [{"item_name": "Foo"}, {"item_name": "Bar"}, {"item_name": "Baz"}]
class CommonQueryParams:
def __init__(self, q: str = None, skip: int = 0, limit: int = 100):
self.q = q
self.skip = skip
self.limit = limit
@app.get("/items/")
async def read_items(commons: CommonQueryParams = Depends(CommonQueryParams)):
response = {}
if commons.q:
response.update({"q": commons.q})
items = fake_items_db[commons.skip : commons.skip + commons.limit]
response.update({"items": items})
return response
...it has the same parameters as our previous common_parameters
:
from fastapi import Depends, FastAPI
app = FastAPI()
async def common_parameters(q: str = None, skip: int = 0, limit: int = 100):
return {"q": q, "skip": skip, "limit": limit}
@app.get("/items/")
async def read_items(commons: dict = Depends(common_parameters)):
return commons
@app.get("/users/")
async def read_users(commons: dict = Depends(common_parameters)):
return commons
Those parameters are what FastAPI will use to "solve" the dependency.
In both cases, it will have:
- an optional
q
query parameter. - a
skip
query parameter, with a default of0
. - a
limit
query parameter, with a default of100
.
In both cases the data will be converted, validated, documented on the OpenAPI schema, etc.
Use it¶
Now you can declare your dependency using this class.
And as when FastAPI calls that class the value that will be passed as commons
to your function will be an "instance" of the class, you can declare that parameter commons
to be of type of the class, CommonQueryParams
.
from fastapi import Depends, FastAPI
app = FastAPI()
fake_items_db = [{"item_name": "Foo"}, {"item_name": "Bar"}, {"item_name": "Baz"}]
class CommonQueryParams:
def __init__(self, q: str = None, skip: int = 0, limit: int = 100):
self.q = q
self.skip = skip
self.limit = limit
@app.get("/items/")
async def read_items(commons: CommonQueryParams = Depends(CommonQueryParams)):
response = {}
if commons.q:
response.update({"q": commons.q})
items = fake_items_db[commons.skip : commons.skip + commons.limit]
response.update({"items": items})
return response
Type annotation vs Depends
¶
In the code above, you are declaring commons
as:
commons: CommonQueryParams = Depends(CommonQueryParams)
The last CommonQueryParams
, in:
... = Depends(CommonQueryParams)
...is what FastAPI will actually use to know what is the dependency.
From it is that FastAPI will extract the declared parameters and that is what FastAPI will actually call.
In this case, the first CommonQueryParams
, in:
commons: CommonQueryParams ...
...doesn't have any special meaning for FastAPI. FastAPI won't use it for data conversion, validation, etc. (as it is using the = Depends(CommonQueryParams)
for that).
You could actually write just:
commons = Depends(CommonQueryParams)
..as in:
from fastapi import Depends, FastAPI
app = FastAPI()
fake_items_db = [{"item_name": "Foo"}, {"item_name": "Bar"}, {"item_name": "Baz"}]
class CommonQueryParams:
def __init__(self, q: str = None, skip: int = 0, limit: int = 100):
self.q = q
self.skip = skip
self.limit = limit
@app.get("/items/")
async def read_items(commons=Depends(CommonQueryParams)):
response = {}
if commons.q:
response.update({"q": commons.q})
items = fake_items_db[commons.skip : commons.skip + commons.limit]
response.update({"items": items})
return response
But declaring the type is encouraged as that way your editor will know what will be passed as the parameter commons
, and then it can help you with code completion, type checks, etc:
Shortcut¶
But you see that we are having some code repetition here, writing CommonQueryParams
twice:
commons: CommonQueryParams = Depends(CommonQueryParams)
FastAPI provides a shortcut for these cases, in where the dependency is specifically a class that FastAPI will "call" to create an instance of the class itself.
For those specific cases, you can do the following:
Instead of writing:
commons: CommonQueryParams = Depends(CommonQueryParams)
...you write:
commons: CommonQueryParams = Depends()
So, you can declare the dependency as the type of the variable, and use Depends()
as the "default" value (the value after the =
) for that function's parameter, without any parameter, instead of having to write the full class again inside of Depends(CommonQueryParams)
.
So, the same example would look like:
from fastapi import Depends, FastAPI
app = FastAPI()
fake_items_db = [{"item_name": "Foo"}, {"item_name": "Bar"}, {"item_name": "Baz"}]
class CommonQueryParams:
def __init__(self, q: str = None, skip: int = 0, limit: int = 100):
self.q = q
self.skip = skip
self.limit = limit
@app.get("/items/")
async def read_items(commons: CommonQueryParams = Depends()):
response = {}
if commons.q:
response.update({"q": commons.q})
items = fake_items_db[commons.skip : commons.skip + commons.limit]
response.update({"items": items})
return response
...and FastAPI will know what to do.
Tip
If all that seems more confusing than helpful, disregard it, you don't need it.
It is just a shortcut. Because FastAPI cares about helping you minimize code repetition.