class: inverse, middle, left, my-title-slide, title-slide # Day 3: Testing models, predictions & model uncertainty ### November 9, 2021 --- # Today: 1. Evaluating model uncertainty and making predictions -- 2. Model checking -- 3. Model selection methods: - `select = TRUE` - AIC - ANOVA --- # Recap — Flu data .pull-left[ ```r flu <- read.csv(here('data',"california-flu-data.csv")) %>% mutate(season = factor(season)) flu2010 <- flu %>% filter(season=="2010-2011") ``` ```r flu2010_posmod <- gam(tests_pos ~ s(week_centered, k = 15, by = ) + offset(log(tests_total)), data= flu2010, family = poisson, method = "REML") ``` ] .pull-right[ ![](03-predictions-and-model-checking_files/figure-html/richness-violin-1.svg) ] --- # Confidence bands .row[ .col-6[ `plot()` ```r plot(flu2010_posmod) ``` ![](03-predictions-and-model-checking_files/figure-html/plot-richness-model-1.svg) ] .col-6[ `gratia::draw()` ```r draw(flu2010_posmod) ``` ![](03-predictions-and-model-checking_files/figure-html/draw-richness-model-1.svg) ] ] What do the bands represent? --- # Confidence intervals for smooths Bands are a bayesian 95% credible interval on the smooth `plot.gam()` draws the band at ± **2** std. err. `gratia::draw()` draws them at `\((1 - \alpha) / 2\)` upper tail probability quantile of `\(\mathcal{N}(0,1)\)` `gratia::draw()` draws them at ~ ±**1.96** std. err. & user can change `\(\alpha\)` via argument `ci_level` -- So `gratia::draw()` draws them at ~ ±**2** st.d err --- # Across the function intervals The *frequentist* coverage of the intervals is not pointwise — instead these credible intervals have approximately 95% coverage when *averaged* over the whole function Some places will have more than 95% coverage, other places less -- Assumptions yielding this result can fail, where estimated smooth is a straight line -- Correct this with `seWithMean = TRUE` in `plot.gam()` or `overall_uncertainty = TRUE` in `gratia::draw()` This essentially includes the uncertainty in the intercept in the uncertainty band --- # Correcting for smoothness selection The defaults assume that the smoothness parameter(s) `\(\lambda_j\)` are *known* and *fixed* -- But we estimated them -- Can apply a correction for this extra uncertainty via argument `unconditional = TRUE` in both `plot.gam()` and `gratia::draw()` --- # But still, what do the bands represent? ```r sm_fit <- evaluate_smooth(flu2010_posmod, 's(week_centered)') # tidy data on smooth sm_post <- smooth_samples(flu2010_posmod, 's(week_centered)', n = 20, seed = 42) # more on this later draw(sm_fit) + geom_line(data = sm_post, aes(x = .x1, y = value, group = draw), alpha = 0.3, colour = 'red') ``` ![](03-predictions-and-model-checking_files/figure-html/plot-conf-band-plus-posterior-smooths-1.svg) --- class: inverse middle center subsection # Making predictions with uncertainty --- # Predicting with `predict()` `plot.gam()` and `gratia::draw()` show the component functions of the model on the link scale -- Prediction (via the `predict` function) allows us to evaluate the model at known values of covariates on different scales: - response scale (`type = "response"`) - overall link scale (`type= "link"`) - Predictions for individual smooth terms (`type="terms"` or `type = "iterms"`) - For individual basis functions -- Provide `newdata` with a data frame of values of covariates --- # `predict()` ```r new_flu <- with(flu2010, tibble(week_centered = seq(min(week_centered), max(week_centered), length.out = 100), tests_total = 1)) pred <- predict(flu2010_posmod, newdata = new_flu, se.fit = TRUE, type = 'link') pred <- bind_cols(new_flu, as_tibble(as.data.frame(pred))) pred ``` ``` ## # A tibble: 100 x 4 ## week_centered tests_total fit se.fit ## <dbl> <dbl> <dbl> <dbl> ## 1 -11 1 -4.65 0.358 ## 2 -10.5 1 -4.70 0.304 ## 3 -9.97 1 -4.73 0.258 ## 4 -9.45 1 -4.75 0.224 ## 5 -8.94 1 -4.75 0.201 ## 6 -8.42 1 -4.72 0.187 ## 7 -7.91 1 -4.66 0.179 ## 8 -7.39 1 -4.56 0.170 ## 9 -6.88 1 -4.44 0.159 ## 10 -6.36 1 -4.29 0.146 ## # ... with 90 more rows ``` --- # `predict()` → response scale ```r ilink <- inv_link(flu2010_posmod) # inverse link function crit <- qnorm((1 - 0.89) / 2, lower.tail = FALSE) # or just `crit <- 2` pred <- mutate(pred, pos_rate = ilink(fit), lwr = ilink(fit - (crit * se.fit)), # lower... upr = ilink(fit + (crit * se.fit))) # upper credible interval pred ``` ``` ## # A tibble: 100 x 7 ## week_centered tests_total fit se.fit pos_rate lwr upr ## <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> ## 1 -11 1 -4.65 0.358 0.00951 0.00537 0.0169 ## 2 -10.5 1 -4.70 0.304 0.00913 0.00562 0.0148 ## 3 -9.97 1 -4.73 0.258 0.00882 0.00584 0.0133 ## 4 -9.45 1 -4.75 0.224 0.00865 0.00605 0.0124 ## 5 -8.94 1 -4.75 0.201 0.00866 0.00628 0.0119 ## 6 -8.42 1 -4.72 0.187 0.00893 0.00662 0.0120 ## 7 -7.91 1 -4.66 0.179 0.00949 0.00713 0.0126 ## 8 -7.39 1 -4.56 0.170 0.0104 0.00794 0.0137 ## 9 -6.88 1 -4.44 0.159 0.0118 0.00913 0.0152 ## 10 -6.36 1 -4.29 0.146 0.0136 0.0108 0.0172 ## # ... with 90 more rows ``` --- # `predict()` → plot Tidy objects like this are easy to plot with `ggplot()` ```r ggplot(pred, aes(x = week_centered)) + geom_ribbon(aes(ymin = lwr, ymax = upr), alpha = 0.2) + geom_line(aes(y = pos_rate)) + labs(y = "Test postivity rate", x = NULL) ``` ![](03-predictions-and-model-checking_files/figure-html/plot-predictions-richness-1.svg) --- class: inverse middle center subsection # Your turn! --- class: inverse middle center subsection # Posterior simulation --- # Remember this? ![](03-predictions-and-model-checking_files/figure-html/plot-conf-band-plus-posterior-smooths-1.svg) -- Where did the red lines come from? --- # Posterior distributions Each red line is a draw from the *posterior distribution* of the smooth Remember the `\(\beta_j\)` from the first lecture? Together they are distributed *multivariate normal* with * mean vector given by `\(\hat{\beta}_j\)` * covariance matrix `\(\boldsymbol{\hat{V}}_{\beta}\)` `$$\text{MVN}(\boldsymbol{\hat{\beta}}, \boldsymbol{\hat{V}}_{\beta})$$` -- The model as a whole has a posterior distribution too -- We can simulate data from the model by taking draws from the posterior distribution --- # Posterior simulation for a smooth Sounds fancy but it's only just slightly more complicated than using `rnorm()` To do this we need a few things: 1. The vector of model parameters for the smooth, `\(\boldsymbol{\hat{\beta}}\)` 2. The covariance matrix of those parameters, `\(\boldsymbol{\hat{V}}_{\beta}\)` 3. A matrix `\(\boldsymbol{X}_p\)` that maps parameters to the linear predictors (i.e. basis functions) for the smooth `$$\boldsymbol{\hat{\eta}}_p = \boldsymbol{X}_p \boldsymbol{\hat{\beta}}$$` -- Let's do this for `flu2010_posmod` --- # Posterior sim for a smooth — step 1 The vector of model parameters for the smooth, `\(\boldsymbol{\hat{\beta}}\)` ```r sm_week <- get_smooth(flu2010_posmod, "s(week_centered)") # extract the smooth object from model idx <- gratia:::smooth_coefs(sm_week) # indices of the coefs for this smooth idx ``` ``` ## [1] 2 3 4 5 6 7 8 9 10 11 12 13 14 15 ``` ```r beta <- coef(flu2010_posmod) # vector of model parameters ``` --- # Posterior sim for a smooth — step 2 The covariance matrix of the model parameters, `\(\boldsymbol{\hat{V}}_{\beta}\)` ```r Vb <- vcov(flu2010_posmod) # default is the bayesian covariance matrix ``` --- # Posterior sim for a smooth — step 3 A matrix `\(\boldsymbol{X}_p\)` that maps parameters to the linear predictor for the smooth We get `\(\boldsymbol{X}_p\)` using the `predict()` method with `type = "lpmatrix"` ```r new_weeks <- with(flu2010, tibble(week_centered = seq_min_max(week_centered, n = 100), tests_total = 1)) Xp <- predict(flu2010_posmod, newdata = new_weeks, type = 'lpmatrix') dim(Xp) ``` ``` ## [1] 100 15 ``` --- # Posterior sim for a smooth — step 4 Take only the columns of `\(\boldsymbol{X}_p\)` that are involved in the smooth of `week_centered` ```r Xp <- Xp[, idx, drop = FALSE] dim(Xp) ``` ``` ## [1] 100 14 ``` --- # Posterior sim for a smooth — step 5 Simulate parameters from the posterior distribution of the smooth of `week_centered` ```r set.seed(42) beta_sim <- rmvn(n = 20, beta[idx], Vb[idx, idx, drop = FALSE]) dim(beta_sim) ``` ``` ## [1] 20 14 ``` Simulating many sets (20) of new model parameters from the estimated parameters and their uncertainty (covariance) Result is a matrix where each row is a set of new model parameters, each consistent with the fitted smooth --- # Posterior sim for a smooth — step 6 .row[ .col-6[ Form `\(\boldsymbol{\hat{\eta}}_p\)`, the posterior draws for the smooth ```r sm_draws <- Xp %*% t(beta_sim) dim(sm_draws) ``` ``` ## [1] 100 20 ``` ```r matplot(sm_draws, type = 'l') ``` A bit of rearranging is needed to plot with `ggplot()` ] .col-6[ ![](03-predictions-and-model-checking_files/figure-html/richness-posterior-draws-1.svg) ] ] -- Or use `smooth_samples()` --- # Posterior sim for a smooth — steps 1–6 ```r sm_post <- smooth_samples(flu2010_posmod, 's(week_centered)', n = 20, seed = 42) draw(sm_post) ``` ![](03-predictions-and-model-checking_files/figure-html/plot-posterior-smooths-1.svg) --- # Posterior simulation from the model Simulating from the posterior distribution of the model requires 1 modification of the recipe for a smooth and one extra step We want to simulate new values for all the parameters in the model, not just the ones involved in a particular smooth -- Additionally, we could simulate *new response data* from the model and the simulated parameters (**not shown** below) --- # Posterior simulation from the model ```r beta <- coef(flu2010_posmod) # vector of model parameters Vb <- vcov(flu2010_posmod) # default is the Bayesian covariance matrix Xp <- predict(flu2010_posmod, type = 'lpmatrix') set.seed(42) beta_sim <- rmvn(n = 1000, beta, Vb) # simulate parameters eta_p <- Xp %*% t(beta_sim) # form linear predictor values mu_p <- inv_link(flu2010_posmod)(eta_p) # apply inverse link function mean(mu_p[1, ]) # mean of posterior for the first observation in the data ``` ``` ## [1] 0.01009361 ``` ```r quantile(mu_p[1, ], probs = c(0.025, 0.975)) ``` ``` ## 2.5% 97.5% ## 0.004696046 0.018737832 ``` --- # Posterior simulation from the model ```r week0_row <- which(flu2010$week_centered==0) ggplot(tibble(positivity_rate = mu_p[week0_row , ]), aes(x = positivity_rate)) + geom_histogram() + labs(title = "Posterior distribution of positivity rates for\nthe first week of January, 2011") ``` ![](03-predictions-and-model-checking_files/figure-html/posterior-sim-model-hist-1.svg) --- class: inverse middle center subsection # Your turn! --- class: inverse middle center subsection # Part 2: Model comparisons --- # Are predictions or inference any good? Only if model specification matches the data-generating process ![](03-predictions-and-model-checking_files/figure-html/misspecify-1.svg) --- background-image: url(figures/mug.jpg) background-size: contain --- # How do we test for misspecification? - Examine residuals and diagostic plots: `gam.check()` part 1 - Test for residual patterns in data: `gam.check()` part 2 - Look for confounding relationships amongst variables: `concurvity()` ??? --- # First let's simulate some data ```r set.seed(2) n <- 400 x1 <- rnorm(n) x2 <- rnorm(n) y_val <- 1 + 2*cos(pi*x1) + 2/(1+exp(-5*(x2))) y_norm <- y_val + rnorm(n, 0, 0.5) y_negbinom <- rnbinom(n, mu = exp(y_val),size=10) y_binom <- rbinom(n,1,prob = exp(y_val)/(1+exp(y_val))) ``` --- class: inverse middle center subsection # Using `gam.check()` part 1: Visual Checks --- # Gaussian model on Gaussian data ```r norm_model <- gam(y_norm ~ s(x1, k=12) + s(x2, k=12), method = 'REML') gam.check(norm_model, rep = 500) ``` ![](03-predictions-and-model-checking_files/figure-html/gam_check_plots1-1.svg) --- # Negative binomial data, Poisson model ```r pois_model <- gam(y_negbinom ~ s(x1, k=12) + s(x2, k=12), family=poisson, method= 'REML') gam.check(pois_model, rep = 500) ``` ![](03-predictions-and-model-checking_files/figure-html/gam_check_plots2-1.svg) --- # NB data, NB model ```r negbin_model <- gam(y_negbinom ~ s(x1, k=12) + s(x2, k=12), family = nb, method = 'REML') gam.check(negbin_model, rep = 500) ``` ![](03-predictions-and-model-checking_files/figure-html/gam_check_plots3-1.svg) --- class: inverse middle center subsection # `gam.check()` part 2: do you have the right functional form? --- # How good is the smooth? - Many choices influence whether a smooth is right for the data, one key one is **k**, the number of basis functions used to construct the smooth. - **k** sets the _maximum_ wiggliness of a smooth. The smoothing penalty `\((\lambda)\)` remove "extra wiggliness" (_up to a point!_) - We want enough **k** to model all our complexity, but larger **k** means larger computation time (sometimes `\(O(n^2)\)`) - Set **k** per term in your model: `s(x, k=10)` or `s(x, y, k=100)`. Default values must be checked! --- # Checking basis size `gam.check()` prints diagnostics for basis size. Significant values indicate non-random residual patterns not captured by smooths. ```r norm_model_1 <- gam(y_norm~s(x1, k = 4) + s(x2, k = 4), method = 'REML') gam.check(norm_model_1) ``` ``` ## ## Method: REML Optimizer: outer newton ## full convergence after 8 iterations. ## Gradient range [-0.0003467788,0.0005154578] ## (score 736.9402 & scale 2.252304). ## Hessian positive definite, eigenvalue range [0.000346021,198.5041]. ## Model rank = 7 / 7 ## ## Basis dimension (k) checking results. Low p-value (k-index<1) may ## indicate that k is too low, especially if edf is close to k'. ## ## k' edf k-index p-value ## s(x1) 3.00 1.00 0.13 <2e-16 *** ## s(x2) 3.00 2.91 1.04 0.77 ## --- ## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1 ``` --- background-image: url(figures/rookie.jpg) background-size: contain --- # Checking basis size Increasing basis size can move issues to another part of the model. ```r norm_model_2 <- gam(y_norm ~ s(x1, k = 12) + s(x2, k = 4), method = 'REML') gam.check(norm_model_2) ``` ``` ## ## Method: REML Optimizer: outer newton ## full convergence after 11 iterations. ## Gradient range [-5.658609e-06,5.392657e-06] ## (score 345.3111 & scale 0.2706205). ## Hessian positive definite, eigenvalue range [0.967727,198.6299]. ## Model rank = 15 / 15 ## ## Basis dimension (k) checking results. Low p-value (k-index<1) may ## indicate that k is too low, especially if edf is close to k'. ## ## k' edf k-index p-value ## s(x1) 11.00 10.84 0.99 0.330 ## s(x2) 3.00 2.98 0.86 0.005 ** ## --- ## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1 ``` --- # Checking basis size Successively check issues in all smooths. ```r norm_model_3 <- gam(y_norm ~ s(x1, k = 12) + s(x2, k = 12),method = 'REML') gam.check(norm_model_3) ``` ``` ## ## Method: REML Optimizer: outer newton ## full convergence after 8 iterations. ## Gradient range [-1.136192e-08,6.794565e-13] ## (score 334.2084 & scale 0.2485446). ## Hessian positive definite, eigenvalue range [2.812271,198.6868]. ## Model rank = 23 / 23 ## ## Basis dimension (k) checking results. Low p-value (k-index<1) may ## indicate that k is too low, especially if edf is close to k'. ## ## k' edf k-index p-value ## s(x1) 11.00 10.85 0.98 0.29 ## s(x2) 11.00 7.95 0.95 0.14 ``` --- # Checking basis size ![](03-predictions-and-model-checking_files/figure-html/gam_check_norm4-1.svg) --- class: inverse center middle subsection # `concurvity()`: how independent are my variables? --- # What is concurvity? - Nonlinear measure of variable relationships, similar to co-linearity - Generally a property of a _model_ and data, not data alone - In linear models, we may be concerned about co-linear variables, which we can find with `cor(data)`, or `pairs(data)` of the data - When using GAMs, we use `concurvity(model)` ??? Concurvity must be a model property because it depends on the type of curves allowed --- # Effects of concurvity Independent variables yield nice, separable nonlinear GAM terms ![](03-predictions-and-model-checking_files/figure-html/concurve1-1.svg) --- # Effects of concurvity Modest dependence between predictor variables increases uncertainty. ![](03-predictions-and-model-checking_files/figure-html/concurve2-1.svg) --- # Effects of concurvity Smooth forms and intervals go **buck wild** under strong dependence. ![](03-predictions-and-model-checking_files/figure-html/concurve4-1.svg) --- # Use `concurvity()` to diagnose (It's easier to read with `round()`) .pull-left[ ```r round(concurvity(some_model), 2) ``` ``` ## para s(x1_cc) s(x2_cc) ## worst 0 0.84 0.84 ## observed 0 0.22 0.57 ## estimate 0 0.28 0.60 ``` - `full=TRUE` how much each smooth is explained by _all_ others - `full=FALSE` how much each smooth is explained by _each_ other - 3 estimates provided ] .pull-right[ ```r lapply( concurvity(some_model, full= FALSE), round, 2) ``` ``` ## $worst ## para s(x1_cc) s(x2_cc) ## para 1 0.00 0.00 ## s(x1_cc) 0 1.00 0.84 ## s(x2_cc) 0 0.84 1.00 ## ## $observed ## para s(x1_cc) s(x2_cc) ## para 1 0.00 0.00 ## s(x1_cc) 0 1.00 0.57 ## s(x2_cc) 0 0.22 1.00 ## ## $estimate ## para s(x1_cc) s(x2_cc) ## para 1 0.00 0.0 ## s(x1_cc) 0 1.00 0.6 ## s(x2_cc) 0 0.28 1.0 ``` ] --- # Concurvity: Remember - Can make your model unstable to small changes - `cor(data)` not sufficient: use the `concurvity(model)` function - Not always obvious from plots of smooths!! --- # Let's look at an example using the richness data .pull-left[ ```r # load the data trawls <- read.csv(here("data","trawl_nl.csv")) trawls2010 <- filter(trawls,year==2010) rich_tempdepth <- gam(richness ~ s(log10(depth),k=30)+s(temp_bottom) + lat, data= trawls2010, family = poisson, method ="REML") draw(rich_tempdepth) ``` ] .pull-right[ ![](03-predictions-and-model-checking_files/figure-html/rich-spatial2-1.svg) ] --- .pull-left[ ```r concurvity(rich_tempdepth) ``` ] .pull-right[ ``` ## para s(log10(depth)) s(temp_bottom) ## worst 0.9986329 0.7712929 0.8027293 ## observed 0.9986329 0.2205268 0.7859323 ## estimate 0.9986329 0.5174799 0.7027520 ``` ] --- class: inverse middle center subsection # part 3: Model selection --- # How do we choose between alternative models? - Models can differ in # of predictors, basis functions used, family, etc. - When comparing models, we have to account for model fit and the flexibility of each model - MGCV uses the effective degrees of freedom of smooth terms when comparing models via ANOVA or AIC --- # How do we choose between alternative models? Possible approaches: - Look at terms within a model - AIC - ANOVA table - Fitting full model and using `select = TRUE` option. --- # A few caveats first: * you cannot compare models that differ in the number of data points, or in type of data (assuming count vs. continuous data, for example) * p-values for terms within each model are approximate, from ANOVA even more approximate * Make sure to use the same method ("ML", "REML" or "GCV.Cp") for all models to be compared --- # Viewing smooth terms within a model: ```r rich_tempdepth <- gam(richness ~ s(log10(depth),k=30)+s(temp_bottom), data= trawls2010, family = poisson, method ="REML") summary(rich_tempdepth) ``` ``` ## ## Family: poisson ## Link function: log ## ## Formula: ## richness ~ s(log10(depth), k = 30) + s(temp_bottom) ## ## Parametric coefficients: ## Estimate Std. Error z value Pr(>|z|) ## (Intercept) 3.19764 0.00923 346.4 <2e-16 *** ## --- ## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1 ## ## Approximate significance of smooth terms: ## edf Ref.df Chi.sq p-value ## s(log10(depth)) 5.032 6.343 143.301 <2e-16 *** ## s(temp_bottom) 1.002 1.004 0.635 0.428 ## --- ## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1 ## ## R-sq.(adj) = 0.218 Deviance explained = 21.6% ## -REML = 1509.9 Scale est. = 1 n = 482 ``` --- # Using ANOVA to compare two models ```r rich_depth <- gam(richness ~ s(log10(depth),k=30), data= trawls2010, family = poisson, method ="REML") anova(rich_depth, rich_tempdepth,test = "Chisq") ``` ``` ## Analysis of Deviance Table ## ## Model 1: richness ~ s(log10(depth), k = 30) ## Model 2: richness ~ s(log10(depth), k = 30) + s(temp_bottom) ## Resid. Df Resid. Dev Df Deviance Pr(>Chi) ## 1 474.05 565.84 ## 2 473.10 565.67 0.94931 0.17041 0.6586 ``` --- # Using ANOVA to compare two models Note for anova.gam: This assumes that models do not differ in terms that can be completely smoothed away (like simple random effects). See `?anova.gam` for more details --- # Using AIC to compare two models .pull-left[ ```r AIC(rich_depth, rich_tempdepth) ``` ``` ## df AIC ## rich_depth 6.643459 2997.568 ## rich_tempdepth 7.582491 2999.275 ``` ] .pull-right[ * A corrected version of AIC (2k - 2logLik) to account for reduced degrees of freedom from smoothing, and uncertainty in smoothing parameters. * See ?`mgcv::AIC.gam` for more details ] --- background-image: url(figures/wood-quote.png) background-size: contain --- # Final method: selection of smooth terms within a model * If we think a given smooth term can be removed from the model, it should also be possible to penalize the term to zero within the model -- * Only works if a given term is penalized; remember from day 1 that some function shapes are not penalized (are in the null space of the model) -- * If we set `select=TRUE` this adds a penalty to the null space of all models, letting mgcv remove the term if need be --- ```r rich_tempdepth_nonull <- gam(richness ~ s(log10(depth),k=30)+s(temp_bottom), data= trawls2010, family = poisson, method ="REML", select = TRUE) summary(rich_tempdepth_nonull) ``` ``` ## ## Family: poisson ## Link function: log ## ## Formula: ## richness ~ s(log10(depth), k = 30) + s(temp_bottom) ## ## Parametric coefficients: ## Estimate Std. Error z value Pr(>|z|) ## (Intercept) 3.197728 0.009229 346.5 <2e-16 *** ## --- ## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1 ## ## Approximate significance of smooth terms: ## edf Ref.df Chi.sq p-value ## s(log10(depth)) 5.246284 29 159.254 <2e-16 *** ## s(temp_bottom) 0.002459 9 0.002 0.428 ## --- ## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1 ## ## R-sq.(adj) = 0.22 Deviance explained = 21.6% ## -REML = 1506.9 Scale est. = 1 n = 482 ``` --- ```r draw(rich_tempdepth_nonull) ``` ![](03-predictions-and-model-checking_files/figure-html/unnamed-chunk-7-1.svg) --- class: inverse middle center subsection # Final exercise


