Chart.js 3.0 introduces a number of breaking changes. Chart.js 2.0 was released in April 2016. In the years since then, as Chart.js has grown in popularity and feature set, we’ve learned some lessons about how to better create a charting library. In order to improve performance, offer new features, and improve maintainability, it was necessary to break backwards compatibility, but we aimed to do so only when worth the benefit. Some major highlights of v3 include:
dist/chart.js
.Chart.bundle.js
and Chart.bundle.min.js
. Please see the installation and integration docs for details on the recommended way to setup Chart.js if you were using these builds.moment
is no longer specified as an npm dependency. If you are using the time
or timeseries
scales, you must include one of the available adapters and corresponding date library. You no longer need to exclude moment from your build.Chart
constructor will throw an error if the canvas/context provided is already in usenpm
module in a project and want to make use of this feature, you need to import and register the controllers, elements, scales and plugins you want to use, for a list of all the available items to import see integration. You will not have to call register
if importing Chart.js via a script
tag or from the auto
register path as an npm
module, in this case you will not get the tree shaking benefits. Here is an example of registering components:import { Chart, LineController, LineElement, PointElement, LinearScale, Title } from `chart.js`
Chart.register(LineController, LineElement, PointElement, LinearScale, Title);
const chart = new Chart(ctx, {
type: 'line',
// data: ...
options: {
plugins: {
title: {
display: true,
text: 'Chart Title'
}
},
scales: {
x: {
type: 'linear'
},
y: {
type: 'linear'
}
}
}
})
horizontalBar
chart type was removed. Horizontal bar charts can be configured using the new indexAxis
optionA number of changes were made to the configuration options passed to the Chart
constructor. Those changes are documented below.
backgroundColor: ['red', 'green']
will result in alternating 'red'
/ 'green'
if there are more than 2 data points.elements.rectangle
is now elements.bar
hover.animationDuration
is now configured in animation.active.duration
responsiveAnimationDuration
is now configured in animation.resize.duration
elements.arc.angle
is now configured in degrees instead of radians.startAngle
option is now consistent with Radar
, 0 is at top and value is in degrees. Default is changed from -½π
to 0
.rotation
option is now in degrees and 0 is at top. Default is changed from -½π
to 0
.circumference
option is now in degrees. Default is changed from 2π
to 360
.cutoutPercentage
was renamed to cutout
and accepts pixels as numer and percent as string ending with %
.scale
option was removed in favor of options.scales.r
(or any other scale id, with axis: 'r'
)scales.[x/y]Axes
arrays were removed. Scales are now configured directly to options.scales
object with the object key being the scale Id.scales.[x/y]Axes.barPercentage
was moved to dataset option barPercentage
scales.[x/y]Axes.barThickness
was moved to dataset option barThickness
scales.[x/y]Axes.categoryPercentage
was moved to dataset option categoryPercentage
scales.[x/y]Axes.maxBarThickness
was moved to dataset option maxBarThickness
scales.[x/y]Axes.minBarLength
was moved to dataset option minBarLength
scales.[x/y]Axes.scaleLabel
was renamed to scales[id].title
scales.[x/y]Axes.scaleLabel.labelString
was renamed to scales[id].title.text
scales.[x/y]Axes.ticks.beginAtZero
was renamed to scales[id].beginAtZero
scales.[x/y]Axes.ticks.max
was renamed to scales[id].max
scales.[x/y]Axes.ticks.min
was renamed to scales[id].min
scales.[x/y]Axes.ticks.reverse
was renamed to scales[id].reverse
scales.[x/y]Axes.ticks.suggestedMax
was renamed to scales[id].suggestedMax
scales.[x/y]Axes.ticks.suggestedMin
was renamed to scales[id].suggestedMin
scales.[x/y]Axes.ticks.unitStepSize
was removed. Use scales[id].ticks.stepSize
scales.[x/y]Axes.ticks.userCallback
was renamed to scales[id].ticks.callback
scales.[x/y]Axes.time.format
was renamed to scales[id].time.parser
scales.[x/y]Axes.time.max
was renamed to scales[id].max
scales.[x/y]Axes.time.min
was renamed to scales[id].min
scales.[x/y]Axes.zeroLine*
options of axes were removed. Use scriptable scale options instead.steppedLine
was removed. Use stepped
showLines
was renamed to showLine
to match the dataset option.startAngle
was moved to radial
scale options.platform: PlatformClass
in the config object. Note that the class should be passed, not an instance of the class.aspectRatio
defaults to 1 for doughnut, pie, polarArea, and radar chartsTimeScale
does not read t
from object data by default anymore. The default property is x
or y
, depending on the orientation. See data structures for details on how to change the default.tooltips
namespace was renamed to tooltip
to match the plugin namelegend
, title
and tooltip
namespaces were moved from options
to options.plugins
.tooltips.custom
was renamed to plugins.tooltip.external
global
namespace was removed from defaults
. So Chart.defaults.global
is now Chart.defaults
overrides
. For example Chart.defaults.line
is now Chart.overrides.line
default
prefix was removed from defaults. For example Chart.defaults.global.defaultColor
is now Chart.defaults.color
defaultColor
was split to color
, borderColor
and backgroundColor
defaultFontColor
was renamed to color
defaultFontFamily
was renamed to font.family
defaultFontSize
was renamed to font.size
defaultFontStyle
was renamed to font.style
defaultLineHeight
was renamed to font.lineHeight
'index'
to 'nearest'
to match vertical bar chartslegend
, title
and tooltip
namespaces were moved from Chart.defaults
to Chart.defaults.plugins
.elements.line.fill
default changed from true
to false
.interaction
mode. Default is changed from 'index'
to 'nearest'
.The configuration options for scales is the largest change in v3. The xAxes
and yAxes
arrays were removed and axis options are individual scales now keyed by scale ID.
The v2 configuration below is shown with it’s new v3 configuration
options: {
scales: {
xAxes: [{
id: 'x',
type: 'time',
display: true,
title: {
display: true,
text: 'Date'
},
ticks: {
major: {
enabled: true
},
font: function(context) {
if (context.tick && context.tick.major) {
return {
weight: 'bold',
color: '#FF0000'
};
}
}
}
}],
yAxes: [{
id: 'y',
display: true,
title: {
display: true,
text: 'value'
}
}]
}
}
And now, in v3:
options: {
scales: {
x: {
type: 'time',
display: true,
title: {
display: true,
text: 'Date'
},
ticks: {
major: {
enabled: true
},
color: (context) => context.tick && context.tick.major && '#FF0000',
font: function(context) {
if (context.tick && context.tick.major) {
return {
weight: 'bold'
};
}
}
}
},
y: {
display: true,
title: {
display: true,
text: 'value'
}
}
}
}
distribution: 'series'
was removed and a new scale type timeseries
was introduced in its placeautoSkip
is now enabled by default for consistency with the other scalesAnimation system was completely rewritten in Chart.js v3. Each property can now be animated separately. Please see animations docs for details.
custom
attribute of elements was removed. Please use scriptable optionshover
property of scriptable options context
object was renamed to active
to align it with the datalabels plugin.options.hover
and options.plugins.tooltip
now both extend from options.interaction
. Defaults are defined at defaults.interaction
level, so by default hover and tooltip interactions share the same mode etc.interactions
are now limited to the chart area + allowed overflow{mode: 'label'}
was replaced with {mode: 'index'}
{mode: 'single'}
was replaced with {mode: 'nearest', intersect: true}
modes['X-axis']
was replaced with {mode: 'index', intersect: false}
options.onClick
is now limited to the chart areaoptions.onClick
and options.onHover
now receive the chart
instance as a 3rd argumentoptions.onHover
now receives a wrapped event
as the first parameter. The previous first parameter value is accessible via event.native
.options.hover.onHover
was removed, use options.onHover
.options.gridLines
was renamed to options.grid
options.gridLines.offsetGridLines
was renamed to options.grid.offset
.options.gridLines.tickMarkLength
was renamed to options.grid.tickLength
.options.ticks.fixedStepSize
is no longer used. Use options.ticks.stepSize
.options.ticks.major
and options.ticks.minor
were replaced with scriptable options for tick fonts.Chart.Ticks.formatters.linear
was renamed to Chart.Ticks.formatters.numeric
.options.ticks.backdropPaddingX
and options.ticks.backdropPaddingY
were replaced with options.ticks.backdropPadding
in the radial linear scale.xLabel
and yLabel
were removed. Please use label
and formattedValue
filter
option will now be passed additional parameters when called and should have the method signature function(tooltipItem, index, tooltipItems, data)
custom
callback now takes a context object that has tooltip
and chart
propertiesoptions
property.data
parameter. The tooltip item parameter contains the chart and dataset insteadindex
parameter was renamed to dataIndex
and value
was renamed to formattedValue
xPadding
and yPadding
options were merged into a single padding
objectWhile the end-user migration for Chart.js 3 is fairly straight-forward, the developer migration can be more complicated. Please reach out for help in the #dev Slack channel if tips on migrating would be helpful.
Some of the biggest things that have changed:
Element._model
and Element._view
are no longer used and properties are now set directly on the elements. You will have to use the method getProps
to access these properties inside most methods such as inXRange
/inYRange
and getCenterPoint
. Please take a look at the Chart.js-provided elements for examples.updateElement
to provide the element properties. There are also methods such as getSharedOptions
and includeOptions
that have been added to skip redundant computation. Please take a look at the Chart.js-provided controllers for examples.string
and converts it to a number
where necessary. Previously this was done on the fly as charts were rendered. Now it’s done up front with the ability to skip it for better performance if users provide data in the correct format. If you’re using standard data format like x
/y
you may not need to do anything. If you’re using a custom data format you will have to override some of the parse methods in core.datasetController.js
. An example can be found in chartjs-chart-financial, which uses an {o, h, l, c}
data format.A few changes were made to controllers that are more straight-forward, but will affect all controllers:
global
was removed from the defaults namespace as it was unnecessary and sometimes inconsistentx
instead of xAxes
and y
instead of yAxes
)updateElement
was changed to updateElements
and has a new method signature as described below. This provides performance enhancements such as allowing easier reuse of computations that are common to all elements and reducing the number of function callsThe following properties and methods were removed:
Chart.animationService
Chart.active
Chart.borderWidth
Chart.chart.chart
Chart.Bar
. New charts are created via new Chart
and providing the appropriate type
parameterChart.Bubble
. New charts are created via new Chart
and providing the appropriate type
parameterChart.Chart
Chart.Controller
Chart.Doughnut
. New charts are created via new Chart
and providing the appropriate type
parameterChart.innerRadius
now lives on doughnut, pie, and polarArea controllersChart.lastActive
Chart.Legend
was moved to Chart.plugins.legend._element
and made privateChart.Line
. New charts are created via new Chart
and providing the appropriate type
parameterChart.LinearScaleBase
now must be imported and cannot be accessed off the Chart
objectChart.offsetX
Chart.offsetY
Chart.outerRadius
now lives on doughnut, pie, and polarArea controllersChart.plugins
was replaced with Chart.registry
. Plugin defaults are now in Chart.defaults.plugins[id]
.Chart.plugins.register
was replaced by Chart.register
.Chart.PolarArea
. New charts are created via new Chart
and providing the appropriate type
parameterChart.prototype.generateLegend
Chart.platform
. It only contained disableCSSInjection
. CSS is never injected in v3.Chart.PluginBase
Chart.Radar
. New charts are created via new Chart
and providing the appropriate type
parameterChart.radiusLength
Chart.scaleService
was replaced with Chart.registry
. Scale defaults are now in Chart.defaults.scales[type]
.Chart.Scatter
. New charts are created via new Chart
and providing the appropriate type
parameterChart.types
Chart.Title
was moved to Chart.plugins.title._element
and made privateChart.Tooltip
is now provided by the tooltip plugin. The positioners can be accessed from tooltipPlugin.positioners
ILayoutItem.minSize
BarController.getDatasetMeta().bar
DatasetController.addElementAndReset
DatasetController.createMetaData
DatasetController.createMetaDataset
DoughnutController.getRingIndex
Element.getArea
Element.height
Element.hidden
was replaced by chart level status, usable with getDataVisibility(index)
/ toggleDataVisibility(index)
Element.initialize
Element.inLabelRange
Line.calculatePointY
helpers.addEvent
helpers.aliasPixel
helpers.arrayEquals
helpers.configMerge
helpers.findIndex
helpers.findNextWhere
helpers.findPreviousWhere
helpers.extend
. Use Object.assign
insteadhelpers.getValueAtIndexOrDefault
. Use helpers.resolve
instead.helpers.indexOf
helpers.lineTo
helpers.longestText
was made privatehelpers.max
helpers.measureText
was made privatehelpers.min
helpers.nextItem
helpers.niceNum
helpers.numberOfLabelLines
helpers.previousItem
helpers.removeEvent
helpers.roundedRect
helpers.scaleMerge
helpers.where
Layout.defaults
LinearScaleBase.handleDirectionalChanges
LogarithmicScale.minNotZero
Scale.getRightValue
Scale.longestLabelWidth
Scale.longestTextCache
is now privateScale.margins
is now privateScale.mergeTicksOptions
Scale.ticksAsNumbers
Scale.tickValues
is now privateTimeScale.getLabelCapacity
is now privateTimeScale.tickFormatFunction
is now privateIPlugin.afterScaleUpdate
. Use afterLayout
insteadLegend.margins
is now privateonClick
, onHover
, and onLeave
options now receive the legend as the 3rd argument in addition to implicitly via this
onClick
, onHover
, and onLeave
options now receive a wrapped event
as the first parameter. The previous first parameter value is accessible via event.native
.Title.margins
is now privatex
and y
attributes were replaced by element
. You can use element.x
and element.y
or element.tooltipPosition()
instead.The following public APIs were removed.
getElementAtEvent
is replaced with chart.getElementsAtEventForMode(e, 'nearest', { intersect: true }, false)
getElementsAtEvent
is replaced with chart.getElementsAtEventForMode(e, 'index', { intersect: true }, false)
getElementsAtXAxis
is replaced with chart.getElementsAtEventForMode(e, 'index', { intersect: false }, false)
getDatasetAtEvent
is replaced with chart.getElementsAtEventForMode(e, 'dataset', { intersect: true }, false)
The following private APIs were removed.
Chart._bufferedRender
Chart._updating
Chart.data.datasets[datasetIndex]._meta
DatasetController._getIndexScaleId
DatasetController._getIndexScale
DatasetController._getValueScaleId
DatasetController._getValueScale
Element._ctx
Element._model
Element._view
LogarithmicScale._valueOffset
TimeScale.getPixelForOffset
TimeScale.getLabelWidth
Tooltip._lastActive
The following properties were renamed during v3 development:
Chart.Animation.animationObject
was renamed to Chart.Animation
Chart.Animation.chartInstance
was renamed to Chart.Animation.chart
Chart.canvasHelpers
was merged with Chart.helpers
Chart.elements.Arc
was renamed to Chart.elements.ArcElement
Chart.elements.Line
was renamed to Chart.elements.LineElement
Chart.elements.Point
was renamed to Chart.elements.PointElement
Chart.elements.Rectangle
was renamed to Chart.elements.BarElement
Chart.layoutService
was renamed to Chart.layouts
Chart.pluginService
was renamed to Chart.plugins
helpers.callCallback
was renamed to helpers.callback
helpers.drawRoundedRectangle
was renamed to helpers.roundedRect
helpers.getValueOrDefault
was renamed to helpers.valueOrDefault
LayoutItem.fullWidth
was renamed to LayoutItem.fullSize
Point.controlPointPreviousX
was renamed to Point.cp1x
Point.controlPointPreviousY
was renamed to Point.cp1y
Point.controlPointNextX
was renamed to Point.cp2x
Point.controlPointNextY
was renamed to Point.cp2y
Scale.calculateTickRotation
was renamed to Scale.calculateLabelRotation
Tooltip.options.legendColorBackgroupd
was renamed to Tooltip.options.multiKeyBackground
The private APIs listed below were renamed:
BarController.calculateBarIndexPixels
was renamed to BarController._calculateBarIndexPixels
BarController.calculateBarValuePixels
was renamed to BarController._calculateBarValuePixels
BarController.getStackCount
was renamed to BarController._getStackCount
BarController.getStackIndex
was renamed to BarController._getStackIndex
BarController.getRuler
was renamed to BarController._getRuler
Chart.destroyDatasetMeta
was renamed to Chart._destroyDatasetMeta
Chart.drawDataset
was renamed to Chart._drawDataset
Chart.drawDatasets
was renamed to Chart._drawDatasets
Chart.eventHandler
was renamed to Chart._eventHandler
Chart.handleEvent
was renamed to Chart._handleEvent
Chart.initialize
was renamed to Chart._initialize
Chart.resetElements
was renamed to Chart._resetElements
Chart.unbindEvents
was renamed to Chart._unbindEvents
Chart.updateDataset
was renamed to Chart._updateDataset
Chart.updateDatasets
was renamed to Chart._updateDatasets
Chart.updateLayout
was renamed to Chart._updateLayout
DatasetController.destroy
was renamed to DatasetController._destroy
DatasetController.insertElements
was renamed to DatasetController._insertElements
DatasetController.onDataPop
was renamed to DatasetController._onDataPop
DatasetController.onDataPush
was renamed to DatasetController._onDataPush
DatasetController.onDataShift
was renamed to DatasetController._onDataShift
DatasetController.onDataSplice
was renamed to DatasetController._onDataSplice
DatasetController.onDataUnshift
was renamed to DatasetController._onDataUnshift
DatasetController.removeElements
was renamed to DatasetController._removeElements
DatasetController.resyncElements
was renamed to DatasetController._resyncElements
LayoutItem.isFullWidth
was renamed to LayoutItem.isFullSize
RadialLinearScale.setReductions
was renamed to RadialLinearScale._setReductions
RadialLinearScale.pointLabels
was renamed to RadialLinearScale._pointLabels
Scale.handleMargins
was renamed to Scale._handleMargins
The APIs listed in this section have changed in signature or behaviour from version 2.
Scale.getLabelForIndex
was replaced by scale.getLabelForValue
Scale.getPixelForValue
now only requires one parameter. For the TimeScale
that parameter must be millis since the epoch. As a performance optimization, it may take an optional second parameter, giving the index of the data point.Scale.afterBuildTicks
now has no parameters like the other callbacksScale.buildTicks
is now expected to return tick objectsScale.convertTicksToLabels
was renamed to generateTickLabels
. It is now expected to set the label property on the ticks given as inputScale.ticks
now contains objects instead of stringsautoSkip
option is enabled, Scale.ticks
now contains only the non-skipped ticks instead of all ticks.getValueForPixel
now returns milliseconds since the epochupdateHoverStyle
is now an array of objects containing the element
, datasetIndex
, and index
resize
changed, the first silent
parameter was removed.updateElement
was replaced with updateElements
now taking the elements to update, the start
index, count
, and mode
setHoverStyle
and removeHoverStyle
now additionally take the datasetIndex
and index
element
, datasetIndex
, and index
ILayoutItem.update
no longer has a return valueAll helpers are now exposed in a flat hierarchy, e.g., Chart.helpers.canvas.clipArea
-> Chart.helpers.clipArea
drawPoint
is now the full options object, so style
, rotation
, and radius
are no longer passed explicitlyhelpers.getMaximumHeight
was replaced by helpers.dom.getMaximumSize
helpers.getMaximumWidth
was replaced by helpers.dom.getMaximumSize
helpers.clear
was renamed to helpers.clearCanvas
and now takes canvas
and optionally ctx
as parameter(s).helpers.retinaScale
accepts optional third parameter forceStyle
, which forces overriding current canvas style. forceRatio
no longer falls back to window.devicePixelRatio
, instead it defaults to 1
.Chart.platform
is no longer the platform object used by charts. Every chart instance now has a separate platform instance.Chart.platforms
is an object that contains two usable platform classes, BasicPlatform
and DomPlatform
. It also contains BasePlatform
, a class that all platforms must extend from.OffscreenCanvas
, the BasicPlatform
is automatically used.isAttached
method was added to platform.chart
, args
and options
. This means change in signature for these hooks: beforeInit
, afterInit
, reset
, beforeLayout
, afterLayout
, beforeRender
, afterRender
, beforeDraw
, afterDraw
, beforeDatasetsDraw
, afterDatasetsDraw
, beforeEvent
, afterEvent
, resize
, destroy
.afterDatasetsUpdate
, afterUpdate
, beforeDatasetsUpdate
, and beforeUpdate
now receive args
object as second argument. options
argument is always the last and thus was moved from 2nd to 3rd place.afterEvent
and beforeEvent
now receive a wrapped event
as the event
property of the second argument. The native event is available via args.event.native
.resize
is no longer silent. Meaning that resize
event can fire between beforeInit
and afterInit
install
, start
, stop
, and uninstall
afterEvent
should notify about changes that need a render by setting args.changed
to true. Because the args
are shared with all plugins, it should only be set to true and not false.


