Что такое hq и bigops
Перейти к содержимому

Что такое hq и bigops

Log in

Some of our services on the new web platform require more information about our users. An account on digitalsme.eu allows us to interact more directly with our users and restrict access. For example, only full members are allowed to view content relating to board activities. Asking you to log in/register an account also enables us to give full visibility to your organisation. For example, if you apply to the European Digital Innovators Club or any working group, we need items such as your organisation name, sector, and logo. Adding this information through an account on digitalsme.eu enables us to display your company logo among other European innovators. We will never forward your data to third parties for commercial purposes. For more information, read our privacy policy and our Innovators Clubs Terms & Conditions.

Scott Brinker: From Big Data to Big Ops

Scott Brinker Hexagon-1

Now, this is the big one. Scott Brinker himself is here to bless our eyes, ears, and anything in-between with his insight on big data and big ops.

So, let’s see what Scott’s got. And what Scott’s got, is a lot. And it’s hot. Sorry, I’ll stop messing around.

And if after this, you’re still not Scott-ed out, check out our latest interview with the Godfather of martech here. We delve into topics like the martech industry, the effects of the pandemic (of course), the challenges of martech, and more.

This sesh, if you were lucky enough to catch it, went into depth about the new foundations of marketing and customer experience.

But in case you haven’t heard of him, sacrilegious as that is, Scott is the editor of chiefmartec.com, the VP Platform Ecosystem at HubSpot, and is the best selling author of ‘Hacking Marketing’.

And, most notably, he’s the mastermind behind the Marketing Technology landscape since 2011. And he’s been standing side-by-side with the industry as it’s grown 5,233% since 2011. In fact, we’ve seen the number of martech solutions grow from 150, to 8,000 in just under a decade.

Marketing Technology Landscape Supergraphic (2019): Martech 5000 (actually 7,040) - Chief Marketing Technologist

But the truth is, says Scott, that’s just the tip of the iceberg. In fact, more than 500m digital apps and services will be developed and deployed using cloud native approaches by 2023.

Not all of these will be commercially packaged apps like the ones on the martech landscape. But the vast majority will be custom apps, built for individual companies.

This is not our story today, but the catalyst. In fact, we are in an era moving away from big data, to the era of big ops.

So, how do we go from big data, with a scale and complexity of data collected, stored and analysed, to big ops, with the scale and complexity of apps and automation interacting with data.

Scott asks us to consider it this way. If you think of data as this big data lake, far away, where you need a professional guide to help you find it, and hike up to it. Big ops is instead like an interactive water park.

And this interaction is key. Though data is growing, the interactions with it are growing even faster.

Scott Brinker

This is triggered by a proliferation of ops related functions inside the modern digital business.

Okay, let’s stop listing these. Just take a peep at this behemoth of a graph:

Scott Brinker

So, Scott turned to his twitter followers to clarify the roles, and asked «What do other people think ‘ops’ roles do?»

  1. «Buy ALL the tools»
  2. «We say NO a lot»
  3. «Send emails all day»
  4. «Put milk & cookies out for the magic elves who come in at night and do all the hard work»

and Scott’s favourite:

I am a laptop-wielding technology-wizard marketing Rockstar who’s beloved by all.»

Let’s start with DevOps.

Basically, this meme sums it up.

Scott Brinker

But this is no joke. Okay, that’s a little bit of a joke. But this is an actual problem.

Software used to be developed by software engineers, and then handed over to deployment. But this slowed stuff down, and encouraged finger pointing.

So, DevOps became all about embedding ops responsibility with the development teams.

But what does this have to do with marketing?

Websites & web apps. Mobile Apps. Product-Led Growth. Custom-developed martech. All of this is software. All of this is relevant to marketing.

Scott moves on to the custom martech side. He referenced research from our martech report (download here), specifically asking respondents «What best describes your organisation’s customer/ marketing data platform?»

Now this is interesting, Scott says. 16% of respondents reported their platform is self built, either in-house or custom developed. 38.5% reported a hybrid platform, in-house or custom developed, and with vendor solutions. This totals to 54.5%.

Scott said someone on Twitter joked that half of this is probably spreadsheets (and they might not be 100% wrong). But there’s still a lot of development happening.

But what Scott wants to do is to pull themes from DevOps.

The Three Themes of DevOps

Number One: Agile Culture

This accelerates the loop, to be able to develop, deploy, learn. And repeat. It’s about bringing the agile cycle up to speed, and has been adapted for marketing.

In fact, 51% of marketing departments are using at least some parts of an agile marketing approach in 2021.

Number Two: Shifting left

This involves moving responsibilities in the ‘Dev’ of ‘DevOps’. But this shift is also happening within marketing, with the growth of no-code marketing ‘superpowers’, for providing non-technical marketers the ability to perform «no-code» capabilities.

  • Automation. This means being able to automate activities and processes.
  • Augmentation. This means being able to be imbued with new powers to create and analyse.
  • Integration. This means being able to be connected to other tools and data.

A big part of all this is automation.

Number three: Automation

This is certainly something that’s been seen in the DevOps world, with 90% of high-maturity DevOps teams have automated the most repetitive tasks, compared to only 25% for low-maturity DevOps teams.

The department with the largest number of automation is not surprisingly IT and Engineering, with 39.8%. But what is surprising is the second is Finance (26.4%) and the third is sales and marketing (13.3%).

This gets us into data ops.

Data Ops

There are so many water-themed references in this space, Scott says. Data Lake, Data Stream, Data Cloud, and when it’s bad — Data Swamp.

But there’s a few lesser known data water metaphors. These are:

  • Data Bourne — Stored identity data
  • Data Creek — Trickle-down data
  • Data Fjord — Steep learning curve data
  • Data Gulf — Can’t quite reach the data
  • Data Moat — Unique Competitive data
  • Data Puddle — Excel Spreadsheet

And there’s one more water metaphor. The Water Cycle. You’ll find there’s a similar ecosystem for data.

Scott Brinker

So, you’ll see the data being all pooled around. Another water reference.

And it wouldn’t be a S.B presentation without some sort of landscape:

Scott Brinker

And this is just a sample.

Next up, two ideas from Data Ops, which are relevant to all Big Ops.

Two Ideas from DataOps

Number One: Aggregation

First up, its aggregation over consolidation. But what’s the difference?

Well, consolidation is about reducing a lot of different sets of things, into a smaller number of things, or just one.

Aggregation, on the other hand, is making a large set of things easier to consume or access through a single source.

Scott Brinker

Scott Brinker

For example, Social media platforms are highly consolidated, but have millions of social creators.

Scott Brinker

So, this is something Scott’s looked at with martech.

«With integration, we have the mechanisms to do aggregation» at the data level, workflow, UI, and governance, he says.

Scott Brinker

So, you see aggregation in the following layers:

  • Data: Data warehouses/data Lakes; specialised data; shared spreadsheets.
  • Workflow (logic): iPaaS, Workflow Automation and BPM; Robotic Process Automation; Data Pipelining and ETL automation.
  • UI (presentation): Shared collaboration tools; Shared analytics tools; Domain platforms.
  • Governance: SaaS management; Privacy and data governance; Identity access management.

What’s exciting about this aggregation, says Scott, is that it’s taking us from an age where fragile tech stacks break when new apps or data is added, to antifragile stacks which gain value from new apps and data.

This is because aggregation platforms get more value as more is added, as they have more things to aggregate through them.

This is how we make our tech stacks as agile as the rest of our business needs to be.

Number Two: Reintegration of Martech

The CMO council asked a number of c-suite leaders «Where do you see leadership holes or gaps in your marketing organisation?»

  • 42% said modernisation of marketing organisation, systems, and operations
  • 40% said proficient, technically savvy managers in key digital roles
  • 37% report it to be greater customer knowledge and market understanding
  • 34% claim adaptive, informed decision-making based on good data

Actually all these things are all related around the technology and data infrastructure of marketing»

How did marketing fall behind?

In many ways martech was leading the charge of digitisation of modern business, says Scott.