title: RegExp Match Indices status: proposal stage: 3 location: https://github.com/tc39/proposal-regexp-match-indices contributors: Ron Buckton, Ecma International
This proposal is developed on GitHub with the help of the ECMAScript community. There are a number of ways to contribute to the development of this specification:
Community:


Google mobile or web applications
Embedded system design with Intelprocessor or FPGA
System design and modeling with MathWorks MATLAB and Simulink
Microsoft Windows or cloud software applications


Audio description via video swap
This demo uses a separate video to deliver audio description. If Description is toggled on, the user gets the described version; otherwise they get the non-described version.
One limitation of this method, as opposed to using a WebVTT file for audio description, is that the description text is not included in the interactive transcript. This limitation can be overcome by adding a transcript of the description content in a WebVTT descriptions track.


Preparation time
1-2 hours
Cooking time
1 to 2 hours
Serves
Makes 12 large Danish pastries
Dietary
Light, flaky Danish pastry topped with pecans, maple syrup and a vanilla icing.
For this recipe you will need a food processor and a piping bag fitted with a plain nozzle.
For the pastry dough, put the flour, salt and sugar on one side of a mixing bowl and the yeast on the opposite side. Add the eggs, egg yolk, warm milk and 80ml/2½fl oz water and mix for one minute using a fork until combined. Add a little more water if needed to form a firm dough.
Dust a work surface with flour and turn out the dough. Dust with a little flour and knead for 5 minutes, then shape into a ball.
 Put the dough in the bowl and cover with the cling film. Set aside in a warm place to prove for an hour, or until almost doubled in size.