The Web is a collection of HTML documents that includes hyperlinks, or links for short. One can view HTML documents using a browser such as Firefox, Chrome, or my new preference Safari. Browsers connect to the internet to acquire files that are hosted on computers known as servers. All of this is done by using HTTP; a protocol that allows for the communication between a browser and server.
HTML is straight forward and requires that I know how to use tags to format a webpage, is there software that allows for easier editing of HTML code? I mean an editor that allows me to easily search for tags from a menu. Will I learn how to make a web page more dynamic with animations and moving objects? Is there a standard of how I format a web page so that it is visually pleasing? I don't know if what I created does the job with organization and structure? Well those are the questions and comments that I have. Thanks for commenting on this.


This example demonstrates revealing an image using another image as the mask. The mask is created by drawing a shape, and then caching the shape to make an image with an alpha channel. It is then applied to the image as an mask using the AlphaMaskFilter filter. Another copy of the image is added below with a BlurFilter to make the effect cooler.


keyword search with faceting
Remarks: currently only searching in rdfs:label|skos:prefLabel. facetting by type
rdfs:label|skos:prefLabel


@inputText(organistionForm("field_abbreviation"),
'_label -> "Abbreviation (An abbreviation for this organisation (no more that 8 characters). e.g. 'BL', 'NLS', 'NLW' etc)",
'id -> "inputAbbreviation",
'class -> "form-control"
)(FieldConstructor(genericInput.f), lang)