Well, the truth is the rest of the organisation has caught up with its maturity. And increasingly there’s a demand for martech to be re-integrated into the rest of the IT platform.

That doesn’t mean that marketing won’t have some of their own tools, but these tools need to integrate with the other enterprise systems. And in some cases where there’s universal enterprise systems that work for marketing needs too, so there’s a need to be able to take advantage of them seamlessly.

And finally, we have:

RevOps

This involves pooling together marketing ops, partner ops, and sales ops. We can go back to the meme, he says:

Scott Brinker

Scott Brinker

In many ways, Scott suggests, the relationship between marketing and sales, and customer success, is often like the parable of the blind men and an elephant. No, it’s not about an elephant being trained as a service animal.

Instead, the men are all touching a different piece, and describe what they see, with very mixed perspectives. So, in our case, it translates to ‘the parable of the blind department and a customer’. Or mis-aligned systems and data, and processes.

And really, at its heart, RevOps is about aligning systems and data, and processes, across marketing, sales and customer service.

A way to look at the power of RevOps is to look at the seven roles that it can play in the modern organisation.

«RevOps sitting above these three departments can be the cartographer of the entire customer journey», not just through marketing or sales, but the end-to-end, says Scott.

What’s exciting is all seven of these roles are all connected to the data that is being managed.

The other roles include:

  • Cartographer of the customer journey map. mapping the context of data.
  • Curator of the customer data and assets. standardising data organisation.
  • Architect of customer systems and services. generating and processing data.
  • Orchestrator of processes and automations. building data-triggered workflows.
  • Analyst of insights and performance. analysing and refining data.
  • Outfitter of self-service capabilities. enabling self-service use of data.
  • Guardian of quality and compliance. assuring data quality and compliance.

How do DevOps, DataOps and RevOps all connect?

Scott believes that we are early on in this journey of big ops, and that’s what’s exciting about this.

Just as many marketing operations and marketing tech people led this first generation of the martech revolution, the second generation of the martech revolution, in a much larger context of big ops, has so much opportunity”

He leaves us with this quote from MarTech Alliance fave Darrell Alfonso:

No-code, BigOps, экосистемы: 5 главных технологий для маркетологов на ближайшие 10 лет

Как будут развиваться маркетинговые технологии в ближайшие 10 лет? Анна Амброзевич, спикер WIM.Academy и сооснователь Future Leader, проанализировала новые прогнозы CRM-гуру Скотта Бринкера — и рассказала, можно ли адаптировать эти тренды к российскому рынку. Если кратко, то маркетологам пора работать с маркетплейсами, запускать сервисы через no-code и использовать большие данные во благо бизнеса.

Автор статьи: Анна Амброзевич, спикер WIM.Academy, сооснователь Future Leader, эксперт в области маркетинговых технологий. Более 10 лет в сфере CRM, персонализации и управления данными.

Автор статьи: Анна Амброзевич, спикер WIM.Academy, сооснователь Future Leader, эксперт в области маркетинговых технологий. Более 10 лет в сфере CRM, персонализации и управления данными.

Скотта Бринкера, вице-президента компании HubSpot и главного редактора сайта martech.com, называют «крестным отцом» технологичного маркетинга. Он ежегодно публикует прогнозы отрасли — и 2022 год не стал исключением. В новом отчете авторы (Скотт Бринкер выпустил материал вместе с Джейсоном Болдуин из WPP) раскрывают 5 основных трендов в маркетинговых технологиях на ближайшие 10 лет.

Речь идет не о массовых технологиях для пользователей, таких как 5G и VR, а о маркетинговых решениях для развития бизнеса. Несмотря на нестабильную ситуацию в России, не стоит думать, что эти предсказания для нас больше не актуальны, — глобальные маркетинговые тренды будут влиять и на отечественный рынок даже при некоторых ограничениях.

Вначале важно отметить, что пандемия подтолкнула компании к digital-реорганизации: по словам CEO Microsoft Сатьи Наделлы, всего за 2 месяца произошла такая цифровая трансформация, которая ранее заняла бы 2 года. Бизнес продолжит идти по этому пути и интегрировать в работу новые технологичные подходы.

1. No-code (технологии без программного кода)

No-code — это инструменты, которые дают возможность собрать сайт, приложение или чат-бот с помощью готового конструктора. Не придется привлекать разработчиков, писать код и тратить много ресурсов. Например, это Tilda, Chatfuel, Airtable и т. д. Количество таких решений за последние 10 лет выросло в несколько сотен раз.

Любые воркфлоу, приложения — все это могут создавать обычные пользователи без дорогостоящих разработчиков.

Это позволит автоматизировать и сделать более эффективными большинство процессов в маркетинге, но вместе с тем потребует централизованного управления и контроля.

Важно сказать, что высококлассные специалисты не перестанут пользоваться спросом, они будут востребованы для решения более продвинутых и сложных задач. И, конечно, ключевым функционалом всех no-code-решений будет наличие API для гибкой интеграции с любым другим сервисом или для нативного встраивания в существующую экосистему.

Кстати, для no-code-разработчиков уже существует свой маркетплейс — это проект нашего соотечественника WeLoveNoCode, где пользователи могут найти исполнителей для такого типа задач.

Что делать уже сейчас? Изучите самые популярные no-code-решения для создания своей базы знаний: типы, тарифы и т. д. Какие-то из этих решений вы можете использовать самостоятельно в ближайшее время, а для каких-то можно будет найти исполнителя.

2. Платформы, сети и маркетплейсы. Экосистемная экономика

В нашем быстро меняющемся мире для выживания (в России это приобретает особый смысл) бизнесу необходимы такие качества, как гибкость, адаптивность и устойчивость. Они помогают развивать и упрочивать экосистемы, состоящие из платформ, сетей и маркетплейсов.

Под платформами мы понимаем современные SaaS-решения, такие как HubSpot, Salesforce, InSales и т. д. Ключевая роль платформ в текущем спектре задач — обеспечивать высокую адаптивность, ведь они позволяют быстро запустить актуальные для рынка решения.

Сети позволят компаниям получить доступ к неограниченному количеству ценной информации: источникам новых клиентов, знаний и сотрудников. Самой дальновидной стратегией компании будет создание своей собственной сети: партнеров, клиентов, представителей, стартапов и т. д. Так, например, делает Amazon.

Маркетплейсы уже сейчас создают идеальную среду для взаимодействия поставщиков и конечных покупателей, что и привело к их стремительному росту. Они устанавливают общие правила работы, что снижает риски для обеих сторон. Кроме B2C-маркетплейсов, таких как Ozon, СберМегаМаркет, существуют и B2B — Cargo.one, Alibaba и др.

Интересно, что продавцы и покупатели маркетплейса по факту тоже создают собственную сеть, а многие маркетплейсы созданы на базе готовых платформ. Рекламные площадки уже активно сотрудничают с маркетплейсами, а монетизация данных последних имеет безграничные возможности.

Платформы, сети и маркетплейсы, а также экосистема пользователей вокруг них станут самой большой ценностью, которой может обладать компания.

Лидирующими технологическими компаниями станут те, кто будет включать в себя все эти 3 составляющих. Яндекс, Mail.ru Group и Сбербанк — хорошие примеры такой синергии. По факту такие компании «не выпускают» пользователя из своего контура.

Что делать сейчас? Отслеживайте стратегии развития основных крупных игроков на российском и мировом рынке через публичную информацию и новости, чтобы понимать векторы развития и составы ключевых экосистем.

3. Экспансия мобильных приложений

Количество мобильных приложений в мире поражает воображение. Если в 2011 году на рынке маркетинговых технологий было представлено около 150 решений, то в 2020-м эта цифра приблизилась к 8 000. Рост составил более 5 000%! А к 2030 году прогнозируется несколько миллиардов мобильных приложений, включая так называемые микро- и наноприложения для часов, микрофонов, весов и т. д.

Вместе с ростом рынка приложений происходит и их консолидация за счет таких гигантов, как Сбербанк, Яндекс. Это приводит к монополизации определенных категорий рынка технологий.