For the filling, in a food processor, pulse 100g/3½oz of the pecans until fine. Transfer to a bowl and stir in the sugar, maple syrup and butter. Cover and leave at room temperature. Roughly chop the remaining pecans to use as a garnish.
To make the pastry, sandwich the chilled butter between the open wrapper and a piece of cling film. Using a rolling pin, beat the butter until it is flattened to roughly 1.5cm/⅝in. Roll out the dough on a lightly floured work surface until 1cm/½in thick and roughly double the size of the butter.
Arrange the dough with a short edge nearest you and put the butter in the middle. Fold the top and bottom of the pastry over the butter so it is just overlapping. Press all the edges and sides together to ensure the butter is sealed within the pastry. Using a rolling pin, tap the dough from the middle upwards and from the middle downwards. This ensures the butter is evenly distributed.
Roll out the pastry to a large rectangle approximately 1cm/½in thick. Turn dough so you have a long edge nearest you, then fold the right third into the middle and cover with the left third. Chill in the fridge for 30 minutes. Do this turning, folding and chilling three more times.
Preheat the oven to 200C/180C Fan/Gas 6. Line two large baking trays with non-stick baking paper.
Roll out the dough to a 30x40cm/12x16in rectangle. Using a pizza cutter or a sharp knife, cut the dough into 12 equal squares.
To shape the pastry, cut a line from every corner almost into the middle of the square. Brush the tip of each corner with a little of the egg and milk mixture, and fold the alternate corners into the middle pressing down firmly, creating a pinwheel.
Transfer the pastries to the prepared trays. Using your finger, press down to create a hollow in the middle of the pastry for the filling. Put 1 teaspoon of the ground pecan mixture into the centre of each pastry and scatter with a few chopped pecans to decorate. Cover the baking trays with cling film and set aside in a warm place to rise for 10 minutes.
To finish, brush each pastry with egg wash and bake for 15–20 minutes, or until the pastry is crisp and golden-brown.
Meanwhile, for the apricot glaze, combine the apricot jam and lemon juice with 2 tablespoons water in a small saucepan. Slowly heat the mixture, stirring gently, until runny. Pass through a sieve and set aside. While the pastries are still warm brush them with the apricot glaze.
For the icing, mix the icing sugar, boiling water and vanilla extract together until smooth. Transfer to a piping bag fitted with a small plain nozzle and pipe lines across the cooled pastries to finish.


|
|
| ProxyServiceRegistration (Type registrationInterface, Type concreteType, int registrationGroup=Services.REGISTRATION_GROUP_DEFAULT) |
| |
|
ServiceRegistration | SetRegistrationGroup (int registrationGroup) |
| |
|
void | SetServiceRegistration (ServiceLoader loader) |
| |
|
void | RegisterService (Services toLocator) |
| |
|
virtual void | InitService (Services serviceLocator, System.Action onCompleteCallback) |
| |
|
bool | UnregisterService (Services toLocator) |
| |
|
ServiceType | GetService< ServiceType > (Services serviceLocator) |
| |
|
object | GetService (Services serviceLocator) |
| |
|
override string | ToString () |
| |
|
|
Type | registrationType [get] |
| |
|
Type | proxyInterface [get] |
| |
|
int | registrationGroup [get] |
| |
|
bool | isProxy [get] |
| |
|
int | registrationGroup [get] |
| |
|
bool | isProxy [get] |
| |
|
Type | registrationType [get] |
| |
The documentation for this class was generated from the following file:
- Runtime/services/ServiceRegistration/ProxyServiceRegistration.cs


This should load immediately
Show #test-fn-1
This will show on click
noscript test
Click me for new element


The first week went by so quickly! Somehow we’re starting – as Harsh called it this morning – ‘Season 4, Episode 2’ (Cohort 4, Week 2).
Truthfully last week I really struggled with the Ruby basics. I have a general grasp of things I want to do and how I should do them, but my actual implementation needs refinement. Fortunately I have a great friend who came over and walked through some of the projects with me. And today, I’m happy to report, my pair and I were able to get through all the exercises. I was even able to get through the Extension exercise! :)
So here are my take-aways from the last week:
TDD is the best thing ever. If you use it right, it walks you through how to code the solution!
Watch your arrays vs hashes vs objects.
- When you don’t write your own tests for TDD make sure you know what’s being asked for. So much frustration came from me returning the right idea but in the wrong way.
Frustration is part of the game, but don’t give up. Go for a walk or get away from the problem, but keep coming back and trying different stuff. Even when I can’t get there without help, I’ve been so close, or I’ve tried something so close to the right answer. It’s not encouraging in the moment, but it’s nice when you come to the solution and can look back at your process and see how close you were. Learn from that.
With regards to practical newbie tips, here are my favorite 2.
When looping through a hash, you can call the key AND the value, like so
inventory.each do |item|
puts "There are #{item[:quantity]} #{item[:name]}(s) and they cost #{item[:price]} each."
puts "the total cost of #{item[:name]} is #{item[:price].to_f * item[:quantity]}"
total += item[:price].to_f * item[:quantity]
puts total
end
One of those things that seems obvious in retrospect, but gave me so much trouble.
The other neat thing I learned was stubbing time for an rspec test. For instance, if you want to make sure your script is going to return ‘late’ after a given time, you can write your test like
it 'should show late if past 30 min' do
thing = Thing.new
@time_now = Time.parse("Feb 11 2014")
Time.stub(:now).and_return(@time_now)
expect(thing.late?).to eq(true)
end
et voila!
So much magic to learn, so little time.


You click on repository/experimental/index.yml to download the package metadata.
Add the following to your Skipper Server configuration to register this repository.
spring:
cloud:
skipper:
server:
packageRepositories:
-
name: experimental
url: "http://skipper-repository.cfapps.io/repository/experimental"
description: Experimental Skipper Repository