CREATE A QUOTE
Author
Name is required
Publisher
Name is required
Quote
the Quote is required
Date
Date is required
POST QUOTE


* 159 CVs in GCs
* 8 % DN if GC CVs
* 1800 CVs total
* 40 % dwarf nova
* Spectra Only 8 in 4 GCs M5, NGC 6624, 47 Tuc
* period Only 16 in 7 GCs
*
Binaries in NGC 6397
Known X-ray sources
- Cataclysmic Variables
- 15 CV Candidates
- Two Bimodal Population:
- Bright and Faint (Cohn et al. 2011)
- Millisecond Pulsars (MSPs):
- One radio confirmed and one candidate
- Neutron Stars:
- One qLMXB and possibly ultracompact
Characterize and find new binaries
Detected CVs
Compact Binaries in NGC 6397
Spectral Analysis
Work in progress
- CVs:
- Mass ratio:
- From the H$\alpha$ double peaked emission (Casares 2016)
- Magnetism:
- No He II. Strongest He II outside range (4686 Å)
- qLMXB:
- Place limit on the H$\alpha$ flux
- MSPs:
- Nature of accretion(?) from H$\alpha$ line (narrow vs broad)
Future Work
- Follow up Observations
- MUSE Adaptive Optics and extended range
- Deeper observation for qLMXB
- Variability:
- Lot of Hubble data in Optical and UV
- Datacube:
- Systematically search for emission:
- Helium emitters (AM CVn ?)
- Planetary Nebula
- Active Binaries
Conclusion
An IFU like MUSE can be used to efficiently study the population of compact objects in globular clusters. Deeper observation are needed but a single exposure allowed us to recover the optical spectra of various known X-ray sources.
Gracias
|
Department of Physics and Astronomy |


About Luke
Luke is a strange nocturnal creature, best observed at dusk scurrying towards an unguarded buffet. He is rarely seen in the light of day, unless of course he is getting paid.
Luke is a strange nocturnal creature, best observed at dusk scurrying towards an unguarded buffet. He is rarely seen in the light of day, unless of course he is getting paid.
Ranked the 6th best coding bootcamp in the world, iOAcademy teaches everything you need to know to become a full-stack python developer in just 16 weeks.
To test our HTML and CSS skills, we were tasked with creating a portfolio site that had at least an about, project, and contact sections. The result is what you see before you ^_^
PLACE HOLDER
PLACE HOLDER
PLACE HOLDER


WITNESS LIST Redistricting Committee April 26, 2001-2:00P HB 150 Committee Substitute (Jones) For: Hinojosa, Walter (Texas AFL-CIO) Against: Perales, Nina (Mexican American Legal Defense and Educational Fund, Inc.) On: Almager, David (Mexican American Legal Defense and Educational Fund, Inc.) Archer, Jeffrey S. (Texas Legislative Council) Engstrom, Richard (Self) Gray, Rick (Self)


Today:
Application for CPB travel funds. DONE
Faxed receipts from Felsenstein’s visit. DONE
Seminar on Species trees
Coop/Moore Seminar on *BEAST (Heled & Drummond, 2009) and BEST (Liu et. al. 2008).
Essential differences: BEST uses Mr. Bayes to compute probabilities over gene trees (over uniform prior). Then estimates the species tree by importance sampling from this distribution to reflect constraints under a convergence model. Integrates over effective population sizes rather than estimating (highly uncertain anyway), requires rooting, and a rather fast/loose implementation of ultra-metricizing trees. In text notes in Mendeley Phylogenetics section.
*BEAST offers a hierarchical approach (simultaneously estimating gene trees and species trees), estimates effective population sizes (with linear rate variation across phylogeny/through time). Integrates over possible out groups. Suffers midpoint rooting problems do to rate heterogeneity (whenever two comparably sized clades split by substantial variation in substitution rates, will root between them). Priors to get species tree prior 1) includes birth-death model for tree ->Prior on waiting times of speciation 2) Prior on coalescence times 3) Prior on topologies (uniform over unlabeled histories) Prior on gene trees, all as in BEAST/etc, also reflects the species trees
Warning Signals in an Economic Context
Meeting with Jim and Alan 2:30-4p: (notes to be transcribed)
Misc
- Algorithms group:
Solved our little puzzle about Bayes factors, corrected the notes. Decided we’ll actually meet sometime Wednesday to do MCMC.
Presentation for Wainwright lab tomorrow
Looking at DataONE APIs. Investigator API looks a bit sparse, but more on member node API.
Hmm..Software Infrastructure for Sustained Innovation sounds interesting.
CPB travel funding application
Application requires a list of outreach activities. Assembling here for my records.
I attend CPB Tuesday seminars regularly. I participated in Fall Monte Carlo with Bruce Rannala on phylogenetic methods, and then voluntarily joined the Winter Monte Carlo with Sharon Strauss on broader impacts and public outreach, as it is a topic I am both interested and involved in.
I helped design and organize the CPB workshop on Hierarchical modeling this January.
I gave an presentation to the first year pop bio students during their orientation (entitled “What I wish I knew three years earlier…”) on computer based research tools for organizing literature, setting up an academic website, and for networking in sciences.
I independentlyorganized a CPB workshop on Data Management, to discuss the implications and opportunities created by new data archiving requirements from NSF and many of our journals. I recruited participation from four editors-in-chief of journals in ecology and evolution, and also the director and assistant director of the California Digital archives to discuss the issues. I arranged that the event would be video-recorded for those that could not attend, which have been viewed 124 times last month.
Throughout this year I have I co-chaired an interdisciplinary group called the Graduate Teaching Community which has been popular among CPB students and other graduate programs as a space to explore and share experiences, methodology, and read literature on studies in effective education strategies.
I also help organize a student group on Open Science, which tries to promote awareness and potential of open access publishing, public data archiving, reproducible research, and tools and opportunities to make large-scale collaborative science possible.
I volunteered as an instructor in the UC Davis Bodega Phylogenetics Workshop.
I served as the student member on the steering committee for the CPB program review.
I served on the student panel interviewing all of the candidates for the Dean of the College of Biological Sciences, and met with the Department of Ecology and Evolution Committee to discuss its recommendation.
References
Heled J and Drummond A (2009). “Bayesian Inference of Species Trees From Multilocus Data.” Molecular Biology And Evolution, 27. ISSN 0737-4038, https://dx.doi.org/10.1093/molbev/msp274.
Liu L, Pearl D, Brumfield R and Edwards S (2008). “Estimating Species Trees Using Multiple-Allele Dna Sequence Data.” Evolution, 62. ISSN 00143820, https://dx.doi.org/10.1111/j.1558-5646.2008.00414.x.


--- title: About class: compressed ---
Braneshop is focused on improving the AI ecosystem, and making it a more inclusive and representative space. Our aim is to support people with their own goals and dreams within AI.
We want to see a world in which AI is used to create positive and inclusive social change.
Below are some videos from our recent events/workshops.
$for(videos)$ $if(vimeo)$Watch on Vimeo - $title$ - $date$
Watch on YouTube - $title$ - $date$


Guard Stan:
Impressive! It takes a whole heap of dedication and practice to be 100% wrong! Go on... try again.
What's the color of the first coin?
"Gold."
"Silver."
"Blood red."


My Team
Steve Rogers
Manager
ID:
1
Email:
<EMAIL_ADDRESS>Office number:
1
Tony Stark
Engineer
ID:
2
Email:
<EMAIL_ADDRESS>GitHub:
ironman
Steven Strange
Engineer
ID:
3
Email:
<EMAIL_ADDRESS>GitHub:
docstrange
Bruce Banner
Engineer
ID:
4
Email:
<EMAIL_ADDRESS>GitHub:
thehulk
Thor Odison
Engineer
ID:
5
Email:
<EMAIL_ADDRESS>GitHub:
thor
Peter Parker
Intern
ID:
6
Email:
<EMAIL_ADDRESS>School:
The Midweek School
Pepper Potts
Intern
ID:
7
Email:
<EMAIL_ADDRESS>School:
Iron Man university