С помощью no-code-решений практически любой пользователь или бренд может легко и быстро запустить свое приложение. Это позволит полностью оцифровать взаимодействие с пользователями не только в B2C-сегменте, но и B2B.

Пятикратный рост количества решений для маркетинговых технологий за 10 лет

Пятикратный рост количества решений для маркетинговых технологий за 10 лет

В то же время распространение умных устройств и высокоскоростная связь между ними позволят создать больше маркетинговых площадок, включая автоматическое создание рекламы. Это запустит новую волну креатива в рекламе и маркетинге.

Что делать сейчас? Проанализируйте, какие приложения уже существуют в вашем бизнесе и на вашем рынке, а каких еще нет. Используя свои знания no-code-рынка (тренд №1), выберите оптимальное решение для создания вашего приложения.

4. От больших данных (Big Data) к большим операционным процессам (BigOps)

2010-е были эпохой господства больших данных, когда потоки постоянно росли в объеме. В 2020-х на первый план выходят большие операционные процессы (BigOps), следующий «слой» мира данных и их растущего объема и многообразия.

Под BigOps мы понимаем экосистему решений по автоматизации обмена данными между различными отделами — маркетинга, продаж, сервисного обслуживания и т. д. Важно не просто собрать все данные в единую систему (с учетом актуального законодательства), обработать их и сделать консистентными, а создать процесс обмена актуальными данными между различными системами в компании. Например, создание профиля клиента — когда все точки касания бренда с ним не только хранятся в единой системе, но и мгновенно доставляются во все каналы коммуникации, в отчетность и отдел клиентского сервиса.

Последние исследования показали, что 44% всех доступных для компаний данных не записываются, а если и записываются, то 43% не используются.

Задача BigOps — извлечь из данных реальную пользу для бизнеса через управление растущим количеством приложений, решениями по автоматизации, процессами и воркфлоу.

Работа с данными в BigOps будет состоять из двух основных этапов:

  1. Сбор данных из разных источников: точность и актуальность, происхождение и соответствие законодательству, эксклюзивность.
  2. Эффективная обработка и использование данных в бизнес-процессах и клиентском опыте.

В конкурентной борьбе выиграют те компании, которые сумеют извлечь из данных инсайты и встроить их в операционные процессы в режиме реального времени.

Компаниям нужно будет инвестировать в обучение своих сотрудников в области работы с данными (data-грамотность), так как это станет одним из важнейших hard skills будущего. Однако законодательство и этика будут ограничивать количество доступной информации о клиентах, поэтому маркетологам придется находить золотую середину в таргетинге и персонализации.

К 2025 году количество провайдеров данных и продуктов для работы с данными будет расти на 25% в год. Альянсы и экосистемы данных будут играть еще более важную роль в маркетинговых процессах и потребуют более серьезного регулирования работы с данными.

Что делать сейчас? Проанализируйте текущий статус работы с данными в вашей компании: какие из них не используются, поступают ли данные во все отделы в актуальном и полном виде и т. д. Начните строить BigOps процессы.

5. Гармония между людьми и машинами

В мае 2020 года опрос среди маркетологов показал: 59% из них переживают, что ИИ и машинное обучение будут препятствием для их личного роста (в 2019 году эта цифра составляла 14%).

Искусственный интеллект не заменит человека в маркетинге в этом десятилетии, но даст возможность перераспределить свои ресурсы и время в пользу работы со стратегией, инновациями, креативом и эмпатией по отношению к клиентам, коллегам и сотрудникам. То есть в те сферы бизнеса, которые машина и автоматизация охватить не смогут.

Можно выделить 3 основных вида взаимодействия между людьми и машинами в digital-мире:

1. Человек + человек

Звонки, электронная почта, живые встречи и чаты с оператором. Эта модель взаимодействия между клиентом и брендом и дальше будет актуальной, особенно для сфер бизнеса, основанных на высоком уровне персонального сервиса и личных отношениях. В данном формате технологии будут играть поддерживающую роль: сотрудники отдела продаж будут обучаться с помощью ИИ-сервисов с персональными рекомендациями и релевантным контентом. А клиенты будут использовать своих AI-помощников для поиска наиболее выгодных предложений и условий сервиса.

2. Человек + машина

Электронная коммерция и чат-боты, где человек общается с машиной-продавцом. В данном случае человек на стороне продавца играет поддерживающую роль — он лишь управляет клиентским опытом и подключается в нестандартных случаях. В данном случае клиенты также будут использовать умных помощников.

3. Машина + машина

Покупатели делегируют процесс покупки своим AI-помощникам, которые будут взаимодействовать по API с машинами продавца. Это называется bot commerce — такой тип взаимодействия требует другого вида дизайна и оптимизации от маркетологов. Вместо UX (где мы работаем с опытом пользователя) фокус будет смещен на BX (опыт для бота), в данном случае нужно будет создавать опыт для робота. Пример такого типа взаимодействия — SEO, где сайт общается с поисковым движком.

Что делать сейчас? При создании стратегии обязательно учитывайте цифровизацию ваших покупателей и тренды современных технологий в маркетинге. Кроме этого, проанализируйте, какие текущие процессы вы можете автоматизировать и делегировать ИИ.

Итак, каждый из этих пяти трендов по-своему повлияет на возможности маркетологов: они смогут создавать инновации, экспериментировать и анализировать по-новому. Важно держать руку на пульсе, изучать технологии и думать, какие из них можно и нужно внедрять в свои стратегии в самое ближайшее время.

Library iris.algebra.gmap

From stdpp Require Export list gmap .
From iris.algebra Require Export list cmra .
From iris.algebra Require Import gset .
From iris.algebra Require Import updates local_updates proofmode_classes big_op .
From iris.prelude Require Import options .

Section ofe .
Context ` .
Implicit Types m : gmap K A .
Implicit Types i : K .

Local Instance gmap_dist : Dist ( gmap K A ) := λ n m1 m2 ,
∀ i , m1 !! i ≡< n >≡ m2 !! i .
Definition gmap_ofe_mixin : OfeMixin ( gmap K A ).
Proof .
split .
— intros m1 m2 ; split .
+ by intros Hm n k ; apply equiv_dist .
+ intros Hm k ; apply equiv_dist ; intros n ; apply Hm .
— intros n ; split .
+ by intros m k .
+ by intros m1 m2 ? k .
+ by intros m1 m2 m3 ?? k ; trans ( m2 !! k ).
— intros n m m1 m2 ? ? k . eauto using dist_le with si_solver .
Qed .
Canonical Structure gmapO : ofe := Ofe ( gmap K A ) gmap_ofe_mixin .

Program Definition gmap_chain ( c : chain gmapO )
( k : K ) : chain ( optionO A ) := <| chain_car n := c n !! k |>.
Next Obligation . by intros c k n i ?; apply ( chain_cauchy c ). Qed .
Definition gmap_compl ` : Compl gmapO := λ c ,
map_imap ( λ i _ , compl ( gmap_chain c i )) ( c 0).
Global Program Instance gmap_cofe ` : Cofe gmapO :=
<| compl := gmap_compl |>.
Next Obligation .
intros ? n c k . rewrite / compl / gmap_compl map_lookup_imap .
oinversion ( λ H , chain_cauchy c 0 n H k ); simplify_option_eq ; auto with lia .
by rewrite conv_compl /=; apply reflexive_eq .
Qed .

Global Instance gmap_ofe_discrete : OfeDiscrete A → OfeDiscrete gmapO .
Proof . intros ? m m’ ? i . by apply ( discrete_0 _ ). Qed .
Global Instance gmapO_leibniz : LeibnizEquiv A → LeibnizEquiv gmapO .
Proof . intros ; change ( LeibnizEquiv ( gmap K A )); apply _ . Qed .

Global Instance lookup_ne k : NonExpansive ( lookup k : gmap K A → option A ).
Proof . by intros n m1 m2 . Qed .
Global Instance lookup_total_ne ` k :
NonExpansive ( lookup_total k : gmap K A → A ).
Proof . intros n m1 m2 . rewrite ! lookup_total_alt . by intros →. Qed .
Global Instance partial_alter_ne n :
Proper ( ( dist n ==> dist n ) ==> (=) ==> dist n ==> dist n )
( partial_alter ( M := gmap K A )).
Proof .
by intros f1 f2 Hf i ? |];
rewrite ? lookup_partial_alter ? lookup_partial_alter_ne //;
try apply Hf ; apply lookup_ne .
Qed .
Global Instance insert_ne i : NonExpansive2 ( insert ( M := gmap K A ) i ).
Proof . intros n x y ? m m’ ? j ; apply partial_alter_ne ; by try constructor . Qed .
Global Instance singleton_ne i : NonExpansive ( singletonM i : A → gmap K A ).
Proof . by intros . ; apply insert_ne . Qed .
Global Instance delete_ne i : NonExpansive ( delete ( M := gmap K A ) i ).
Proof .
intros n m m’ ? j ; destruct ( decide ( i = j )); simplify_map_eq ;
[ by constructor | by apply lookup_ne ].
Qed .
Global Instance alter_ne ( f : A → A ) ( k : K ) n :
Proper ( dist n ==> dist n ) f → Proper ( dist n ==> dist n ) ( alter ( M := gmap K A ) f k ).
Proof . intros ? m m’ Hm k’ . by apply partial_alter_ne ; [ solve_proper |..]. Qed .

