text:
---
title: (BKS15) Dictionary Learning and Tensor Decomposition via the Sum-of-Squares Method
published: 2016-08-30
modified: 2016-08-30
tags: dictionary learning, tensor, sparse coding
type: paper
showTOC: True
---

**Theorem**. Given $\ep>0,\si\ge 1, \de>0$ there exists $d$ and a polytime algorithm that given input

* a $\si$-dictionary $n\times m$,
* $(d,\tau=n^{-\de})$-nice $\{x\}$,
* $n^{O(1)}$ samples from $y=Ax$,

outputs with probability $\ge 0.9$ a set $\ep$-close to columns of $A$.

* A $\si$-dictionary has $AA^T\preceq \si I$ (analytic proxy for overcompleteness $\fc mn$).
* A distribution is $(d,\tau)$-nice if $\E x_i^{d/2}x_j^{d/2}\le \tau$ for all $i\ne j$, and $\E x^\al=0$ for all $|\al|\le d$. (Ex. Bernoulli($\tau$) times Gaussian with $\E z_i^d = \rc\tau$.)

Note on running time:

* $\ep$-accuracy with running time depending on $\poly\prc{\ep}$ in the exponent. So this is better for giving an initial solution for local search methods.

# Noisy tensor decomposition 1

Given noisy version of $\sumo im \an{a^i, u}^d = \ve{A^Tu}_d^d$, recover $\{a^1,\ldots, a^m\}$.

**Theorem** (Noisy tensor decomposition). For every $\ep>0,\si\ge 1$ there exist $d,\tau$ such that a probabilistic $n^{O(\ln n)}$-time agorithm, given $P$ with
$$\ve{A^T u}_d^d - \tau \ve{u}_2^d \preceq P \preceq \ve{A^Tu}_d^d + \tau \ve{u}_2^d,$$
outputs with probability 0.9 $S$ that is $\ep$-close to $\{a^1,\ldots, a^m\}$. ($\preceq$ means the difference is a sum of squares.)

Note this allows significant noise since we expect $\ve{A^Tu}_d^d\sim mn^{-\fc d2}\ll \tau$.

## Reduction

Take
$$ P = \EE_{i} \an{y_i, u}^{2d}.$$

## Algorithm

1. Use SoS to find degree-$k$ pseudo-distribution $\{u\}$ that maximizes $P(u)$ under $\ve{u}^2=1$.
2. Let $W$ be a product of $O(\ln n)$ rndom linear functions.
3. Output top eigenvector of $M$, $M_{ij} = \wt \E W(u)^2 u_iu_j$.

**SoS Algorithm**: given $\ep>0, k,n,M$, $P_1,\ldots, P_m\in \R[x_1,\ldots, x_n]$ with coefficients in $[0,M]$, if there exists a degree $k$ pseudo-distribution with $P_i=0,i\in [m]$, then we can find $u'$ satisfying $P_i\le \ep, P_i\ge -\ep$ for every $i\in [m]$ in time $(n\polylog\prc{M}{\ep})^{O(k)}$.

(Proof: This is a feasibility problem. Use ellipsoid method.)

Steps

1. If $u$ is an actual distribution, the the output is close to a column.
2. Generalize to pseudo-distributions.
3. Generalize to getting all columns.

Idea: If not correlated, then $P(u)$ is small. The inequalities can be turned into polynomial inequalities provable by SoS.

# Noisy tensor decomposition

**Theorem** (Noisy tensor decomposition, 4.3).
There is a probabilistic algorithm that given

* $\ep>0$
* $\si \ge 1$
* degree $d\ge d(\ep,\si) = O\pf{\ln \si}{\ep}$
* noise parameter $\tau \le \tau(\ep) = \Om(\ep)$
*   degree $d$ polynomial $P\in \R[u]$ such that
	$$\ve{A^T u}_d^d - \tau \ve{u}_2^d \preceq P \preceq \ve{A^Tu}_d^d + \tau \ve{u}_2^d,$$
outputs with high probability $S$ that is $\ep$-close to $\{a^1,\ldots, a^m\}$. ($\preceq$ means the difference is a sum of squares.)

## Algorithm