Chapter 2 Absoprtion and Reward
Caveat: From now on, all Markov chains will have finite state spaces.
2.1 Absorption
Remember the “Tennis” example from a few lectures ago and the question we asked there, namely, how does the probability of winning a single point affect the probability of winning the overall game? An algorithm that will help you answer that question will be described in this lecture.
The first step is to understand the structure of the question asked in the light of the canonical decomposition of the previous lecture. In the “Tennis” example, all the states except for the winning ones are transient, and there are two one-element recurrent classes {“Player 1 wins”} and {“Player 2 wins”} The chain starts from a transient state \((0,0)\), moves around a bit, and, eventually, gets absorbed in one of the two. The probability we are interested in is not the probability that the chain will eventually get absorbed. That probability is always \(1\). We are, instead, interested in the probability that the absorption will occur in a particular state - the state “Player 1 wins” (as opposed to “Player 2 wins”) in the “Tennis” example.
A more general version of the problem above is the following: let \(i\in S\) be any state, and let \(j\) be a recurrent state. If the set of all recurrent states is denoted by \(C\), and if \(\tau_{C}\) is the first hitting time of the set \(C\), then \(X_{\tau_{C}}\) denotes the first recurrent state visited by the chain. Equivalently, \(X_{\tau_{C}}\) is the value of \(X\) at (random) time \(\tau_{C}\); its value is the name of the state in which it happens to find itself the first time it hits the set of all recurrent states. For any two states \(i,j\in S\), the \(u_{ij}\) is defined as \[u_{ij}={\mathbb{P}}_i[ X_{\tau_C}=j]={\mathbb{P}}_i[\text{ the first recurrent state visited by $X$ is $j$ }].\] There are several boring situations to discard first:
\(j\) is transient: in this case \(u_{ij}=0\) for any \(i\) because \(j\) cannot possibly be the first recurrent state we hit - it is not even recurrent.
\(j\) is recurrent, and so is \(i\). Since \(i\) is recurrent, i.e., \(i\in C\), we clearly have \(\tau_C=0\). Therefore \(u_{ij} = {\mathbb{P}}_i[ X_0= j]\), and this equals to either \(1\) or \(0\), depending on whether \(i=j\) or \(i\ne j\).
That leaves us with the situation where \(i \in T\) and \(j\in C\) as the interesting one. In many calculations related to Markov chains, the method of first-step decomposition works miracles. Simply, we cut the probability space according to what happened in the first step and use the law of total probability (assuming \(i\in T\), \(j\in C\)) \[\label{equ:system-for-u} \nonumber \begin{split} u_{ij} & ={\mathbb{P}}_i[ X_{\tau_C}=j]=\sum_{k\in S} {\mathbb{P}}[X_{\tau_C}=j|X_0=i, X_1=k] {\mathbb{P}}[ X_1=k|X_0=i]\\ &= \sum_{k\in S} {\mathbb{P}}[X_{\tau_C}=j|X_1=k]p_{ik} \end{split}\] The conditional probability \({\mathbb{P}}[X_{\tau_C}=j|X_1=k]\) is an absorption probability, too. If \(k=j\), then \({\mathbb{P}}[X_{\tau_C}=j|X_1=k]=1\). If \(k\in C\setminus\{j\}\), then we are already in C, but in a state different from \(j\), so \({\mathbb{P}}[ X_{\tau_C}=j|X_1=k]=0\). Therefore, the sum above can be written as \[\label{equ:syst} \begin{split} u_{ij}= \sum_{k\in T} p_{ik} u_{kj} + p_{ij}, \end{split}\] which is a system of linear equations for the family \(( u_{ij}, i\in T, j\in C)\). Linear systems are typically better understood when represented in the matrix form. Let \(U\) be a \(T\times C\)-matrix \(U=(u_{ij}, i\in T, j\in C)\), and let \(Q\) be the portion of the transition matrix \(P\) corresponding to the transitions from \(T\) to \(T\), i.e. \(Q=(p_{ij},i\in T, j\in T)\), and let \(R\) contain all transitions from \(T\) to \(C\), i.e., \(R=(p_{ij})_{i\in T, j\in C}\). If \(P_C\) denotes the matrix of all transitions from \(C\) to \(C\), i.e., \(P_C=(p_{ij}, i\in C, j\in C)\), then the canonical form of \(P\) looks like this: \[P= \begin{bmatrix} P_C & 0 \\ R & Q \end{bmatrix}.\] The system now becomes: \[U= QU+R,\text{ i.e.,  If the matrix \(I-Q\) happens to be invertible, we are in business, because we then have an explicit expression for \(U\): \[U= (I-Q)^{-1} R.\] So, is \(I-Q\) invertible? It is when the state space \(S\) is finite; here is the argument, in case you are interested:
Theorem. When the state space \(S\) is finite, the matrix \(I-Q\) is invertible and \[ \begin{split} (I-Q)^{-1} = \sum_{n=0}^{\infty} Q^n. \end{split}\] Moreover, the entry at the position \(i,j\) in \((I-Q)^{-1}\) is the expected total number of visits to the state \(j\), for a chain started at \(i\).
Proof. For \(k\in{\mathbb{N}}\), the matrix \(Q^k\) is the same as the submatrix corresponding to the transient states of the full \(k\)-step transition matrix \(P^k\). Indeed, going from a transient state to another transient state in \(k\) steps can only happen via other transient states (once we hit a recurrent class, we are stuck there forever).
Using the same idea as in the proof of Proposition \[pro:geom-markov\] from the set of notes on classification of states, we can conclude that for any two transient states \(i\) and \(j\), we have (remember \({\mathbb{E}}_i[ \mathbf{1}_{\{X_n = j\}}] = {\mathbb{P}}_i[X_n = j] = p_{ij}^{(n)}\)) \[{\mathbb{E}}_i[ \sum_{n=0}^{\infty} \mathbf{1}_{\{X_n = j\}}] = \sum_{n\in\Nz} p^{(n)}_{ij} = \sum_{n\in\Nz} q^{(n)}_{ij} = (\sum_{n\in{\mathbb{N}}_0} Q^n)_{ij}.\] On the other hand, the left hand side above is simply the expected number of visits to the state \(j\), if we start from \(i\). Since both \(i\) and \(j\) are transient, this number will either be \(0\) (if the chain never even reaches \(j\) from \(i\)), or a geometric random variable (if it does). In either case, the expected value of this quantity is finite, and, so \[\sum_{n\in{\mathbb{N}}_0} q^{(n)}_{ij}<\infty.\] Therefore, the matrix sum \(F = \sum_{n\in{\mathbb{N}}_0} Q^n\) is well defined, and it remains to make sure that \(F = (I-Q)^{-1}\), which follows from the following simple computation: \[QF = Q \sum_{n\in{\mathbb{N}}_0} Q^n = \sum_{n\in{\mathbb{N}}_0} Q^{n+1} = \sum_{n\in{\mathbb{N}}} Q^n = \sum_{n\in{\mathbb{N}}_0} Q^n - I = F - I. \text{ Q.E.D.}\]
When the inverse \((I-Q)^{-1}\) exists (like in the finite case), it is called the fundamental matrix of the Markov chain.
Before we turn to the “Tennis” example, let us analyze a simpler case of Gambler’s ruin with \(a=3\).
What is the probability that a gambler coming in at \(x=\$1\) in a Gambler’s ruin problem with \(a=3\) succeeds in “getting rich”? We do not assume that \(p=\tfrac{1}{2}\).
The states \(0\) and \(3\) are absorbing, and all the others are transient. Therefore \(C_1=\{0\}\), \(C_2=\{3\}\) and \(T=T_1=\{1,2\}\). The transition matrix \(P\) in the canonical form (the rows and columns represent the states in the order \(0,3,1,2\)) \[P= \begin{bmatrix} 1 & 0 & 0 & 0\\ 0 & 1 & 0 & 0\\ 1-p & 0 & 0 & p\\ 0 & p & 1-p & 0 \end{bmatrix}\] Therefore, \[R= \begin{bmatrix} 1-p & 0 \\ 0 & p \end{bmatrix} \text{ and } Q= \begin{bmatrix} 0 & p \\ 1-p & 0 \end{bmatrix}.\] The matrix \(I-Q\) is a \(2\times 2\) matrix so it is easy to invert: \[(I-Q)^{-1}= \frac{1}{1-p+p^2}\begin{bmatrix} 1 & p \\ 1-p & 1 \end{bmatrix}.\] So \[U= \frac{1}{1-p+p^2}\begin{bmatrix} 1 & p \\ 1-p & 1 \end{bmatrix} \begin{bmatrix} 1-p & 0 \\ 0 & p \end{bmatrix} = \begin{bmatrix} \frac{1-p}{1-p+p^2} & \frac{p^2}{1-p+p^2} \\ \frac{(1-p)^2}{1-p+p^2} & \frac{p}{1-p+p^2} \\ \end{bmatrix}.\] Therefore, for the initial “wealth” is 1, the probability of getting rich before bankruptcy is \(u_{13}=p^2/(1-p+p^2)\) (the entry in the first row (\(x=1\)) and the second column (\(a=3\)) of \(U\).)
Find the probability of winning a whole game of Tennis, for a player whose probability of winning a single rally is \(p=0.45\).
In the “Tennis” example, the transition matrix is \(20\times 20\), with only 2 recurrent states (each in its own class). In order to find the matrix \(U\), we (essentially) need to invert an \(18\times 18\) matrix and that is a job for a computer. We start with an R function which produces the transition matrix \(P\) as a function of the single-rally probability \(p\). Even though we only care about \(p=0.45\) here, the extra flexibility will come in handy soon:
c("0-0", "0-15", "15-0", "0-30", "15-15", "30-0", "0-40", "15-30",
S="30-15", "40-0", "15-40", "30-30", "40-15", "40-30", "30-40",
"40-40", "40-A", "A-40", "P1", "P2")
function(p) {
tennis_P =matrix(c(
0,1-p,p,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,1-p,p,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,1-p,p,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,1-p,p,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,1-p,p,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,1-p,p,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,p,0,0,0,0,0,0,0,0,1-p,
0,0,0,0,0,0,0,0,0,0,1-p,p,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,1-p,p,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,1-p,0,0,0,0,0,p,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,p,0,0,0,0,1-p,
0,0,0,0,0,0,0,0,0,0,0,0,0,p,1-p,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,1-p,0,0,0,0,p,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1-p,0,0,p,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,p,0,0,0,1-p,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1-p,p,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,p,0,0,0,1-p,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1-p,0,0,p,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1),
byrow=T, ncol = 20 )
}
The positions of the initial state “0-0” in the state-space vector
S
is \(1\), and the
positions of the two absorbing states “P1” and “P2” are \(19\) and \(20\).
Therefore the matrices \(Q\) and \(R\) are obtained by vector indexing as follows:
tennis_P(0.45)
P = P[1:18, 1:18]
Q = P[1:18, 19:20] R =
Linear systems are solved by using the command solve
in R:
diag(18) # the identity matrix the same size as Q
I = solve(I - Q, R)
U =1, ]
U[## [1] 0.3768515 0.6231485
Therefore, the probability that Player 1 wins the entire rally is about \(0.377\). Note
that this number is smaller than \(0.45\), so it appears that the game is
designed to make it easier for the better player to win. For more evidence,
let’s draw the graph of this probability for several values of \(p\)
(sapply
is the version of apply
for vectors):
function(p) {
prob_win =if (p %in% c(0, 1))
return(p)
tennis_P(p)
P = P[1:18, 1:18]
Q = P[1:18, 19:20]
R = solve(diag(18) - Q, R)
U =1, 1]
U[
} seq(0, 1, by = 0.01)
ps = sapply(ps, prob_win) prob_game =
A graph of p
vs. prob_game
, where the dashed line is the line \(y=x\) looks like this:
Using a symbolic software package (like Mathematica) we can even get an explicit expression for the win probability in this case: \[\begin{align} u_{(0,0)\ \ "P1\ wins"} = p^4 + 4 p^4 q + 10 p^4 q^2 + \frac{20 p^5 q^3}{1-2pq}. \end{align}\] Actually, you don’t really need computers to derive the expression above. Can you do it by finding all the ways in which the game can be won in \(n=4,5,6,8, 10, 12, \dots\) rallies, computing their probabilities, and then adding them all up?
2.2 Expected reward
Suppose that each time you visit a transient state \(j\in T\) you receive a reward \(g(j)\in{\mathbb{R}}\). The name “reward” is a bit misleading since the negative \(g(j)\) corresponds more to a fine than to a reward; it is just a name, anyway. Can we compute the expected total reward before absorption \[v_i={\mathbb{E}}_i[ \sum_{n=0}^{\tau_{C}-1} g(X_n)] ?\] And if we can, what is it good for? Many things, actually, as the following two special cases show:
If \(g(j)=1\) for all \(j\in T\), then \(v_i\) is the expected time until absorption. We will calculate \(v_{(0,0)}\) for the “Tennis” example to compute the expected duration of a tennis game.
If \(g(k)=1\) and \(g(j)=0\) for \(j\not =k\), then \(v_i\) is the expected number of visits to the state \(k\) before absorption. In the “Tennis” example, if \(k=(40,40)\), the value of \(v_{(0,0)}\) is the expected number of times the score \((40,40)\) is seen in a tennis game.
We compute \(v_i\) using the first-step decomposition: \[\label{equ:} % \nonumber \begin{split} v_i &={\mathbb{E}}_i[ \sum_{n=0}^{\tau_C - 1} g(X_n)] = g(i)+ {\mathbb{E}}_i[ \sum_{n=1}^{\tau_C - 1} g(X_n)]\\ &= g(i)+ \sum_{k\in S} {\mathbb{E}}_i[ \sum_{n=1}^{\tau_C - 1} g(X_n)|X_1=k] {\mathbb{P}}_i[X_1=k]\\ & = g(i)+ \sum_{k\in S} p_{ik}{\mathbb{E}}_i[ \sum_{n=1}^{\tau_C - 1} g(X_n)|X_1=k] \end{split}\] If \(k\in T\), then the Markov property implies that \[{\mathbb{E}}_i[ \sum_{n=1}^{\tau_C - 1} g(X_n)|X_1=k]={\mathbb{E}}_k[ \sum_{n=0}^{\tau_C - 1} g(X_n)]=v_k.\] When \(k\not\in T\), then \[{\mathbb{E}}_i[ \sum_{n=1}^{\tau_C - 1} g(X_n)|X_1=k]=0,\] because we have “arrived” and no more rewards are going to be collected. Therefore, for \(i\in T\) we have \[v_i=g(i)+\sum_{k\in T} p_{ik} v_k.\] If we organize all \(v_i\) and all \(g(i)\) into column vectors \(v=(v_i, i\in T)\), \(g=(g(i), i\in T)\), we get \[v=Qv+g, \text{ i.e., } v=(I-Q)^{-1} g = Fg.\]
Having derived the general formula for various rewards, we can provide another angle to the interpretation of the fundamental matrix \(F\). Let us pick a transient state \(j\) and use the reward function \(g\) given by \[g(k)=\mathbf{1}_{\{k=j\}}= \begin{cases} 1, & k=j \\ 0,& k\not= j. \end{cases}\] By the discussion above, the \(i^{th}\) entry in \(v=(I-Q)^{-1} g\) is the expected reward when we start from the state \(i\). Given the form of the reward function, \(v_i\) is the expected number of visits to the state \(j\) when we start from \(i\). On the other hand, as the product of the matrix \(F=(I-Q)^{-1}\) and the vector \(g=(0,0,\dots, 1, \dots, 0)\), \(v_i\) is nothing but the \((i,j)\)-entry in \(F=(I-Q)^{-1}\).
Let’s illustrate these ideas on some of our example chains:What is the expected duration of a game of tennis? Compute it for several values of the parameter \(p\).
The main idea is to perform a reward computation with \(g(i)=1\) for all transient states \(i\). The R code is very similar to the one in the absorption example:
function(p) {
expected_duration =if (p %in% c(0, 1))
return(4)
tennis_P(p)
P = P[1:18, 1:18]
Q = matrix(1, nrow = 18, ncol = 1)
g = solve(diag(18) - Q, g)
v =1, ]
v[
} seq(0, 1, by = 0.01)
ps = sapply(ps, expected_duration) duration_game =
As above, here is the graph of p
vs. duration_game
:
The maximum of the curve about equals to \(6.75\), and is achieved when the players are evenly matched (\(p=0.5\)). Therefore, a game between fairly equally matched opponents lasts \(6.75\). The game cannot be shorter than \(4\) rallies and that is exactly the expected duration when one player wins with certainty in each rally.
What is the expected number of “deuces”, i.e., scores \((40,40)\)? Compute it for several values of the parameter \(p\).
This can be computed exactly as above, except that now the reward function is given by \[\begin{align} g(i) = \begin{cases} 1, & \text{ if } i = (40,40),\\ 0, & \text{ otherwise.} \end{cases} \end{align}\] Since the code is almost identical to the code from the last example, we skip it here and only draw the graph: As expected, there are no dueces when \(p=0\) or \(p=1\), and the maximal expected number of dueces - \(0.625\) - occurs when \(p=1/2\).
 The reason is that the expectation is a poor summary of for the full distribution of the number of deuces. The best way yo to get a feeling for the entire distribution is to run some simulations. Here is the histogram of \(10000\) simulations of a game of tennis for the most interesting case \(p=0.5\):
We see that most of the games have no deuces. However, in the cases where a deuce does happen, it is quite possible it will be repeated. A sizable number of draws yielded \(4\) of more deuces.
We end with another example from a different area:
Alice plays the following game. She picks a pattern consisting of three letters from the set \(\{H,T\}\), and then tosses a fair coin until her pattern appears for the first time. If she has to pay \(\$1\) for each coin toss, what is the expected cost she is going to incur? What pattern should she choose to minimize that cost?
We start by choosing a pattern, say \(HTH\), and computing the number of coin tosses Alice expects to make before it appears. This is just the kind of computation that can be done using our absorption-and-reward techniques, if we can find a suitable Markov chain. It turns out that the following will do (green arrows stand for probability \(1/2\)):
As Alice tosses the coin, she keeps track of the largest initial portion of her pattern that appears at last several places of the sequence of past tosses. The state \(0\) represents no such portion (as well as the intial state), while \(HT\) means that the last two coin tosses were \(H\) and \(T\) (in that order) so that it is possible to end the game by tossing a \(H\) next. On the other hand, if the last toss was a \(T\), there is no need to keep track of that - it is as good as \(0\).
Once we have this chain, all we have to do is perform the absorption and reward computation with the reward function \(g\equiv 1\). The \(Q\)-matrix of this chain (with the transient states ordered as \(0, H, HT\)) is \[Q = \begin{bmatrix} 1/2 & 1/2 & 0 \\ 0 & 1/2 & 1/2 \\ 1/2 & 0 & 0\\ \end{bmatrix}\] and the fundamental matrix \(F\) turns out to be \[F = \begin{bmatrix} 4 & 4 & 2 \\ 2 & 4 & 2 \\ 2 & 2 & 2 \\ \end{bmatrix} .\] Therefore, the required expectation is the sum of all the elements on the first row, i.e., \(10\).
Let us repeat the same for the pattern \(HHH\). We build a similar Markov chain:
We see that there is a subtle difference. One transition from the state \(H\), instead of going back to itself, is directed towards \(0\). It is clear from here, that this can only increase Alice’s cost. Indeed, the fundamental matrix is now given by \[F = \begin{bmatrix} 8 & 4 & 2 \\ 6 & 4 & 2 \\ 4 & 2 & 2 \\ \end{bmatrix},\] and the expected number of tosses before the first appearance of \(HHH\) comes out as \(14\).
Can you do this for other patterns? Which one should Alice choose to minimize her cost?
2.3 Additional Problems for Chapter 7
Note: do not use simulations in any of the problems below. Using R (or other software) to manipulate matrices or perform other numerical computation is fine.
The fundamental matrix associated to a finite Markov chain is \(F = \begin{bmatrix} 3 & 3 \\ 3/2 & 3\end{bmatrix}\), with the first row (and column) corresponding to the state \(A\) and the second to \(B\). Some of the following statements are true and the others are false. Find which ones are true and which are false; give explanations for your choices.
The chain has \(2\) recurrent states.
If the chain starts in \(A\), the expected number of visits to \(B\) before hitting the first recurrent state is \(3\).
If the chain is equally likely to start from \(A\) or \(B\), the expected number of steps it will take before it hits its first recurrent state is \(\frac{21}{4}\).
\({\mathbb{P}}_A[X_1=C] =0\) for any recurrent state \(C\).
ar-prob-01
In a Markov chain with a finite number of states, the fundamental matrix is given by \[F=\begin{bmatrix} 3 & 4 \\ \tfrac{3}{2} & 4\end{bmatrix}.\] The initial distribution of the chain is uniform on all transient states. Compute the expected value of \[\tau_C=\min \{ n\in{\mathbb{N}}_0\, : \, X_n\in C\},\] where \(C\) denotes the set of all recurrent states.
Using the reward \(g\equiv 1\), the vector \(v\) of expected values of \(\tau_C\), where each entry corresponds to a different transient initial state is \[v= F g= \begin{bmatrix} 3 & 4 \\ \tfrac{3}{2} & 4\end{bmatrix} \begin{bmatrix} 1 \\ 1 \end{bmatrix} = \begin{bmatrix} 7 \\ \tfrac{11}{2} \end{bmatrix}\] The initial distribution puts equal probabilities on the two transient states, so, by the law of total probability, \[{\mathbb{E}}[\tau_C]= \tfrac{1}{2}\times 7 + \tfrac{1}{2}\times \tfrac{11}{2}= \tfrac{25}{4}.\]
Consider “Gambler’s ruin” model with parameter \(p\). Write code that will compute the probability that the gambler will go bankrupt before her wealth reaches \(\$1000\) for each initial wealth \(x = 0,1,\dots, 1000\). Plot the graphs for \(0.4, 0.49, 0.499\) and \(0.5\) on top of each other.
We use R and start by constructing the matrices \(Q\) and \(R\) and the solving the system \((I-Q) U = R\).
function(p) {
win_probability = matrix(0, ncol = 1001, nrow = 1001)
P =1, 1] = 1
P[1001, 1001] = 1
P[for (i in 2:1000) {
- 1] = 1 - p
P[i, i + 1] = p
P[i, i
}
P[2:1000, 2:1000]
Q = P[2:1000, c(1, 1001)]
R =solve(diag(999) - Q, R)[, 2]
}
par(lwd = 2)
plot(win_probability(0.4), ylab = "probability of winning $1000", xlab = "Initial wealth",
type = "l", col = "maroon", ylim = c(0, 1), lwd = 2)
points(win_probability(0.49), type = "l", col = "darkblue", lwd = 2)
points(win_probability(0.499), type = "l", col = "seagreen", lwd = 2)
points(win_probability(0.5), type = "l", col = "black", lwd = 2)
legend(10, 0.9, legend = c("p=0.5", "p=0.499", "p=0.49", "p=0.4"), col = c("black",
"seagreen", "darkblue", "maroon"), lty = 1, lwd = 2)
A basketball player is shooting a series of free throws. The probability of hitting any single one is \(1/2\), and the throws are independent of each other. What is the expected number of throws the player will attempt before hitting 3 free throws in a row (including those 3)?
Let \(X_n\) be the size of the longest winning streak so far. The value of \(X_{n+1}\) then equals \(1+X_n\) with probability \(1/2\) and \(0\) with probability \(1/2\) so that the transition matrix of the Markov chain \(X\), on the state space \(S=\{0,1,2,3\}\) is \[P = \begin{bmatrix} 1/2 & 1/2 & 0 & 0 \\ 1/2 & 0 & 1/2 & 0 \\ 1/2 & 0 & 0 & 1/2 \\ 0 & 0 & 0 & 1\end{bmatrix}\] where we made the state \(3\) absorbing. The required expectation is \(v_0\), where \(v_i\) is the expected number of steps until absorption starting from the state \(i\). The system of equations satisfied by \(v\) is \[\begin{aligned} v_0 &= 1+ 1/2 v_0 + 1/2 v_1 \\ v_1 &= 1+ 1/2 v_0 + 1/2 v_2 \\ v_2 &= 1+ 1/2 v_0 \end{aligned}\] From here, we get \[\begin{align} v_0 &= 1+ 1/2 v_0 + 1/2 v_1 = 1 + 1/2 v_0 + 1/2 (1+1/2 v_0 + 1/2 v_2)\\ &= 1 + 1/2 v_0 + 1/2 ( 1 + 1/2 v_0 + 1/2(1+1/2 v_0)) \\ &= (1+1/2+1/4) + v_0 (1/2+ 1/4+1/8) = \frac{7}{4} + \frac{7}{8} v_0 \end{align}\] so that \(v_0 = 14\).
Let \(\{X_n\}_{n\in {\mathbb{N}}_0}\) be a Markov chain with the following transition matrix \[P= \begin{bmatrix} 1/2 & 1/2 & 0 \\ 1/3 & 1/3 & 1/3 \\ 0 & 0 & 1\\ \end{bmatrix}\] Suppose that the chain starts from the state \(1\).
What is expected time that will pass before the chain first hits \(3\)?
What is the expected number of visits to state \(2\) before \(3\) is hit?
Would your answers to 1. and 2. change if we replaced values in the third row of \(P\) by any other values (as long as \(P\) remains a stochastic matrix)? Would \(1\) and \(2\) still be transient states?
Use the idea of part 3. to answer the following question. What is the expected number of visits to the state \(2\) before a Markov chain with transition matrix \[P= \begin{bmatrix} 17/20 & 1/20 & 1/10\\ 1/15 & 13/15 & 1/15\\ 2/5 & 4/15 & 1/3\\ \end{bmatrix}\] hits the state \(3\) for the first time (the initial state is still \(1\))? Remember this trick for your next exam.
The states 1 and 2 are transient and 3 is recurrent, so the canonical decomposition is \(C=\{3\}\), \(T=\{1,2\}\) and the canonical form of the transition matrix is \[P= \begin{bmatrix} 1 & 0 & 0 \\ 0 & 1/2 & 1/2 \\ 1/3 & 1/3 & 1/3 \end{bmatrix}\] The matrices \(Q\) and \(R\) are given by \[Q= \begin{bmatrix} 1/2 & 1/2 \\ 1/3 & 1/3 \end{bmatrix}, R=\begin{bmatrix} 0 \\ 1/3 \end{bmatrix},\] and the fundamental matrix \(F=(I-Q)^{-1}\) is \[F= \begin{bmatrix} 4 & 3 \\ 2 & 3 \end{bmatrix}.\]
No, all states would be recurrent. The moral of the story that the absorption calculations can be used even in the settings where all states are recurrent. You simply need to adjust the probabilities, as shown in the following part of the problem.
A fair 6-sided die is rolled repeatedly, and for \(n\in{\mathbb{N}}\), the outcome of the \(n\)-th roll is denoted by \(Y_n\) (it is assumed that \(\{Y_n\}_{n\in{\mathbb{N}}}\) are independent of each other). For \(n\in{\mathbb{N}}_0\), let \(X_n\) be the remainder (taken in the set \(\{0,1,2,3,4\}\)) left after the sum \(\sum_{k=1}^n Y_k\) is divided by \(5\), i.e. \(X_0=0\), and \[%\label{} \nonumber \begin{split} X_n= \sum_{k=1}^n Y_k \ (\,\mathrm{mod}\, 5\,),\text{ for } n\in{\mathbb{N}}, \end{split}\] making \(\{X_n\}_{n\in {\mathbb{N}}_0}\) a Markov chain on the state space \(\{0,1,2,3,4\}\) (no need to prove this fact).
Write down the transition matrix of the chain.
Classify the states, separate recurrent from transient ones, and compute the period of each state.
Compute the expected number of rolls before the first time \(\{X_n\}_{n\in {\mathbb{N}}_0}\) visits the state \(2\), i.e., compute \({\mathbb{E}}[\tau_2]\), where \[\tau_2=\min \{ n\in{\mathbb{N}}_0\, : \, X_n=2\}.\]
Compute \({\mathbb{E}}[\sum_{k=0}^{\tau_2-1} X_k]\).
1/6*matrix(
Q =c(1,2,1,1,
1,1,1,1,
1,1,1,2,
2,1,1,1),
byrow=T, ncol=4)
matrix(1, nrow=4, ncol=1)
g1 =v = solve( diag(4) - Q, g1 ))
(## [,1]
## [1,] 4.861736
## [2,] 4.167203
## [3,] 4.996785
## [4,] 4.977492
Since we are starting from state \(1\), the answer is 4.8617363.
matrix(c(0, 1, 3, 4), nrow = 4, ncol = 1)
g2 =v = solve(diag(4) - Q, g2))
(## [,1]
## [1,] 7.350482
## [2,] 7.157556
## [3,] 11.054662
## [4,] 11.382637
so that \({\mathbb{E}}[\sum_{k=0}^{\tau_2-1} X_k]=\) 7.3504823.
\[pro:MC15\] Let \(\{Y_n\}_{n\in {\mathbb{N}}_0}\) be a sequence of die-rolls, i.e., a sequence of independent random variables with distribution \[Y_n \sim \left( \begin{array}{cccccc} 1 & 2 & 3 & 4 & 5 & 6 \\ 1/6 & 1/6 & 1/6 & 1/6 & 1/6 & 1/6 \end{array} \right).\] Let \(\{X_n\}_{n\in {\mathbb{N}}_0}\) be a stochastic process defined by \(X_n=\max (Y_0,Y_1, \dots, Y_n)\). In words, \(X_n\) is the maximal value rolled so far.
Explain why \(X\) is a Markov chain, and find its transition matrix and the initial distribution.
Supposing that the first roll of the die was \(3\), i.e., \(X_0=3\), what is the expected time until a \(6\) is reached?
Under the same assumption as above (\(X_0=3\)), what is the probability that a \(5\) will not be rolled before a \(6\) is rolled for the first time?
Starting with the first value \(X_0=3\), each time a die is rolled, the current record (the value of \(X_n\)) is written down. When a \(6\) is rolled for the first time all the numbers are added up and the result is called \(S\) (the final \(6\) is not counted). What is the expected value of \(S\)?
Note: You don’t need Markov chains to solve this part; the expected time to absorption is nothing but the waiting time until the first \(6\) is rolled - a shifted geometrically distributed random variable with parameter \(1/6\). Therefore, its expectation is \(1+ \frac{5/6}{1/6}=6\).
Note: You don’t need Markov chains to solve this part either; the probability that \(6\) will be seen before \(5\) is the same as the probability that \(5\) will appear before \(6\). The situation is entirely symmetric. Therefore, the answer must be \(1/2\).
Note: Can you do this without the use of the Markov-chain theory?
Go back to the problem with the professor and his umbrellas in the first lecture on Markov chains and answer the questions in part 2., but this time using an absorption/reward computation.
We run the following Python code which uses the markov362m
package:
\[\includegraphics[scale=0.7]{prof-comp-snippet.pdf}\] Lines 1-3 import
the package and initialize the chain. To get the initial distribution
(concentrated on "H2"
), we create a dictionary initial_dict
on line
4 and turn it into a row vector a0_T
on lines 6-7 by setting all
values other than "H2"
to \(0\). Similarly, we build the reward (column)
vector g
by setting all values to \(1\) on lines 8-10. Finally, we
compute the expected reward (time to absorption in this case) by
multiplying the three matrices on line 12, and get that the expected
number of steps before the professor gets wet is approximately \(39.1\).
That corresponds to approximately \(19.5\) days.
For the second question, we perform the absorption probability computation on line 12, and turn the answer into a dictionary on line 13 to make it easier to associate states to matrix rows and columns. Since we are looking for the probability that the professor gets wet on the way home, the answer is approximately \(0.99\).
Go back to the problem with Basil the rat in the he first lecture on Markov chains and answer the question 2., but this time using an absorption/reward computation.
We run the following Python code which uses the markov362m
package:
\[\includegraphics[scale=0.7]{prof-comp-snippet.pdf}\] Lines 1-3 import
the package and initialize the chain. To get the initial distribution
(concentrated on "H2"
), we create a dictionary initial_dict
on line
4 and turn it into a row vector a0_T
on lines 6-7 by setting all
values other than "H2"
to \(0\). Similarly, we build the reward (column)
vector g
by setting all values to \(1\) on lines 8-10. Finally, we
compute the expected reward (time to absorption in this case) by
multiplying the three matrices on line 12, and get that the expected
number of steps before the professor gets wet is approximately \(39.1\).
That corresponds to approximately \(19.5\) days.
For the second question, we perform the absorption probability computation on line 12, and turn the answer into a dictionary on line 13 to make it easier to associate states to matrix rows and columns. Since we are looking for the probability that the professor gets wet on the way home, the answer is approximately \(0.99\).
Go back to Problem \[pro:MC14\] (the one with airline reservation system and the computer-repair facility). Assuming that \(p=0.3\), and that the system starts with both computers operational, compute the expected time before both computers break down. Assuming that each day with only one computer operational costs the company \(\$10,000\), what is the total cost the company is expected to incur before both computers break down?
The following Python code, which uses the markov362m
package, does all
the work : \[\includegraphics[scale=0.7]{facility-comp-snippet.pdf}\] In
lines 1-3 we initialize the package and the chain. The original Markov
chain is recurrent, so the absorption-and-reward computations cannot be
performed directly. Since we are not interested in what happens after
both computers break down, we can make the two states 0-1-0-1 and
0-0-1-1 absorbing. This is accomplished on line 5-9.
This way all other states become transient, and makes it possible for
problem to be interpreted as an expected-reward question with the reward
function \(g\) which takes the value \(\$10000\) on states 1-0-1-0 and
1-1-0-0, and \(0\), everywhere else. We build the initial vector a0_T
on
lines 11-2 and the reward vector g
on lines 14-16 from dictionaries;
the actual computation is performed on line 18 by multiplying three
matrices, yielding the expected reward of approximately \(\$36225\).


Tea plants are native to East Asia, and probably originated in the borderlands of north Burma and southwestern China.
Tea drinking may have begun in the region of Yunnan region, when it was used for medicinal purposes. It is also believed that in Sichuan, "people began to boil tea leaves for consumption into a concentrated liquid without the addition of other leaves or herbs, thereby using tea as a bitter yet stimulating drink, rather than as a medicinal concoction.”
Chinese legends attribute the invention of tea to the mythical Shennong (in central and northern China) in 2737 BC although evidence suggests that tea drinking may have been introduced from the southwest of China (Sichuan/Yunnan area). The earliest written records of tea come from China. The word tú 荼 appears in the Shijing and other ancient texts to signify a kind of "bitter vegetable" (苦菜), and it is possible that it referred to many different plants such as sowthistle, chicory, or smartweed, as well as tea. In the Chronicles of Huayang, it was recorded that the Ba people in Sichuan presented tu to the Zhou king. The Qin later conquered the state of Ba and its neighbour Shu, and according to the 17th century scholar Gu Yanwu who wrote in Ri Zhi Lu (日知錄): "It was after the Qin had taken Shu that they learned how to drink tea." Another possible early reference to tea is found in a letter written by the Qin Dynasty general Liu Kun who requested that some "real tea" to be sent to him.
The earliest known physical evidence of tea was discovered in 2016 in the mausoleum of Emperor Jing of Han in Xi'an, indicating that tea from the genus Camellia was drunk by Han Dynasty emperors as early as the 2nd century BC. The Han dynasty work, "The Contract for a Youth", written by Wang Bao in 59 BC, contains the first known reference to boiling tea. Among the tasks listed to be undertaken by the youth, the contract states that "he shall boil tea and fill the utensils" and "he shall buy tea at Wuyang". The first record of tea cultivation is also dated to this period (the reign of Emperor Xuan of Han), during which tea was cultivated on Meng Mountain (蒙山) near Chengdu. Another early credible record of tea drinking dates to the third century AD, in a medical text by Hua Tuo, who stated, "to drink bitter t'u constantly makes one think better." However, before the mid-8th century Tang dynasty, tea-drinking was primarily a southern Chinese practice. It became widely popular during the Tang Dynasty, when it was spread to Korea, Japan, and Vietnam.
Through the centuries, a variety of techniques for processing tea, and a number of different forms of tea, were developed. During the Tang dynasty, tea was steamed, then pounded and shaped into cake form, while in the Song dynasty, loose-leaf tea was developed and became popular. During the Yuan and Ming dynasties, unoxidized tea leaves were first pan-fried, then rolled and dried, a process that stops the oxidation process that turns the leaves dark, thereby allowing tea to remain green. In the 15th century, oolong tea, in which the leaves were allowed to partially oxidize before pan-frying, was developed. Western tastes, however, favoured the fully oxidized black tea, and the leaves were allowed to oxidize further. Yellow tea was an accidental discovery in the production of green tea during the Ming dynasty, when apparently sloppy practices allowed the leaves to turn yellow, but yielded a different flavour as a result.
Tea was first introduced to Portuguese priests and merchants in China during the 16th century, at which time it was termed chá. The earliest European reference to tea, written as Chiai, came from Delle navigationi e viaggi written by a Venetian, Giambattista Ramusio, in 1545. The first recorded shipment of tea by a European nation was in 1607 when the Dutch East India Company moved a cargo of tea from Macao to Java, then two years later, the Dutch bought the first assignment of tea which was from Hirado in Japan to be shipped to Europe. Tea became a fashionable drink in The Hague in the Netherlands, and the Dutch introduced the drink to Germany, France and across the Atlantic to New York.
The first record of tea in English came from a letter written by Richard Wickham, who ran an East India Company office in Japan, writing to a merchant in Macao requesting "the best sort of chaw" in 1615. Peter Mundy, a traveller and merchant who came across tea in Fujian in 1637, wrote, "chaa – only water with a kind of herb boyled in it ". Tea was sold in a coffee house in London in 1657, and Catherine of Braganza took the tea-drinking habit to the British court when she married Charles II in 1662. Tea, however, was not widely consumed in Britain until the 18th century, and remained expensive until the latter part of that period. Tea smuggling during the 18th century led to the general public being able to afford and consume tea. The British government removed the tax on tea, thereby eliminating the smuggling trade by 1785. The price of tea in Europe fell steadily during the 19th century, especially after Indian tea began to arrive in large quantities; by the late 19th century tea had become an everyday beverage for all levels of society. The popularity of tea also informed a number of historical events – the Tea Act of 1773 provoked the Boston Tea Party that escalated into the American Revolution.
Chinese small leaf type tea was introduced into India in 1836 by the British in an attempt to break the Chinese monopoly on tea. In 1841, Archibald Campbell brought seeds of Chinese tea from the Kumaun region and experimented with planting tea in Darjeeling. The Alubari tea garden was opened in 1856 and Darjeeling tea began to be produced. In 1848, Robert Fortune was sent by the East India Company on a mission to China to bring the tea plant back to Great Britain. The Chinese tea plants he brought back were introduced to the Himalayas, though most did not survive. The British had discovered that a different variety of tea was endemic to Assam and the northeast region of India and that it was used by the local Singpho people, and these were then grown instead of the Chinese tea plant and then were subsequently hybridized with Chinese small leaf type tea as well as likely closely related wild tea species. Using the Chinese planting and cultivation techniques, the British launched a tea industry by offering land in Assam to any European who agreed to cultivate it for export. Tea became widely popular in India in the 1950s because of a successful advertising campaign by the India Tea Board.


TAMPOPO
A Film Review by Brian Takeshita
Rating: ***1/2 out of ****
After watching the first ten minutes of this Japanese film, you will never eat a bowl of ramen the same way again. There is a scene where an old man is teaching a young one how to eat the soupy bowl of noodles, as a master would teach an eager apprentice. "You caress the noodles with the chopsticks," he says, "then put the roast pork on the side of the bowl and apologize to it by saying, 'see you soon.'" Of course, it's meant to be a parody, but there is an earnestness underneath the silliness that makes you take it with a certain degree of sobriety. You begin to appreciate the food as not merely something you eat, not something you like, not something you enjoy, but rather something you experience. Experiencing it is a process which engages all of the senses, fulfilling each one on its own terms and weaving them so that the total is a pleasure that is more than the sum of its parts. Trust me, you really want to go find a noodle shop at this point.
Juzo Itami's TAMPOPO brings the same sense of the serious parody of food to the forefront by making the story follow the pattern of an American western, set in modern day Japan. A stranger, Goro (Tsutomu Yamazaki), comes into town and finds Tampopo (Nobuko Miyamoto), the proprietor of a small, hole-in-the-wall noodle shop, trying to fend off the insults of the local strongman, Pisken (Rikiya Yasuoka). Goro, to defend the honor of this woman and her noodles, gets into a fight with the ringleader and his henchmen, emerging bloodied, but victorious. Goro finds that Tampopo's ambition is to have a shop that people would flock to from far away, just to eat a bowl of her ramen. The problem is, her fare is something less than popular, and less than appetizing. However, Goro agrees to help Tampopo in her quest, and in the process they seek the wisdom of an elderly noodle expert, enlist the aid of a wealthy patron, and make friends with the former enemy.
 Take, for example, when Tampopo tries to buy the recipe for a delicious soup from another shop owner. The price is too high, but the owner of the store next door will secretly sell it to her for a more affordable sum. Tampopo meets him at his store late at night, and he leads her to a back room. She protests, thinking that perhaps this man has ulterior motives, but he insists. Just when she is about to bolt for the exit, he shows her a small gap in the wall adjoining his store with the noodle shop next door. She peers through and takes notes as she watches the cook make the soup for the next day, her face filled with a joy that can be felt by the audience. This scene, while comical, is very effective at filling the viewer with a sense of trepidation, then of relief and discovery.
 We even watch as one of them sneaks into the kitchen of a restaurant and expertly prepares a French omelet. The scene is meant to bring a laugh, but it also says that no matter whether people are rich or poor, food is something which everyone has in common, and the enjoyment of food is an experience shared by all.
There are also a number of unrelated vignettes appearing throughout the film, which help to illustrate and accentuate the role of food in people's lives. A particularly effective one involves a wife and mother being tended to in her home by a doctor.  Her husband comes home, and seeing her worsened condition, demands that she get up and make dinner. The viewer knows the husband's intention is not to be mean; he is desperate for the normalcy of which he and his family has obviously been deprived, and the wife making dinner is an essential part of this. In a near miracle, the wife drags herself to the kitchen and prepares a quick meal, then brings it to her awaiting family. As the family eats, she looks on them and smiles. Preparing food for her family is a joy and a comfort to her, and for a brief moment, she too enjoys the normalcy. Then she falls over, dead. For a moment, the family is stunned, but then the father yells at the children, "Keep eating!  Crying as they do so, the family finishes the meal. The scene is comical, awkward, moving, and beautiful.
By including the vignettes, Itami ran the risk of creating a disjointed film, but surprisingly, they do not interrupt the pacing of the main storyline. Instead, they even help contribute to the idea that Tampopo's goal of being able to serve exceptional food is worthy and even noble. Because the film parodies a western, the construction of the plot is fairly predictable, but is still enjoyable as we watch the familiar way in which the "good guys" come together for the final showdown. In this case, the showdown is against the ramen. If they eat Tampopo's ramen, soup and all, Tampopo knows she has succeeded. It's pretty obvious what the outcome will be, but when a film changes your whole perspective on something you consume every day of your life, you can afford to cut it a little slack.
Review posted January 31, 1998
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


CMainFrame
class
(usually found in MainFrm.h
) to include a member variable:
public:
CSplitterWnd m_SplitterWindow;
Name: CMyListView
Base Class: CListView
Name: CMyTreeView
Base Class: CTreeView
Class name:
combobox.
Messages:
listbox.
Add Function
button.
Member functions:
listbox.
return CFrameWnd::OnCreateClient(lpcs, pContext);
with the following code:
m_SplitterWindow.CreateStatic( this, 1, 2, WS_CHILD | WS_VISIBLE );
CWnd * desktop_window_p = GetDesktopWindow();
CRect rectangle;
if ( desktop_window_p == NULL )
{
rectangle.SetRect( 0, 0, 640, 480 );
}
else
{
desktop_window_p->GetWindowRect( rectangle );
}
SIZE size;
// Make the tree control pane 25% of the window size
size.cx = (long) ( rectangle.Width() * 0.25 );
size.cy = rectangle.Height();
m_SplitterWindow.CreateView( 0, 0,
RUNTIME_CLASS( CMyTreeView ),
size,
pContext );
// Make the list control 75% of the window size
size.cx = rectangle.Width() - size.cx;
m_SplitterWindow.CreateView( 0, 1,
RUNTIME_CLASS( CMyListView ),
size,
pContext );
SetActiveView( (CView *) m_SplitterWindow.GetPane( 0, 0 ) );
return( TRUE );
CMainFrame.cpp
file (or
whatever filename has CMainFrame in it) and find the line that
looks like: #include "CMainFrame.h"
Now add these lines immediately after it:
#include "MyTreeView.h"
#include "MyListView.h"
stdafx.h
file and delete the following lines:
#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers
#ifndef _AFX_NO_AFXCMN_SUPPORT
#endif // _AFX_NO_AFXCMN_SUPPORT
Now add this line to the rest of the includes:
#include <afxcview.h>
public:
CMyTreeView * TreeView;
CMyListView * ListView;
#include "MyTreeView.h"
#include "MyListView.h"
Documents and views are very incestuous.
Each has to know way too much about the other in order to function.
This means the document class is a great place to put information
about all of the views of that document. As long as your document
doesn't represent data, everything is fine. Just think of your document
class as the guy that manages all of the views (a View Manager
if you will).
You can have pointers
to data in the document class but I do not recommend putting any real
data in there.
public:
CImageList ImageList;
HTREEITEM RootItem;
HTREEITEM CurrentItem;
IDB_IMAGELIST
.
Make your grid settings 17 pixels high by 16 wide (via the Image->Grid Settings...)
Use the darker purple on the color palette bar for your transparent color (the background
color).
16
17
1
in the first tile.
2
in the second tile.
3
in the third tile.
This usually happens when a graphic artist gets hired by your company.
IDB_BITMAP1
in the ResourceView pane
to highlight it.
IDB_IMAGELIST
then close the window
CMyTreeView
in the Class name: combobox.
CMyTreeView
in the Object IDs: listbox.
WM_CREATE
in the Messages: listbox.
if (CTreeView::OnCreate(lpCreateStruct) == -1)
return -1;
// TODO: Add your specialized creation code here
return 0;
with this code:
lpCreateStruct->style |= ( TVS_HASLINES | TVS_HASBUTTONS | TVS_LINESATROOT );
if ( CTreeView::OnCreate( lpCreateStruct ) == (-1) )
{
return( -1 );
}
MyDocument * document_p = GetDocument();
ASSERT( document_p != NULL );
document_p->TreeView = this;
ImageList.Create( IDB_IMAGELIST, 16, 0, RGB( 255, 0, 255 ) );
ImageList.SetBkColor( GetSysColor( COLOR_WINDOW ) );
CTreeCtrl& tree_control = GetTreeCtrl();
tree_control.SetImageList( &ImageList, TVSIL_NORMAL );
UpdateWindow();
RootItem = tree_control.InsertItem( "Root", IMAGE_ROOT, IMAGE_ROOT );
return( 0 );
#include "MyDocument.h"
MyTreeView.h
header file to start adding defined
constants for the images in the tree control (the tiles in the image list).
#define IMAGE_ROOT 0
#define IMAGE_TILE_2 1
#define IMAGE_TILE_3 2
CMyListView
in the Class name: combobox.
CMyListView
in the Object IDs: listbox.
WM_CREATE
in the Messages: listbox.
if (CListView::OnCreate(lpCreateStruct) == -1)
return -1;
// TODO: Add your specialized creation code here
return 0;
with this code:
lpCreateStruct->style |= LVS_REPORT;
if ( CListView::OnCreate( lpCreateStruct ) == (-1) )
{
return( -1 );
}
CMyDocument * document_p = (CMyDocument *) GetDocument();
document_p->ListView = this;
return( 0 );
#include "MyDocument.h"
public:
void DeleteChildren( HTREEITEM parent_item );
Implemented thusly:
void CMyTreeView::DeleteChildren( HTREEITEM parent_item )
{
CTreeCtrl& tree_control = GetTreeCtrl();
HTREEITEM child_item = (HTREEITEM) NULL;
child_item = tree_control.GetChildItem( parent_item );
while( child_item != NULL )
{
tree_control.DeleteItem( child_item );
child_item = tree_control.GetChildItem( parent_item );
}
}
public:
BOOL AddColumn( LPCTSTR column_name,
int column_number,
int width = (-1),
int nSubItem = (-1),
int mask = LVCF_FMT | LVCF_WIDTH |
LVCF_TEXT | LVCF_SUBITEM,
int format = LVCFMT_LEFT );
BOOL AddItem( int row_number,
int column_number,
LPCTSTR text,
int image_index = (-1) );
void Empty( void );
Implemented thusly:
BOOL CMyListView::AddColumn( LPCTSTR column_name,
int column_number,
int width,
int sub_item,
int mask,
int format )
{
CListCtrl& list_control = GetListCtrl();
LV_COLUMN list_view_column;
list_view_column.mask = mask;
list_view_column.fmt = format;
list_view_column.pszText = (LPTSTR) column_name;
if ( width == (-1) )
{
list_view_column.cx = list_control.GetStringWidth( column_name ) + 15;
}
else
{
list_view_column.cx = width;
}
if ( mask & LVCF_SUBITEM )
{
if ( sub_item != (-1) )
{
list_view_column.iSubItem = sub_item;
}
else
{
list_view_column.iSubItem = column_number;
}
}
return( list_control.InsertColumn( column_number, &list_view_column ) );
}
BOOL CMyListView::AddItem( int row_number,
int column_number,
LPCTSTR text,
int image_index )
{
LV_ITEM list_view_item;
list_view_item.mask = LVIF_TEXT;
list_view_item.iItem = row_number;
list_view_item.iSubItem = column_number;
list_view_item.pszText = (LPTSTR) text;
if ( image_index != (-1) )
{
list_view_item.mask |= LVIF_IMAGE;
list_view_item.iImage = image_index;
}
CListCtrl& list_control = GetListCtrl();
if ( column_number == 0 )
{
return( list_control.InsertItem( &list_view_item ) );
}
else
{
return( list_control.SetItem( &list_view_item ) );
}
}
void CMyListView::Empty( void )
{
CListCtrl& list_control = GetListCtrl();
list_control.DeleteAllItems();
while( list_control.DeleteColumn( 0 ) )
{
;
}
UpdateWindow();
}
Generally speaking, when the user selects branches in the tree view, you want the list view (I prefer report view) to show details of that item. This means you should add a function to the list view class to show the details of each type of item. We also need a way to associate tree items with objects that will be displayed in these functions. In general, the document class is responsible for loading the object (and sub objects). The tree view is then passed this object and populates the tree items. When the user selects a tree item, the tree view figures out (via mapping) what the object selected was and tells the list view to display it.
CDocument
as
a view manager and data router. It gets told by the framework to
load new data (via the OpenDocument
method).
I suggest putting a pointer to your real data-centric object in
the document class.
Here's the steps you need to take to add your own code to load a file:
CMyDocument
in the Class name: combobox.
CMyDocument
in the Object IDs: listbox.
OnOpenDocument
in the Messages: listbox.
To map what the user click on to what it represents, do the following:
MyTreeView.h
header file (this is the
one that contains the image identifiers IMAGE_xxx
defines).
CMyTreeView
class. These
enumerations will represent the objects.
class CMyTreeView : public CTreeView
{
public:
enum _what_it_is
{
IT_IS_THE_ROOT = 1,
IT_IS_AN_XML_DOCUMENT,
IT_IS_AN_ELEMENT,
IT_IS_A_LIST_OF_ATTRIBUTES,
IT_IS_AN_ATTRIBUTE
};
CMyTreeView
to convert
image id's to what they represent:
DWORD ImageToWhatItIs( DWORD image_id ) const;
implemented thusly:
DWORD CMyTreeView::ImageToWhatItIs( DWORD image_id ) const
{
switch( image_id )
{
case IMAGE_ROOT:
return( IT_IS_THE_ROOT );
case IMAGE_TILE_2:
return( IT_IS_AN_XML_DOCUMENT );
case IMAGE_TILE_3:
return( IT_IS_AN_ELEMENT );
default:
return( 0 );
}
}
OnOpenDocument()
) and other methods
to add individual items. For example:
void CMyTreeView::Populate( CExtensibleMarkupLanguageDocument * xml_p )
{
// Start with an empty tree
DeleteChildren( RootItem );
if ( xml_p == NULL )
{
return;
}
CTreeCtrl& tree_control = GetTreeCtrl();
HTREEITEM document_item;
document_item = tree_control.InsertItem( TEXT( "XML" ), IMAGE_TILE_2, IMAGE_TILE_2, RootItem );
tree_control.SetItemData( document_item, (DWORD) xml_p );
CExtensibleMarkupLanguageElement * element_p = xml_p->GetRootElement();
AddElement( tree_control, document_item, element_p );
}
To make things easy (and keep them straight in my little head), I put
a comment block at the top of the file to give me a nice map
to what everything means.
/*
** Image Identifier to What It Is to Item Data mappings
**
** IMAGE ID | WHAT IT IS | GetItemData() returns
** -------------+-----------------------+------------------------------------
** IMAGE_ROOT | IT_IS_THE_ROOT |
** IMAGE_TILE_2 | IT_IS_AN_XML_DOCUMENT | CExtensibleMarkupLanguageDocument *
** IMAGE_TILE_3 | IT_IS_AN_ELEMENT | CExtensibleMarkupLanguageElement *
*/
Here's where you will explain how to handle change notifications.


Chris's DMX Controller
Channels
Fixtures
Universe {{universe.number}}
{{ connected ? 'Connected' : 'Reconnect' }}
Blackout
Unblackout
Beat
Channels
No channels available
Channel {{channel.id}}
Fixtures
No fixtures available


Home
Videos
Files
Products
Contact Us
Home
Videos
Files
Products
Contact Us
menu
Title
Watch Video For How To Installation Tutorial
Subscribe To RawTech For Download a File
Click Here For Visit Youtube Channel
Verify your Subscription to RawTech
Note:- We are not storing your information.Login credentials just needed to verify subscription.
Verify your Subscription
Try Again
Download Links
Download File