Global Instance gmap_empty_discrete : Discrete ( ∅ : gmap K A ).
Proof .
intros m Hm i ; specialize ( Hm i ); rewrite lookup_empty in Hm |- ×.
inversion_clear Hm ; constructor .
Qed .
Global Instance gmap_lookup_discrete m i : Discrete m → Discrete ( m !! i ).
Proof .
intros ? [ x |] Hx ; [| by symmetry ; apply : discrete ].
assert ( m ≡< 0 >≡ <[ i := x ]>m )
by ( by symmetry in Hx ; inversion Hx ; ofe_subst ; rewrite insert_id ).
by rewrite ( discrete_0 m ( <[ i := x ]>m )) // lookup_insert .
Qed .
Global Instance gmap_insert_discrete m i x :
Discrete x → Discrete m → Discrete ( <[ i := x ]> m ).
Proof .
intros ?? m’ Hm j ; destruct ( decide ( i = j )); simplify_map_eq .
< by apply : discrete ; rewrite - Hm lookup_insert . >
by apply : discrete ; rewrite — Hm lookup_insert_ne .
Qed .
Global Instance gmap_singleton_discrete i x :
Discrete x → Discrete ( <[ i := x ]> : gmap K A ).
Proof . rewrite / singletonM / map_singleton . apply _ . Qed .
Lemma insert_idN n m i x :
m !! i ≡< n >≡ Some x → <[ i := x ]> m ≡< n >≡ m .
Proof . intros ( y’ &?&->)% dist_Some_inv_r’ . by rewrite insert_id . Qed .

Global Instance gmap_dom_ne n :
Proper ( (≡< n >@ < gmap K A >≡) ==> (=) ) dom .
Proof . intros m1 m2 Hm . apply set_eq ⇒ k . by rewrite ! elem_of_dom Hm . Qed .
End ofe .

Global Instance map_seq_ne start :
NonExpansive ( map_seq ( M := gmap nat A ) start ).
Proof .
intros n l1 l2 Hl . revert start .
induction Hl ; intros ; simpl ; repeat ( done || f_equiv ).
Qed .

Global Arguments gmapO _ < _ _ >_ .

Non-expansiveness of higher-order map functions and big-ops

Global Instance merge_ne ` n :
Proper ( ( dist ( A := option A ) n ==> dist ( A := option B ) n ==> dist ( A := option C ) n ) ==>
dist n ==> dist n ==> dist n ) ( merge ( M := gmap K )).
Proof .
intros ?? Hf ?? Hm1 ?? Hm2 i . rewrite ! lookup_merge .
destruct ( Hm1 i ), ( Hm2 i ); try apply Hf ; by constructor .
Qed .
Global Instance union_with_ne ` n :
Proper ( ( dist n ==> dist n ==> dist n ) ==>
dist n ==> dist n ==> dist n ) ( union_with ( M := gmap K A )).
Proof .
intros ?? Hf ?? Hm1 ?? Hm2 i ; apply ( merge_ne _ _ ); auto .
by do 2 destruct 1; first [ apply Hf | constructor ].
Qed .
Global Instance map_fmap_ne ` ( f : A → B ) n :
Proper ( dist n ==> dist n ) f → Proper ( dist n ==> dist n ) ( fmap ( M := gmap K ) f ).
Proof . intros ? m m’ ? k ; rewrite ! lookup_fmap . by repeat f_equiv . Qed .
Global Instance map_zip_with_ne ` ( f : A → B → C ) n :
Proper ( dist n ==> dist n ==> dist n ) f →
Proper ( dist n ==> dist n ==> dist n ) ( map_zip_with ( M := gmap K ) f ).
Proof .
intros Hf m1 m1′ Hm1 m2 m2′ Hm2 . apply merge_ne ; try done .
destruct 1; destruct 1; repeat f_equiv ; constructor || done .
Qed .

Global Instance gmap_union_ne ` :
NonExpansive2 ( union ( A := gmap K A )).
Proof . intros n . apply union_with_ne . by constructor . Qed .
Global Instance gmap_disjoint_ne ` n :
Proper ( dist n ==> dist n ==> iff ) ( map_disjoint ( M := gmap K ) ( A := A )).
Proof .
intros m1 m1′ Hm1 m2 m2′ Hm2 ; split ;
intros Hm i ; specialize ( Hm i ); by destruct ( Hm1 i ), ( Hm2 i ).
Qed .

Lemma gmap_union_dist_eq ` ( m m1 m2 : gmap K A ) n :
m ≡< n >≡ m1 ∪ m2 ↔ ∃ m1′ m2′ , m = m1′ ∪ m2′ ∧ m1′ ≡< n >≡ m1 ∧ m2′ ≡< n >≡ m2 .
Proof .
split ; last first .
< by intros ( m1' & m2' &->&<-&<-). >
intros Hm .
∃ ( filter ( λ ‘ ( l , _ ) , is_Some ( m1 !! l )) m ),
( m2 ∩ m1 ∪ filter ( λ ‘ ( l , _ ) , is_Some ( m2 !! l )) m ).
split_and !; [ apply map_eq |..]; intros k ; move : ( Hm k );
rewrite ? lookup_union ? lookup_intersection ! map_lookup_filter ;
case _ : ( m !! k )=> [ x |] /=; case _ : ( m1 !! k )=> [ x1 |] /=;
case _ : ( m2 !! k )=> [ x2 |] /=; by inversion 1.
Qed .

Lemma big_opM_ne_2 ` ` ( f g : K → A → M ) m1 m2 n :
m1 ≡< n >≡ m2 →
( ∀ k y1 y2 ,
m1 !! k = Some y1 → m2 !! k = Some y2 → y1 ≡< n >≡ y2 → f k y1 ≡< n >≡ g k y2 ) →
( [^ o map ] k ↦ y ∈ m1 , f k y ) ≡< n >≡ ( [^ o map ] k ↦ y ∈ m2 , g k y ) .
Proof .
intros Hl Hf . apply big_opM_gen_proper_2 ; try ( apply _ || done ).
< by intros ?? →. >
< apply monoid_ne . >
intros k . assert ( m1 !! k ≡ < n >≡ m2 !! k ) as Hlk by ( by f_equiv ).
destruct ( m1 !! k ) eqn . ( m2 !! k ) eqn :?; inversion Hlk ; naive_solver .
Qed .

Section cmra .
Context ` .
Implicit Types m : gmap K A .

Local Instance gmap_unit_instance : Unit ( gmap K A ) := ( ∅ : gmap K A ).
Local Instance gmap_op_instance : Op ( gmap K A ) := merge op .
Local Instance gmap_pcore_instance : PCore ( gmap K A ) := λ m , Some ( omap pcore m ).
Local Instance gmap_valid_instance : Valid ( gmap K A ) := λ m , ∀ i , ✓ ( m !! i ) .
Local Instance gmap_validN_instance : ValidN ( gmap K A ) := λ n m , ∀ i , ✓< n > ( m !! i ) .