For the best possible service, please place your orders 24 hours in advance.
We take cash, credit cards, and local checks. We will provide all you need as
far as plates, cutlery, and cups.
ASK IF DELIVERY IS AVAILABLE
Delivery charge may apply.
We care about our environment. We use eco-friendly products that help make a difference. Most of our containers are made from renewable resources & are 100% compostable.
Menu and pricing are subject to change -- please call to verify.
1 serving
Each box comes with gourmet kettle chips & a fresh baked chocolate chip cookie for one.
$8.99 -- sliced roast beef + chipotle aioli + sauteed red bell peppers + romaine lettuce serve on our freshly-baked multigrain bread
$8.99 -- portabella mushrooms + zucchini + red pepper + spring mix + balsamic dressing on foccacia
$8.99 -- house-made chicken salad (marinated chicken, apples, grapes, and onion with special sauce) + romaine lettuce + toasted pecans on multigrain bread
$8.99 -- smoked turkey + cheddar + sweet apple + strawberry mayo on multigrain bread
$8.99 -- housemade tuna salad + tomato + cucumber + spring mix in a spinach tortilla
$8.99 -- foccacia + chicken + provolone + red bell pepper + pine nuts + basil pesto
$8.99 -- turkey + bacon + romaine lettuce + avocado + mayo in a spinach tortilla
$8.99 -- pit ham + swiss + portabella mushrooms + apricot dijon mustard on multigrain bread
$8.99 -- smoked turkey + feta basil mayo + tomato + romaine lettuce served on our freshly-baked multigrain bread.
$7.99 -- romaine lettuce + feta + tomato + black olives + cucmber + red onion + oregano
ADD chicken $2.00
$8.99 -- our house-made pasta salad mixed with spring mix + marinated chicken + pine nuts + Italian dressing served with a freshly-baked baguette
$7.99 -- spinach + strawberries + apple + pecans + raspberry vinaigrette + bleu cheese
ADD chicken $2.00
8 - 10 servings
$59.99 -- house-made chicken salad (marinated chicken, apples, grapes, and onion with special sauce) + romaine lettuce + toasted pecans + cracked pepper wrapped in a spinach tortilla
$59.99 -- turkey + bacon + romaine lettuce + avocado + mayo in a spinach tortilla
$59.99 -- tomato + cucumber + red onion + avocado + romaine lettuce + carrot + sunflower seeds + ranch in a spinach tortilla
$59.99 -- sliced roast beef + chipotle aioli + sauteed red bell peppers + romaine lettuce serve on our freshly-baked multigrain bread
$59.99 -- smoked turkey + feta basil mayo + tomato + romaine lettuce served on our freshly-baked multigrain bread.
$59.99 -- house-made chicken salad (marinated chicken, apples, grapes, and onion with special sauce) + romaine lettuce + toasted pecans on multigrain bread
$59.99 -- foccacia + chicken + provolone + red bell pepper + pine nuts + basil pesto
$59.99 -- smoked turkey + cheddar + sweet apple + strawberry mayo on multigrain bread
$59.99 -- pit ham + swiss + portabella mushrooms + apricot dijon mustard on multigrain bread
$59.99 -- portabella mushrooms + zucchini + red pepper + spring mix + balsamic dressing on foccacia
$36.99 -- romaine lettuce + feta + tomato + black olives + cucmber + red onion + oregano served with toasted pita bread
$36.99 -- our house-made pasta salad mixed with spring mix + marinated chicken + pine nuts + Italian dressing served with a freshly-baked baguette
$36.99 -- spinach + strawberries + apple + pecans + raspberry vinaigrette + a side of bleu cheese served with a freshly-baked baguette
10 - 12 servings
$25.99 -- danishes + cinnamon rolls + morning buns + scones + muffins
$12.99 -- vanilla yogurt + mixed berries + crunchy granola
$25.99 -- fresh seasonal fruit with our sweet yogurt dip
$15.99 -- your choice of our hot, fresh coffee served in an insulated, portable container
10 servings
$22.00 -- our delicious lemon loaf
$32.00 -- rockslide brownies + toffee crunch blondies + white chocolate raspberry cheesecake bars
$14.00 -- freshly baked chocolate chip cookies
10-12 servings
$15.00 -- add on to any sandwich tray order
$25.00 -- add on to any sandwich tray order
choose from an assortment of soda, water, and bottled juices
Choose any amount.
Call or stop in to get yours today!


Sunho Kwon
presidentTimothy Chan
Vice-PresidentHey I'm Katie! I am a second year studying Economics at Murray Edwards college. I was born in China and migrated to the UK in 2010. When I'm not studying or applying to internships, I'm either painting, playing the piano, hanging with friends, or obsessively listening to Taylor Swift. I attended almost every single one of ABACUS's events in my first year of uni and I am super excited to be a part of the committee! Can't wait to have you all in this awesome family.
Katie Yuan
TreasurerRobbie Chow
SecretaryHi everyone! I'm Justin, a second year medic at Trinity. I grew up in London but have family from all over the world. You will probably see me in all sorts of restaurants in Cambridge or in market square as I love enjoying food with friends. I'm excited to meet everyone joining ABACUS at our super fun events!


Thread Dump Action Plugin
Plugin Information |
|---|
View Thread Dump Action on the plugin site for more information. |
Provides an easy mechanism to obtain a Jenkins thread dump.
Root Action |
|
The root action to launch a Thread Dump |
|---|---|---|
Thread Dump |
|
The Jenkins generated thread dump |
Changelog
1.0 (released 2012-03-03)
- fully I18N
- initial implementation


--- title: How to Make Awesome R Markdown for Blogdown author: John Houghton date: '2018-11-13' slug: how-to-make-awesome-r-markdown-for-blogdown categories: - Markdown - R tags: [] description: '' featured: '' featuredalt: '' featuredpath: '' linktitle: '' ---
knitr::read_chunk('~/Documents/Github/r_snippets/blogdown.R')
https://medium.com/@jeffmcmorris/tips-and-tricks-for-building-a-theme-in-hugo-4806bdd747d7
The github README.md provides some good examples


Let's play!
Rules:
Ping Pong will count up to your number from 1 with the following exceptions:
- Numbers divisible by 3 become "ping"
- Numbers divisible by 5 become "pong"
- Numbers divisible by 3 and 5 become "pingpong"
Rules:
Ping Pong will count up to your number from 1 with the following exceptions:
- Numbers divisible by 3 become "ping"
- Numbers divisible by 5 become "pong"
- Numbers divisible by 3 and 5 become "pingpong"
Ping Pong will count up to your number from 1 with the following exceptions:
- Numbers divisible by 3 become "ping"
- Numbers divisible by 5 become "pong"
- Numbers divisible by 3 and 5 become "pingpong"
- Numbers divisible by 3 become "ping"
- Numbers divisible by 5 become "pong"
- Numbers divisible by 3 and 5 become "pingpong"


{% extends "base.html" %} {% load socialaccount %} {% if error_message %}
{{ error_message }}
{% endif %} {% block title %}Welcome! Please login with Google to get started so you can find study groups!
Study Buddies hopes to assist others in finding their own study buddies. Due to COVID-19, socializing with peers is difficult. As college students ourselves, we understand how isolating and challenging online learning can be. Zoom Univeristy has taken away more natural, in person opportunities for you and your classmates to interact before, during, and after class. Have no fear! Study Buddies is here. We hope to help other people find their true study buddy or buddies. We strongly believe in upholding the University of Virginia's Honor System. We urge our users to promote a virtual community of trust on this platform. Be kind and supportive to your fellow study buddies. Good luck studying! You've got this!
Click the button below to contact us directly. We will get back to you as soon as we can!
Contact Us!


{{title}}
Course Code
Course Unit
Grade
Action
{{student.code | uppercase}}
{{student.unit}}
{{student.grade | uppercase}}
Add New Score
Calculate GPA
Your GP is : {{GradePoint}}