1. Start with $S=\phi$. Let $\ga = \fc{C}{\ep}$ for $C$ large enough. ?? What's $k$?
2. Loop:
    1. Attempt to find a degree $k$ pseudo-distribution $U$ satisfying the constraints $P(U) \ge 1-\tau$, $\ve{U}_2^2=1$, $\an{s,U}^2\le 1-\ga$ for every $s\in S$ (to repel it away from vectors we already found). If fail, stop.
	2.  Use the "sampling pseudo-distributions" algorithm to obtain a unit vector $c'$ such that
	    \begin{align}
		P(c') & \ge e^{-\ep d} - \tau\\
		\ep &:= O(\pf{\tau}{d} + \fc{\ln \si}{d} \fc{\ln m}k)
		\end{align}
	3. Add $c'$ to $S$.

### Sampling pseudo-distributions

## Proof

1. Existence of $c'$.
    * $U$ exists because any column of $A$ is a solution. (CHECK columns far!!)
	*   $U$ is correlated with $A$: By assumption, for $\ve{U}_2^2=1$, $P\in \ve{A^T U}_d^d + \tau[-1,1]$. Thus $P(U)\ge 1-\tau$ implies
	    $$\ve{A^TU}_d^d \ge 1-2\tau.$$
	*   If $U$ correlates well with $A$, then $U$ correlates with some column of $A$.
	<!--Any column of $A$ satisfies $\wt \E \an{c,u}^k \ge e^{-\ep' k}$.-->

	    *Lemma 6.1*. Given

		* $A$ is $\si$-overcomplete
		* $u$ is degree $3k$ pd over $\R^n$ satisfying $\ve{A^Tu}_d^d \ge e^{-\de d}, \ve{u}_2^2 = 1$,
		* $d-2\mid k$ (?? this seems to be necessary. Think of $k\gg d$.)

		there exists a column of $A$ such that $\wt \E \an{c,u}^k \ge e^{-\ep k}$, $\ep=O(\de + \fc{\ln \si}{d} + \fc{\ln m}k)$.

		*   Motivation for proof: First, let's see how to prove this if $u$ is an actual vector. By averaging, there is a column such that
			$$ \ve{A_{\cdot i}^T u}_{k}^k \ge \pf{1-\ep}{m}\implies A_{\cdot i}^Tu \ge \pf{1-\ep}{m}^{\rc k}\approx e^{\fc{\ln m}{k}}.$$
			(This also shows why we expect $\ln m$ in the exponent.) This averaging argument still works for pseudo-distributions when $d=k$---the first inequality still holds true, if we have $d=k$. (The first inequality would no longer imply the second, though.) (?? Why wouldn't we take $d=k$?)
		*   ?? For some reason, we want to use an inequality not depending on $m$ (depending on $\ve{A^Tu}_2$ is good, because we have control of this using $\si$), in which case instead of using the inequality $\ve{v}_{\iy} \ge \fc{\ve{v}_d}{m^{\rc d}}$ we use $\ve{v}_{\iy}^{d-2}\ge \fc{\ve{v}_d^d}{\ve{v}_2^2}$. We need to change this into a SoS inequality, so replace $\iy$ by $k$ for $k$ large,
		    $$\ve{v}_d^{\fc{dk}{d-2}} \le \ve{v}_k^k (\ve{v}_2^2)^{\fc{k}{d-2}}$$
			provable by SoS (expand and then use Muirhead/AM-GM).
		*   <!-- For the actual proof, we just need to relate the $d$ and $k$ norms. We want to lower-bound the $k$th norm in terms of the $d$th norm. Use
			$$ \ve{v}_k^{d-2} \ve{v}_2^2 \ge \ve{v}_d^d. $$
			(This is true for $k=1$ by expanding, and hence for all $k$.)-->
			*Proof*.
			$$
			\ve{A^Tu}_k^k \ge \fc{(\ve{A^Tu}_d^d)^{\fc k{d-2}}}{(\ve{A^Tu}_2^2)^{\fc{k}{d-2}}} \ge \fc{e^{-\de d}}{\si^{\fc k{d-2}}}.
			$$
			Now use averaging on $\ve{A^Tu}_k^k$.
	*   Here $\de = O\pf{\tau}d$ so we get
		$$ \wt E \an{c,u}^k \ge e^{-\ep' k},\quad \ep' = O(\fc{\tau}d + \fc{\ln \si}{d} +\fc{\ln m}{k}).$$
		This means we set $k=\boxed{\frac{C\ln m}{\ep}}$. This also means we need $d=\Om(\rc{\ep}\ln \si)$, $\tau=O(\ep)$.
	*   Example: if $u$ is the actual distribution $u=A_{\cdot i}$ with probability $\rc{m}$, then $\wt E\an{c,u}^k = \rc m$. Hence we can't do better than $k=\Om(\ln m)$.
2.  Now we analyze the algorithm to "sample pseudo-distributions": given a PD that correlates with a vector, find a vector close to it. We prove:

	**Theorem 5.1**. The "sample pseudo-distributions" algorithm, given

	* even $k\ge 0$
	* degree $k$ p.d. with $\ve{u}_2^2=1$ and $\wt \E\an{c,u}^k \ge e^{-\ep k}$ (?? I think we want this for $k-2$.)

	outputs $c'\in \R^n$ with $\an{c,c'}\ge 1-O(\ep)$ with probability $2^{-\fc{k}{\poly(\ep)}}$.

	* Here is the idea. We want to compute the tensor decomposition by using SVD (because there aren't other good ways to compute overcomplete tensor decomposition...). Suppose that $u$ were an actual distribution; since it is correlated with $A$, it is approximately supported on columns of $A$. Then $\wt \E uu^T = \sum p_i a_i a_i^T$. The $a_i$ are not uniquely identifiable from this (that's the whole problem with SVD, why we want tensors in the first place!). Idea: consider $\wt \E p(u) uu^T = \sum p_i p(a_i) a_ia_i^T$ instead. If $p$ is a function that is large on $a_i$ and small on all other $a_j$, then we win. Take $p$ to be a product of linear factors. If we put in enough factors, then with good probability the $p(a_i)$ will become farther apart, and one outruns the others, $|p(a_i)|\gg \sqrt m|p(a_i)|$. Take $p =W^2$ where $W$ is a product of $O(\ln n)$ random linear functions $\an{u,v}, \ve{v}_2=1$.
	*   We are given $c$ such that $\wt E\an{c,u}^k \ge e^{-\de d}$ (high correlation) and we want that $c$ to be a value of $v$ that makes  (the quadratic form) $v\mapsto \wt \E W(U) \an{v,U}^2$ large. In fact, what we want is that <!--the value is way bigger than any other singular values; i.e.,--> when normalized so the sum of the eigenvalues is 1, the singular value corresponding to $c$ is close to 1.

		There are 3 parts. (a) We need to understand how "renormalization" of pseudo-distributions works. (b) We need to show that for our choice of $W$, we have with some probability a lower bound for $\wt \E W(U) \an{c,U}^2$. This is the hardest part. (c) We need to show that $c$ is close to the singular vector (which we output). (I think (c) is in essence a matrix/eigenvector perturbation result, but it's cloaked in the language of SoS here---unravel!)
	*   **Lemma** (reweighting). Let $U$ be a degree $k$ p.d. Then for every SoS polynomial $W$ of degree $d<k$, $\wt \E W>0$, there exists a degree $(k-d)$ p.d. $U'$ such that for every $\deg P \le k-d$,
		$$\wt E_{U'} P(U') = \rc{\wt \E_U W(U)} \wt \E_{U} W(U)P(U).$$
		*Proof*. Just verify the positivity property.
	*   **Lemma 5.2**. Let $U$ be a degree-$k+2$ pseudo-distribution over $\R^n$ with $\ve{U}_2^2=1$ and
		such that there exists a unit vector $c\in \R^n$ such that $\wt \E\an{c,u}^k \ge e^{-\ep k}$.
		$W=\rc{M^{k/2}} \prod_{i=1}^{k/2} w^{(i)}$ where $w^{(i)}$ are iid draws from $w=\an{\xi,u}^2$, $\xi\sim N(0,I_n)$. Then with probability $2^{-O\pf{k}{\poly(\ep)}}$, $\wt \E\an{c,u}^2W \ge (1-O(\ep))\wt \E W$.

		(?? Discrepancy between $k$ and $k+2$.)
	*   By reweighting, there exists a degree 2 p.d. $U'$ such that
		$$\wt \E_{U'} \an{v,u'}^2 = \rc{\wt \E_U W(U)} \wt\E_{U} W(U) \an{v,U}^2.$$
		By Lemma 5.2, the value at $c$ is $\ge 1-O(\ep)$.
	*   *Proof* (Sketch). This is more likely to be true if $\an{c,\xi}$ is large. Let $w=\an{\xi,u}^2$. Let $\tau_M$ be such that $\E_{\xi_0|\xi_0\ge \tau_M}\xi_0^2 =M$. Conditioning on $\an{c,\xi}\ge \tau_{M+1}$ and expanding $\xi=\an{c,\xi}c+\xi'$, find that
		$$ \E_{\xi | \an{c,\xi}\ge \tau_{M+1}} w = M\an{c,u}^2 + \ve{U}_2^2.$$
		Let $\ol W = \E W = \pa{\an{c,U}^2 + \rc M}^{\fc k2}$ (assume $\ve{u}_2^2=1$). Algebra shows
		\begin{align}
		\ol W \an{c,U}^2 &\succeq \pa{1-\fc 2M } \ol W - \pa{1-\rc M}^{\fc k2}\\
		\EE_W \wt \E W\an{c,u}^2 & \ge (1-O(\ep)) \EE_W \wt \E W.
		\end{align}
		(Take $M=\rc{\ep}\ln \prc{\ep}$.)
		This is almost what we want, except that we conditioned on $\an{c,\xi}\ge \tau_{M+1}$ and that this is an inequality about absolute values.

		To get rid of the conditioning, note that the event $\forall i, \an{\xi^{(i)},c}\ge \tau_{M+1}$ has probability  $2^{-O(kM^2)}$.

		To get the result with not-too-small probability, rearrange as
		$$
		O(\ep) \EE_W \wt \E W \ge \EE_W \wt \E W - \EE_W \wt \E W\an{c,U}^2,
		$$
		bound second moments $\E_W(\wt \E W)^2$, and use
		* **Lemma 5.3**. Let $A,B$ be distributions such that $0\le A\le B$, $\de \in [0,1]$. If $\E A\le \ep \E B$ and $\E B^2 \le t(\E B)^2$, then $\Pj(A\le e^\de \ep B) \ge \fc{\de^2}{9t}$.
	*   (From degree 2 p.d. to a vector)

		**Lemma 5.4**. Let $c\in \R^n$ be unit and $U$ be a degree-2 p.d. over $\R^n$ satisfying $\ve{U}_2^2=1$. If $\wt \E\an{c,U}^2 \ge 1-\ep$, then letting $\xi$ match the first two moments of $U$ and $v=\fc{\xi}{\ve{\xi}_2}$, we have $\Pj[\an{c,v}^2 \ge 1-2\ep] =\Om(1)$.

		*Proof*. Again use Lemma 5.3, just check $\E\ve{\xi}_2^t \le O(\E\ve{\xi}_2^2)^2$.
	* Summary of parameters in Theorem 5.1.
		* Running time $n^{O(k)}$: Just to evaluate $W$ on a degree $k$ p.d. takes $n^{O(k)}$ time.
		* Success probability $2^{-k/\poly(\ep)}$: $W$ succeeded if each $\an{c,\xi^{(i)}}$ is large, so we get $-k$ in the exponent. (!! This seems like a very crude bound---I expect we can do much better, maybe even subexponential?) $M$ depends polynomially on $\rc{\ep}$; $\rc{\poly(\ep)}$ is in the exponent because the algorithm relies on sampling to get close enough.
3. Finish.
    * In step 1, from 6.1, we get $\wt \E \an{c,u}^k \ge e^{-\ep' k}$, $\ep' = O\pa{\fc\tau d+ \fc{\ln \si}d + \fc{\ln m}k}$.
	* From 5.1, we get $c'$ close to a column $c$ of $A$: $\an{c,c'}\ge 1-O(\ep')$ with probability $2^{-\fc{k}{\poly(\ep')}}$. Repeat $2^{\fc{k}{\poly(\ep')}}$ times to get this with good probability. ($\ep = \Te(\ep')$.)
	* (Far from other vectors already in $S$) We have $P(c') \ge c^Tc' - \tau\ve{c'}_2^2 \ge e^{-\ep d}-\tau$. Calculation using the triangle inequality on (after doing $\bullet^{\ot 2}$ because the inequality we have is $\an{s,U}^2\le 1-\ga$) gives $\an{c',s}\le 1-\fc{\ga}{10}$. (We chose $\ga = C\ep$.)
	  <img src="/images/bks15-tri.png">
	* (Every $s\in S$ is close to some column.) Use 6.1 on $s$ (which is an actual vector! not a p.d.), $\ve{A^T s}_d^d \ge e^{-\ep d}-2\tau$ to get $\an{s,c}^2 \ge 1-O(\ep)$.
	* (Can't have 2 $s\in S$ close to same $c$) More triangle inequalities.
	* The algorithm then terminates after $|S|=m$. The total time is $n^{O(k)/\poly(\ep)} = n^{\fc{\ln m}{\poly(\ep)}}$. There's an extra $d$ in the exponent because accessing $P$ takes $n^d$ time. (CHECK!!)

# Dictionary learning

# Theorem

The algorithm below, given

* $\ep>0$
* overcompleteness $\si\ge 1$
* $d\ge D:=O\pf{\ln \si}{\ep}$,
* $\tau \le (D\si)^{-D}$. (In 4.2 it says $D^D$, but I think it should be this.)
* $\wt O \pf{n^{2d}}{\tau^2}$ samples from $y=Ax$ for $(d,\tau)$-nice $x$,

outputs in time $n^{\fc{d+\ln m}{\ep^{O(1)}}}$ a set of vectors $\ep$-close to $A$.

## Algorithm

Take $\wt O \fc{n^{2d}}{\tau^2}$ samples $x^{(i)}$ and apply noisy tensor decomposition to the polynomial
$$
\EE_i x^{(i)} \an{Ax,u}^d
$$
where $d\ge D:=O(\ep^{-1}\ln \si)$.

Note that $\an{Ax,u}^d$ is the polynomial ($n$-ic form) corresponding to the tensor $(Ax)^{\ot d}$, just as $u^T vv^Tu = \an{u,v}^2$ is the quadratic form corresponding to the matrix $vv^T$.

*Proof*.

1.  (Calculate expectation) *Lemma 4.5*. If the distribution of $x$ is $(d,\tau)$-nice and $A$ is $\si$-overcomplete, then
    $$\EE_x \an{Ax,u}^d \in \ve{A^Tu}_d^d + [0,\tau \si^dd^d \ve{u}_2^d]$$
	(where inequalities are in the SoS sense).

	*Proof*. Expand the sum as $\sum_\al x_\al (A^Tu)_\al$. For $\al=[i,\ldots, i]$ we get the term $(A^Tu)_i^d$. For the other terms, <!--each even term $\al\ne [i,\ldots, i]$ we get the term -->
	\begin{align}
	0 &\le \sum_{\al \in [n]^d,\al \ne [i,\ldots, i] }(\E x_\al) (A^Tu)_\al \\
	& \le \tau \sum_{\al \in [n]^d,\al \ne [i,\ldots, i] } (A^Tu)_\al \\
	& \le \tau d^d\sum_{\be \in [n]^{d/2},\be \ne [i,\ldots, i] } (A^Tu)_\be\\
	& \le \tau d^d\ve{A^Tu}_2^d \le \tau \si^d \ve{u}_2^d.
	\end{align}
	(The $d^d$ bound is crude; this is not the bottleneck.) Note the lower inequality depends on there only being even nonzero terms.
2.  (Calculate concentration, Proof of 4.2) We use a Chebyshev bound[^cheb]. We have $|(A^Tx)_\al|\le 1$. **I think we need assumption on $\ve{A^Tx}_{\iy}$**. Thus taking $\wt \Om\pf{n^{2d}}{\tau^2}$ samples we get that the coefficients are whp $\fc{\tau}{n^d}$-close. This means the value at $u$ is $n^d \si^d\fc{\tau}{n^d}$-close, and we get whp
	$$P\in \ve{A^Tu}_d^d + 2\tau \si^d d^d \ve{u}_2^d[-1,1].$$
3.  Use noisy tensor decomposition. Check parameters. There we needed $d \ge D=O(\rc{\ep}\ln \si)$. We need $\tau\le \fc{\ep}{\si^DD^D}$. (**Errata?** The value of $\tau$ is different than in the theorem.)

[^cheb]: Can we do better if we use polynomial concentration?

# Polytime algorithm

This means polytime for fixed $\ep$. Note to get $\rc{\ln n}$ closeness (ex. for initialization of an iterative DL algorithm), we need quasipolytime, $n^{O(\ln n)}$.

The bottleneck is the $\ln m$ in Lemma 6.1, where we used averaging to conclude that if $U$ has large correlation with $A$, then $U$ has large correlation with a column of $A$.

<!-- We want to sidestep this! So directly fix a column, and instead of comparing $W$ to -->

| Before | Now |
|---|---|
| 5.2 | 7.2 |
| 5.1 | 7.1 |
| 6.1 | 7.3 |

To summarize the previous argument, we show our distribution of $W$ satisfies inequalities given in 5.2, and then use reweighting to obtain that $u$ is correlated with some column in 5.1. Now we use the weak lemma 6.1 which recovers that column, with $\ln m$ loss.

If we weaken the conclusion of 6.1, then we can hope that 6.1', i.e., 7.3, doesn't have a $\ln m$ in the place we care about. Then we need 5.1', i.e., 7.1, to work with these weaker conditions. Sparsity allows us to weaken the conditions on correlation, provided we have better bounds information about the distribution $W$ that we choose.

(Not quite: 5.2 was a lemma for 5.1. 7.1 is a lemma for 7.2, we use 7.1+5.1 to get 7.1.)

Specifically, the condition on the p.d. $U$ (degree $2(1+2k)$) is (7.2)
$$ \wt \E\an{c,U}^{2(1+2k)} \ge e^{-\ep k} \wt \E \an{c,U}^2, \qquad \wt E\an{c,u}^2\ge \tau^k.
$$
This is easier to satisfy: the $\rc m$ that causes problems is moved to the second inequality (as long as we have sparsity $\tau^k\le \rc m$ we are OK). The second inequality is true if sparsity is $\tau$ (CHECK!!). $k$ no longer needs a factor $\rc{\ln m}$ in the denominator to satisfy this.

Note 5.2, 5.1 don't mention the sparsity at all, while 7.2, 7.1 mention $\tau$ which will be related to the sparsity.

Some changes: instead of reducing from degree $k$ to $2$ we reduce from degree $\approx 4k$ to $2k$. (??)

So how does the algorithm work now, given that our assumption is (7.2) rather than a bound on $\wt \E \an{c,u}$? 7.1 has the following inequality on $\ol W= \E_WW$, (7.1):
$$\an{c,U}^{2(1+k)}\preceq \ol W \preceq (\an{c,U}^2 + \tau\ve{U}_2^2)^{1+k}.$$
Using this, get an upper bound on $\wt \E \ol W$ and lower bound on $\wt \E \an{c,U}^{k}$ to get a lower bound on $\wt\E \ol W\an{c,U}^{2k}$:
$$\wt \E \ol W\an{c,U}^{2k} \wt \E \ol W \ge [\wt \E(\ol W \an{c,U}^k)]^2.$$

The bound on $\ol W$ comes from sparsity. Take $W=\prodo i{k/2-1} \an{y_i=Ax_i,U}^2$. $\ol W$ does not actually satisfy (7.1); it does after reweighting by $\prodo i{k/2-1} x_{i,1}^2$. (This is a distribution over polynomials. Take the probability that $\prod \an{Ax_i,U}^2$ is chosen and multiply it by $\prod x_{i,1}^2$ and normalize the probabilities. (Not multiply the polynomial.)) Consider $c\an{Ax,u}^2$ reweighted by $x_i^2$; expand and use sparsity to get a nice bound on expectations.

This is much better than the previous analysis on $W$! It actually seems to take into account some kind of concentration...

Final theorem is 7.6.

# Todo

* Summarize changes to get down to polytime. What's the key idea?

(Q: can you adapt something like this for NMF?)

repository: holdenlee/notebook

repo_name: holdenlee/notebook


text:
# Vanilla JS - fade   [![ko-fi](https://www.ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/X8X81MJAP)

[![npm version](https://badge.fury.io/js/vanilla-fade.svg)](https://badge.fury.io/js/vanilla-fade) ![David](https://img.shields.io/david/dev/matteobad/vanilla-fade.svg) ![David](https://img.shields.io/david/matteobad/vanilla-fade.svg) [![Build Status](https://travis-ci.org/matteobad/vanilla-fade.svg?branch=master)](https://travis-ci.org/matteobad/vanilla-fade/) [![Greenkeeper badge](https://badges.greenkeeper.io/matteobad/vanilla-fade.svg)](https://greenkeeper.io/) [![semantic-release](https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg)](https://github.com/semantic-release/semantic-release) [![Commitizen friendly](https://img.shields.io/badge/commitizen-friendly-brightgreen.svg)](http://commitizen.github.io/cz-cli/) [![Contributor Covenant](https://img.shields.io/badge/Contributor%20Covenant-v1.4%20adopted-ff69b4.svg)](code-of-conduct.md)

Simple **Vanilla JS** implementation of the `fadeIn()`, `fadeOut()`, `fadeTo()` and `fadeToggle()` methods. This little package once loaded will add the mentioned methods to the `Element` prototype. All of the above methods accept the same paramaters: [duration, easing, complete]. Furthermore the `prefers-reduce-motion` is natively supported. You can read more about it [here](https://developers.google.com/web/updates/2019/03/prefers-reduced-motion).

* [Installation](#installation)
* [Usage](#usage)
* [prefers-reduce-motion](https://developers.google.com/web/updates/2019/03/prefers-reduced-motion)
* [Broser support](#browser-support)
* [Demo](https://matteobad.github.io/vanilla-fade)

---

**Find this usefull? ☕ [Buy me a coffee!](https://ko-fi.com/matteobad)**

---

## Installation

This package can be downloaded from the NPM registry `npm install vanilla-fade --save`. Or included in via a standard script tag from [this url](https://unpkg.com/vanilla-fade/dist/vanilla-fade.js).  The methods accepts the following paramenters:

```javascript
Element.fadeIn(duration = 250, easing = 'linear', complete = null)
Element.fadeOut(duration = 250, easing = 'linear', complete = null)
Element.fadeTo(duration = 250, opacity = NaN, easing = 'linear', complete = null)
Element.fadeToggle(duration = 250, easing = 'linear', complete = null)
```

* **duration** can be a number or a string representing and integer of milliseconds.
* **opacity** final opacity value. _Required only in **fadeTo**_
* **easing** should be one of the following string: _[linear, quadratic, swing, circ, bounce]_.
* **complete** is a callback that will be executed after the animation completes.

The Element display property won't change after fading out. No assumption on the original display value or opacity value are made. Once triggered the opacity will go from 0 -> 1 and viceversa. So if the element original opacity was .5 this value won't be considered when toggling the fading effect.

## Browser support

Babel will automatically transpile according to the following browserslist:

```json
# Browsers that we support

defaults
```

license: MIT

repository: matteobad/vanilla-fade

branch_name: refs/heads/master

extension: md

gha_language: JavaScript

gha_license_id: MIT

license_type: permissive

repo_name: matteobad/vanilla-fade


text:
# Clostridium ganghwense Kim et al., 2006 SPECIES

#### Status
ACCEPTED

#### According to
The Catalogue of Life, 3rd January 2011

#### Published in
Kim, Jeong, Kim & Chun. 2006. Clostridium ganghwense sp. nov. , isolated from tidal flat sediment. International Journal of Systematic and Evolutionary Microbiology    Volume: 56    Pages: 691-693    Part: Part 4

#### Original name
null

### Remarks
null

repository: mdoering/backbone

repo_name: mdoering/backbone


text:
# ErgoDox EZ

All about the ErgoDox EZ

- Configuring your ErgoDox
    - [Installing a configuration](#installing-a-configuration)
    - [Keyboard configuration tools](#keyboard-configuration-tools)
    - [Existing configurations you can examine or download](https://github.com/ErgoDox-EZ/docs/wiki/Existing-configurations)
    - [Write/update your own configuration (in c!)](#writeupdate-your-own-configuration (in c!))
- Information about the ErgoDox EZ
    - [Original Crowdfunding campaign](https://www.indiegogo.com/projects/ergodox-ez-an-incredible-mechanical-keyboard)
    - [Purchase one](https://www.indiegogo.com/projects/ergodox-ez-an-incredible-mechanical-keyboard)
    - [Specifications](#technical-specifications)
    - [Accessories](#accessories)
- [Articles and reviews](#articles-and-reviews)

## Configuring your ErgoDox

### Installing a configuration

a.k.a. flashing the firmware

First, make sure:

* Your keyboard is plugged in
* You know what the "Teensy reset button" is ([the tiny hole in the upper right](tiny_reset_button.jpg)). Alternatively, you can use the "teensy" key if it's in your keymap.
* Download the [firmware.eep](firmware.eep) from this repository

Then:

1. Download and run the [Teensy Loader app](http://www.pjrc.com/teensy/loader.html)
2. Press and release the Teensy reset button
3. Click the "Auto" button on the upper right hand side of the Teensy-Loader window
4. Drag and drop the '.eep' file onto the Teensy loader window.
5. Drag and drop the '.hex' file onto the Teensy loader window.
6. Press and release the Teensy reset button

Notes:

* If this process fails in the "Auto" button stage, try dragging in a .eep and a .hex file, then pressing auto and restarting the process from the beginning.
* For a more detailed account, check out the [ergodox-firmware repository](https://github.com/benblazak/ergodox-firmware#load-firmware-onto-the-teensy)

### Keyboard configuration tools

- [keyboard-configurator from massdrop](https://keyboard-configurator.massdrop.com/ext/ergodox)
    - Works and looks good *check the comments on that page for information about special keys, like hold-key-for-layer and media keys*
    - Isn't open source. Doesn't provide a way to load other people's configurations into the tool.
- [fusion](https://github.com/ErgoDox-EZ/fusion)
    - Open source. Work in progress. Will exist soon.

### Existing configurations

[Look at the list of existing configurations on the wiki](https://github.com/ErgoDox-EZ/docs/wiki/Existing-configurations)

### Write/update your own configuration (in c!)

This requires a little bit of familiarity with coding.

1. Go to [github.com/jackhumbert/qmk_firmware](https://github.com/jackhumbert/qmk_firmware) and read the Readme at the base of the repository, top to bottom.
2. Follow the instructions for [ergodox_ez configuration](https://github.com/jackhumbert/qmk_firmware/tree/master/keyboard/ergodox_ez)
3. Create a repository to track your configuration and [add it to this readme](#existing-configurations)

## Information about the ErgoDox EZ

The ErgoDox EZ was created by Erez, who ran a [successful Indiegogo campaign](https://www.indiegogo.com/projects/ergodox-ez-an-incredible-mechanical-keyboard) in 2015 and shipped keyboards in December of 2015

You can still purchase one on the indiegogo page.

### Technical Specifications

The compact and ergonomic open-source ErgoDox mechanical keyboard, fully assembled in Taiwan in an injection-molded ABS plastic case, with:

- Two independent halves connected by a 3.5mm jack cable (replace cable for custom length)
- USB jack and starter cable (replace cable for custom length)
a full (including flashing alternative firmware, switching keycaps, but not opening case or dunking in aquarium) 2-year manufacturer's warranty
- A Teensy 2 (32 KB) micro-controller running QMK firmware with support for N-key rollover (NKRO), unicode input up to at least 0xfff, mouse keys, and fully customizable layouts

## Options and accessories

#### Official options/accessories

- Printed keycaps in DSA (flat) profile
- Blank keycaps come in DCS (sculptured) profile.
- Tilt/Tent kit: six rubber-footed metal legs for custom tilt (front-to-back) and tent (side-to-side) angle adjustments of each keyboard half, standard thumb screw size
- Wing wrist rest
- one-handed version (seen by computer as 2 keyboards)

#### Unofficial options

This list is ongoing and a work in progress. Please update with more information!

- home row indicators, [e.g. Part #<PHONE_NUMBER>](http://shop.hooleon.com/)
- [o-ring dampers](http://www.wasdkeyboards.com/index.php/cherry-mx-rubber-o-ring-switch-dampeners-125pcs.html)
- [graffiti wrist rests](http://www.grifiti.com/products/ergodox-fat-wrist-pad-set-custom-fit-massdrop-split-keyboard-set)
- Custom 3.5mm and/or USB cables
- New/custom keycaps: WASD, Signature, etc.
- Bluetooth adapters, e.g. [Nulaxy](https://www.indiegogo.com/projects/keyboard-mouse-bluetooth-adapter/x/10804964) (compatibility?)

## Articles and Reviews

- [Deskthority ErgoDox article](http://deskthority.net/wiki/ErgoDox)
- [Why any developer should check out the ErgoDox keyboard](http://jjt.io/2013/11/25/why-any-developer-should-check-out-the-ergodox-keyboard/)
- makeuseof: [Why Hardware Startups Are Hard: Bringing the ErgoDox to Life](http://www.makeuseof.com/tag/time-founding-hardware-startup/)
- [The Evolution And Commercialization Of The ErgoDox Keyboard](http://trauring.org/the-evolution-and-commercialization-of-the-ergodox-keyboard/)
- [Typing an DIY ErgoDox — video](https://www.youtube.com/watch?v=M8aQS4bRv6w)
- geekhack: [How are you liking your ErgoDox?](https://geekhack.org/index.php?topic=42231.0)
- [DIY Infinity ErgoDox](https://www.massdrop.com/buy/infinity-ergodox)

#### Also

Much thanks to [@inkthink](https://github.com/inkthink) for his original unofficial wiki, [@sethherr](https://github.com/sethherr) and [@ezuk](https://github.com/ezuk)

repository: inkthink/docs

extension: markdown

repo_name: inkthink/docs


text:
# Tablecloth Sizing Tool 🔧

![tablecloth sizing tool](https://user-images.githubusercontent.com/17105490/121664737-a5a83b80-ca5c-11eb-80d7-65fd9e9b9b02.png)

A webapp that helps users visualize how tablecloths of different shapes and sizes fit on a table.

This was my intern project at Ya Ya Creations which runs [efavormart.com](https://www.efavormart.com/), a store that specializes in wedding and party suppplies. It helps convert sales for tablecloths which is our most popular product!

View the webapp here:
https://www.efavormart.com/pages/tablecloth-sizing-tool

repository: richardshu/TableclothSizingTool

repo_name: richardshu/TableclothSizingTool


text:
### Project Overview

 ****Inferential Statistics****

**Problem Statement**

Bank Of New York wants to expand its branches and for that, it has a certain hypothesis and statements it wants to verify. Using the inferential statistics method I have learned, we help the bank achieve its objectives.

Dataset has data from 9578 customers with the following 15 features:

- Feature	- Description
- customer.id	- ID of the customer
- credit.policy	- If the customer meets the credit underwriting criteria of LendingClub.com or not
- purpose	- The purpose of the loan(takes values :"creditcard", "debtconsolidation", "educational", "majorpurchase", "smallbusiness", and "all_other").
- int.rate	- The interest rate of the loan
- installment	- The monthly installments owed by the borrower if the loan is funded
- log.annual.inc	- The natural log of the self-reported annual income of the borrower
- dti	- The debt-to-income ratio of the borrower (amount of debt divided by annual income)
- fico	- The FICO credit score of the borrower
- days.with.cr.line	- The number of days the borrower has had a credit line.
- revol.bal	- The borrower's revolving balance (amount unpaid at the end of the credit card billing cycle)
- revol.util	- The borrower's revolving line utilization rate (the amount of the credit line used relative to total credit available)
- pub.rec	- The borrower's number of derogatory public records (bankruptcy filings, tax liens, or judgments)
- inq.last.6mths	- The borrower's number of inquiries by creditors in the last 6 months
- delinq.2yrs	- The number of times the borrower had been 30+ days past due on a payment in the past 2 years
- paid.back.loan	- Whether the user has paid back loan

### Learnings from the project

 After completing this project, I got a better understanding of how to use inferential statistics. In this project, I have applied the following concepts:

- Confidence Interval
- Central Limit Theorem
- Hypothesis Testing
- Chi-Square Test

repository: SufiyanDilawarkhan/ga-learner-dsmp-repo

repo_name: SufiyanDilawarkhan/ga-learner-dsmp-repo


text:
Using SQL
========

Since version 2x, [Tarantool](https://tarantool.org/ "Tarantool") provides [SQL interface](https://www.tarantool.io/en/doc/2.2/tutorials/sql_tutorial/).

Tarantalk supports executing SQL synchronously / asynchronously utilizing this feature.

## Installation ##

Make sure you have installed tarantool 2.x series.
(1.10 does not have SQL interface.)

```bash
$ tarantool -v
```
->
```bash
Tarantool 2.1.2-111-ga3f3cc627
```
For details, please see Tarantool [download section](https://www.tarantool.io/en/download/).

## Basic API ##

You can use `TrObject >> #executeSql:` series for synchronous SQL execution.

## Create Table

Let's create a student table.

```smalltalk
tarantalk := TrTarantalk connect: 'taran:talk@localhost:3301'.
tarantalk executeSql: 'create table students (studentNumber integer primary key, name text)'.
```

## Insert values

Now insering some students.

```smalltalk
1 to: 5 do: [ :idx |
	tarantalk executeSql: 'insert into students values (?, ?)' values: {idx. ('student-', idx asString)}.
].
```

Please note that postgres-style parameter placeholder ('?') is supported with `#executeSql:values:`.

Named parameters can also be used by `#executeSql:mapped:`.

```smalltalk
tarantalk executeSql: 'insert into students values (:id, :name)' mapped: { 'id'->6. 'name'->'Masashi Umezawa' }
```

### Getting changed row count

On non-select queries, you can get a changed row count as a return value.

```smalltalk
sqlInfo := tarantalk executeSql: 'insert into students values (?, ?)' values: {7. 'Taran Talk'}.
sqlInfo changedRowCount. "=> 1"
```

## Select rows

Now, let's select all the rows.

```smalltalk
result := tarantalk executeSql: 'select * from students'.
result do: [ :each | Transcript cr; show: each ].
```
In your Transcript, you can see:

```smalltalk

#(1 'student-1')
#(2 'student-2')
#(3 'student-3')
#(4 'student-4')
#(5 'student-5')
#(6 'Masashi Umezawa')
#(7 'Taran Talk')
```

### Getting column metadata

On select queries, the result contains metadata as well as the actual data.

```smalltalk
metadata := result metadata.
metadata columns do: [ :each | Transcript cr; show: each ].
```
Now you can see in Transcript:

```smalltalk
TrColumnMetadata ( name: 'STUDENTNUMBER' type: 'integer')
TrColumnMetadata ( name: 'NAME' type: 'string')
```

## Async API ##

There are also `TrObject >> #asyncExecuteSql:` series.
The query result can be retrieved asynchronously or you can just ignore.

```smalltalk
futureResult := tarantalk asyncExecuteSql: 'select * from students where studentNumber = ?' values: {7}.
futureResult ifDone: [:result | Transcript cr; show: result] ifFailed: [:error | error signal].
Transcript clear.
```

When you evaluate above expressions, Transcript will be firstly cleared and result will be displayed a bit later.
```smalltalk

#(#(7 'Taran Talk'))
```

repository: mumez/Tarantalk

gha_language: Smalltalk

repo_name: mumez/Tarantalk


text:
# Frequency Domain Effects (FFT)

// 	1) Fast Fourier Transform examples
//	2) Language manipulation of bins

Most of the well known audio effects process audio in the time domain, typically varying samples in amplitude (ring modulation, waveshaping, distortion) or time (filters or delays). Fast Fourier Transform (FFT) is a computational algorithm that allows us to manipulate sound in the frequency domain, performing various calculations on the independent frequency bins of the signal.

In FFT, windows are taken from the sound signal and analysed one by one. (The window size is typically 512 or 1024 samples creating list of 256 or 512 bins: values of magnitude and phase). The processing (using the PV plugins of SC) is done in the frequency domain and then converted back to the time domain before playback. The windows are normally overlapped mixed using with a Hanning window to prevent smearing between frequencies.

Using FFT in SuperCollider, you need to do the FFT analysis, using the FFT UGen, then diverse PV_Ugens (Phase Vocoder Ugens) can be applied to operate mathematically on the signal, finally the resulting signal will need to be converted back into the time domain using the Inverse Fast Fourier Transform (IFFT).

Or, in short:  FFT -> PV_Ugens -> IFFT

where FFT translates the signal from the time domain into the frequency domain, the PV_UGens perform some functions on the sound and then we use Inverse Fast Fourier Transform (IFFT) to translate the signal back to the time domain.

Frequency bins are a sets of magnitude and phase. The larger the windows, the better pitch resolution we have, but worse precision in time. The smaller the windows, the worse pitch resolution but better precision in time.

sample rate/window size
44100/512  = 86.1328125 	// so the first (lowest) frequency of a 512 window is 86.13 Hz
44100/1024 = 43.06640625 	// so the first (lowest) frequency of a 1024 window is 43.06 Hz

For a  window size of 1024 samples we get 512 bins. These are the frequencies of which we will get the mag and phase:
Post << 512.collect({|i| (22050/512)*(i+1)})
(And we would need a 1024 frame Buffer to store that (mag and phase for each freq))

The full list of frequencies, including DC, that a 1024-point FFT theoretically generates:
a = 1024.collect({|i| (44100/1024)*i});
Except we ignore the bins above Nyquist since they're redundant:
a = a[..512];
Resulting in:
a.postcs;""

NOTE : some of the examples below use the FFT plugins from the library of Bhob Rainey
http://bhobrainey.net

So in general, it is important to understand that FFT analysis of a sound gives you two arrays,
bins (frequencies - depending upon the size of the window) and mags (the magnitude/amplitude of
the frequencies). FFT Ugens do manipulation on either the bins or the mags.

## Fast Fourier Transform examples

// load the buffers (and place your sounds into the buffers)
(
b = Buffer.alloc(s,2048,1);
c = Buffer.alloc(s,2048,1);
//d = Buffer.read(s,"sounds/oceanMONO.aif");
//d = Buffer.read(s,"sounds/insand/camina.aif");
d = Buffer.read(s,"sounds/digireedoo.aif");
e = Buffer.read(s,"sounds/holeMONO.aif");
f = Buffer.read(s, "sounds/a11wlk01.wav");
)

### MagAbove

Passes only bins whose magnitude are above a given threshold.

(
SynthDef(\pvmagabove, { arg out=0, soundBufnum1;
	var in, chain;
	in = PlayBuf.ar(1, soundBufnum1, BufRateScale.kr(soundBufnum1), loop: 1);
	//in = WhiteNoise.ar(0.2);
	chain = FFT(LocalBuf(2048), in);
	chain = PV_MagAbove(chain, MouseY.kr(30, 1));
	Out.ar(out, 0.5 * IFFT(chain)!2);
}).play(s,[\out,0, \soundBufnum1, e.bufnum]);
)

### BrickWall

Clears bins above or below a cutoff point (works as lowpass or highpass filters)
(
SynthDef(\pvbrickwall, { arg out=0, soundBufnum1;
	var in, chain;
	in = PlayBuf.ar(1, soundBufnum1, BufRateScale.kr(soundBufnum1), loop: 1);
	//in = WhiteNoise.ar(0.2);
	chain = FFT(LocalBuf(2048), in);
	chain = PV_BrickWall(chain, MouseX.kr(-1,1));
	Out.ar(out, 0.5 * IFFT(chain)!2);
}).play(s,[\out,0, \soundBufnum1, e.bufnum]);
)

### RectComb

Generates a series of gaps in a spectrum
(
SynthDef(\pvrectcomb, { arg out=0, soundBufnum1;
	var in, chain;
	in = PlayBuf.ar(1, soundBufnum1, BufRateScale.kr(soundBufnum1), loop: 1);
	//in = WhiteNoise.ar(0.2);
	chain = FFT(LocalBuf(2048), in);
	chain = PV_RectComb(chain, 8, LFTri.kr(0.097,0,0.4,0.5),
		LFTri.kr(0.24,0,-0.5,0.5));
	Out.ar(out, 0.5 * IFFT(chain)!2);
}).play(s,[\out,0,\bufnum,b.bufnum, \soundBufnum1, e.bufnum]);
)

// rectcomb - controllable with mouse
(
SynthDef(\pvrectcomb, { arg out=0, soundBufnum1;
	var in, chain;
	in = PlayBuf.ar(1, soundBufnum1, BufRateScale.kr(soundBufnum1), loop: 1);
	//in = WhiteNoise.ar(0.2);
	chain = FFT(bufnum, in);
	chain = PV_RectComb(chain,  MouseX.kr(0, 32), MouseY.kr, 0.2);
	Out.ar(out, 0.5 * IFFT(chain));
}).play(s,[\out,0, \soundBufnum1, e.bufnum]);
)

### MagFreeze

Freezes magnitudes at current levels when freeze > 0

(
SynthDef(\pvmagfreeze, { arg out=0, soundBufnum1;
	var in, chain;
	in = PlayBuf.ar(1, soundBufnum1, BufRateScale.kr(soundBufnum1), loop: 1);
	//in = WhiteNoise.ar(0.2);
	chain = FFT(LocalBuf(2048), in);
	chain = PV_MagFreeze(chain, MouseX.kr(-1, 1) ); // on the right side it freezes
	Out.ar(out, 0.5 * IFFT(chain)!2);
}).play(s,[\out,0, \soundBufnum1, f.bufnum]);
)

### CopyPhase

Combines magnitudes of first input and phases of the second input.

(
SynthDef(\pvcopy, { arg out=0, soundBufnum=2;
	var inA, chainA, inB, chainB, chain;
	inA = PlayBuf.ar(1, soundBufnum, BufRateScale.kr(soundBufnum), loop: 1);
	inB =  SinOsc.ar(SinOsc.kr(SinOsc.kr(0.08, 0, 6, 6.2).squared, 0, 100, 800));
	chainA = FFT(LocalBuf(2048), inA);
	chainB = FFT(LocalBuf(2048), inB);
	chain = PV_CopyPhase(chainA, chainB);
	Out.ar(out,  0.5 * IFFT(chain).dup);
}).play(s,[\out, 0, \soundBufnum, d.bufnum]);

)

### Magnitude smear

Average a bin's magnitude with its neighbours.

(
SynthDef(\pvmagsmear, { arg out=0, soundBufnum=2;
	var in, chain;
	in = PlayBuf.ar(1, soundBufnum, BufRateScale.kr(soundBufnum), loop: 1);
	chain = FFT(LocalBuf(2048), in);
	chain = PV_MagSmear(chain, MouseX.kr(0, 100));
	Out.ar(out, 0.5 * IFFT(chain).dup);
}).play(s,[\out, 0, \soundBufnum, e.bufnum]);
)

### Morph

Morphs between two buffers

(
SynthDef(\pvmorph, { arg out=0, soundBufnum1=2, soundBufnum2=3;
	var inA, chainA, inB, chainB, chain;
	inA = PlayBuf.ar(1, soundBufnum1, BufRateScale.kr(soundBufnum1), loop: 1);
	inB = PlayBuf.ar(1, soundBufnum2, BufRateScale.kr(soundBufnum2), loop: 1);
	chainA = FFT(LocalBuf(2048), inA);
	chainB = FFT(LocalBuf(2048), inB);
	chain = PV_Morph(chainA, chainB, MouseX.kr);
	Out.ar(out,  IFFT(chain).dup);
}).play(s,[\out, 0, \soundBufnum1, d.bufnum, \soundBufnum2, e.bufnum]);
)

### XFade

Interpolates bins between two buffers.

(
SynthDef(\pvmorph, { arg out=0, soundBufnum1=2, soundBufnum2=3;
	var inA, chainA, inB, chainB, chain;
	inA = PlayBuf.ar(1, soundBufnum1, BufRateScale.kr(soundBufnum1), loop: 1);
	inB = PlayBuf.ar(1, soundBufnum2, BufRateScale.kr(soundBufnum2), loop: 1);
	chainA = FFT(LocalBuf(2048), inA);
	chainB = FFT(LocalBuf(2048), inB);
	chain = PV_XFade(chainA, chainB, MouseX.kr);
	Out.ar(out,  IFFT(chain).dup);
}).play(s,[\out, 0, \soundBufnum1, d.bufnum, \soundBufnum2, e.bufnum]);
)

### Softwipe

Copies low bins from one input and the high bins of the other
(
SynthDef(\pvsoftwipe, { arg out=0, soundBufnum1=2, soundBufnum2=3;
	var inA, chainA, inB, chainB, chain;
	inA = PlayBuf.ar(1, soundBufnum1, BufRateScale.kr(soundBufnum1), loop: 1);
	inB = PlayBuf.ar(1, soundBufnum2, BufRateScale.kr(soundBufnum2), loop: 1);
	chainA = FFT(LocalBuf(2048), inA);
	chainB = FFT(LocalBuf(2048), inB);
	chain = PV_SoftWipe(chainA, chainB, MouseX.kr);
	Out.ar(out,  IFFT(chain).dup);
}).play(s,[\out, 0, \soundBufnum1, d.bufnum, \soundBufnum2, e.bufnum]);
)

### MagMinus

Subtracting spectral energy - Subtracts buffer B's magnitudes from buffer A.

(
SynthDef(\pvmagminus, { arg out=0, soundBufnum1=2, soundBufnum2=3;
	var inA, chainA, inB, chainB, chain;
	inA = PlayBuf.ar(1, soundBufnum1, BufRateScale.kr(soundBufnum1), loop: 1);
	inB = PlayBuf.ar(1, soundBufnum2, BufRateScale.kr(soundBufnum2), loop: 1);
	chainA = FFT(LocalBuf(2048), inA);
	chainB = FFT(LocalBuf(2048), inB);
	chain = PV_MagMinus(chainA, chainB, MouseX.kr(0, 1));
	Out.ar(out,  IFFT(chain).dup);
}).play(s,[\out, 0, \soundBufnum1, d.bufnum, \soundBufnum2, e.bufnum]);
)

## Language manipulation of bins

The PV_ UGens are blackboxes. We can read their helpfiles, but we don't see clearly what they do unless we look at their C++ sourcecode. But what if we want to manipulate the bins on the language side?

A pvcollect method (phase vocoder collect) SuperCollider allows this, so instead of:

	FFT -> PV_Ugens -> IFFT

as we looked at above, we can now do:

	FFT -> our bin calculations -> IFFT

We do this through pvcollect (see the collect method in the Collection helpfile) pvcollect processes each bin of an FFT chain separately (see pvcollect helpfile), but pvcollect takes a function and it is inside this function that we can have fun with the magnitude and the phase of the signal (as taken into the frequency domain).

We have magnitude, phase and index to play with. The pvcollect returns an array of [mag, phase]. We can then use all kinds of algorithms to play with the mag and the phase, for example using the index as a parameter in the calculations.

(
s.boot.doWhenBooted{
c = Buffer.read(s,"sounds/a11wlk01.wav");
}
)

Spectral delay - here we use a DelayN UGen to delay the bins according to MouseX location

(
{
	var in, chain, v;
	in = PlayBuf.ar(1, c, BufRateScale.kr(c), loop: 1);
	chain = FFT(LocalBuf(1024), in);

	v = MouseX.kr(0.1, 1);

	chain = chain.pvcollect(b.numFrames, {|mag, phase, index|
		mag + DelayN.kr(mag, 1, v);
	}, frombin: 0, tobin: 256, zeroothers: 1);

	Out.ar(0, 0.5 * IFFT(chain).dup);
}.play(s);
)

Another type of spectral delay where the high frequencies get longer delay times, this is the trick: 250.do({|i|(i*(250.reciprocal)).postln;})
(
{
	var in, chain, v;
	in = PlayBuf.ar(1, c, BufRateScale.kr(c), loop: 1);
	chain = FFT(LocalBuf(1024), in);

	v = MouseX.kr(0.1, 2);

	chain = chain.pvcollect(b.numFrames, {|mag, phase, index|
		mag + DelayN.kr(mag, 1, v*(index*256.reciprocal));
	}, frombin: 0, tobin: 256, zeroothers: 0);

	Out.ar(0, 0.5 * IFFT(chain).dup);
}.play(s);
)

Yet another spectral delay where the each bin gets a random delay time

(
{
	var in, chain, v;
	in = PlayBuf.ar(1, c, BufRateScale.kr(c), loop: 1);
	chain = FFT(LocalBuf(1024), in);

	v = MouseX.kr(0.1, 2);

	chain = chain.pvcollect(b.numFrames, {|mag, phase, index|
		mag + DelayN.kr(mag, 1, v*1.0.rand);
	}, frombin: 0, tobin: 256, zeroothers: 0);

	Out.ar(0, 0.5 * IFFT(chain).dup);
}.play(s);
)

Spectral delay where the delaytimes are modulated by an oscillator

(
{
	var in, chain, v;
	in = PlayBuf.ar(1, c, BufRateScale.kr(c), loop: 1);
	chain = FFT(LocalBuf(1024), in);

	v = MouseX.kr(0.1, 2);

	chain = chain.pvcollect(b.numFrames, {|mag, phase, index|
		mag + DelayN.kr(mag, 1, v*SinOsc.ar(0.5).range(0.1,1));// play with Tri or LFSaw, etc.
	}, frombin: 0, tobin: 256, zeroothers: 0);

	Out.ar(0, 0.5 * IFFT(chain).dup);
}.play(s);
)

Amplitude controlled with MouseX and phase manipulation with MouseY

(
{
	var in, chain, v;
	in = PlayBuf.ar(1, c, BufRateScale.kr(c), loop: 1);
	chain = FFT(LocalBuf(1024), in);

	chain = chain.pvcollect(b.numFrames, {|mag, phase, index|
		[mag * MouseX.kr(0.5, 2), phase / MouseY.kr(0.5, 30)]
	}, frombin: 0, tobin: 250, zeroothers: 0);

	Out.ar(0, 0.5 * IFFT(chain).dup);
}.play(s);
)

Here we add noise to the phase

(
{
	var in, chain, v;
	in = PlayBuf.ar(1, c, BufRateScale.kr(c), loop: 1);
	chain = FFT(LocalBuf(1024), in);

	chain = chain.pvcollect(b.numFrames, {|mag, phase, index|
		[mag, LFNoise0.kr.range(0, 3.14)];
	}, frombin: 0, tobin: 250, zeroothers: 1);

	Out.ar(0, 0.5 * IFFT(chain).dup);
}.play(s);
)

Square the magnitude and put a random phase (from 0 to pi (3.14))

(
{
	var in, chain, v;
	in = PlayBuf.ar(1, c, BufRateScale.kr(c), loop: 1);
	chain = FFT(LocalBuf(1024), in);

	chain = chain.pvcollect(b.numFrames, {|mag, phase, index|
		[mag.sqrt, pi.rand];
	}, frombin: 0, tobin: 256, zeroothers: 1);

	Out.ar(0, 0.5 * IFFT(chain).dup);
}.play(s);
)

Here we use the index and we subtract it with a LFPar on a slow sweep
(
{
	var in, chain, v;
	in = PlayBuf.ar(1, c, BufRateScale.kr(c), loop: 1);
	chain = FFT(LocalBuf(1024), in);

	chain = chain.pvcollect(b.numFrames, {|mag, phase, index|
		if((index-LFPar.kr(0.1).range(2, b.numFrames/20)).abs < 10, mag, 0); // swept bandpass
	}, frombin: 0, tobin: 250, zeroothers: 0);

	Out.ar(0, 0.5 * IFFT(chain).dup);
}.play(s);
)

repository: mauriziobrt/scoring

repo_name: mauriziobrt/scoring


text:
# Gazette #

Gazette is Premium Theme for [Ghost](https://ghost.org)

### Gazette - Ghost ###

* It's magazine/news type theme.
* [Demo](https://gazette.bironthemes.com)
* For download visit [bironthemes.com](https://bironthemes.com)

repository: DevAshleyD/ghost-on-heroku

repo_name: DevAshleyD/ghost-on-heroku


text:
# bash-utils

Bash Utility Scripts

# What is shell?

Computer understand the language of 0's and 1's called binary language. In early days of computing, instruction are provided using binary language, which is difficult for all of us, to read and write. So in Os there is special program called Shell. Shell accepts your instruction or commands in English (mostly) and if its a valid command, it is pass to kernel.

Shell is a user program or it's environment provided for user interaction. Shell is an command language interpreter that executes commands read from the standard input device (keyboard) or from a file.

Shell is not part of system kernel, but uses the system kernel to execute programs, create files etc.

Prints the available shells in your system.
```sh
$ cat /etc/shells
```
To find your current shell type following command
```sh
$ echo $SHELL
```

repository: HarshitKaushik/bash-utils

repo_name: HarshitKaushik/bash-utils


text:
# Argo CD Image Updater

A tool to automatically update the container images of Kubernetes workloads
that are managed by
[Argo CD](https://github.com/argoproj/argo-cd).

!!!warning "A note on the current status"
    Argo CD Image Updater was born just recently. It is not suitable for
    production use yet, and it might break things in unexpected ways.

    You are welcome to test it out on non-critical environments, and to
    contribute by sending bug reports, enhancement requests and - most
    appreciated - pull requests.

    There will be (probably a lot of) breaking changes from release to
    release as development progresses until version 1.0. We will do our
    best to indicate any breaking change and how to un-break it in the
    [Changelog](https://github.com/argoproj-labs/argocd-image-updater/CHANGELOG.md)

## Overview

The Argo CD Image Updater can check for new versions of the container images
that are deployed with your Kubernetes workloads and automatically update them
to their latest allowed version using Argo CD. It works by setting appropriate
application parameters for Argo CD applications, i.e. similar to
`argocd app set --helm-set image.tag=v1.0.1` - but in a fully automated
manner.

Usage is simple: You annotate your Argo CD `Application` resources with a list
of images to be considered for update, along with a version constraint to
restrict the maximum allowed new version for each image. Argo CD Image Updater
then regulary polls the configured applications from Argo CD and queries the
corresponding container registry for possible new versions. If a new version of
the image is found in the registry, and the version constraint is met, Argo CD
Image Updater instructs Argo CD to update the application with the new image.

Depending on your Automatic Sync Policy for the Application, Argo CD will either
automatically deploy the new image version or mark the Application as Out Of
Sync, and you can trigger the image update manually by syncing the Application.
Due to the tight integration with Argo CD, advanced features like Sync Windows,
RBAC authorization on Application resources etc. are fully supported.

## Limitations

The three most important limitations first. These will most likely not change
anywhere in the near future, because they are limitations by design.

Please make sure to understand these limitations, and do not send enhancement
requests or bug reports related to the following:

* The applications you want container images to be updated **must** be managed
  using Argo CD. There is no support for workloads not managed using Argo CD.

* Argo CD Image Updater can only update container images for applications whose
  manifests are rendered using either *Kustomize* or *Helm* and - especially
  in the case of Helm - the templates need to support specifying the image's
  tag (and possibly name) using a parameter (i.e. `image.tag`).

* Your images' tags need to follow the semantic versioning scheme. Argo CD
  Image Updater will not be able to update images that are just made from
  arbitrary strings, or consist solely of Git SHA strings.

Otherwise, current known limitations are:

* Image pull secrets must exist in the same Kubernetes cluster where Argo CD
  Image Updater is running in (or has accesst to). It is currently not possible
  to fetch those secrets from other clusters.

repository: jsoref/argocd-image-updater

repo_name: jsoref/argocd-image-updater


text:
# skelex

- [Maven Dependency][jitpack]
- [User Manual][manual]
- [Javadoc (1.0.0)][javadoc]
- [Javadoc (latest)][snapdoc]

[manual]: /doc/README.md
[jitpack]: https://jitpack.io/#norswap/skelex
[javadoc]: https://jitpack.io/com/github/norswap/skelex/-1.0.0-g8036bda-1/javadoc/index.html
[snapdoc]: https://jitpack.io/com/github/norswap/skelex/-SNAPSHOT/javadoc/

Skelex is a [regular expression] matching library with three specificities:

[regular expression]: https://en.wikipedia.org/wiki/Regular_expression

1. It works on stream of objects, instead of streams of characters as is usual.

2. It produces fully structure matching information (~ a parse tree). Usual regex matching
   engines can only match flat pieces of input. For instance, the regex `(a)*`, when applied
   on the input `aaa` will only capture the last repetition of `a`. skelex, on the other hand,
   would capture a list with three occurences of `a`.

3. Skelex is able to match many regexes at the same time on the same input.

## Installation

If you are using Maven (or another popular JVM build tool), [see here][jitpack].

A self-contained JAR file is also available [here][jar] as part of [a release] that also
includes sources and javadoc.

[jar]: https://github.com/norswap/skelex/releases/download/1.0.0/skelex-1.0.0-fatjar.jar
[a release]: https://github.com/norswap/skelex/releases

## Usage

Here is a toy usage example:

```
import norswap.skelex.*;
import java.util.Arrays;
import java.util.List;

import static norswap.skelex.DSL.*;

public class Test
{
    public static void main (String[] args)
    {
        Runner runner = new Runner();

        Regex expr = seq(Integer.class, zeromore(choice("+", "-", "*", "/"), Integer.class));
        runner.add(expr);

        List<?> input = Arrays.asList(1, "+", 2, "-", 3);
        runner.advance(input);

        MatchTree match = runner.matches().longest_tree();
        System.out.println(match);
        // prints the match: [1, [[(0, +), 2], [(1, -), 3]]]
    }
}
```

For fairly simple operations, one-liner versions are available through the [Skelex] class.

[Skelex]: https://jitpack.io/com/github/norswap/skelex/-SNAPSHOT/javadoc/norswap/skelex/Skelex.html

## Roadmap

- Add lazy repetition operators.
- [Random generation testing](http://norswap.com/gen-testing/)
- Simplify / speed-up the transition graphs somewhat.

repository: norswap/skelex

repo_name: norswap/skelex


text:
# React Tic Tac Toe App
This project was bootstrapped with [Create React App](https://github.com/facebookincubator/create-react-app).

Below you will find some information on how to perform common tasks.

> All commit messages are generated by the [What the Commit](http://whatthecommit.com)

## Installing packages
Run `npm install` and wait.

## Development server
Run the app in the development mode using `npm start`.

Open [http://localhost:3000](http://localhost:3000) to view it in the browser.

The page will reload if you make edits.

You will also see any lint errors in the console.

## License
This repository is licensed under the [MIT License](https://github.com/mvmjacobs/tic-tac-toe/blob/master/LICENSE.md).

repository: mvmjacobs/tic-tac-toe

repo_name: mvmjacobs/tic-tac-toe


text:
# language_autocorr
A python implementation of "Long-Range Memory in Literary Texts: On the Universal Clustering of the Rare Words"(2016) authored by Kumiko Tanaka-Ishii and Armin Bunde. It works on python2.7 and python3.6 environment (the results may slightly differ).

# Usage
1. Install the dependencies by "pip install -r requirements.txt".
2. Run the script by "python auto_correlation.py file_name.txt".
This script generates file_name_language_acf.png, the double log plot of the auto-correlation function of the text.

# Notes
## Text format
In our implementation, the split symbol between words in the text file is expect to be '\n'.
We put mobyDick.txt as an example retrieved from Gutenberg project. The text file is preprocessed to exclude irrelevant texts to the content.
You can simply modify it by updating "splitter = '\n'".

## Parameter
The parameter of this quantification methodology is Q which defines the ratio of rare words (1/Q) in a text.
It is set to 16 in this implementation.


text:
# Vulnerability Management: Working Group Charter

## Mission

Provides discreet management of security vulnerabilities issues relevant for active CF projects.

## Goals

* Provide a single point of contact for security vulnerability reporting and management.
* Provide management of security vulnerability reports through to resolution, including but not limited to triage, reporter and team coordination, embargo negotiation, CVSS scoring, CVE assignments, pre-disclosure and disclosure.

## Scope

* Triage incoming security vulnerability reports to [security@cloudfoundry.org](mailto:security@cloudfoundry.org).
* Manage vulnerabilities through dedicated slack channels.
* When appropriate, negotiate suitable embargo periods with the reporter to afford component teams time to fix the issue before it becomes known publicly.
* When appropriate, assign CVE numbers to vulnerabilities/fixes.
* Publish pre-disclosures to allow all CF distributions time to adopt fixes for high/critical vulnerabilities before they become known publicly.
* Publish disclosures of reported security vulnerabilities.

## Non-Goals

* Add security-related features to Cloud Foundry projects.

## Technical Lead(s):
- [Paul Warren](https://github.com/paulcwarren)

## Execution Lead(s):
- [Monty Ijzerman](https://github.com/ijzerman)
- [Khushboo Soni](https://github.com/skhushboo-vm)
- [Mathias Essenpreis](https://github.com/Essenpreis)
- [Prateek Mehrotra](https://github.com/mehrotra-prateek)

## Technical Assets

Security process and broadcast channels for security disclosures.

* [Security Advisories](https://www.cloudfoundry.org/foundryblog/security-advisory/)
* [#security](https://cloudfoundry.slack.com/archives/C0DEQSW9W)
* [cff-security-pre-disclosure<EMAIL_ADDRESS>

repository: fifthposition/community

branch_name: refs/heads/main

repo_name: fifthposition/community


text:
# Init - first steps in DevOps enviroment.

This project covers the basics of system administration on Unix. It consists of many small tasks divided into three groups:
* network
* system
* scripts

### How to test init?
Many tasks with .sh extention may be tested directly from a shell. In order to test other exercises, you will need Debian virtual machine. See [the subject](https://github.com/psprawka/Init/blob/master/init.en.pdf) to get more information about the problems to solve.

repository: psprawka/Init

repo_name: psprawka/Init


text:
---
title: WebGL Context
layout: webgl4jtutorial
section: 1
permalink: /webgl4j-tutorial-series/webgl-context/
---

Welcome back to the second part of the WebGL4J tutorial series. In the previous part, we learned how to setup the workspace with Gradle as the build tool and created a basic application in which we have a black canvas on an empty page. This time, we will be learning what a context is and how WebGL4J allows multiple contexts.

## What is a context?

The key term that we say very often is **context**, which is an object that manages the state of OpenGL. In WebGL, this context also contains the OpenGL ES functions that are exposed to JavaScript which we can call. Before continuing, let's take a look at what we had in the previous tutorial.

~~~java
WebGL10.createContext(canvas);
~~~

What we are doing here is creating a WebGL 1.0 context on our canvas. We need to create a context before we can draw anything using WebGL. The `createContext` method creates a WebGL context and returns a [WebGLContext](http://webgl4j.goharsha.com/?com/shc/webgl4j/client/WebGLContext.html) object that is used to refer to a WebGL context. The newly created context will immediately be made as current context.

## The current context

In desktop versions of OpenGL there is a concept of contexts which WebGL4J emulates to be similar to the desktop OpenGL, as the main aim of this library is to support porting of desktop OpenGL applications to the web. You can think of a context as the OpenGL object containing all of the OpenGL states. There can be multiple contexts in a page, and each context is associated with an HTML5 canvas element.

We call it current since there can be many other contexts. All the WebGL functions defined in the WebGL10 and WebGL20 classes operate on the current context. Rather than explaining in text, I'll show you a simple example of using multiple contexts (of course, this is very rarely used in applications).

~~~java
WebGLContext ctx1 = WebGL10.createContext(canvas1);
WebGLContext ctx2 = WebGL10.createContext(canvas2);

// [... all GL calls now operate on ctx2 ...]
~~~

Here we created two contexts with two canvas elements. By default, a context is automatically made current, and since all the GL calls will now operate on `ctx2`,  the output is seen on the second canvas. In order to make the rendering take place using the first context, you need to make it current.

~~~java
ctx1.makeCurrent();

// [... all GL calls now operate on ctx1 ...]
~~~

WebGL4J also exports the active context object to the 'window' variable in the host page, which is helpful when debugging. The `gl` object is of the `WebGLRenderingContext` type, and `glv`is a float containing the version of the active context. These two are contained in a `ctx` object in the window variable.

## Context Attributes

WebGL allows some attributes to be specified before creating the context, as well as retrieving the attributes from any context. See the documentation on the  [WebGLContext.Attributes](http://webgl4j.goharsha.com/index.html?com/shc/webgl4j/client/WebGLContext.Attributes.html) class to see what options are available. The following example shows the creation of a context with a stencil buffer attached to it.

~~~java
WebGLContext.Attributes attrib = WebGLContext.Attributes.create();
attrib.setStencil(true);

// Create the context with the specified attributes
WebGLContext ctx = WebGL10.createContext(canvas, attrib);
~~~

Even though you can request the attributes on a canvas, there is no guarantee that the WebGL implementation will grant you all of them. Therefore you should be checking the attributes after the creation of the context. To do this, we can use the following code.

~~~java
if (ctx.getAttributes().getStencil())
    // Success!! Stencil buffer exists for this context
else
    // Failed!! :(
~~~

The attributes only fail to be set if the hardware is low end (such as mobiles) or lack of graphics drivers on the device, which is very rare to occur. Apart from this, there is one more feature that WebGL4J provides through WebGL contexts: the fullscreen mode. However, let's keep that for another tutorial.

## Source code

There is no source code attached to this tutorial, since all it does is explain how the contexts work. No source code from the previous tutorial is modified.

license: Unlicense

gha_license_id: Unlicense


text:
# Subset Sum Problem

https://practice.geeksforgeeks.org/problems/subset-sum-problem-1611555638/1

Given an array of non-negative integers, and a value sum, determine if there is a subset of the given set with sum equal to given sum.

Example 1:

Input:
N = 6
arr[] = {3, 34, 4, 12, 5, 2}
sum = 9
Output: 1
Explanation: Here there exists a subset with
sum = 9, 4+3+2 = 9.
Example 2:

Input:
N = 6
arr[] = {3, 34, 4, 12, 5, 2}
sum = 30
Output: 0
Explanation: There is no subset with sum 30.

Your Task:
You don't need to read input or print anything. Your task is to complete the function isSubsetSum() which takes the array arr[], its size N and an integer sum as input parameters and returns boolean value true if there exists a subset with given sum and false otherwise.
The driver code itself prints 1, if returned value is true and prints 0 if returned value is false.

Expected Time Complexity: O(sum*N)
Expected Auxiliary Space: O(sum*N)

Constraints:
1 <= N <= 100
1<= arr[i] <= 100
1<= sum <= 10^5

repository: aadhityasw/Competitive-Programs

repo_name: aadhityasw/Competitive-Programs


text:
# React Native
- React Native is like React, but it uses native components instead of web components as building blocks.
- You can do the component in React Native by using class or function.

## props
components can also use props.This lets you make a single component that is used in many different places in your app, with slightly different properties in each place.
 Refer to props.{NAME} in your functional components or this.props.{NAME} in your class components.
What’s the difference between state and props in React? In a React component, the props are the variables that we pass from a parent component to a child component.
 Similarly, the state is also variables, with the difference that they are not passed as parameters, but rather that the component initializes and manages them internally.
React Native combines the best parts of native development with React, a best-in-class JavaScript library for building user interfaces.
You can use React Native today in your existing Android and iOS projects or you can create a whole new app from scratch.

## Seamless Cross-Platform
React components wrap existing native code and interact with native APIs via React’s declarative UI paradigm and JavaScript.
This enables native app development for whole new teams of developers and can let existing native teams work much faster.

## Expo
Expo apps are written in pure JS and never “drop-down” to the native iOS or Android layer.Expo allows you to eject your pure-JS project from the Expo iOS/Android clients, providing you with native projects that can be opened and built with Xcode and Android Studio. Those projects will have dependencies on ExpoKit.


text:
# Cosmos Governance Working Group
## Month #2 Community Call
[discuss here](https://forum.cosmos.network/t/gwg-community-calls-updates/3238)

Date: Thursday, February 27

Time: 14:00 UTC

Duration: 60 minutes (was actually 50 minutes)

Host: Gavin Birch ([Figment Networks](https://figment.network))

Video conference URL: https://zoom.us/j/350368377

## Prior to the meeting
1. [Join us!](http://bit.ly/2sukvxa) Please share any contact information that you feel comfortable sharing.
2. Please indicate [your primary governance interests here](https://docs.google.com/document/d/1jdSwln5L7KLvEkkM91GhlblniSynmAjMyAWSLONxTGQ/edit?usp=sharing).

## Agenda

#### 1. Newcomer introductions
Please keep intros brief! Ideally your name, organization, primary governance interest in a single sentence :)

#### 2. GWG updates
- mid-month topic call review (initial proposal intake process)
- update from Gavin ([Figment Networks](https://figment.network)) re: documentation & best practices for [community-spend](https://github.com/gavinly/CosmosCommunitySpend) & [parameter-change](https://github.com/gavinly/CosmosParametersWiki) proposals

#### 3. Proposed Topic: How can governance work be made sustainable?
There may be big players that can subsidize governance work:
- exchanges and uninvolved validators need to be alerted to breaking changes
- exchanges may need support to understand the implications of a proposal
- multi-asset wallets may need to be alerted to breaking changes

What is the low-hanging fruit for supporting governance work?

#### 4. Future planning
- What single topic is a current priority for the next mid-month call?
- Consider recommendations for GWG Q2 initiatives ie. what could a Q2 GWG community-spend proposal look like?

## Notes
The Zoom video link in the calendar invite failed, making it difficult for attendees to join. We started recording the call ten minutes late at 14:10 UTC and finished on time at 15:00 UTC.

### 1. New attendees
21 attendees in total, with introductions from new attendees:
- Zaki ([Iqlusion](https://www.iqlusion.io)) - A joint-venture institutional structure to interact with on-chain governance
- Mira ([Ztake](https://ztake.org)) - Concerned with how governance can make or break the network
- Taariq ([Promise](https://www.promiseprotocols.com)) - Focused on how governance participation can expose enterprise to Cosmos
- Gregory ([Regen Network](https://www.regen.network)) - High quality user experience of governance
- James ([Lunie](https://lunie.io/#/)) - How governance changes affect end-users
- James ([Enigma](https://lunie.io/#/)) - Learning about governance and collaborating
- Anil ([Vitwit](https://www.vitwit.com/)) - Role of validators in governance
- Ping ([Ping.pub](https://ping.pub/)) - Learning about governance and Chinese translations

Attendees that joined after introductions (feel free to message Gavin to be added):
- name ([organization)](https://google.com)

#### 2. GWG updates
##### Mid-month topic call review from Gavin ([Figment Networks](https://figment.network))
On Feb 13 we had a short call to discuss how the GWG should accept draft governance proposals in order to provide feedback. We decided that anyone with a late-stage proposal can engage on the forum, Telegram, Discord, Twitter, etc and as a group we can review their draft proposal. For proposals that we are prepared to provide support, we'll invite the proposer to the private Discord channel for fluid discussion and we'll provide feedback via Google Docs.

##### Governance work updates from Gavin ([Figment Networks](https://figment.network))
On Feb 26, Gavin ([Figment Networks](https://figment.network)) published v1.0 of the Community-Spend Best Practices doc. The end-user can use these docs to make the proposal process easier. The GWG can use this to provide support for people drafting community-spend proposals. Gavin is looking for feedback as people use the docs to improve upon the docs. You can read more about that [here](https://figment.network/resources/cosmos-community-spend-best-practices/).

#### 3. How can governance work be made sustainable?
Zaki ([Iqlusion](https://www.iqlusion.io)) - What is governance work right now? How to resource three components: 1) the right institutions to interact with on-chain governance, 2) promoting governance & engaging with stakeholders and 3) interfacing users with governance. Zaki wants to work on a join-venture structure in order to address component #1. Other protocols are interested in a join venture legal structure. Meeting with a lawyer on Mar 16. The idea here is to fund a legal entity (via the community pool) to do the work that All in Bits has done to support Cosmos development.

Zaki ([Iqlusion](https://www.iqlusion.io)) - perhaps there should be a budget for the governance work involved in getting a proposal passed, eg. as part of community-spend proposals; ICF grants; etc.

Gregory ([Regen Network](https://www.regen.network)) - some sort of DAO with a budget from the community pool with reputable members that disburse funding.

Gavin ([Figment Networks](https://figment.network)) - There may be big players that can subsidize governance work:
- exchanges and uninvolved validators need to be alerted to breaking changes
- exchanges may need support to understand the implications of a proposal
- multi-asset wallets may need to be alerted to breaking changes

What is the low-hanging fruit for supporting governance work? Let's keep discussing how to fund governance work. We've also opened a new dimension of governance work: how can we get dev work done sustainably?

#### 4. Future planning
- Perhaps our mid-month single topic call could be about how the Cosmos governance mechanism could interface with a legal entity
- Rather than a Q2 GWG community-spend proposal, what kind of governance work could be proposed for funding in Q2?

repository: gavinly/CosmosGWG

repo_name: gavinly/CosmosGWG


text:
# responsibility

- buck stops here
  - **The ultimate responsibility is mine**. A set phrase used when the speaker intends to resolve a situation mired(进退不得) in indecision or inaction.
  - **The need to act or take responsibility**, that other people pass on to still other people, **ultimately ends up here**. (An expression made famous by U.S. President Harry Truman(杜鲁门), about the finality of decisions a president must make.)

This strike can't go on any longer, so the buck stops here—I will personally meet with the head of the union today.

After everyone else has avoided making the decision, I will have to do it. The buck stops here.

> 这让我想了“逐鹿天下，舍我其谁”

- buck
  - 雄鹿；公兔 a male deer , hare or rabbit
  - （用于某些表达方式）责任，过失 used in some expressions to refer to the responsibility or blame for sth

![the_buck_stops_here](../images/the_buck_stops_here.jpg)

![buck-stops-here](../images/buck-stops-here.jpg)

- accountability
  - 责任 responsibility to give account of

repository: lsieun/learn-english

repo_name: lsieun/learn-english


text:
Figlet fonts
------------
A slight mod of [Figlet.js](https://github.com/scottgonzalez/figlet-js) which I hope will make it to NPM in pure js form someday, rather than requiring a command line dependency.

Figlet fonts are an ASCII art font standard, widely used for terminal output.

repository: TridentSecurity/Trident-Selfbot

repo_name: TridentSecurity/Trident-Selfbot


text:
# ProfnerTask7
The UoB-NLP team participated in the ProfNER-ST shared subtask 7a.
The objective of the task was to detect when a profession is mentioned in social media text.
Our team developed four systems using pre-trained BERT models:
  1. mBERT-base
  2. BERT-base
  3. mBERT-Aug
  4. Bilingual model

Our team experiments with data augmentation and bilingual models to meet the objective of the task.
The best performing model on the test data is the mBERT-Aug model, which consists of mBERT fine-tuned on augmented data using back-translation.

## Model details and hyperparameters:

Each model was trained using the training data provided by ProfNER-ST task organizers. Please see task [website](https://temu.bsc.es/smm4h-spanish/) for details.

The following libraries were used:
  * Keras
  * Demoji
  * Hugging Face Transformers
  * Pandas
  * Numpy
  * Scikit-learn
  * Google Translate API

### Preprocessing
Punctuation, hashtags, twitter handles, emojis and URL's were removed from English and Spanish tweets.
Tweets were tokenised using Hugging Face Transformers library.
All tweets were specified to have the max length of 80. Any higher or any less would significatly degrade performance of the models.

### mBERT, BERT, and mBERT-Aug Details

These three models consist of:
  1. two input layers, input_ids and input_masks which are fed to the transformer model.
  2. a dense layer with sigmoid as the activation function.
  3. binary crossentropy loss
  4. Adam optimizer with a learning rate of 3e-5 (mBERT and BERT) a learning rate of 5e-5 was used for mBERT-Aug
  5. batch-size 32
  6. Epochs 3

 ### Bilingual Model
 This model consist of mBERT-base and BERT-base.
 The outputs of both these models are concatenated and fed to a dense layer.

 The the model consists of:
  1. four input layers, input_ids and input_masks for both Spanish and English tweets, which are fed to the corresponding transformer models.
  2. a dense layer with sigmoid as the activation function.
  3. binary crossentropy loss
  4. Adam optimizer with a learning rate of 3e-5
  5. batch-size 32
  6. Epochs 4

## Results

The best performing model on test data was mBERT-Aug, followed by mBERT, Bilingual model, and BERT-base.

|Model          |Precision           |Recall           |F-1  |
| :---          |  :----:            |  :----:         | ---:|
|mBERT          | 0.9538             | 0.7127          | 0.82|
|BERT-Base      | 0.6620             | 0.1015          | 0.18|
|mBert-Aug      | 0.9171             | **0.7646**      |**0.83**|
|Bilingual      |0.9579              | 0.6393          | 0.77|

The code for the preprocessing and training of models is provided in this repository, titled Profner, and the code used to translate the examples is titled Translate_Data.


text:
---
layout: default
---

# 1997-08-21 - Re: coercion proof timestamping services

## Header Data

From: Tim May<EMAIL_ADDRESS>To: Adam Back<EMAIL_ADDRESS>Message Hash: 14fb5345f9d97a73726c7d21c2996da0ba88191635ad6ccccc9a4fcf40cbf6ca

Message ID<EMAIL_ADDRESS>Reply To<EMAIL_ADDRESS>UTC Datetime: 1997-08-21 02:55:20 UTC

Raw Date: Thu, 21 Aug 1997 10:55:20 +0800

## Raw message

```
{% raw  %}From: Tim May<EMAIL_ADDRESS>Date: Thu, 21 Aug 1997 10:55:20 +0800
To: Adam Back<EMAIL_ADDRESS>Subject: Re: coercion proof timestamping services
In-Reply-To<EMAIL_ADDRESS>Message-ID<EMAIL_ADDRESS>MIME-Version: 1.0
Content-Type: text/plain

At 2:37 PM -0700 8/20/97, Adam Back wrote:
>Just some thoughts about creating more robust time-stamping services.
>
>Current time stamping services just generate a PGP key, and sign any
>messages you send them.  PGP signatures already include a time stamp.
>
>Problem: if we find some interesting uses for time-stamps where it
>becomes important that no one can coerce the timestamping service into
>back-signing timestamps in the past, the current timestampers will be
>able to comply, or as they are automated services, simply confiscating
>the machine will likely give the attacker all information required to
>back date any number of time-stamps.

The Surety folks do (or did, as I don't know their current market status) a
lot more than this, and the published hash makes "back-signing"
problematic! Their URL is www.surety.com, and my own Cyphernomicon has a
description.

--Tim May

There's something wrong when I'm a felon under an increasing number of laws.
Only one response to the key grabbers is warranted: "Death to Tyrants!"
---------:---------:---------:---------:---------:---------:---------:----
Timothy C. May              | Crypto Anarchy: encryption, digital money,
<EMAIL_ADDRESS>408-728-0152 | anonymous networks, digital pseudonyms, zero
W.A.S.T.E.: Corralitos, CA  | knowledge, reputations, information markets,
Higher Power: 2^1398269     | black markets, collapse of governments.
"National borders aren't even speed bumps on the information superhighway."

{% endraw %}
```

## Thread

+ Return to [August 1997](/archive/1997/08)

+ Return to "[Adam Back <aba@dcs.ex.ac.uk>](/authors/adam_back_aba_at_dcs_ex_ac_uk_)"
+ Return to "[Alan <alan@ctrl-alt-del.com>](/authors/alan_alan_at_ctrlaltdel_com_)"
+ Return to "[Tim May <tcmay@got.net>](/authors/tim_may_tcmay_at_got_net_)"
+ Return to "["William H. Geiger III" <whgiii@amaranth.com>](/authors/william_h_geiger_iii_whgiii_at_amaranth_com_)"

+ 1997-08-20 (Thu, 21 Aug 1997 06:10:35 +0800) - [coercion proof timestamping services](/archive/1997/08/8b3c2c9d9664b37651d53e25f31cf6b426ea305c052dbbce40ff13da69bfbe22) - _Adam Back<EMAIL_ADDRESS>  + 1997-08-21 (Thu, 21 Aug 1997 08:00:57 +0800) - [Re: coercion proof timestamping services](/archive/1997/08/bdc89f778585eaefa4cceccc7a5b5d04c64d28446ed03d27adc64638aed4ad08) - _"William H. Geiger III"<EMAIL_ADDRESS>  + 1997-08-21 (Thu, 21 Aug 1997 08:10:58 +0800) - [Re: coercion proof timestamping services](/archive/1997/08/d2ff92f58faf9e1e3504d0fc703280bbe67521765cdf9e77ab71454f9e9efde4) - _Alan<EMAIL_ADDRESS>  + 1997-08-21 (Thu, 21 Aug 1997 10:55:20 +0800) - Re: coercion proof timestamping services - _Tim May<EMAIL_ADDRESS>


text:
---
authors: dovholuknf
---

# Scraping Anything, Anywhere in Action

_This is part three of a three-part article. This article builds on the previous two articles. Here we will take a look at what we built
and use it to explore the power of a zitified Prometheus. See [part one](./part1.md) for the necessary background about the series. See
[part two](./part2.md) for detailed instructions covering how to setup the environment you're about to explore_

## The Payoff

Ok. Here it is. We are at the end of the series and here is where we'll put it all together and really start to understand the sort of
innovations you can create when you zitify an application. As a reminder, we are working with [Prometheus](https://prometheus.io/), a
CNCF project which we will use to monitor a workload deployed in two separate [Kubernetes](https://kubernetes.io) clusters. To save you
from flipping back to a previous article, here is what that solution looks like.

![overview](./kubernetes-prometheus-after.svg)

Now we are ready to start using our Prometheus servers. We'll use our OpenZiti overlay network to connect to a workload which will
generate a metric we want to display in Prometheus. We'll then configure Prometheus to scrape the workload and put it on a graph to
prove it works. Once that's complete, we'll play around with the setup and see if we really can scrape anything, anywhere. Let's begin.

## Developer Access

In the [previous article](./part2.md), we established our entire solution using the OpenZiti overlay, `kubectl` and `helm`. We saw
everything get installed and it all "seems to work". But how do we **know** it works?  Let's provision an identity for yourself now and
let's enroll it in your local tunneling app and find out.  Once you have that installed, provision an identity and enroll it with your tunneling client.

```text
ziti edge create identity user dev.client -a "prometheus-clients","reflectz-clients"
```

You should have access to six total services when this identity is enrolled:

```text
Service Name: kubeA.prometheus.svc
   Intercept: kubeA.prometheus.svc:80
Service Name: kubeA.reflect.svc
   Intercept: kubeA.reflect.svc.ziti:80
Service Name: kubeA.reflect.scrape.svc
   Intercept: kubeA.reflect.scrape.svc.ziti:80

Service Name: kubeB.prometheus.svc
   Intercept: kubeB.prometheus.svc:80
Service Name: kubeB.reflect.svc
   Intercept: kubeB.reflect.svc.ziti:80
Service Name: kubeB.reflect.scrape.svc
   Intercept: kubeB.reflect.scrape.svc.ziti:80
```

## ClusterA

With your developer access you should be able to navigate your browser to http://kubea.prometheus.svc/targets.

> [!NOTE]
> We won't dwell on this for long in this article but notice that this is showing off another superpower of OpenZiti, private DNS.
> Notice that you were able to browse to a totally fictitious domain name: kubea.prometheus.svc. ".svc" is **not** a legitimate top level
> domain.
> [Look at the full list of top level domains starting with S](https://en.wikipedia.org/wiki/List_of_Internet_top-level_domains#S). You
> won't find ".svc" on that list at this time

![kubea.prom.init](./kubea.prom.init.png)

You should see the following. You might have noticed that the chart deployed has a few other containers we have not discussed yet. We'll
not go into those containers in this article. What's important is that this Prometheus server has a few targets already for us to access.
Neat, but this isn't what we want to actually monitor.

What we really want to monitor is the workload we deployed: `reflectz`. We can do this by editing the Prometheus configmap using
`kubectl`. Let's go ahead and do this now:

```text
kubectl edit cm prometheuz-prometheus-server
```

This will open an editor in your terminal and allow you to update the config map for the pod. Once the editor is open, find the section
labeled "scrape_config" and add the following entry:

```text
    - job_name: 'kubeA.reflectz'
      scrape_interval: 5s
      honor_labels: true
      scheme: 'ziti'
      params:
        'match[]':
          - '{job!=""}'
        'ziti-config':
          - '/etc/prometheus/scrape.json'
      static_configs:
        - targets:
          - 'kubeA.reflect.scrape.svc-kubeA.reflect.id'
```

This is yaml and yaml is sensitive to spaces. The block above is properly indented for the config that the helm chart installs. You
should be able to simply copy it and add it under the scrape_config. Remember, there is a `configmap-reload` container in
the pod which monitors the configmap. On successful edit, this container will notice and will issue a web hook to the
`prometheus-server` container. The trigger is not immediate, don't worry if it takes a while. It can take around a minute for the
trigger to fire.

While we wait for the trigger, let's explain what this is doing. This is informing the Prometheus server to monitor a workload which can
be found at the provided target of `kubeA.reflect.scrape.svc-kubeA.reflect.id`. Notice that no port is included in this target, and also
notice that this is a very strange looking FQDN. That's because this is a zitified version of Prometheus. We have extended Prometheus to
understand a "scheme" of `ziti`. When we configure this job with a scheme of ziti, we can then supply targets to the job which represent
an OpenZiti service.  We need to supply the `ziti-config` node with the path to the identity we want Prometheus to use to issue the
scrape. This will always be `/etc/prometheus/scrape.json` at this time. Should the community desire it, we can look into changing the
location of the identity.

If you would like to tail the `configmap-reloadz` container, you can issue this one liner. This will instruct `kubectl` to tail the logs
from `configmap-reloadz`.

```text
pod=$(kubectl get pods | grep server | cut -d " " -f1); echo POD: $pod; kubectl logs -f "$pod" prometheus-server-configmap-reload
```

When the trigger happens for ClusterA you will see a message like the one below. Notice that `configmap-reloadz` is using the underlay
network: `http://<IP_ADDRESS>:9090/-/reload`

```text
2022/04/23 20:01:23 config map updated
2022/04/23 20:01:23 performing webhook request (1/1/http://<IP_ADDRESS>:9090/-/reload)
2022/04/23 20:01:23 successfully triggered reload
```

### Config Reloaded

Once you've correctly updated the configmap, and `configmap-reloadz` detected the change and told Prometheus to reload. You'll see a new
target has been reported by Prometheus at http://kubea.prometheus.svc/targets. You should now see "kubeA.reflectz (1/1 up)" showing.
Congratulations! You have just successfully scraped a target from zitified Prometheus! Remember this workload does not listen on the
Kubernetes underlay network. It's only accessible from the OpenZiti overlay.

![kubea.target1.png](./kubea.target1.png)

### Let's Graph It!

Cool, we have a target. The target can be scraped by Prometheus over the OpenZiti overlay. We're also able to securely access the
Prometheus UI over the same OpenZiti overlay. Let's use the Prometheus UI to graph the data point we want to see, the
`reflect_total_connections` metric.

1. Navigate to http://kubea.prometheus.svc/graph
2. enter `reflect_total_connections`
3. click Graph (notice I changed my time to '10s', located just under Graph)
4. click Execute
5. Notice there are no connections (0)

![grpah it](./kubea.graph.png)

### Generate Some Data

Now let's change that graph of `reflect_total_connections` from 0 to 1 (or more). One of the services you will have access to will
intercept `kubeA.reflect.svc.ziti:80`.

> [!NOTE]
> If you are using Windows and Windows Subsystem for Linux (WSL) as I am, you **might** need to understand how get WSL to use your Ziti
> Desktop Edge for Windows as your DNS resolver when inside WSL. Generally speaking this is as easy as editing /etc/resolv.conf and
> adding the IP as the first nameserver: `nameserver <IP_ADDRESS>` (or whatever the DNS IP is). Try it first, depending on how you setup
> WSL it might 'just work' for you. You can also just use cygwin or any other netcat tool from Windows (not WSL) too.

Now we can use netcat to open a connection through this intercept a few times. The metric tracks the total number of connections to the
reflect service. Connect, send some text, the use ctrl-c to disconnect. Do that a few times then click 'execute' again on the graph page.
You can see I did this over a minute and moved my total count on kubeA to 8, shown below.

```text
/tmp/prometheus$ nc kubeA.reflect.svc.ziti 80
kubeA reflect test
you sent me: kubeA reflect test
^C
/tmp/prometheus$ nc kubeA.reflect.svc.ziti 80
another reflect test
you sent me: another reflect test
^C
/tmp/prometheus$ nc kubeA.reflect.svc.ziti 80
another reflect test
you sent me: another reflect test
^C
```

![kubea.more.total.conn.png](./kubea.more.total.conn.png)

### Scrape Something Else

Hopefully you agree with me that this is pretty neat. Well what if we take it to the next level? What if we tried to scrape the
workload we deployed to ClusterB? Could we get that to work? Recall from above how we enabled the job named 'kubeA.reflectz'. What if we
simply copied/pasted that into the configmap changing kubeA --> kubeB. Would it work? Let's see.

```text
# edit the configmap on ClusterA:
kubectl edit cm prometheuz-prometheus-server

#add the job - and wait for the configmap to reload

    - job_name: 'kubeB.reflectz'
      scrape_interval: 5s
      honor_labels: true
      scheme: 'ziti'
      params:
        'match[]':
          - '{job!=""}'
        'ziti-config':
          - '/etc/prometheus/scrape.json'
      static_configs:
        - targets:
          - 'kubeB.reflect.scrape.svc-kubeB.reflect.id'
```

After watching the logs from `configmap-reloadz` on ClusterA and seeing the webhook trigger. Just go back to the Prometheus server in
the browser. You should be at the 'graph' url but if not navigate back and execute another graph for `reflect_total_connections`. When
we do that it probably doesn't look much different but... Wait a second? In the legend? Can it be? That's right. From Kubernetes
ClusterA, we have just scraped a workload from Kubernetes ClusterB, entirely over the OpenZiti overlay.

![kubeA-and-kubeB.png](./kubeA-and-kubeB.png)

Generate some data like you did before by running a few netcat connection/disconnects and click 'Execute' again. Don't forget to send
the connection request to kubeB though!

```text
nc kubeB.reflect.svc.ziti 80
this is kubeb
you sent me: this is kubeb
^C
nc kubeB.reflect.svc.ziti 80
another to kube b
you sent me: another to kube b
^C
nc kubeB.reflect.svc.ziti 80
one more for fun and profit
you sent me: one more for fun and profit
^C
```

![kubeB from kubeA](./kubeB-from-kubeA.png)

## Scraping All the Things!

By now, you are probably starting to get the idea just how powerful this is for Prometheus. A zitified Prometheus can scrape things
easily and natively by just deploying a `Prometheuz` instance into the location you want to scrape. Or, you can just enable a scrape
target using a tunneling app, or in Kubernetes using the `ziti-host` helm chart.  Let's complete our vision now and stand up a
Prometheus server on our local workstation using Docker.

When we run `Prometheuz` locally using docker we'll need a config file to give to docker using a volume mount. We also provide the
identity used to connect to the OpenZiti overlay in the same fashion. Let's start up a docker container locally and see if we can grab
data from our two Prometheus instances using a locally deployed `Prometheuz` via docker.

GitHub has a sample Prometheus [file you can download](https://raw.githubusercontent.com/openziti/ziti-doc/main/docusaurus/blog/zitification/prometheus/scripts/local.prometheus.yml).
Below, I used curl to download it and put it into the expected location.

```text
curl -s https://raw.githubusercontent.com/openziti/ziti-doc/main/docusaurus/blog/zitification/prometheus/scripts/local.prometheus.yml > /tmp/prometheus/prometheus.config.yml

ziti edge create identity user local.prometheus.id -o /tmp/prometheus/local.prometheus.id.jwt -a "reflectz-clients","prometheus-clients"
ziti edge enroll /tmp/prometheus/local.prometheus.id.jwt -o /tmp/prometheus/local.prometheus.id.json

docker run \
  -v /tmp/prometheus/local.prometheus.id.json:/etc/prometheus/ziti.id.json \
  -v /tmp/prometheus/prometheus.config.yml:/etc/prometheus/prometheus.yml \
  -p 9090:9090 \
  openziti/prometheuz
```

![local-docker-targets.png](./local-docker-targets.png)

Look at what we've just done. We have started a Prometheus instance locally, and used it to connect to four Prometheus targets via
scrape configurations when all four targets are hidden entirely from my local computer (and any computer) unless the computer has an
OpenZiti identity. I personally think that is incredibly cool!

## Taking it to 11

But wait, I'm not done. That docker instance is listening on an underlay network. It's exposed to attack by anything on my local network.
I want to fix that too. Let's start this docker container up listening only on the OpenZiti overlay. Just like in [part 2](./part2.md)
we will make a config, a service and two policies to enable identities on the OpenZiti overlay.

```text
curl -s https://raw.githubusercontent.com/openziti/ziti-doc/main/docusaurus/blog/zitification/prometheus/scripts/local.prometheus.yml > /tmp/prometheus/prometheus.config.yml

# create the config and service for the local prometheus server
ziti edge create config "local.prometheus.svc-intercept.v1" intercept.v1 \
  '{"protocols":["tcp"],"addresses":["local.prometheus.svc"],"portRanges":[{"low":80, "high":80}], "dialOptions": {"identity":"local.prometheus.id"}}'

ziti edge create service "local.prometheus.svc" \
  --configs "local.prometheus.svc-intercept.v1"

# grant the prometheus clients the ability to dial the service and the local.prometheus.id the ability to bind
ziti edge create service-policy "local.prometheus.svc.dial" Dial \
  --service-roles<EMAIL_ADDRESS>\
  --identity-roles "#prometheus-clients"
ziti edge create service-policy "local.prometheus.svc.bind" Bind \
  --service-roles<EMAIL_ADDRESS>\
  --identity-roles<EMAIL_ADDRESS>```

Once that's done - let's see if we can start the docker container. The helm charts are configured to translate the `--set` flags
provided into "container friendly" settings like environment variables, volumes and mounts etc. In docker we need to provide those. If
you're familiar with docker these will probably all make sense. The most important part of the command below is the **lack** of a `-p`
flag. The `-p` flag is used to expose a port from inside docker, outside docker. Look at the previous docker sample and you'll find we
were mapping local underlay port 9090 to port 9090 in the docker container.

After configuring the OpenZiti overlay, we just need to open a browser and navigate to http://local.prometheus.svc/targets. SUCCESS!

![local-docker-targets-no-listener.png](./local-docker-targets-no-listener.png)

### SUCCESS!
![local-docker-graph-no-listener.png](./local-docker-graph-no-listener.png)

## Wrap Up

This was quite the journey and a lot of fun. We have taken a wildly popular open source project and brought OpenZiti to it with really
not much code at all. Then using OpenZiti we were able to give Prometheus superpowers and enable it to scrape any target regardless of
where that target is or what network it is on.

Think of the possibilities here. Are you a cloud provider looking to monitor your client's services which are deployed on-prem? That's
so easy with OpenZiti and without sacrificing security **at all**. In fact, using OpenZiti like this provides amazing reach while
**strengthening** the security posture of the solution because you're now using the concepts of
[zero trust networking principles](https://en.wikipedia.org/wiki/Zero_trust_security_model) and applying them to your alerting and
monitoring solution.

What do you think? Was this series interesting? Do you think OpenZiti is cool and you are looking to try it out? What are you going to
zitify? Tell us on twitter or on discourse! Both links are included in this page. Let us know what you think! Go star the
[openziti/ziti](http://github.com/openziti/ziti) repo and help us spread the word of OpenZiti to the world!

repository: dovholuknf/ziti-doc

repo_name: dovholuknf/ziti-doc