Lemma gmap_op m1 m2 : m1 ⋅ m2 = merge op m1 m2 .
Proof . done . Qed .
Lemma lookup_op m1 m2 i : ( m1 ⋅ m2 ) !! i = m1 !! i ⋅ m2 !! i .
Proof . rewrite lookup_merge . by destruct ( m1 !! i ), ( m2 !! i ). Qed .
Lemma lookup_core m i : core m !! i = core ( m !! i ).
Proof . by apply lookup_omap . Qed .

Lemma lookup_includedN n ( m1 m2 : gmap K A ) : m1 ≼< n > m2 ↔ ∀ i , m1 !! i ≼< n > m2 !! i .
Proof .
split ; [ by intros [ m Hm ] i ; ∃ ( m !! i ); rewrite — lookup_op Hm |].
revert m2 . induction m1 as [| i x m Hi IH ] using map_ind ⇒ m2 Hm .
< ∃ m2 . by rewrite left_id . >
destruct ( IH ( delete i m2 )) as [ m2′ Hm2′ ].
< intros j . move : ( Hm j ); destruct ( decide ( i = j )) as [->|].
— intros _ . rewrite Hi . apply : ucmra_unit_leastN .
— rewrite lookup_insert_ne // lookup_delete_ne //. >
destruct ( Hm i ) as [ my Hi’ ]; simplify_map_eq .
∃ ( partial_alter ( λ _ , my ) i m2′ )=> j ; destruct ( decide ( i = j )) as [->|].
— by rewrite Hi’ lookup_op lookup_insert lookup_partial_alter .
— move : ( Hm2′ j ). by rewrite ! lookup_op lookup_delete_ne //
lookup_insert_ne // lookup_partial_alter_ne .
Qed .

Lemma lookup_included ( m1 m2 : gmap K A ) : m1 ≼ m2 ↔ ∀ i , m1 !! i ≼ m2 !! i .
Proof .
split ; [ by intros [ m Hm ] i ; ∃ ( m !! i ); rewrite — lookup_op Hm |].
revert m2 . induction m1 as [| i x m Hi IH ] using map_ind ⇒ m2 Hm .
< ∃ m2 . by rewrite left_id . >
destruct ( IH ( delete i m2 )) as [ m2′ Hm2′ ].
< intros j . move : ( Hm j ); destruct ( decide ( i = j )) as [->|].
— intros _ . rewrite Hi . apply : ucmra_unit_least .
— rewrite lookup_insert_ne // lookup_delete_ne //. >
destruct ( Hm i ) as [ my Hi’ ]; simplify_map_eq .
∃ ( partial_alter ( λ _ , my ) i m2′ )=> j ; destruct ( decide ( i = j )) as [->|].
— by rewrite Hi’ lookup_op lookup_insert lookup_partial_alter .
— move : ( Hm2′ j ). by rewrite ! lookup_op lookup_delete_ne //
lookup_insert_ne // lookup_partial_alter_ne .
Qed .

Lemma gmap_cmra_mixin : CmraMixin ( gmap K A ).
Proof .
apply cmra_total_mixin .
— eauto .
— intros n m1 m2 m3 Hm i ; by rewrite ! lookup_op ( Hm i ).
— intros n m1 m2 Hm i ; by rewrite ! lookup_core ( Hm i ).
— intros n m1 m2 Hm ? i ; by rewrite -( Hm i ).
— intros m ; split .
+ by intros ? n i ; apply cmra_valid_validN .
+ intros Hm i ; apply cmra_valid_validN ⇒ n ; apply Hm .
— intros n m Hm i ; apply cmra_validN_S , Hm .
— by intros m1 m2 m3 i ; rewrite ! lookup_op assoc .
— by intros m1 m2 i ; rewrite ! lookup_op comm .
— intros m i . by rewrite lookup_op lookup_core cmra_core_l .
— intros m i . by rewrite ! lookup_core cmra_core_idemp .
— intros m1 m2 ; rewrite ! lookup_included ⇒ Hm i .
rewrite ! lookup_core . by apply cmra_core_mono .
— intros n m1 m2 Hm i ; apply cmra_validN_op_l with ( m2 !! i ).
by rewrite — lookup_op .
— intros n m y1 y2 Hm Heq .
refine ( ( λ FUN , _ ) ( λ i , cmra_extend n ( m !! i ) ( y1 !! i ) ( y2 !! i ) ( Hm i ) _ ) );
last by rewrite — lookup_op .
∃ ( map_imap ( λ i _ , projT1 ( FUN i )) y1 ).
∃ ( map_imap ( λ i _ , proj1_sig ( projT2 ( FUN i ))) y2 ).
split ; [| split ]=> i ; rewrite ? lookup_op ! map_lookup_imap ;
destruct ( FUN i ) as ( z1i & z2i & Hmi & Hz1i & Hz2i )=>/=.
+ destruct ( y1 !! i ), ( y2 !! i ); inversion Hz1i ; inversion Hz2i ; subst =>//.
+ revert Hz1i . case : ( y1 !! i )=>[?|] //.
+ revert Hz2i . case : ( y2 !! i )=>[?|] //.
Qed .
Canonical Structure gmapR := Cmra ( gmap K A ) gmap_cmra_mixin .

Global Instance gmap_cmra_discrete : CmraDiscrete A → CmraDiscrete gmapR .
Proof . split ; [ apply _ |]. intros m ? i . by apply : cmra_discrete_valid . Qed .

Lemma gmap_ucmra_mixin : UcmraMixin ( gmap K A ).
Proof .
split .
— by intros i ; rewrite lookup_empty .
— by intros m i ; rewrite /= lookup_op lookup_empty ( left_id_L None _ ).
— constructor ⇒ i . by rewrite lookup_omap lookup_empty .
Qed .
Canonical Structure gmapUR := Ucmra ( gmap K A ) gmap_ucmra_mixin .

Global Arguments gmapR _ < _ _ >_ .
Global Arguments gmapUR _ < _ _ >_ .

