Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
8fff536
start work on this
jcp19 Jan 20, 2026
3f67c3b
continue working on a model
jcp19 Jan 20, 2026
05f9026
change todos
jcp19 Jan 20, 2026
76b439c
resalgebraNoAxioms
jcp19 Jan 20, 2026
4e44225
add assumption to make verification pass
jcp19 Jan 20, 2026
9a5598a
backup
jcp19 Jan 20, 2026
bdb8b65
fix typo
jcp19 Jan 20, 2026
fe28b82
Merge branch 'main' into resalgebra2
jcp19 Jan 20, 2026
e898264
Merge branch 'main' into resalgebra2
jcp19 Jan 20, 2026
68dc6af
backup
jcp19 Jan 20, 2026
db29a30
clean-up
jcp19 Jan 20, 2026
46da2e4
backup
jcp19 Jan 20, 2026
37734ff
add init code
jcp19 Jan 20, 2026
0647c03
progress with proof
jcp19 Jan 20, 2026
a41cb20
drop duplicated code
jcp19 Jan 20, 2026
2a7ff7f
drop assumptions
jcp19 Jan 20, 2026
c9472c8
clean-up, verify some assumptions
jcp19 Jan 21, 2026
a9b0dc2
Merge branch 'main' into resalgebra2
jcp19 Jan 21, 2026
3ad5e99
another assumption proven
jcp19 Jan 21, 2026
545d582
anoda one
jcp19 Jan 21, 2026
35a7232
prove another assumption
jcp19 Jan 21, 2026
71a44b3
prove another assumption
jcp19 Jan 21, 2026
aa13f67
prove two more assumptions
jcp19 Jan 21, 2026
4709ed0
prove one more assumption
jcp19 Jan 21, 2026
0eb6783
simplify proof obligation
jcp19 Jan 21, 2026
7015069
cleanup
jcp19 Jan 21, 2026
142427d
made RA lemmas pure to make them easier to work with
jcp19 Jan 21, 2026
ed9e7c1
One more assumption proved
jcp19 Jan 21, 2026
a6cf4f1
last assumption
jcp19 Jan 21, 2026
1047c69
add explanation on missing invariant
jcp19 Jan 21, 2026
fd169f4
add body to all functions that depend on the invariant
jcp19 Jan 25, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions genericmonomap/monomap.gobra
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,21 @@ pure func (m MonoMap) ToDict() dict[Key]Val {
(m.inUse ? (let smallMap := MonoMap(m.next).ToDict() in smallMap[m.k = m.v]) : dict[Key]Val{})
}

ghost
requires m.Inv()
decreases m.Inv()
pure func (m MonoMap) KeySet() set[Key] {
return domain(m.ToDict())
}

ghost
requires m.Inv()
requires k elem domain(m.ToDict())
decreases m.Inv()
pure func (m MonoMap) Get(k Key) Val {
return let d := m.ToDict() in Val(d[k])
}

pred (m MonoMap) Witness(k Key, v Val) {
acc(&m.inUse, _) && acc(&m.next, _) && acc(&m.k, _) && acc(&m.v, _) &&
isComparable(k) &&
Expand Down
140 changes: 140 additions & 0 deletions resalgebraNoAxioms/auth.gobra
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
// Copyright 2025 ETH Zurich
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// +gobra

package resalgebraNoAxioms

var _ RA = TypeAuthRA{}
var AuthRA TypeAuthRA = TypeAuthRA{}

type IntWithTopBot interface {}
type Top struct{}
type Bottom struct{}
type Int struct {
V int
}

type AuthCarrier struct {
Fst IntWithTopBot
Snd int
}

type TypeAuthRA struct{}

ghost
decreases
pure func AuthView(m int) Elem {
return AuthCarrier{Int{m}, 0}
}

ghost
decreases
pure func FragView(m int) Elem {
return AuthCarrier{Bottom{}, m}
}


ghost
decreases
pure func (ra TypeAuthRA) IsElem(e Elem) (res bool) {
return typeOf(e) == type[AuthCarrier] &&
let c := e.(AuthCarrier) in
c.Fst === Bottom{} ||
c.Fst === Top{} ||
typeOf(c.Fst) == type[Int]
}

ghost
requires ra.IsElem(e)
decreases
pure func (ra TypeAuthRA) IsValid(e Elem) bool {
return let x := e.(AuthCarrier) in
x.Fst === Bottom{} ||
(typeOf(x.Fst) == type[Int] && x.Fst.(Int).V >= x.Snd)
}

ghost
requires ra.IsElem(e)
ensures res !== none[Elem] ==> ra.IsElem(get(res))
decreases
pure func (ra TypeAuthRA) Core(e Elem) (ghost res option[Elem]) {
return let x := e.(AuthCarrier) in
some(Elem(AuthCarrier{Bottom{}, x.Snd}))
}

ghost
requires ra.IsElem(e1) && ra.IsElem(e2)
ensures ra.IsElem(res)
decreases
pure func (ra TypeAuthRA) Compose(e1 Elem, e2 Elem) (res Elem) {
return let c1 := e1.(AuthCarrier) in
let c2 := e2.(AuthCarrier) in
(c1.Fst === Bottom{} ?
AuthCarrier{c2.Fst, max(c1.Snd, c2.Snd)} :
(c2.Fst === Bottom{} ?
AuthCarrier{c1.Fst, max(c1.Snd, c2.Snd)} :
AuthCarrier{Top{}, max(c1.Snd, c2.Snd)}))
}

ghost
decreases
pure func max(a int, b int) int {
return a > b ? a : b
}

// all lemmas proven automatically


ghost
decreases
pure func (ra TypeAuthRA) ComposeAssoc(e1 Elem, e2 Elem, e3 Elem) Unit {
// proved
return Unit{}
}

ghost
decreases
pure func (ra TypeAuthRA) ComposeComm(e1 Elem, e2 Elem) Unit {
// proved
return Unit{}
}

ghost
decreases
pure func (ra TypeAuthRA) CoreId(e Elem) Unit {
// proved
return Unit{}
}

ghost
decreases
pure func (ra TypeAuthRA) CoreIdem(e Elem) Unit {
// proved
return Unit{}
}

ghost
decreases
pure func (ra TypeAuthRA) CoreMono(e1 Elem, e2 Elem) Unit {
// proved
return Unit{}
}

ghost
decreases
pure func (ra TypeAuthRA) ValidOp(e1 Elem, e2 Elem) Unit {
// proved
return Unit{}
}
144 changes: 144 additions & 0 deletions resalgebraNoAxioms/cooliomapio.gobra
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
// Copyright 2025 ETH Zurich
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// +gobra

package resalgebraNoAxioms

// map that can only grow monotically. adding a new element to the map
// requires and ensures the map invariant, but checking that a key-pair value (or a key is in the map) is in the map
// should not require the map inv

ghost type key = LocName
ghost type val = cooliosetio

ghost type node ghost struct {
inUse bool
next gpointer[node]
k key
v val
p perm
}

// todo: change
ghost type cooliomapio gpointer[node]

pred inv(m cooliomapio) {
acc(m, 1/2) &&
(m.next == nil ==> !m.inUse && acc(m, 1/2)) &&
(m.next != nil ==>
m.inUse &&
acc(&m.p, 1/2) &&
inv(m.next) &&
m.p > 0 &&
acc(&m.inUse, m.p) && acc(&m.next, m.p) && acc(&m.k, m.p) && acc(&m.v, m.p))
}

ghost
mayInit
ensures inv(m)
ensures toDict(m) == dict[key]val{}
decreases
func allocMap() (m cooliomapio) {
var g@ node
fold inv(&g)
return &g
}

ghost
requires inv(m)
decreases inv(m)
pure func toDict(m cooliomapio) dict[key]val {
return unfolding inv(m) in (m.inUse ? (let smallMap := toDict(m.next) in smallMap[m.k = m.v]) : dict[key]val{})
}

// ghost
// requires witness(m, k)
// decreases
// pure func getVal(m cooliomapio, k key) val

pred witness(m cooliomapio, k key, v val) {
acc(&m.inUse, _) && acc(&m.next, _) && acc(&m.k, _) && acc(&m.v, _) &&
(!m.inUse ==> false) &&
(m.k == k && m.v != v ==> false) &&
(m.k != k ==> witness(m.next, k, v))
}

ghost
requires inv(m)
requires !(k elem domain(toDict(m)))
ensures inv(m)
ensures witness(m, k, v)
// ensures getVal(m, k) === v
ensures toDict(m) === old(toDict(m))[k = v]
decreases inv(m)
func add(m cooliomapio, k key, v val) {
unfold inv(m)
if !m.inUse {
next@ := node{}
assert acc(m)
m.inUse = true
m.p = 1/4
m.next = &next
m.k = k
m.v = v
fold inv(m.next)
fold inv(m)
assert toDict(m) === unfolding inv(m) in toDict(m.next)[m.k = m.v]
assert toDict(m) === dict[key]val{k : v}
fold witness(m, k, v)
} else {
add(m.next, k, v)
assert witness(m.next, k, v)
m.p = m.p/2
fold inv(m)
fold witness(m, k, v)
}
}

ghost
requires 0 < p
requires acc(inv(m), p)
//requires witness(m, k)
requires witness(m, k, v)
ensures acc(inv(m), p)
ensures witness(m, k, v)
ensures k elem domain(toDict(m))
ensures toDict(m)[k] === v // v may not be comparable
decreases acc(inv(m), p)
func lemmaWitness(m cooliomapio, k key, v val, p perm) {
d := toDict(m)
unfold acc(inv(m), p)
unfold witness(m, k, v)
if m.k == k {
assert k elem domain(d)
} else {
lemmaWitness(m.next, k, v, p)
}
fold acc(inv(m), p)
fold witness(m, k, v)
}

ghost
requires witness(m, k, v)
ensures witness(m, k, v) && witness(m, k, v)
decreases witness(m, k, v)
func dupWitness(m cooliomapio, k key, v val) {
unfold witness(m, k, v)
if m.k != k {
dupWitness(m.next, k, v)
}
fold witness(m, k, v)
fold witness(m, k, v)
}
Loading
Loading