--- title: Improving a Visualization author: Jonathan Carroll date: '2021-07-02' slug: improving-a-visualization categories: [R] tags: [rstats] type: '' subtitle: '' image: '' ---
I saw this post on Reddit’s r/dataisbeautiful showing this plot of streaming services market share, comparing 2020 to 2021
and thought it looked like a good candidate for trying out some plot improvement techniques.
I saw this post on Reddit’s r/dataisbeautiful showing this plot of streaming services market share, comparing 2020 to 2021
and thought it looked like a good candidate for trying out some plot improvement techniques.
Yes, that was a reasonably long while ago, this post has taken quite some time to put together. Life.
I’ve played with adding images to plot axes several times (also here, here, here) so that part shouldn’t pose too much of a challenge. First, I’ll try to rebuild the original. The original was built in powerpoint but I’ll be reproducing it with R (surprise, surprise).
The data itself appears to be captured from something like this page (paywalled) but the precise values aren’t important; I’ll just take them directly from the original plot manually
streaming <- tibble::tribble(
~service, ~`2020`, ~`2021`,
"netflix", 29, 20,
"prime", 21, 16,
"hulu", 16, 13,
"disney", 12, 11,
"apple", 4, 5,
"peacock", 0, 5,
"hbo", 3, 12,
"paramount", 2, 3,
"other", 13, 15,
)
I can build a simple barplot from this data with {ggplot2}
. First we’ll need it in long format, with the services ordered as
they are in the original. From that I can build a basic bar plot with dodged bars. There’s a few fiddly bits to work out, which I’ll try to
go through with code comments.
library(ggplot2)
## pivot to long format with the
## year and share as their own columns
streaming_long <- tidyr::pivot_longer(streaming,
cols = -service,
names_to = "year",
values_to = "share")
## plot the years side-by-side in the original order
p <- ggplot(streaming_long) +
geom_col(aes(factor(service, levels = streaming$service),
share, fill = year), position = position_dodge(width = 0.9)) +
## add a hidden set of points to make the legend circles easily
geom_point(aes(x = service, y = -10, color = year, fill = year), size = 4) +
## add the percentages just above each bar
geom_text(aes(service, share + 1, label = paste0(share, "%"), group = year),
position = position_dodge(width = 0.9), size = 3) +
## use similar colours to the original
scale_fill_manual(values = c(`2020` = "red3", `2021` = "black")) +
scale_color_manual(values = c(`2020` = "red3", `2021` = "black")) +
## hide the fill legend and make the color legend horizontal
guides(fill = "none", color = guide_legend(direction = "horizontal")) +
scale_y_continuous(labels = scales::percent_format(scale = 1),
limits = c(0, 35)) +
labs(title = "US Streaming Market Share",
subtitle = "2020 vs 2021",
caption = "Source: Ampere Analytics via The Wrap
Other Streatming Services include ESPN+, Showtime,
Sling TV, Youtube TV, and Starz",
x = "", y = "") +
theme_minimal() +
theme(axis.text = element_text(size = 10),
plot.title = element_text(size = 28, hjust= 0.5),
plot.subtitle = element_text(size = 28, hjust = 0.5),
plot.caption = element_text(size = 7, color = "grey60"),
plot.background = element_rect(fill = "#f4f7fc", size = 0),
legend.title = element_blank(),
legend.text= element_text(size = 12),
panel.grid = element_blank(),
## move the color legend to an inset
legend.position = c(0.85, 0.8))
p
## Warning: Removed 18 rows containing missing values (geom_point).
Not bad. Let’s get some of the other elements looking right. I used a font identifying site to pick a similar font which seems to be Josefin Slab SemiBold.
library(extrafont)
fontfamily <- "Josefin Slab SemiBold"
p <- p + theme(plot.title = element_text(family = fontfamily),
plot.subtitle = element_text(family = fontfamily))
p
## Warning: Removed 18 rows containing missing values (geom_point).
That’s fairly close. For the logos I’ll use the versions on Wikipedia
wiki <- "https://upload.wikimedia.org/wikipedia/commons/thumb/"
logos <- tibble::tribble(
~service, ~logo,
"netflix", paste0(wiki, "0/08/Netflix_2015_logo.svg/340px-Netflix_2015_logo.svg.png"),
"prime", paste0(wiki, "1/11/Amazon_Prime_Video_logo.svg/450px-Amazon_Prime_Video_logo.svg.png"),
"hulu", paste0(wiki, "e/e4/Hulu_Logo.svg/440px-Hulu_Logo.svg.png"),
"disney", paste0(wiki, "3/3e/Disney%2B_logo.svg/320px-Disney%2B_logo.svg.png"),
"apple", paste0(wiki, "2/28/Apple_TV_Plus_Logo.svg/500px-Apple_TV_Plus_Logo.svg.png"),
"peacock", paste0(wiki, "d/d3/NBCUniversal_Peacock_Logo.svg/440px-NBCUniversal_Peacock_Logo.svg.png"),
"hbo", paste0(wiki, "d/de/HBO_logo.svg/440px-HBO_logo.svg.png"),
"paramount", paste0(wiki, "a/a5/Paramount_Plus.svg/440px-Paramount_Plus.svg.png"),
"other", "other.png"
) %>%
mutate(path = file.path("images", paste(service, tools::file_ext(logo), sep = ".")))
labels <- setNames(paste0(""), logos$service)
labels[["other"]] <- "other
streaming
services"
and save a local copy for faster loading/just in case
for (r in 1:8) {
download.file(logos$logo[r], logos$path[r])
}
I can leverage {ggtext}
to set these as the axis labels
p <- p +
scale_x_discrete(labels = labels) +
theme(axis.text.x = ggtext::element_markdown())
p
## Warning: Removed 18 rows containing missing values (geom_point).
That’s not too bad - for the sake of scrolling, here’s the original again
Now to try to improve it.
My first thought on seeing this plot with the legend was that {ggtext}
makes this a lot easier to read by using the
title as the legend. For the sake of the ‘removed rows containing missing values’ warning I’ll also drop the points layer
p$layers[[2]] <- NULL ## drop the geom_points layer
p <- p +
labs(subtitle = "2020 vs 2021") +
theme(plot.subtitle = ggtext::element_markdown(), legend.position = "none")
p
To help make the black bars more distinct from the text, we could make these a different colour
p <- p +
scale_fill_manual(values = c(`2020` = "red3", `2021` = "darkcyan")) +
labs(subtitle = paste0("2020 ",
"vs 2021")) +
theme(plot.subtitle = ggtext::element_markdown(), legend.position = "none")
## Scale for 'fill' is already present. Adding another scale for 'fill', which
## will replace the existing scale.
p
Now to see if there’s a better way to represent this data. These are fractions of the total share… would a pie chart be a candidate?
streaming_pie <- left_join(streaming_long, logos, by = "service")
p_pie <- ggplot(streaming_pie, aes(1, share, fill = service, image = path)) +
geom_col() +
coord_polar("y") +
ggimage::geom_image(size = 0.12, position = position_stack(vjust = 0.5)) +
facet_wrap(~year, strip.position = "bottom") +
guides(fill = "none", color = guide_legend(direction = "horizontal")) +
labs(title = "US Streaming Market Share", subtitle = "2020 vs 2021", x = "", y = "") +
theme_void() +
theme(text = element_text(size = 32),
plot.title = element_text(family = fontfamily, size = 26, hjust = 0.5),
plot.subtitle = element_text(family = fontfamily, size = 26, hjust = 0.5),
plot.background = element_rect(fill = "#f4f7fc", size = 0),
legend.title = element_blank())
p_pie
No, that’s harder for making comparisons. Forget that idea.
This should possibly be a horizontal bar plot so that the labels read nicely
p +
coord_flip() +
scale_x_discrete(labels = labels, limits = rev(streaming$service)) +
theme(axis.text.y = ggtext::element_markdown())
## Scale for 'x' is already present. Adding another scale for 'x', which will
## replace the existing scale.
The ‘insight’ this is trying to display is how each service’s share has grown or shrunk. It wasn’t obvious to me that the original was ordered by that - decreases shown first, then increases (in some order, I’m still not sure what). What might make for a better plot to center it on the 2020 share and show the growth (positive or negative)
streaming_delta <- dplyr::mutate(streaming, growth = `2021` - `2020`)
p <- ggplot(streaming_delta) +
geom_col(aes(factor(service, levels = streaming$service), growth, fill = growth > 0)) +
labs(title = "US Streaming Market Share Growth", x = "", y = "") +
theme_minimal() +
theme(text = element_text(family = fontfamily),
plot.title = element_text(size = 26),
plot.subtitle = element_text(size = 26)) +
scale_x_discrete(labels = labels) +
coord_flip() +
theme(axis.text.y = ggtext::element_markdown()) +
scale_fill_manual(values = c(`TRUE` = "darkcyan", `FALSE` = "red3")) +
labs(subtitle = paste0("Growth ",
"vs Loss (% of 2020)")) +
theme(plot.subtitle = ggtext::element_markdown(),
plot.background = element_rect(fill = "#f4f7fc", size = 0))
p
Each comparison in the original required two bars, and the separation between the services didn’t make that easy to read. In this version, the absolute scale is lost (services starting high and decreasing aren’t so distinct from those starting low and gaining slightly) so what about using a dumbbell plot to show the separation between the two values while retaining their overall scales, rather than relying on comparing two bars?
library(ggalt, include.only = "geom_dumbbell")
p <- ggplot(streaming) +
ggalt::geom_dumbbell(aes(factor(service, levels = rev(streaming$service)),
x = `2020`, xend = `2021`),
colour_x = "red3", size_x = 6,
colour_xend = "darkcyan", size_xend = 6,
size = 1, dot_guide = TRUE,
dot_guide_size = 0.5,
dot_guide_colour = "grey25") +
scale_x_continuous(labels = scales::percent_format(scale = 1),
limits = c(0, 35)) +
scale_y_discrete(labels = labels) +
labs(title = "US Streaming Market Share", x = "", y = "") +
labs(subtitle = paste0("2020 ",
"vs 2021")) +
theme_minimal() +
theme(plot.title = element_text(family = fontfamily, size = 26),
plot.subtitle = element_text(family = fontfamily, size = 26)) +
theme(axis.text.y = ggtext::element_markdown(),
plot.subtitle = ggtext::element_markdown(),
plot.background = element_rect(fill = "#f4f7fc", size = 0),
legend.position = "none")
p
## Warning: Use of `streaming$service` is discouraged. Use `service` instead.
One last option to bring this data to life would be to animate between the two states…
library(gganimate)
p <- ggplot(streaming_long) +
geom_point(aes(share,
factor(service, levels = streaming$service)),
size = 5, color = "darkcyan") +
scale_y_discrete(labels = labels) +
labs(title = "US Streaming Market Share", x = "", y = "") +
labs(subtitle = "{closest_state}") +
scale_x_continuous(labels = scales::percent_format(scale = 1),
limits = c(0, 35)) +
theme_minimal() +
theme(text = element_text(family = fontfamily),
plot.title = element_text(size = 26),
plot.subtitle = element_text(size = 26),
legend.position = "none") +
theme(axis.text.y = ggtext::element_markdown(),
plot.background = element_rect(fill = "#f4f7fc", size = 0))
anim <- p +
transition_states(year, transition_length = 4) +
ease_aes() +
enter_fade() +
exit_fade()
animate(anim, renderer = gifski_renderer())
anim_save(filename = "images/streaming.gif")
I think these last few communicate more than the original. It’s always amazing how easy it is to bring this data into R and start playing with different presentations. Sure, perfecting the plots can take a little while, but the data is there to be played with.
One visualization which might have been interesting would be if we had the data on the transitions between services. Then an alluvial plot would be very informative. Simulating that…
streaming_flow <- tibble::tribble(
~`2020`, ~Freq, ~`2021`,
"netflix", 12, "netflix",
"netflix", 4, "prime",
"netflix", 6, "disney",
"netflix", 3, "apple",
"netflix", 4, "hbo",
"prime", 16, "prime",
"prime", 5, "netflix",
"prime", 2, "hulu",
"prime", 1, "disney",
"prime", 3, "peacock",
"prime", 4, "hbo",
"hulu", 13, "hulu",
"hulu", 1, "netflix",
"hulu", 2, "prime",
"hulu", 1, "disney",
"disney", 11, "disney",
"disney", 1, "netflix",
"disney", 3, "prime",
"disney", 1, "hulu",
"apple", 4, "apple",
"apple", 2, "netflix",
"apple", 1, "prime",
"peacock", 2, "peacock",
"peacock", 1, "netflix",
"hbo", 3, "hbo",
"hbo", 1, "prime"
)
library(ggalluvial)
lodes <- to_lodes_form(streaming_flow, axes = c("2020", "2021"))
lodes <- left_join(lodes, logos, by = c("stratum" = "service"))
lodes <- arrange(lodes, stratum)
ggplot(lodes, aes(x = x, stratum = stratum, alluvium = alluvium,
y = Freq, fill = stratum, label = stratum, image = path)) +
geom_flow() +
geom_stratum(alpha = 0.6) +
geom_text(stat = "stratum", size = 4) +
scale_x_discrete(limits = c("2020", "2021"),
expand = c(0.1, 0.1)) +
labs(title = " US Streaming Market Share Flow",
subtitle = " 2020 to 2021") +
theme_void() +
theme(axis.text.x = element_text(size = 20, vjust = 3),
plot.title = element_text(family = fontfamily, size = 26),
plot.subtitle = element_text(family = fontfamily, size = 26),
plot.background = element_rect(fill = "#f4f7fc", size = 0),
legend.position = "none")
I spent way too long trying to get the logos into this one, but there seems to be
a fundamental issue with combining {ggalluvial}
with {ggimage}
which I coulnd’t resolve.
Do you have a better way to present this data?