Section properties .
Context ` .
Implicit Types m : gmap K A .
Implicit Types i : K .
Implicit Types x y : A .

Global Instance lookup_op_homomorphism i :
MonoidHomomorphism op op (≡) ( lookup i : gmap K A → option A ).
Proof .
split ; [ split |]; try apply _ .
— intros m1 m2 ; by rewrite lookup_op .
— done .
Qed .

Lemma lookup_opM m1 mm2 i : ( m1 ⋅? mm2 ) !! i = m1 !! i ⋅ ( mm2 ≫= (. i ) ) .
Proof . destruct mm2 ; by rewrite /= ? lookup_op ? right_id_L . Qed .

Lemma lookup_validN_Some n m i x : ✓< n > m → m !! i ≡< n >≡ Some x → ✓< n > x .
Proof . by move ⇒ /( _ i ) Hm Hi ; move : Hm ; rewrite Hi . Qed .
Lemma lookup_valid_Some m i x : ✓ m → m !! i ≡ Some x → ✓ x .
Proof . move ⇒ Hm Hi . move 🙁 Hm i ). by rewrite Hi . Qed .

Lemma insert_validN n m i x : ✓< n > x → ✓< n > m → ✓< n > <[ i := x ]> m .
Proof . by intros ?? j ; destruct ( decide ( i = j )); simplify_map_eq . Qed .
Lemma insert_valid m i x : ✓ x → ✓ m → ✓ <[ i := x ]> m .
Proof . by intros ?? j ; destruct ( decide ( i = j )); simplify_map_eq . Qed .
Lemma singleton_validN n i x : ✓< n > ( <[ i := x ]> : gmap K A ) ↔ ✓< n > x .
Proof .
split .
— move =>/( _ i ); by simplify_map_eq .
— intros . apply insert_validN ; first done . apply : ucmra_unit_validN .
Qed .
Lemma singleton_valid i x : ✓ ( <[ i := x ]> : gmap K A ) ↔ ✓ x .
Proof . rewrite ! cmra_valid_validN . by setoid_rewrite singleton_validN . Qed .

Lemma delete_validN n m i : ✓< n > m → ✓< n > ( delete i m ) .
Proof . intros Hm j ; destruct ( decide ( i = j )); by simplify_map_eq . Qed .
Lemma delete_valid m i : ✓ m → ✓ ( delete i m ) .
Proof . intros Hm j ; destruct ( decide ( i = j )); by simplify_map_eq . Qed .

Lemma insert_singleton_op m i x : m !! i = None → <[ i := x ]> m = <[ i := x ]> ⋅ m .
Proof .
intros Hi ; apply map_eq ⇒ j ; destruct ( decide ( i = j )) as [->|].
— by rewrite lookup_op lookup_insert lookup_singleton Hi right_id_L .
— by rewrite lookup_op lookup_insert_ne // lookup_singleton_ne // left_id_L .
Qed .

Lemma gmap_core_id m : ( ∀ i x , m !! i = Some x → CoreId x ) → CoreId m .
Proof .
intros Hcore ; apply core_id_total ⇒ i .
rewrite lookup_core . destruct ( m !! i ) as [ x |] eqn : Hix ; rewrite Hix ; [| done ].
by eapply Hcore .
Qed .
Global Instance gmap_core_id’ m : ( ∀ x : A , CoreId x ) → CoreId m .
Proof . auto using gmap_core_id . Qed .

Lemma singleton_includedN_l n m i x :
<[ i := x ]> ≼< n > m ↔ ∃ y , m !! i ≡< n >≡ Some y ∧ Some x ≼< n > Some y .
Proof .
split .
— move ⇒ [ m’ /( _ i )]; rewrite lookup_op lookup_singleton ⇒ Hi .
∃ ( x ⋅? m’ !! i ). rewrite — Some_op_opM .
split ; first done . apply cmra_includedN_l .
— intros ( y & Hi &[ mz Hy ]). ∃ ( partial_alter ( λ _ , mz ) i m ).
intros j ; destruct ( decide ( i = j )) as [->|].
+ by rewrite lookup_op lookup_singleton lookup_partial_alter Hi .
+ by rewrite lookup_op lookup_singleton_ne // lookup_partial_alter_ne // left_id .
Qed .
Lemma singleton_included_l m i x :
<[ i := x ]> ≼ m ↔ ∃ y , m !! i ≡ Some y ∧ Some x ≼ Some y .
Proof .
split .
— move ⇒ [ m’ /( _ i )]; rewrite lookup_op lookup_singleton .
∃ ( x ⋅? m’ !! i ). by rewrite — Some_op_opM .
— intros ( y & Hi &[ mz Hy ]). ∃ ( partial_alter ( λ _ , mz ) i m ).
intros j ; destruct ( decide ( i = j )) as [->|].
+ by rewrite lookup_op lookup_singleton lookup_partial_alter Hi .
+ by rewrite lookup_op lookup_singleton_ne // lookup_partial_alter_ne // left_id .
Qed .
Lemma singleton_included_exclusive_l m i x :
Exclusive x → ✓ m →
<[ i := x ]> ≼ m ↔ m !! i ≡ Some x .
Proof .
intros ? Hm . rewrite singleton_included_l . split ; last by eauto .
intros ( y &?&->%( Some_included_exclusive _ )); eauto using lookup_valid_Some .
Qed .
Lemma singleton_included i x y :
<[ i := x ]> ≼ ( <[ i := y ]> : gmap K A ) ↔ Some x ≼ Some y .
Proof .
rewrite singleton_included_l . split .
— intros ( y’ & Hi &?). rewrite lookup_insert in Hi . by rewrite Hi .
— intros ?. ∃ y . by rewrite lookup_insert .
Qed .
Lemma singleton_included_total ` i x y :
<[ i := x ]> ≼ ( <[ i := y ]> : gmap K A ) ↔ x ≼ y .
Proof . rewrite singleton_included Some_included_total . done . Qed .
Lemma singleton_included_mono i x y :
x ≼ y → <[ i := x ]> ≼ ( <[ i := y ]> : gmap K A ) .
Proof . intros Hincl . apply singleton_included , Some_included_mono . done . Qed .

Global Instance singleton_cancelable i x :
Cancelable ( Some x ) → Cancelable <[ i := x ]> .
Proof .
intros ? n m1 m2 Hv EQ j . move : ( Hv j ) ( EQ j ). rewrite ! lookup_op .
destruct ( decide ( i = j )) as [->|].
— rewrite lookup_singleton . by apply cancelableN .
— by rewrite lookup_singleton_ne // !( left_id None _ ).
Qed .

Global Instance gmap_cancelable ( m : gmap K A ) :
( ∀ x : A , IdFree x ) → ( ∀ x : A , Cancelable x ) → Cancelable m .
Proof .
intros ?? n m1 m2 ?? i . apply ( cancelableN ( m !! i )); by rewrite -! lookup_op .
Qed .

Lemma insert_op m1 m2 i x y :
<[ i := x ⋅ y ]>( m1 ⋅ m2 ) = <[ i := x ]> m1 ⋅ <[ i := y ]> m2 .
Proof . by rewrite ( insert_merge (⋅) m1 m2 i ( x ⋅ y ) x y ). Qed .

Lemma insert_updateP ( P : A → Prop ) ( Q : gmap K A → Prop ) m i x :
x ~~>: P →
( ∀ y , P y → Q ( <[ i := y ]> m ) ) →
<[ i := x ]> m ~~>: Q .
Proof .
intros Hx % option_updateP’ HP ; apply cmra_total_updateP ⇒ n mf Hm .
destruct ( Hx n ( Some ( mf !! i ))) as ([ y |]&?&?); try done .
< by generalize ( Hm i ); rewrite lookup_op ; simplify_map_eq . >
∃ ( <[ i := y ]>m ); split ; first by auto .
intros j ; move : ( Hm j )=>< Hm >; rewrite ! lookup_op ⇒ Hm .
destruct ( decide ( i = j )); simplify_map_eq /=; auto .
Qed .
Lemma insert_updateP’ ( P : A → Prop ) m i x :
x ~~>: P → <[ i := x ]> m ~~>: λ m’ , ∃ y , m’ = <[ i := y ]> m ∧ P y .
Proof . eauto using insert_updateP . Qed .
Lemma insert_update m i x y : x ~~> y → <[ i := x ]> m ~~> <[ i := y ]> m .
Proof . rewrite ! cmra_update_updateP ; eauto using insert_updateP with subst . Qed .

Lemma singleton_updateP ( P : A → Prop ) ( Q : gmap K A → Prop ) i x :
x ~~>: P → ( ∀ y , P y → Q <[ i := y ]> ) → <[ i := x ]> ~~>: Q .
Proof . apply insert_updateP . Qed .
Lemma singleton_updateP’ ( P : A → Prop ) i x :
x ~~>: P → <[ i := x ]> ~~>: λ m , ∃ y , m = <[ i := y ]> ∧ P y .
Proof . apply insert_updateP’ . Qed .
Lemma singleton_update i ( x y : A ) : x ~~> y → <[ i := x ]> ~~> <[ i := y ]> .
Proof . apply insert_update . Qed .

Lemma delete_update m i : m ~~> delete i m .
Proof .
apply cmra_total_update ⇒ n mf Hm j ; destruct ( decide ( i = j )); subst .
— move : ( Hm j ). rewrite ! lookup_op lookup_delete left_id .
apply cmra_validN_op_r .
— move : ( Hm j ). by rewrite ! lookup_op lookup_delete_ne .
Qed .

Lemma gmap_op_union m1 m2 : m1 ##ₘ m2 → m1 ⋅ m2 = m1 ∪ m2 .
Proof .
intros Hm . apply map_eq ⇒ k . specialize ( Hm k ).
rewrite lookup_op lookup_union . by destruct ( m1 !! k ), ( m2 !! k ).
Qed .

