 About the verification program we heard a nice talk before, by an invited lecturer. We all know thatmez verification is a hard problem. It was just reminded to you in your previous talk. There are a few cases where we have this ability. For example, it is decidable to do verification within sequential programs, with variables ranging over finite domains. in je to boljamo programi, da je v mojimi poslednjih vrtišnjih. Čač si bilo, da nam pogodili, da bilo prezettovati, da je program imel imel imel imel imel imel. Tako, da ima povodnih, da si pogodili, da ne vrtišno bo, da si pogodili, da se vrtišno bo, da si pogodili, da se prišel imel imel imel imel imel imel imel imel imel imel imel i ta. izgledaj, da počuljam veliko delovih daljina svih malih delovih vz stroj. H styla možem sredi počulno se vzgledačne tega v tako organiziivanje vse v kanji stajnji, k začji vzgledačne ljude. Pomeni tudi, zarediljest-gi bov, kjer splah je k accounts in imaš pomočenje, kako je vzgleda. Zelo, da je uvršenja, da je izgleda. Zato smo začali z tudi vseh razliz, vzgleda je zelo nekaj delovih programa, vsi z miskega rečenje in posleda. Zato, da je izgleda, da je izgleda, da je zelo zelo, da je zelo, da je vzela ozelo kaj je. Zato, da je odličila v težkje programe, vzela, da je zelo, da je zelo, da je zelo, če je to pričačne objevanie, je zelo začeljno vzela, in da je zelo, da je zelo, da je zelo, da je zelo, začeljno vzela programe, in vse zrga, kaj je skupnje in zrga spremaril, da je bilo oboječen, ni vse oboječen. So, vse tebe, da je bilo to nekaj framework, da se tako zelo počutno je povedal. Zelo je bilo vse način o češko, o češko, o češko. In in začal bi smo vsezvajati, kar bilo izgledaj oboječen, kjer je si izgledaj oboječen izgledaj oboječen, in tudi vznikovate programov, z timi vznikovati prič. Znači me, da se predstavili, kako je vznikovate programov. Vsešče, ki smo vznikovati vznikovati programov, zato je z njiha vznikovati, vznikovati počet, The novelty compared to the real program is really that we use constants, functions, and relations that are uninterrupted. So in order to have the exact semantics of your program you really need to provide a data model for those. So it's really the data you are using are really terms built on over this constant and function that aren't in terms of... We can use relations in your tests for assumptions. For the concurrent interpretive programs, we allow multiple threads and shared variables that can be used by all these threads. For each thread, you really have sequential program that can really use both locally and shared variables. And here just a sample of what cobal syntax, as you see here, Prepočujemo, da smo rekačno, da se je tega. V tem, ki smo videli, ta nič češnja, je tudi tega. Zato je zelo vseh sej, da se je vsej pomenu, ta je F, ta je vsej sej, za tudi vsej, in tudi je to izgleda, je to spetihovana v problem, tako z tem, ko je izgleda k kontrolu. I zemljamo z tudi, če je tudi tega, skrič je izgleda, da se je tudi tudi po svej pristru, that is be extracted away, and we have this assumed statements that are really used to state conditions, and conditions can be any boolean combination of equality tests and interpreted relations. Ok? Here are an example that we'll use through this stock. So let's assume that we have this shared variables and these are the initial values. F is here a constant, so it's an in izgledaj. Zdaj smo ne boče. Usef je realitava, da je je nespečno, da je bolj v bolj, pa其實 je kadem je konstant, skoči na modelet. In nekaj smo prijevali, da nekaj se prišlo, ki je, in ki je, da je, in je, da je konstant, ki je izgleda, v segmentu listu, začnjenja iz X en Y, in več, ki sem ne nezvečen, ili igrem izvanja všaj povet, ki se mi inovali. Tukaj zelo, ki jih prejmova, če to pripolite v složenje v vso, priključenje, priklječenje, priklječenje skupov. Se razdače drugi vso reduce.Laughter vse je danas štih, konečnja programa. In, kako jih vse finiši, jih dajte, dajte, na 10 minute programa. Tudi tudi elementi, tudi je in interpretivna funkcija. Tudi tudi, tudi in drugi, tudi in interpretivna funkcija. Tudi je tudi terba, tudi. Kako je in executivna tudi programa, nekaj in interpretivna tudi in in inelijno inrelijno v tango informacije na vse producenje. Tudi tudi tudi tudi inelijno vse producenje, nekaj inelijne этих sk artificičnih. Tudi estetice tudi inelijne naspecije inelijne predpredajte inelijne predpredajte, veči nalega. Tudi tebe Oskizujem d Resources statements. We can restrict really, to use only equality in equality conditions, because we can get rid of relations by using new functions in invirables, and these statement essentially. We need really to make evident when we have a code for functions, so we'll use this symbol to really say there is a code for a function, and we have returns, of course, in order to really keep track of the control flow in various threads. Zato, zato, izgledaj, izgledaj, zelo se počeko. Zato, da smo izgledaj, če sem izgleda, vredno. Danes smo počeko na toga. In smo počeko na toga valjev. Zelo smo na toga, da smo izgleda, zato, da smo izgleda, da je bilo nekaj, zato smo izgleda, da smo počeko na toga listu. Danes smo do vrstvih konditij, Pomelo pri keepド Then we can assume that the key is found then we can do this or maybe start with the second thread, so. What is interested for us by this execution is that we look at this execution as the ways of computing terms, so what we look at is in terms computed by its execution, at the same time we also look at the accumulated assumptions. We are. Na različenju, da se prišli do prejdičnjih. Na različenju, da smo tudi variboli, in tudi tudi variboli b&d imali inisiali valjev, ali so imali inisiali v f. Tako, da imali inisiali valjev, da f je konstant, tudi imamo, da je vsef 0, je konstant v teori, vsef. In vse, da imali inisiali valjev, da imali inisiali valjev. Tako, da imamo vsef 1, a zdetevamo do prejdičenju. Logo, da je vsef f vsef s tudiyou. Anda leža ter te vezesom, boysa vsef 0, ček ta je po koš у treb cr. Shupnja vzgradulija tudi nezaj garnish, drug ogudiyi nekaj googori, ti drželo modrene ili každje samov Markov, prije gado bitinaudible Lobov, kjer dobišče, da je počkaj počkaj prizva tjega. Počkaj je tjega tjega tjega 0, in vzvej je f0, ki jih mi vzvežišče, da je izgledajno, da je vzvežiča. Taj sem tjega za primer, da se vedimo, trenusimo zvrstko z vrstko, a z njih praktimumem vzvežimo, ki je vzveža z vrstko. Kaj je vzvežim to, pospojovoj smo išli. The computation has we have the bunch of chrome that has been computed, some of these terms are still in the variable, some others have been dropped, during the computation. We have collected this series of assumptions. OK. So, you have a notion of what is a feasible execution at this point, so as you see the execution is really not kako bilo kante v Dr.っちゃ delati na ob smoothly, ne Here startups are feasible because you can have some contradictions on the Assumtions to do. So the notion of visibility is essentially dis. We want really that all the Assumtions that we collect are not in contradiction. And in this case as we see, there is no contradiction that arises from this assumption. that is feasible in some data model. Essential. So, let's get to the verification problem that we consider. Essentially, we are given with... No, this is just a definition. We will see how we check this later. So right now, it's just a definition saying, OK, what is feasible as a fusion is a fusion če naj Anatolijski tudi sem se prišli pravilno. Ko ne ne zajmo prišli ni, da ni ne vedno vidi. S kjer smo ti posledali tudi prirodnosti, več čas te plywoodje, da tudi bari sređne nekaj. Nekaj ne zrejmo nekaj po še srečno. persistent of zrečne. To je počo, če tri načinu. S nema nekajилj, te ne bo čehljati. To je počo poživati. Kaj je to drugo? The verification problem is that there is a complete execution that is feasible? Yes. No, no. vsega vsega. Ta bilo čo je izgledaj. To je bilo tudi to, da je počelj, da je nekako ne potrebno vrša, so je si tudi začala progrom. A več je to nekaj rekač vsi nekaj reakcentiv, bojo se je vsega počelj pomečna vsega začala, ko je počelj, nekaj posledaj, začal je od nekaj posledaj na prve začala. I nedajte Zgledaj je ampak podljuto in to, da je skvident in believes refusing, sp claro, je da je odgleda, način si napravil je, da je, da je oigen. I vem, da je oskatil, da je odgleda, da je ampak, da je? Zgleda je započit po vseh, ki je odendat. is really the K constant, the K term. This can be really reduced to something like this. We can really offend a piece of code at the end of the second trade and this becomes a feasibility check, essentially. Good. So in general, this problem is undecidable. And the undecidibility comes directly from the undecidability of feasibility in sequential and interpretive programs. Again, we need to... One thing that was proved in that result is that if we relax this currency notion, you get the undecidability. So it's really the list you have to require for this ability. So we require the same thing here, but again, this is still undecidable and this time in undecidability is due to the control flow. We still have recursive calls and a shared variable of memory. And whatever terms you consider, boolean variables are really at the bottom of whatever you can really imagine. No, you can have terms in general. Yeah, when it's a bil, it's enough of boolean variables because you have multiple threads with recursive calls and shared boolean variables. That's enough for undecidability. So for this reason, we consider the other restriction. So in order to gain this ability, we introduce the bounding constraints that have been already introduced for boolean programs. And actually, even for this class of programs, these constraints are enough to gain this ability. So what we consider then is really this bounded verification problem. So given a concurrent and interpretive program and a bounding condition, the question now is that, is there a complete execution of the program that is feasible, coherent, and that satisfies this bounding condition? And the main step in our decision algorithm is really a reduction of this coherency and feasibility check to the emptiness, so reachability, essentially, in multi-stack visibly push-down automaton. This is the key step. All the rest is kind of taken from the literature. I'll talk about coherence, but I haven't said what is exactly coherence. So a program is coherent, let's say a program execution is coherent, if it is both memorizing it as early assumes. What memorizing means? It actually means that if you compute a term, this term, either is a new term, so it's not equivalent to any term that was computed so far. You can really get a term that is equivalent to one of the previously computed ones, but in that case, you must have one representative for this equivalence class in some of the variables of the problem at that time. So this is a memorizing requirement. Early assumes means if you check for equality or disequality two terms, this has to be done early in the computation, in the sense that either you don't have super terms of these terms that have been computed, or all the super terms that have been computed are still in some variable at that time. So this means early assumes. It was shown in a previous publication that relaxing either one of these allows you really to encode two-remachine, essentially. You get undisadability. In this case, the program is coherent in the sense that all the feasible computations are coherent. The reason is that the terms, if you see, here we compute terms, we never go back to previous terms, so it's really always new terms are computed. This key is on the top of several n-nesting application, and the n is always adding n. And there is no assume that really collapse these kind of structures. So really, all these feasible execution are memorizing in this case. And also the early assumes is a requirement that is satisfied, because as we see, in the test we really compare these terms with constants, essentially. And the terms here, when they are computed, are really used immediately. Possibility that we really use in a test term with super terms already computed. So for this reason, this is also as early assumes. So as we mentioned before, since the length of the computation is unspecified, it's unbounded, in order to check this condition, we should really... I mean, we cannot really keep all the information. We need to do something smarter, because the length of computation is unbounded. So what was done for sequential programs is really that they proved. This is a paper by Umang Matur, Matus Dan, and my issue is about this one and ten, probably this year, essentially. Okay, probably it's almost there again, so 2019. So what did is really move the attention to the variables, not to the terms. So they're collecting some information about the terms currently stored in the variables. So they're keeping this equality in equality relations among the terms stored now in the variables. And they keep this map over the direct immediate super term through this variable, for these variables again. And they also keep this information about if a direct immediate super term was computed and then dropped in the computation. So what they show is that if the computation is a coherent, essentially, this is enough really to ensure... Okay, this is enough really to ensure that feasibility and coherency decided on the top of these relations is equivalent to do this on the collection of all terms and all assumptions. Okay. So essentially this relation is used to check feasibility. So equality in equality are sufficient to check feasibility of a computation. This is used only in the updating, the equality in equality relation because once you, for example, you assign a term with a variable, with another variable, you put them in the same equivalence class because they become equivalent. But then you have to propagate this up to all the super terms. And for this you need to remember what are the super terms that are stored in the other variables. So you have to update the equivalence according to this mapping. All this can be updated correctly if the computation is coherent. And this last thing is used only to check in coherency. As soon as you really go and compute the term that was already computed but dropped, you realize it's not memorizing. And similarly you can check if it does not have earlier issue. So for concurrent and interpretive programs, we can really build the same kind of abstraction of that information, but things are way more complex, as you can imagine. So let me give you some hint on why these things are complex. So let's consider quickly this computation. Essentially here we have a term T1, that is stored in a local variable x of thread 1. Then we assume that this term is equal to whatever it was stored in global variable g. So we establish this equivalence at this point. Then we take another term T2 in a local variable of the second thread. And then we do this assume with a global variable. So we are establishing now a relation among this term T1 and T2 are equivalent at this point of the computation because of this. And then we can call arbitrarily. So what happen is that these two terms are equivalent in our computation, but you can have this information stored very deep into the stacks of different threads. And then you have to really keep somehow this information. And then this g can be really compared to other global variables, so you add more equivalences. And at some time g can be dropped, so you lose this link in the shared memory. And you can also drop all the other things, so really you are left with this information. That you can really need to check, to keep this information among two arbitrary terms that are stored as some depth in any stack. So this is really the difficult part of how to keep all this information. OK, the idea is really to establish a kind of relation between elements on the stack and the shared control state. So really we are encoding a kind of lists of information. So the idea is really, for example, we use these shadow variables for this. A shadow variable we have really for each variable of the program, we make a copy for each of the threads. So we have the application of the information. And what is the invariant we consider, is really in the control state, the term that is stored in this shadow variable is really the term that was stored in the original variable at the time of the last call of that thread. And when we do, essentially when we push it in the stack, we really make this assignment. It's like we are really linking the information we have in the control state with the information in the stack, because the copy that we have, I mean the shadow variable that we have in the control state has the same value of the actual variable on the top of the stack. And this relation also for the symbol of the top of the stack and the symbol below it. So it's really, we build this kind of connection between this information. So, for example, when we make a call within t1, as we said, we take this information. So here we're not really storing the terms, but we're storing the equivalences and the mapping that I was telling before. So we have this kind of relation among the terms that are stored, among the variables. So what happens when we do the push, we really project this information only on the part that concerns the thread. So it's really, we keep this part of this information and it's pushed on the top of the stack. And at the same time, then we make this xi equal to x at this point. And this will change, of course, all the information we have in the equivalent of the map. Then when we do the pop, we have to do the reverse action. We have to take this information, this information we have to merge to reconstruct the actual information with this new environment. So, essentially, what we do is really, we impose equality between these two elements, and then we merge the information according to this equivalence. So everything is changed as x1 at this point has the value that it had at the time of the last code. On the other steps, we only modify the information according to what is the modification of the original variables, essentially. So the decision algorithm really goes like this. We construct this MVPA. It's exponential. I will not tell you more about this. Then we construct another MVPA that can capture all the execution for the concurrent program. We take the intersection of the two. And then we really check if there is a computation that is accepted by this automaton and satisfying also the bounding constraints, essentially. So, using the results from the literature, I mean, we had to slightly change just a few of these to get the tight complexity bounds, but we're really minor changes in the original decision algorithm. But what we can show is really that when we apply the bounded content switching, scope bounded, bounded budget, bounded part three restrictions, the problem is at the time complete. Hardness comes from the hardness and feasibility for sequential programs. And when we use these other two conditions instead, so the bounded phase and the ordered restriction, the problem is to explain complete. This time, the lower bound comes from the same problem for Boolean programs. OK, so what we have done, really, we have extended these results that were given for sequential interpreter programs and concurrent Boolean programs. What we think would be interesting is really how to extend this, for example, to parameterized system. So, system where you don't know in advance the number of threads. So, for example, when you have dynamic creation of threads, and our construction does not really extend immediately because we use the name of the threads. And in this case, you should do all this without really referring to a specific thread, in particular. So, this is really an open question now. And another thing that worked pretty well for Boolean program was this sequentialization. So, reducing concurrent program to an equivalent, let's say equivalent sequential program. And that was really used in tools to do verification in practice. And, again, what we have done here does not really extend directly to handle the sequentialization because in sequentialization what you do is really you arrange the ordering of the statements. So, if you start with a program that is coherent, you can end up in a sequential program that is not coherent. OK, this is the main problem, but there should be a way to do it because it's not really changing the semantics. So, there should be something else that should be discovered to decide the problem through the sequential programs. And, of course, I mean, to see if this class of programs, concurrent programs is useful in practice. So, we did not look at the application so far. OK, thank you. Sorry for the time. Checking approach to taking this from these of these programs. Yeah. What about logic approach, like what about... The... OK. It does not extend this level to the last one. I... It's really... So, I think you can... I don't know as a technique, but, for example, you can check precondition. As you see, it really can be reduced to feasibility. So, a precondition can be just placed there as an issue at the beginning of the program. So, I think you can do that kind of analysis, but I don't know if you can really apply those results directly. So, we didn't really look at that. But, I think you can have that kind of verification. Yeah, yeah. Is this necessary? No, no, no. This is not necessary. I think, as long as you use a finite domain, whatever, you are fine. Yeah, yeah. This is really to make it general, in the sense, we don't need to... As you see, in my example, the first thing I say, assume f is different from t. Just to say, OK, I need two values at least, no? Two different constants. But, yeah, as long as you add variables over finite domains, you have no problems. OK. OK. So, you cannot, for instance, say something like this, in the button. You say in a list, for example, the list is an interpolate, because otherwise you have a problem. So, you don't need to provide invites, for example, in this kind of analysis. So, if you want to make that interpolate, I think you need to do something that is not structured, is unbounded information, is unbounded traction. I don't know if this is the question. If you are a successor in the program semali, because you have an ordering of things, that you are. No, I don't completely provide this undesirable information. OK. Go through the... Because what you can do, you can really, in different terms, you can counter separately, and then you can check for you means you, in some form. So, in order to do this, you are to... So, increment, quarter by, increment, and you can... Exactly. No, no, what is equivalent? So, if you cannot interpret when this thing is accurate, you can assume, you make them equivalent. But you cannot assume that says, let's say that f is increment and g is equivalent, no? You can say that the term t is equivalent to f, g, t. Do you want to... Yeah, but it's propagates. The point is that when you have the equivalent assumption, you cannot really collapse this structure. You have to do this on the way. So, in order to... You have to build something, and at some point you go at the bottom, for example, you say these two things are one... ...vers of the others. And at that point you have the construction for the Turing machine, but that's not equivalent anymore. But if you want, we can take offline... These are simple proofs, really. And the trick is always this one, no? You build these structures, and in the end you establish some connection when you lost all the terms in between, essentially.