| bool TKAbstractGestureRecognizer.isTrackingAnyTouch |
( |
List< TKTouch > |
touches | ) |
|
|
protected |
checks to see if any of the touches are currently being tracked by the recognizer
| bool TKAbstractGestureRecognizer.isTrackingTouch |
( |
TKTouch |
t | ) |
|
|
protected |
checks to see if the touch is currently being tracked by the recognizer
| Vector2 TKAbstractGestureRecognizer.startTouchLocation |
( |
| ) |
|
returns the start location of the touches.
If there are multiple touches this will return the centroid of the location.
| override string TKAbstractGestureRecognizer.ToString |
( |
| ) |
|
| Vector2 TKAbstractGestureRecognizer.touchLocation |
( |
| ) |
|
returns the location of the touches.
If there are multiple touches this will return the centroid of the location.
| List<TKTouch> TKAbstractGestureRecognizer._trackingTouches = new List<TKTouch>() |
|
protected |
stores all the touches we are currently tracking
| bool TKAbstractGestureRecognizer.alwaysSendTouchesMoved = false |
|
protected |
when true, touchesMoved will be called for ALL touches.
By default, only the touches a recognizer is tracking (from touchesBegan) will be sent.
| TKRect TKAbstractGestureRecognizer.boundaryFrame = null |
frame that the touch must be within to be recognized.
null means full screen. note that Unity's origin is the bottom left
| bool TKAbstractGestureRecognizer.enabled = true |
| uint TKAbstractGestureRecognizer.zIndex = 0 |
zIndex of touch input.
0 by default. if a zIndex of greater than 0 uses a touch in touchesBegan it will not be passed to any other recognizers. useful if you have some full screen recognizers and you want to overlay a button/control
The documentation for this class was generated from the following file:


The JSONStreamParser
structure provides an event-based
(or stream) parsing model for JSON files. It is suitable
for scanning large files for particular items without having
to first build an in-memory data structure. It can also
be useful to directly translate from JSON to a specific SML
datatype without having to go through the intermediate
JSON.value
representation.
Synopsis
structure JSONStreamParser
Interface
type source
type 'ctx callbacks = {
null : 'ctx -> 'ctx,
boolean : 'ctx * bool -> 'ctx,
integer : 'ctx * IntInf.int -> 'ctx,
float : 'ctx * real -> 'ctx,
string : 'ctx * string -> 'ctx,
startObject : 'ctx -> 'ctx,
objectKey : 'ctx * string -> 'ctx,
endObject : 'ctx -> 'ctx,
startArray : 'ctx -> 'ctx,
endArray : 'ctx -> 'ctx,
error : 'ctx * string -> unit
}
val openStream : TextIO.instream -> source
val openFile : string -> source
val openString : string -> source
val close : source -> unit
val parse : 'ctx callbacks -> (source * 'ctx) -> 'ctx
val parseFile : 'ctx callbacks -> (string * 'ctx) -> 'ctx
Description
type source
-
The abstract type of JSON input sources. Note that this type is the same as
JSONParser.source
. type 'ctx callbacks = { … }
-
This type is a record of the parsing-event call-back functions, where the type parameter
'cxt
is instantiated to the context (or state) needed to preserve information between events. The call-back functions in this record type are invoked as follows:null : 'ctx -> 'ctx
-
called when the JSON null value is encountered.
boolean : 'ctx * bool -> 'ctx
-
called when the JSON true or false values are encountered.
integer : 'ctx * IntInf.int -> 'ctx
-
called when a JSON integral-number value encountered.
float : 'ctx * real -> 'ctx
-
called when a JSON floating-point-number value encountered.
string : 'ctx * string -> 'ctx
-
called when a JSON string value encountered.
startObject : 'ctx -> 'ctx
-
called at the beginning of a JSON object definition (i.e., when a “{” is encountered).
objectKey : 'ctx * string -> 'ctx
-
called when a JSON object key is encountered (including the "`:"). The next call-back will specify the value associated with the key.
endObject : 'ctx -> 'ctx
-
called at the end of a JSON object definition (i.e., when a “}” is encountered).
startArray : 'ctx -> 'ctx
-
called at the beginning of a JSON array definition (i.e., when a “[” is encountered).
endArray : 'ctx -> 'ctx
-
called at the end of a JSON array definition (i.e., when a “]” is encountered).
error : 'ctx * string -> unit
-
called when a syntax error is encountered in the input. The second argument is an error message describing the error. It is expected that this call-back does not return (i.e., it either raises an exception or terminates the program). If it does return, then the parser will raise the
Fail
exception.
val openStream : TextIO.instream → source
-
openStream inS
returns a input source for the given input stream.
val openFile : string → source
-
openStream file
returns a input source for the given file. This function opens an input stream for reading from the file, so one should make sure to callclose
on the source once all of the JSON values have been read from the file. val openString : string → source
-
openStream s
returns a input source for the given string.
val close : source → unit
-
close src
closes the input source, which has the effect of marking the source as closed. Furthermore, ifsrc
was created by a call toopenFile
, then the underlying input stream that was created for the file is closed. This function does not close the input stream for sources created byopenStream
val parse : 'ctx callbacks -> (source * 'ctx) -> 'ctx
-
parse cbs (src, cxt)
will parse the JSON input from the input sourcesrc
, using the record of call-back functionscbs
and the initial contextcxt
. val parseFile : 'ctx callbacks -> (string * 'ctx) -> 'ctx
-
parse cbs (f, cxt)
will parse the JSON input from the filef
, using the record of call-back functionscbs
and the initial contextcxt
. Note that this function will only parse a single JSON value from the file; to parse multiple values, one should used theparse
function with a source created byopenFile
.
Exampless
Consider the following JSON input:
{ "a" : 23,
"b" : [ false, true ],
"c" : "hello world"
}
Parsing this value has the same result as evaluating the following function:
fun f cxt = let
val cxt = startObject cxt
val cxt = objectKey (cxt, "a")
val cxt = integer (cxt, 23)
val cxt = objectKey (cxt, "b")
val cxt = startArray cxt
val cxt = boolean (cxt, false)
val cxt = boolean (cxt, true)
val cxt = endArray cxt
val cxt = objectKey (cxt, "c")
val cxt = objectString (cxt, "hello world")
val cxt = endObject cxt
in
cxt
end
The following function returns a list of all of the string-valued
fields labeled as "name"
in the input file.
fun getNames file = let
fun objectKey ({names, ...}, "name") = {names = names, isName = true}
| objectKey (cxt, _) = cxt
fun string (cxt as {names, isName}, s) = if isName
then {names = s :: names, isName = false}
else cxt
fun default ({names, isName}, _) = {names = names, isName = false}
val cbs = {
null = Fn.id,
boolean = default,
integer = default,
float = default,
string = string,
startObject = Fn.id,
objectKey = objectKey,
endObject = Fn.id,
startArray = Fn.id,
endArray = Fn.id,
error = fn (_, msg) => raise Fail msg
}
val {names, ...} =
JSONStreamParser.parseFile cbs (file, {names = [], isName = false})
in
List.rev names
end


Voting Information
Register to vote, check registration status and find information about your ballot.
Sorry, you're too young to vote
Learn about voting.
Learn how to vote.


Name: Aditya Dutta
Profile: Programmer
Email<EMAIL_ADDRESS>Skills
About me
I was born in New Delhi, India. I have been programming since the age 12. I was excellent in solving puzzles with my general instincts since I was 3 years old. With time passing by, I decided to study Science in high school to finally pursue a career in the gaming industry.
As a young boy, I was always fascinated by games and whenever got a chance, I used to enjoy playing various games available in video parlours in my neighbourhood market or during a local tour with my parents. Thereafter, I started spending hours exploring new games in my computer. The activity never lost its zest and as I grew up, I knew that I wished to become a game developer and started working towards my dream of developing games for the best names in the world. I was confident about my choice and knew that it is the best option as per my interest and ability.
Portfolio
Projects made with love and effort.


{% extends 'base-app-alt.html' %} {% load breaktag %} {% load staticfiles %} {% load breaktag %} {% block headers_css %} {% endblock %} {% block content %}
Wisely is building a cross-platform Massive Open Online learning community to allow MOOC users to meet other students and achieve success together. Wisely is founded by three students who are passionate about the potential of MOOCs but believe there is room for improvement. We are developing a suite of tools to help connect, engage and motivate MOOC students using the principles of gamification, loss aversion and intrinsic and extrinsic incentivization. We hope to bridge the extant gaps in the MOOC ecosystem by building collaboration and relationship-building tools such as group design projects and study rooms.


{% load goldenbraid_extras %}
| Accession | Name | Type | Description | Owner | Entry Date | Genbank File |
|---|---|---|---|---|---|---|
| {{ feature.uniquename|link_if_url:feature }} | {{ feature.name }} | {{ feature.gb_category_name }} | {{ feature.description }} | {{ feature.owner.username }} | {{ feature.timecreation }} | {{ "Download"|link_if_url:feature.genbank_file }} |


HEAD ======= >>>>>>> 5676094d996032005459bb9861331eb6ce407d04
Full stack web developer, with more than 15 years of graphic design experience. Adept at analyzing site needs, managing a team, and meeting tight deadlines. Proficient in HTML5, CSS, Bootstrap, Materialize, JavaScript, JQuery, React JS, Node JS, Express JS, Mongo DB, and MySQL. =======
Full stack web developer, with more than 13 years of graphic design experience. Adept at analyzing site needs, managing a team, and meeting tight deadlines. Proficient in HTML5, CSS, Bootstrap, JavaScript, JQuery, NodeJS, ExpressJS, and MySQL. >>>>>>> 5676094d996032005459bb9861331eb6ce407d04
Bitpop is an avatar creator. It allows a user to create a character and preview their creation on different products that the website offers.
Built using: React, React-Materialize, Node, Express, Mongo DB, Mongoos, A Frame, Fabric, Canvas. DEMO | GITHUB
Asynchronous pictionary game. Users can login, choose to draw or guess. They will be given a random prompt if they choose to draw. If the user want to guess, they will get a random drawing from another user. They can fill out a form to make a guess, and rate the drawing.
<<<<<<< HEADBuilt using: Materialize CSS, Node, Express, Express-Handlebars, MySQL, Sequalize, Canvas. DEMO | GITHUB
Teenage Ninja Turtle themed memory game build with React JS and Bootstrap 4.
A web app that allows a user to track expenses and manage a monthly budget.
2018
2013
2003
Apart from being a web developer, I enjoy creating art. I dabble in digital illustration and some photography.
Tinkering with computer hardware, video games, and comic book movies.


|
Hi (First Name)
Great news! You application to participate in Capstone Project titled (Capstone Project Title) for (Company Name)
have been approved.
Simply click on the link below to get started.
But before you do, there are 3 important things to remember that will greatly assist you get the most out of your
Capstone Project experience:
-
All communication to be recorded in the InternMatch Capstone Project Marketplace Messaging System. This includes
questions, responses and reference material. In doing so everyone gets to see and what is going on. Please DO
NOT use email to communicate with each other, especially your Company Representative or Lecturer.
-
All meetings are to be recorded using the InternMatch Capstone Project Marketplace Recordable Video Conferencing
System.
This will allow participants who may have missed the meeting to view the meeting at a later time.
-
All research, findings, presentations and working documents are to be uploaded in to InternMatch Capstone Project
Marketplace Project Archive. This allows your Company Representative and Lecturer to easily find and review
your work.
So time to get started! We hope you enjoy your Capstone Project experience.
Kind Regards
(Sender Name)
(Sender Title)
(Sender Company Name)
|
|


HEAVY (director/writer: James Mangold; cinematographer: Michael Barrow; editor: Meg Reticker; cast: Pruitt Taylor Vince (Victor), Liv Tyler (Callie), Shelley Winters (Dolly), Debbie Harry (Delores), Joe Grifasi (Leo), Evan Dando (Jeff), David Patrick Kelly (Grey Man in Hospital); Runtime: 103; 1995)
Reviewed by Dennis Schwartz
This is an intense, brooding, slow-moving drama taking place at "Pete & Dolly's" small roadside pizza restaurant, run by the widowed Dolly (Shelley Winters) with help from her shy and obese thirtysomething son Victor (Pruitt Taylor Vince) and the irascible waitress for the last fifteen years, Delores (Deborah Harry-former lead singer of Blondie). The self-development story is seen through Victor's lonely eyes as he tries to come to grips with his sensitivities, his undeveloped personality, his inability to be articulate, and his low opinion of himself. This indie film is filled with many gratifying small touches, as it takes its time developing and forces one to tune into the way Victor sees things. It is set in a Hudson Valley, New York, small town.
We see the balding, hunched over Victor in the narrow confines of the pizza kitchen, where he feels most wanted when making pizzas. This is the kind of human interest story that Hollywood slicks up and can't make in quite the same realistic way that a good indie film can be made, that takes its time in bringing out a number of small truths, so that by the time the story winds down, a big climactic ending is not needed, all the pain and pathos has already been drawn out of it. James Mangold (the son of famous artists) deservedly was awarded the Grand Jury Prize for Best Direction at the Sundance Film Festival in early 1995 for this film.
The restaurant is barely surviving as a place passing truckers frequent and a handful of regulars stop by, until young, beautiful, and lively Callie (Liv Tyler-whose father is Aerosmith's Steven Tyler) gets hired, despite her lack of experience. Dolly takes a liking to this vivacious girl who is dropping out of college, perhaps thinking she could be just right for Victor. Her hiring causes Delores to feel that she has a rival for her job and reacts negatively toward the much younger waitress, while Victor is absorbed by Callie's good looks and sexuality, and fantasizes about her. He fantasizes that he is saving her from drowning and that she has taken his mother's place at the breakfast table.  When he tips the scales at 250-pounds, he decides to go on a crash diet. His mother tries to cheer him up by saying, "You're not fat, you're husky."

Regular customer and hanger-on, Leo (Joe Grifasi), is a heavy drinker hiding his depressive state by acting superior to Victor. He is enamored with the middle-aged Delores, but she mostly returns his affections with stinging comments. Delores is an enigmatic figure, someone Dolly expects had an affair with her husband and therefore harbors a resentment toward her, but not enough to fire her.
When Dolly is hospitalizalized, Victor is asked to drive Delores home and is surprised when she makes a pass at him, as they stop at the airport to watch the airplanes take off. When he rejects her, she snaps, "What, are you saving it for someone special?" Victor when asked later by Callie for a ride home, takes her to the same spot, but she offers him only her friendship.  In contrast to Victor's gentle nature, he's always high-strung. It is clearly because of his looks that Callie goes out with him, setting herself up for a life of disappointments and loneliness.
The film slowly builds to its surprise ending, where we see Victor sitting alone in his restaurant, having to face an uncertain future and the music of loneliness forever, and we are left with a lasting impression that is painful to perceive. The film works so well because the performers are outstanding and the writer/director has come through with a very touching debut effort. There is something precious about this film, whether in Shelley Winters warm performance as a giving but possessive mother, or from Pruitt Taylor Vince's priceless performance of someone who hardly speaks and is a doting son, longing for love and friendship, but who still hasn't matured, or from Liv Tyler's refreshing role as the one who breeds life into the dead feelings of both mother and son, giving them some hope for the future.
The musical score arranged by Thurston Moore helped set the quiet mood needed for the story to gently unfold. Everything about this original film was honest and natural. All the characters know what loneliness is, even if they mask it better than the mama's boy does, and because of that, it is easy to relate to their very demanding problems of loneliness and how it has eaten away at them -- making some fat, others blind to what they are, or bitter.
REVIEWED ON 7/16/2000 GRADE: A
Dennis Schwartz: "Ozus' World Movie Reviews"
http://www.sover.net/~ozus
<EMAIL_ADDRESS>© ALL RIGHTS RESERVED DENNIS SCHWARTZ
The review above was posted to the
rec.arts.movies.reviews newsgroup (de.rec.film.kritiken for German reviews).
The Internet Movie Database accepts no responsibility for the contents of the
review and has no editorial control. Unless stated otherwise, the copyright
belongs to the author.
Please direct comments/criticisms of the review to relevant newsgroups.
Broken URLs inthe reviews are the responsibility of the author.
The formatting of the review is likely to differ from the original due
to ASCII to HTML conversion.
Related links: index of all rec.arts.movies.reviews reviews


{%- extends "base.html" %} {% import "bootstrap/utils.html" as utils %} {% block content %}
A basic minecraft server monitor that tells you what's up on your Minecraft server.
Go here to see the server details - whether it's running, who's whitelisted, etc.
Go here to see the player stats, who's died the most, when they last logged and and stuff.

Not provided as part of this interface to keep the security vulnerabilities down - you'll need to perform some backend admin to change users


Brain Clouds are colorless green ideas that are sleeping happily in your head. If they get going, they could become full fledged BrainStorms.
Here are some recent BrainClouds:
Has anyone looked at a combination of MMURTL (from the book "Build Your Own 32-bit OS") and Kaffe to see if the two could be somehow melded into a quick JOS for the Intel platforms (and maybe easily ported to others?) I'm reading the MMURTL book right now and it has spawned some ideas.
MichaelManley<EMAIL_ADDRESS>A Simple concept of persisting object would be a good idea.
I Think about a DBInputStream and DBOutputStream for a waiy to save an object into a database.
StefanMarx
Maybee we can set up a kind of MUD for chating and discussions about the project.
If we want to do so I will be able to do the Mud-work (I'm a experienced mud-coder for about 3 Years and I have done mud-admin work the last 2 years).
StefanMarx
I think a mud would be a good idea. I'd definately hang out on it when I was online.
NedLovely
Are there yet any plans to build some truly distributed operationg system, providing mechanisms like object migration, or distributed sheduling?
ChristianKurzke
<EMAIL_ADDRESS>Plattform independence of JOS would - as I see it mean to write some microkernel - Hardware Abstraction Layer stuff in another language than Java - where I could imagine that posix compliant C Code should give the best portability to that.
-MichaelWDietrich<EMAIL_ADDRESS>Don't see why the HAL can't be almost entirely in Java (perhaps natively compiled) as well, and in fact as many have pointed out, an emulated HAL on top of existing VMs is probably a good idea. Certainly its interface to the rest of the OS will be as a set of Java classes, with a subset of methods written natively for access to machine registers and such; but these methods should ne a very small part of the system as a whole.
LeeDanielCrocker
|
Content of these pages are owned and copyrighted by the poster.
|
|
Hosted by:
|
|


MapsTotal and Partial Maps
The Coq Standard Library
Require Import Coq.Arith.Arith.
Require Import Coq.Bool.Bool.
Require Import Coq.Strings.String.
Require Import Coq.Logic.FunctionalExtensionality.
Documentation for the standard library can be found at
http://coq.inria.fr/library/.
The Search command is a good way to look for theorems involving
objects of specific types. Take a minute now to experiment with it.
Identifiers
Inductive id : Type :=
| Id : string → id.
Definition beq_id x y :=
match x,y with
| Id n1, Id n2 ⇒ if string_dec n1 n2 then true else false
end.
(The function string_dec comes from Coq's string library.
If you check its result type, you'll see that it does not actually
return a bool, but rather a type that looks like {x = y} + {x
≠ y}, called a sumbool, which can be thought of as an
"evidence-carrying boolean." Formally, an element of sumbool is
either a proof that two things are equal or a proof that they are
unequal, together with a tag indicating which. But for present
purposes you can think of it as just a fancy bool.)
Theorem beq_id_refl : ∀ id, true = beq_id id id.
Proof.
intros [n]. simpl. destruct (string_dec n n).
- reflexivity.
- destruct n0. reflexivity.
Qed.
intros [n]. simpl. destruct (string_dec n n).
- reflexivity.
- destruct n0. reflexivity.
Qed.
The following useful property of beq_id follows from an
analogous lemma about strings:
Theorem beq_id_true_iff : ∀ x y : id,
beq_id x y = true ↔ x = y.
Proof.
intros [n1] [n2].
unfold beq_id.
destruct (string_dec n1 n2).
- subst. split. reflexivity. reflexivity.
- split.
+ intros contra. inversion contra.
+ intros H. inversion H. subst. destruct n. reflexivity.
Qed.
intros [n1] [n2].
unfold beq_id.
destruct (string_dec n1 n2).
- subst. split. reflexivity. reflexivity.
- split.
+ intros contra. inversion contra.
+ intros H. inversion H. subst. destruct n. reflexivity.
Qed.
Similarly:
Theorem beq_id_false_iff : ∀ x y : id,
beq_id x y = false
↔ x ≠ y.
Proof.
intros x y. rewrite <- beq_id_true_iff.
rewrite not_true_iff_false. reflexivity. Qed.
intros x y. rewrite <- beq_id_true_iff.
rewrite not_true_iff_false. reflexivity. Qed.
This useful variant follows just by rewriting:
Theorem false_beq_id : ∀ x y : id,
x ≠ y
→ beq_id x y = false.
Proof.
intros x y. rewrite beq_id_false_iff.
intros H. apply H. Qed.
intros x y. rewrite beq_id_false_iff.
intros H. apply H. Qed.
Total Maps
Definition total_map (A:Type) := id → A.
Intuitively, a total map over an element type A is just a
function that can be used to look up ids, yielding As.
The function t_empty yields an empty total map, given a default
element; this map always returns the default element when applied
to any id.
Definition t_empty {A:Type} (v : A) : total_map A :=
(fun _ ⇒ v).
More interesting is the update function, which (as before) takes
a map m, a key x, and a value v and returns a new map that
takes x to v and takes every other key to whatever m does.
Definition t_update {A:Type} (m : total_map A)
(x : id) (v : A) :=
fun x' ⇒ if beq_id x x' then v else m x'.
This definition is a nice example of higher-order programming:
t_update takes a function m and yields a new function
fun x' ⇒ ... that behaves like the desired map.
For example, we can build a map taking ids to bools, where Id
"bar" is mapped to true and every other key is mapped to false,
like this:
Definition examplemap :=
t_update (t_update (t_empty false) (Id "foo") false)
(Id "bar") true.
This completes the definition of total maps. Note that we
don't need to define a find operation because it is just
function application!
Example update_example1 : examplemap (Id "baz") = false.
Proof. reflexivity. Qed.
Example update_example2 : examplemap (Id "foo") = false.
Proof. reflexivity. Qed.
Example update_example3 : examplemap (Id "quux") = false.
Proof. reflexivity. Qed.
Example update_example4 : examplemap (Id "bar") = true.
Proof. reflexivity. Qed.
To use maps in later chapters, we'll need several fundamental
facts about how they behave.
Even if you don't work the following exercises, make sure
you thoroughly understand the statements of the lemmas!
(Some of the proofs require the functional extensionality axiom,
which is discussed in the Logic chapter.)
Exercise: 1 star, optional (t_apply_empty)
First, the empty map returns its default element for all keys:Lemma t_apply_empty: ∀ A x v, @t_empty A v x = v.
Proof.
(* FILL IN HERE *) Admitted.
Exercise: 2 stars, optional (t_update_eq)
Next, if we update a map m at a key x with a new value v and then look up x in the map resulting from the update, we get back v:Lemma t_update_eq : ∀ A (m: total_map A) x v,
(t_update m x v) x = v.
Proof.
(* FILL IN HERE *) Admitted.
Exercise: 2 stars, optional (t_update_neq)
On the other hand, if we update a map m at a key x1 and then look up a different key x2 in the resulting map, we get the same result that m would have given:Theorem t_update_neq : ∀ (X:Type) v x1 x2
(m : total_map X),
x1 ≠ x2 →
(t_update m x1 v) x2 = m x2.
Proof.
(* FILL IN HERE *) Admitted.
Exercise: 2 stars, optional (t_update_shadow)
If we update a map m at a key x with a value v1 and then update again with the same key x and another value v2, the resulting map behaves the same (gives the same result when applied to any key) as the simpler map obtained by performing just the second update on m:Lemma t_update_shadow : ∀ A (m: total_map A) v1 v2 x,
t_update (t_update m x v1) x v2
= t_update m x v2.
Proof.
(* FILL IN HERE *) Admitted.
Exercise: 2 stars, optional (beq_idP)
Use the proof of beq_natP in chapter IndProp as a template to prove the following:Lemma beq_idP : ∀ x y, reflect (x = y) (beq_id x y).
Proof.
(* FILL IN HERE *) Admitted.
Exercise: 2 stars (t_update_same)
With the example in chapter IndProp as a template, use beq_idP to prove the following theorem, which states that if we update a map to assign key x the same value as it already has in m, then the result is equal to m:Theorem t_update_same : ∀ X x (m : total_map X),
t_update m x (m x) = m.
Proof.
(* FILL IN HERE *) Admitted.
Exercise: 3 stars, recommended (t_update_permute)
Use beq_idP to prove one final property of the update function: If we update a map m at two distinct keys, it doesn't matter in which order we do the updates.Theorem t_update_permute : ∀ (X:Type) v1 v2 x1 x2
(m : total_map X),
x2 ≠ x1 →
(t_update (t_update m x2 v2) x1 v1)
= (t_update (t_update m x1 v1) x2 v2).
Proof.
(* FILL IN HERE *) Admitted.
Partial maps
Definition partial_map (A:Type) := total_map (option A).
Definition empty {A:Type} : partial_map A :=
t_empty None.
Definition update {A:Type} (m : partial_map A)
(x : id) (v : A) :=
t_update m x (Some v).
We now straightforwardly lift all of the basic lemmas about total
maps to partial maps.
Lemma apply_empty : ∀ A x, @empty A x = None.
Proof.
intros. unfold empty. rewrite t_apply_empty.
reflexivity.
Qed.
intros. unfold empty. rewrite t_apply_empty.
reflexivity.
Qed.
Lemma update_eq : ∀ A (m: partial_map A) x v,
(update m x v) x = Some v.
Proof.
intros. unfold update. rewrite t_update_eq.
reflexivity.
Qed.
intros. unfold update. rewrite t_update_eq.
reflexivity.
Qed.
Theorem update_neq : ∀ (X:Type) v x1 x2
(m : partial_map X),
x2 ≠ x1 →
(update m x2 v) x1 = m x1.

Proof.
intros A m v1 v2 x1. unfold update. rewrite t_update_shadow.
reflexivity.
Qed.
intros A m v1 v2 x1. unfold update. rewrite t_update_shadow.
reflexivity.
Qed.
Theorem update_same : ∀ X v x (m : partial_map X),
m x = Some v →
update m x v = m.

Proof.
intros X v1 v2 x1 x2 m. unfold update.
apply t_update_permute.
Qed.
intros X v1 v2 x1 x2 m. unfold update.
apply t_update_permute.
Qed.


{% extends "base.html" %} {% block content %} {# FIXME: Kinda hacky to just store username here somewhere.. we should save it in base#}


Thank you!
You have successfully applied to join CodeReach!
To combat spam, we require that all applicants verify their email. Please check your inbox for a message from<EMAIL_ADDRESS>and click the link inside. If you do not, YOUR APPLICATION WILL NOT BE CONSIDERED.
After confirming your address, watch your inbox for the next week or so, when we will send out emails confirming your status. In the meantime, make sure to follow us on our social media to receive the latest updates!
You can also check your status and change your information by clicking here after you verify your email and logging in with the username and password you chose during signup.
We will be sending emails to:
Instagram: @codereach.vmss
Twitter: @codereach
Email: hello@codereach.ca


"Laws of the House of God, #13: The delivery of good medical care is to do as much nothing as possible.".
Borivali(West),In SFIT clg,3rd Floor
7030514293
Open all the time
Latest Updates
For a Healthy Lifestyle
For Additional Info
Check your Reports
Cost for Hospital Services
For Reports and booking appointments


Doc Cat
Search
Category Management
Document Management
Documents
Add
File Name
Categories
Insert Date (UTC)
Actions
Delete
Recategorize
Delete All Documents and Rebuild Index
×
Add New Document - Step 1
Document Upload
Browse
×
Add New Document - Step 2
Document Contents
×
Add New Document - Step 3
Categorization Results (threshold >= 0.10):
No categories found.
Category:
Search Term:
Score:
Accept Categorization
Reject Categorization


{% extends "layout.html" %} {% block page_title %} Apply for European Structural and Investment Funding {% endblock %} {% block content %} {% include "includes/phase_banner_alpha.html" %} {% include 'includes/page_errors.html' %} Step 2 Delivery partners Will your project have delivery partners? Will your project have delivery partners? A delivery partner is another organisation that will be working on the project. Yes No Save and continue Save and quit {% include "includes/application_info.html" %} {% include "includes/secondary_nav.html" %} {% endblock %}


>
We sometimes think we want to disappear, but all we really want is to be found. Life is but a dream.
Learn MoreNana Ama Adutwumwaah Agyeman is my name. I am the first of four children from a family of six. I am a God-fearing lady,who believes in Family, Fashion and a strong women's advocate so to speak. Very focused, and passionate about the things I believe in. And oops I am a talker, as in I can talk all day. lol
I am a recent graduate from the university of cape Coast, with a bachelor of science degree in Information Technology. I am currently an entrepreneur-in-training at the Meltwater Entrepreneurial school of technology in Ghana, learning Business, Communication skills and Technology which comprises programming, UX/UI and website designing. I was the general-secretary of the computer science and technology students association of the university of cape Coast.
Having a particular interests is almost always difficult for me because,like any human,i believe in diversity. More often than not, I find myself gravitating towards God,technology,fashion,and art. But just as likely find religion, politics,and others just as interesting. I gauge my interests by how much time I spend on each of them. Which is my personal relationship with God,reading (just about anything),and indoor. Though I do not use all my daily time engaging in monastic activities, but I am determined to mold my life in a way that is pleasing to God. And that is my greatest interest. As mention earlier I love and believe in technology a lot!!! Because it makes me feel smarter,powerful and it has a tremendous impact on how I complete anything I try to achieve,whether professional or personal. I just cannot imagine a life without it. It's like putting myself in my great-grandma's shoes,hahaha a life with no blender,washing machine,google search(because I am very inquisitive), microwave, dishwasher, should I go on? I also love fashion because its a medium for me to express myself,to use clothes creatively,to dream,inspire and hope for a better life
© 2015 NANA AMA AGYEMAN


Beep Boop
Turn numbers into beeps and boops
Enter your name:
Enter a number between 1 and 500:
Submit
Reverse Results
Reset Form


Updates
Thank you for using Asana Navigator!
I made an important update. Please reload the Asana task page if this extension doesn't work well just after the update.
I made the following two changes:
- A new feature is added to jump to any other sibling subtasks. You can now display a drop-down list containing all subtasks of the parent task.
- The keyboard shortcut Tab+K (go to previous subtask) is changed to Tab+G. It's because Tab+K is now used to like/heart the task.
Contact
My name is Shun Sakurai, an amateur programmer. To learn more and create better programs, I'd love to hear from users and developers.
- Please feel free to post comments, feature requests, bug reports, and questions through the Chrome Web Store.
- This is an open source project and you can see the source code and report issues at GitHub.


{% extends "base.html" %} {% block content %}
If you want or need to enter more than {{ quantity }} contact me to increase the number, for now I just entered 10 because that's probably the most anyone needs
You don't need to add recitation, labs, or lectures seperately, it does that for you.
*You may need to reload the page to get results* {% endblock %}


Experimental Particle Physics Ph.D candidate
Physics Department University of Science and Technology of China University of Michigan


unique pages have been published so far.
Paste the URL of a published Thimble page below and we'll let you favorite it and stuff.