Lemma gmap_op_valid0_disjoint m1 m2 :
✓< 0 > ( m1 ⋅ m2 ) → ( ∀ k x , m1 !! k = Some x → Exclusive x ) → m1 ##ₘ m2 .
Proof .
unfold Exclusive . intros Hvalid Hexcl k .
specialize ( Hvalid k ). rewrite lookup_op in Hvalid . specialize ( Hexcl k ).
destruct ( m1 !! k ), ( m2 !! k ); [| done ..].
rewrite — Some_op Some_validN in Hvalid . naive_solver .
Qed .
Lemma gmap_op_valid_disjoint m1 m2 :
✓ ( m1 ⋅ m2 ) → ( ∀ k x , m1 !! k = Some x → Exclusive x ) → m1 ##ₘ m2 .
Proof . move ⇒ / cmra_valid_validN /( _ 0). apply gmap_op_valid0_disjoint . Qed .

Lemma dom_op m1 m2 : dom ( m1 ⋅ m2 ) = dom m1 ∪ dom m2 .
Proof .
apply set_eq ⇒ i ; rewrite elem_of_union ! elem_of_dom .
unfold is_Some ; setoid_rewrite lookup_op .
destruct ( m1 !! i ), ( m2 !! i ); naive_solver .
Qed .
Lemma dom_included m1 m2 : m1 ≼ m2 → dom m1 ⊆ dom m2 .
Proof .
rewrite lookup_included =>? i ; rewrite ! elem_of_dom . by apply is_Some_included .
Qed .

Section freshness .
Local Set Default Proof Using «Type*».
Context ` .
Lemma alloc_updateP_strong_dep ( Q : gmap K A → Prop ) ( I : K → Prop ) m ( f : K → A ) :
pred_infinite I →
( ∀ i , m !! i = None → I i → ✓ ( f i ) ) →
( ∀ i , m !! i = None → I i → Q ( <[ i := f i ]> m ) ) → m ~~>: Q .
Proof .
move ⇒ /( pred_infinite_set I ( C := gset K )) HP ? HQ .
apply cmra_total_updateP . intros n mf Hm .
destruct ( HP ( dom ( m ⋅ mf ))) as [ i [ Hi1 Hi2 ]].
assert ( m !! i = None ).
< eapply not_elem_of_dom . revert Hi2 .
rewrite dom_op not_elem_of_union . naive_solver . >
∃ ( <[ i := f i ]>m ); split .
— by apply HQ .
— rewrite insert_singleton_op //.
rewrite — assoc — insert_singleton_op ; last by eapply not_elem_of_dom .
apply insert_validN ; [ apply cmra_valid_validN |]; auto .
Qed .
Lemma alloc_updateP_strong ( Q : gmap K A → Prop ) ( I : K → Prop ) m x :
pred_infinite I →
✓ x → ( ∀ i , m !! i = None → I i → Q ( <[ i := x ]> m ) ) → m ~~>: Q .
Proof .
move ⇒ HP ? HQ . eapply ( alloc_updateP_strong_dep _ _ _ ( λ _ , x )); eauto .
Qed .
Lemma alloc_updateP ( Q : gmap K A → Prop ) m x :
✓ x → ( ∀ i , m !! i = None → Q ( <[ i := x ]> m ) ) → m ~~>: Q .
Proof .
move =>.
eapply ( alloc_updateP_strong _ ( λ _ , True ));
eauto using pred_infinite_True .
Qed .
Lemma alloc_updateP_cofinite ( Q : gmap K A → Prop ) ( J : gset K ) m x :
✓ x → ( ∀ i , m !! i = None → i ∉ J → Q ( <[ i := x ]> m ) ) → m ~~>: Q .
Proof .
eapply alloc_updateP_strong .
apply ( pred_infinite_set ( C := gset K )).
intros E . ∃ ( fresh ( J ∪ E )).
apply not_elem_of_union , is_fresh .
Qed .

Lemma alloc_updateP_strong_dep’ m ( f : K → A ) ( I : K → Prop ) :
pred_infinite I →
( ∀ i , m !! i = None → I i → ✓ ( f i ) ) →
m ~~>: λ m’ , ∃ i , I i ∧ m’ = <[ i := f i ]> m ∧ m !! i = None .
Proof . eauto using alloc_updateP_strong_dep . Qed .
Lemma alloc_updateP_strong’ m x ( I : K → Prop ) :
pred_infinite I →
✓ x → m ~~>: λ m’ , ∃ i , I i ∧ m’ = <[ i := x ]> m ∧ m !! i = None .
Proof . eauto using alloc_updateP_strong . Qed .
Lemma alloc_updateP’ m x :
✓ x → m ~~>: λ m’ , ∃ i , m’ = <[ i := x ]> m ∧ m !! i = None .
Proof . eauto using alloc_updateP . Qed .
Lemma alloc_updateP_cofinite’ m x ( J : gset K ) :
✓ x → m ~~>: λ m’ , ∃ i , i ∉ J ∧ m’ = <[ i := x ]> m ∧ m !! i = None .
Proof . eauto using alloc_updateP_cofinite . Qed .
End freshness .

Lemma alloc_unit_singleton_updateP ( P : A → Prop ) ( Q : gmap K A → Prop ) u i :
✓ u → LeftId (≡) u (⋅) →
u ~~>: P → ( ∀ y , P y → Q <[ i := y ]> ) → ∅ ~~>: Q .
Proof .
intros ?? Hx HQ . apply cmra_total_updateP ⇒ n gf Hg .
destruct ( Hx n ( gf !! i )) as ( y &?& Hy ).
< move :( Hg i ). rewrite ! left_id .
case : ( gf !! i )=>[ x |]; rewrite /= ? left_id //.
intros ; by apply cmra_valid_validN . >
∃ <[ i := y ]>; split ; first by auto .
intros i’ ; destruct ( decide ( i’ = i )) as [->|].
— rewrite lookup_op lookup_singleton .
move : Hy ; case : ( gf !! i )=>[ x |]; rewrite /= ? right_id //.
— move 🙁 Hg i’ ). by rewrite ! lookup_op lookup_singleton_ne // ! left_id .
Qed .
Lemma alloc_unit_singleton_updateP’ ( P : A → Prop ) u i :
✓ u → LeftId (≡) u (⋅) →
u ~~>: P → ∅ ~~>: λ m , ∃ y , m = <[ i := y ]> ∧ P y .
Proof . eauto using alloc_unit_singleton_updateP . Qed .
Lemma alloc_unit_singleton_update ( u : A ) i ( y : A ) :
✓ u → LeftId (≡) u (⋅) → u ~~> y → ( ∅ : gmap K A ) ~~> <[ i := y ]> .
Proof .
rewrite ! cmra_update_updateP ;
eauto using alloc_unit_singleton_updateP with subst .
Qed .

Lemma gmap_local_update m1 m2 m1′ m2′ :
( ∀ i , ( m1 !! i , m2 !! i ) ¬ l ~> ( m1′ !! i , m2′ !! i ) ) →
( m1 , m2 ) ¬ l ~> ( m1′ , m2′ ) .
Proof .
intros Hupd . apply local_update_unital ⇒ n mf Hmv Hm .
apply forall_and_distr ⇒ i . rewrite lookup_op — cmra_opM_fmap_Some .
apply Hupd ; simpl ; first done . by rewrite Hm lookup_op cmra_opM_fmap_Some .
Qed .

Lemma alloc_local_update m1 m2 i x :
m1 !! i = None → ✓ x → ( m1 , m2 ) ¬ l ~> ( <[ i := x ]> m1 , <[ i := x ]> m2 ) .
Proof .
intros Hi ?. apply gmap_local_update ⇒ j .
destruct ( decide ( i = j )) as [->|]; last by rewrite ! lookup_insert_ne .
rewrite ! lookup_insert Hi . by apply alloc_option_local_update .
Qed .

Lemma insert_local_update m1 m2 i x y x’ y’ :
m1 !! i = Some x → m2 !! i = Some y →
( x , y ) ¬ l ~> ( x’ , y’ ) →
( m1 , m2 ) ¬ l ~> ( <[ i := x' ]> m1 , <[ i := y' ]> m2 ) .
Proof .
intros Hi1 Hi2 Hup . apply gmap_local_update ⇒ j .
destruct ( decide ( i = j )) as [->|]; last by rewrite ! lookup_insert_ne .
rewrite ! lookup_insert Hi1 Hi2 . by apply option_local_update .
Qed .

Lemma singleton_local_update_any m i y x’ y’ :
( ∀ x , m !! i = Some x → ( x , y ) ¬ l ~> ( x’ , y’ ) ) →
( m , <[ i := y ]> ) ¬ l ~> ( <[ i := x' ]> m , <[ i := y' ]> ) .
Proof .
intros . apply gmap_local_update ⇒ j .
destruct ( decide ( i = j )) as [->|]; last by rewrite ! lookup_insert_ne .
rewrite ! lookup_singleton lookup_insert .
destruct ( m !! j ); first by eauto using option_local_update .
apply local_update_total_valid0 ⇒ _ _ / option_includedN ; naive_solver .
Qed .

Lemma delete_local_update m1 m2 i x ` :
m2 !! i = Some x → ( m1 , m2 ) ¬ l ~> ( delete i m1 , delete i m2 ) .
Proof .
intros Hi . apply gmap_local_update ⇒ j .
destruct ( decide ( i = j )) as [->|]; last by rewrite ! lookup_delete_ne .
rewrite ! lookup_delete Hi . by apply delete_option_local_update .
Qed .

Lemma delete_singleton_local_update m i x ` :
( m , <[ i := x ]> ) ¬ l ~> ( delete i m , ∅ ) .
Proof .
rewrite -( delete_singleton i x ).
by eapply delete_local_update , lookup_singleton .
Qed .

Lemma delete_local_update_cancelable m1 m2 i mx ` :
m1 !! i ≡ mx → m2 !! i ≡ mx →
( m1 , m2 ) ¬ l ~> ( delete i m1 , delete i m2 ) .
Proof .
intros Hi1 Hi2 . apply gmap_local_update ⇒ j .
destruct ( decide ( i = j )) as [->|]; last by rewrite ! lookup_delete_ne .
rewrite ! lookup_delete Hi1 Hi2 . by apply delete_option_local_update_cancelable .
Qed .

Lemma delete_singleton_local_update_cancelable m i x ` :
m !! i ≡ Some x → ( m , <[ i := x ]> ) ¬ l ~> ( delete i m , ∅ ) .
Proof .
intros . rewrite -( delete_singleton i x ).
apply ( delete_local_update_cancelable m _ i ( Some x ));
[ done | by rewrite lookup_singleton ].
Qed .

Lemma gmap_fmap_mono ( f : A → B ) m1 m2 :
Proper ( (≡) ==> (≡) ) f →
( ∀ x y , x ≼ y → f x ≼ f y ) → m1 ≼ m2 → fmap f m1 ≼ fmap f m2 .
Proof .
intros . rewrite ! lookup_included ⇒ Hm i .
rewrite ! lookup_fmap . by apply option_fmap_mono .
Qed .

Lemma big_opM_singletons m :
( [^ op map ] k ↦ x ∈ m , <[ k := x ]> ) = m .
Proof .
rewrite big_op.big_opM_unseal / big_op.big_opM_def -( list_to_map_to_list m ).
assert ( NoDup ( map_to_list m ).*1 ) as Hnodup by apply NoDup_fst_map_to_list .
revert Hnodup . induction ( map_to_list m ) as [|[ k x ] l IH ]; csimpl ; first done .
intros [??]% NoDup_cons . rewrite IH //.
rewrite insert_singleton_op ? not_elem_of_list_to_map_1 //.
Qed .

Section unital_properties .
Context ` .
Implicit Types m : gmap K A .
Implicit Types i : K .
Implicit Types x y : A .

Global Instance gmap_fmap_ne ` ( f : A → B ) n :
Proper ( dist n ==> dist n ) f → Proper ( dist n ==> dist n ) ( fmap ( M := gmap K ) f ).
Proof . by intros ? m m’ Hm k ; rewrite ! lookup_fmap ; apply option_fmap_ne . Qed .
Lemma gmap_fmap_ne_ext `
( f1 f2 : A → B ) ( m : gmap K A ) n :
( ∀ i x , m !! i = Some x → f1 x ≡< n >≡ f2 x ) →
f1 m ≡< n >≡ f2 m .
Proof .
move ⇒ Hf i .
rewrite ! lookup_fmap .
destruct ( m !! i ) eqn :?; constructor ; by eauto .
Qed .
Global Instance gmap_fmap_cmra_morphism ` ( f : A → B )
` : CmraMorphism ( fmap f : gmap K A → gmap K B ).
Proof .
split ; try apply _ .
— by intros n m ? i ; rewrite lookup_fmap ; apply ( cmra_morphism_validN _ ).
— intros m . apply Some_proper ⇒ i . rewrite lookup_fmap ! lookup_omap lookup_fmap .
case : ( m !! i )=>//= ?. apply cmra_morphism_pcore , _ .
— intros m1 m2 i . by rewrite lookup_op ! lookup_fmap lookup_op cmra_morphism_op .
Qed .
Definition gmapO_map ` ( f : A — n > B ) :
gmapO K A — n > gmapO K B := OfeMor ( fmap f : gmapO K A → gmapO K B ).
Global Instance gmapO_map_ne ` :
NonExpansive (@ gmapO_map K _ _ A B ).
Proof .
intros n f g Hf m k ; rewrite /= ! lookup_fmap .
destruct ( _ !! k ) eqn :?; simpl ; constructor ; apply Hf .
Qed .

Program Definition gmapOF K ` ( F : oFunctor ) : oFunctor := <|
oFunctor_car A _ B _ := gmapO K ( oFunctor_car F A B );
oFunctor_map A1 _ A2 _ B1 _ B2 _ fg := gmapO_map ( oFunctor_map F fg )
|>.
Next Obligation .
by intros K ?? F A1 ? A2 ? B1 ? B2 ? n f g Hfg ; apply gmapO_map_ne , oFunctor_map_ne .
Qed .
Next Obligation .
intros K ?? F A ? B ? x . rewrite /= -( map_fmap_id x ).
apply map_fmap_equiv_ext ⇒ y ??; apply oFunctor_map_id .
Qed .
Next Obligation .
intros K ?? F A1 ? A2 ? A3 ? B1 ? B2 ? B3 ? f g f’ g’ x . rewrite /= — map_fmap_compose .
apply map_fmap_equiv_ext ⇒ y ??; apply oFunctor_map_compose .
Qed .
Global Instance gmapOF_contractive K ` F :
oFunctorContractive F → oFunctorContractive ( gmapOF K F ).
Proof .
by intros ? A1 ? A2 ? B1 ? B2 ? n f g Hfg ; apply gmapO_map_ne , oFunctor_map_contractive .
Qed .

Program Definition gmapURF K ` ( F : rFunctor ) : urFunctor := <|
urFunctor_car A _ B _ := gmapUR K ( rFunctor_car F A B );
urFunctor_map A1 _ A2 _ B1 _ B2 _ fg := gmapO_map ( rFunctor_map F fg )
|>.
Next Obligation .
by intros K ?? F A1 ? A2 ? B1 ? B2 ? n f g Hfg ; apply gmapO_map_ne , rFunctor_map_ne .
Qed .
Next Obligation .
intros K ?? F A ? B ? x . rewrite /= -( map_fmap_id x ).
apply map_fmap_equiv_ext ⇒ y ??; apply rFunctor_map_id .
Qed .
Next Obligation .
intros K ?? F A1 ? A2 ? A3 ? B1 ? B2 ? B3 ? f g f’ g’ x . rewrite /= — map_fmap_compose .
apply map_fmap_equiv_ext ⇒ y ??; apply rFunctor_map_compose .
Qed .
Global Instance gmapURF_contractive K ` F :
rFunctorContractive F → urFunctorContractive ( gmapURF K F ).
Proof .
by intros ? A1 ? A2 ? B1 ? B2 ? n f g Hfg ; apply gmapO_map_ne , rFunctor_map_contractive .
Qed .

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *