Live data from Hacker News

Mathematics for Computer Science (2024)

ocw.mit.edu

101–110 of 115 posts

Re: Mathematics for Computer Science (2024)

#101
post #99

Earlier quoted context omitted.

Need is a strong word. That's why I said effective . You can often iterate to something that kind of works by adding epicycles. What you're left with is something that fails in rare cases you can't explain, is difficult to change (we don't touch that code), and is slow. Compare a complex homegrown data store to a relational database like postgresSQL. Both get the job done, but one has significantly more conceptual cl…

> Compare a complex homegrown data store to a relational database like postgresSQL. Both get the job done, but one has significantly more conceptual clarity and reliability. That's a good example of what I said. Most software engineers don't develop new database management systems. They just use one. And if they merely use it, they don't need or benefit from nontrivial math. The math is abstracted away behind the int…

So did postgres appear out of thin air? What new SW technologies need to be developed?

If you're not interested in acquiring the kind of competency to develop new software, and are just interested in combining existing software, then you don't need a college degree.

Re: Mathematics for Computer Science (2024)

#102

Earlier quoted context omitted.

> The real value comes when you do it with the knowledge of the mathematics in hand because then it allows you to prove your Program as "Correct" (w.r.t. a specification). At the risk of nitpicking: Certainly it's a benefit to structure and understand code such that you can reason about it effectively, but prove goes too far. Almost no real code is proven correct, the ergonomics of formal methods are still far too po…

It depends; the "proving" can be done at a gross high level function or fine grained at statement level. Thus in the former case one could use Meyer's Design-by-Contract (aka DbC) while in the latter case one might choose to follow a detailed Dijkstra methodology. For both of the above you don't need any special tools (eg. Z/VDM/TLA+/Coq/Lean etc.) but merely the knowledge to learn to think about a Program using Math…

Design-by-contract typically refers to runtime checking of invariants, which is not the equivalent of formal verification. It should not be referred to as proving correctness. It doesn't do so.

If you want to prove your program's correctness, that's the domain of formal methods, essentially by definition.

Re: Mathematics for Computer Science (2024)

#103

Earlier quoted context omitted.

It depends; the "proving" can be done at a gross high level function or fine grained at statement level. Thus in the former case one could use Meyer's Design-by-Contract (aka DbC) while in the latter case one might choose to follow a detailed Dijkstra methodology. For both of the above you don't need any special tools (eg. Z/VDM/TLA+/Coq/Lean etc.) but merely the knowledge to learn to think about a Program using Math…

Design-by-contract typically refers to runtime checking of invariants, which is not the equivalent of formal verification. It should not be referred to as proving correctness . It doesn't do so. If you want to prove your program's correctness, that's the domain of formal methods, essentially by definition.

This argument has been made before and that is why i said it depends and put "proving" within quotes. It is a very narrow and wrong way of looking at Formal Methods (both Specification and Verification) and one of the main reasons the "ordinary" software engineer gets intimidated and overawed by formal methods and afraid to even approach the subject (as my comments to user cubefox shows).

A Formal Method defined broadly is the application of Mathematical Concepts/Models and Logic to the specification/implementation/verification of Computer Programs.

DbC is based on Hoare Logic where you try to "prove" the program intellectually and not necessarily tool driven. This was somewhat mechanized (though still a intellectual pursuit) by Dijkstra's technique of deriving weakest-preconditions. Because the whole process can be quite tedious, laborious and rather complex, automatic theorem prover tools were invented to do the job for you. This has resulted in the unfortunate status quo where Formal Specification/Verification have become identified with the use of tools and not the Mathematics behind them. Proving Correctness need not be fine-grained and absolute but can be good enough done partially at a gross level at specific stages in a program as needed and done either by hand and/or using tools.

DbC can be considered a lightweight Formal Method with aspects of both Specification and Verification included. The Programmer plays the role of "theorem prover" when using DbC. However tools exist to map "Design-by-Contract" constructs to "Verified Design-by-Contract" constructs. See for example https://www.eschertech.com/products/verified_dbc.php. Also Eiffel (quintessential DbC language) can be converted using AutoProof to a form which can be proven by Boogie verifier.

Finally; here is a case study Design by contract formal verification for automotive embedded software robustness (abstract & pdf) - https://hal.sorbonne-universite.fr/ERTS2024/hal-05028176v1

Re: Mathematics for Computer Science (2024)

#104

Earlier quoted context omitted.

Design-by-contract typically refers to runtime checking of invariants, which is not the equivalent of formal verification. It should not be referred to as proving correctness . It doesn't do so. If you want to prove your program's correctness, that's the domain of formal methods, essentially by definition.

This argument has been made before and that is why i said it depends and put "proving" within quotes. It is a very narrow and wrong way of looking at Formal Methods (both Specification and Verification) and one of the main reasons the "ordinary" software engineer gets intimidated and overawed by formal methods and afraid to even approach the subject (as my comments to user cubefox shows). A Formal Method defined broa…

> that is why i said it depends and put "proving" within quotes

I feel I need to insist on this point: a design-by-contract methodology using runtime checking may be an effective means of improving software quality, but it certainly isn't proving the correctness of a program. Using the word 'prove' here is just plain wrong. Putting it in quotation marks doesn't help. It simply does not constitute a proof.

> It is a very narrow and wrong way of looking at Formal Methods (both Specification and Verification) and one of the main reasons the "ordinary" software engineer gets intimidated and overawed by formal methods and afraid to even approach the subject

I'm not insisting on a narrow understanding of formal methods, I'm insisting on proper use of established terminology.

I'm all for practical methodologies that benefit software quality without paying the enormous costs of fully applying formal methods. Design-by-contract with runtime checking seems like a reasonable approach. (Static typing is another. Effect-oriented programming might be another.) My point was just about the proper use of the word proof.

> Proving Correctness need not be fine-grained and absolute but can be good enough done partially at a gross level at specific stages in a program as needed and done either by hand and/or using tools.

A program is proven correct only when the proof is absolute, which implies fine-grained. I'm not opposed to the use of partial proofs or 'good enough' proof-sketches, both of which could be useful in producing high-quality software in the real world, but we should be clear in how we refer to them.

I'm not sure about the idea of proving correctness by hand, though. Manually applying a formal model of a real programming language sounds unworkable. If code is well structured, it should be possible for the programmer to reason about it somewhat precisely, like a proof-sketch, but that's not a proof of correctness.

> The Programmer plays the role of "theorem prover" when using DbC

I don't find this convincing. There's nothing stopping the programmer from failing to notice some error. If you aren't actually doing a proof, just say so. There is no stand-in.

> tools exist to map "Design-by-Contract" constructs to "Verified Design-by-Contract" constructs.

Right, I hinted at this in my previous comment. SPARK Ada does this. In that case, correctness properties of the program are indeed formally proven. That's a quite different methodology to design-by-contract with runtime checking though, to the point that it almost seems unhelpful to refer to them both by the same name. I've had to be careful to explicitly state design-by-contract using runtime checking this whole time.

The deeper distinction here is between testing and formal proof, and design-by-contract can in principle refer to either.

> here is a case study Design by contract formal verification for automotive embedded software robustness

Have only skim-read but seems somewhat similar to this case-study about SPARK: https://www.adacore.com/tokeneer

Re: Mathematics for Computer Science (2024)

#105

Earlier quoted context omitted.

This argument has been made before and that is why i said it depends and put "proving" within quotes. It is a very narrow and wrong way of looking at Formal Methods (both Specification and Verification) and one of the main reasons the "ordinary" software engineer gets intimidated and overawed by formal methods and afraid to even approach the subject (as my comments to user cubefox shows). A Formal Method defined broa…

> that is why i said it depends and put "proving" within quotes I feel I need to insist on this point: a design-by-contract methodology using runtime checking may be an effective means of improving software quality, but it certainly isn't proving the correctness of a program. Using the word 'prove' here is just plain wrong. Putting it in quotation marks doesn't help. It simply does not constitute a proof. > It is a v…

I have used SPARK Ada myself on a couple of security focused products developed by a team of 10-15 developers. For a long time, SPARK has made use of formal methods practical for real-world software. Effective use does require learning and commitment, but that's within reason. By the time the projects were nearly done, I felt that the SPARK findings always turned out to be correct and that any remaining problems could be traced back to poor or missing requirements, not the implementation itself.

Re: Mathematics for Computer Science (2024)

#106

Earlier quoted context omitted.

This argument has been made before and that is why i said it depends and put "proving" within quotes. It is a very narrow and wrong way of looking at Formal Methods (both Specification and Verification) and one of the main reasons the "ordinary" software engineer gets intimidated and overawed by formal methods and afraid to even approach the subject (as my comments to user cubefox shows). A Formal Method defined broa…

> that is why i said it depends and put "proving" within quotes I feel I need to insist on this point: a design-by-contract methodology using runtime checking may be an effective means of improving software quality, but it certainly isn't proving the correctness of a program. Using the word 'prove' here is just plain wrong. Putting it in quotation marks doesn't help. It simply does not constitute a proof. > It is a v…

There is a nuanced but distinct difference in my use of the word Proof as used in Program as a Proof and Proof in a Mathematical Algebraic System which you have missed. They are isomorphic but not exact (hence my using the phrase it depends and scare-quotes around "proving").

The reason is because Mathematics deals with ideal and abstract objects whereas objects in the real world (eg. a computer program) can only map to aspects of the ideal world and not in its entirety.

To elaborate; a mathematical algebraic system is a set of objects and a set of operations defined on them. Axioms using those objects/operations are then defined and then inference/reasoning rules using these are defined to prove theorems in the system. There are various techniques for constructing proofs (eg. direct, induction, contradiction etc.) but all of them must map back to the domain of definition of the objects in the algebra to be considered valid and sound in the real world.

As an example, the axiom of associativity w.r.t. addition holds absolutely in mathematics when applied to {N, +} where N is the infinite set of ideal integers. But in computing it is not always the case i.e. (a+b)+c =/= a+(b+c) always because a/b/c are constrained/partial finite sets (i.e. int8/int16/int32 etc.) and thus the axiom of associativity will fail when for example, we take boundary values for a/b and a negative value for c (due to overflow/underflow). Thus any proof which uses the axiom of associativity for signed integers in a computer can never be as absolute and general as its counterpart in pure mathematics i.e. everything is Partial. In general, mathematics uses exact Analytical Techniques while computers use approximate Numerical Techniques to solve a problem which is reflected in the nature of their proofs.

Coming to DbC, since it is based on Hoare Logic (i.e. an algebra with axioms/inference rules), a Program is written as a series of Preconditions/Postconditions/Invariants with the Programmer acting as the Proof deriver. Thus if a series of pre/post/inv holds at a certain stage in the program (i.e. proof) the next post will hold (barring external cataclysms). The fact that the proof obligation is discharged dynamically at runtime is immaterial. But we may not want that in certain categories of real world programs since the question of what to do when the proof obligation is not met at runtime becomes a problem; Do we abort/Do we rollback to older known state etc. For a CRUD app we can abort and have the user restart but for a heart pacemaker app we don't want that. In the latter case since it is a closed system with well defined inputs/outputs we can map DbC to VDbC and then prove it through a verifier statically thus guaranteeing invalid states can never arise at runtime. But note that this is merely an incidental distinction due to the needs of the real world but the essential DbC guarantees remain the same.

It should now be clear that when you map concepts from mathematical to computing domain you need to understand how the same names like "Integer", "Set/Type", "Algebra", "Axiom", "Proof" map from one to the other (though not exactly) and how you can leverage their isomorphism to use symbolic Mathematics effectively in Programming while at the same time keeping in mind their differences due to real world computation constraints and limits.

References:

1) Mathematical Proof - https://en.wikipedia.org/wiki/Mathematical_proof

2) Computer-assisted Proof - https://en.wikipedia.org/wiki/Computer-assisted_proof In particular; see the "Philosophical Objections" section.

3) See also the book From Mathematics to Generic Programming by Alexander Stepanov and Daniel Rose to get an idea of how to map between mathematics and programming.

Re: Mathematics for Computer Science (2024)

#107

Earlier quoted context omitted.

> that is why i said it depends and put "proving" within quotes I feel I need to insist on this point: a design-by-contract methodology using runtime checking may be an effective means of improving software quality, but it certainly isn't proving the correctness of a program. Using the word 'prove' here is just plain wrong. Putting it in quotation marks doesn't help. It simply does not constitute a proof. > It is a v…

There is a nuanced but distinct difference in my use of the word Proof as used in Program as a Proof and Proof in a Mathematical Algebraic System which you have missed. They are isomorphic but not exact (hence my using the phrase it depends and scare-quotes around "proving" ). The reason is because Mathematics deals with ideal and abstract objects whereas objects in the real world (eg. a computer program) can only ma…

Correction: In the 4th para above replace set N (set of natural numbers) with set Z (set of all positive and negative integers).

Re: Mathematics for Computer Science (2024)

#108

Earlier quoted context omitted.

> that is why i said it depends and put "proving" within quotes I feel I need to insist on this point: a design-by-contract methodology using runtime checking may be an effective means of improving software quality, but it certainly isn't proving the correctness of a program. Using the word 'prove' here is just plain wrong. Putting it in quotation marks doesn't help. It simply does not constitute a proof. > It is a v…

There is a nuanced but distinct difference in my use of the word Proof as used in Program as a Proof and Proof in a Mathematical Algebraic System which you have missed. They are isomorphic but not exact (hence my using the phrase it depends and scare-quotes around "proving" ). The reason is because Mathematics deals with ideal and abstract objects whereas objects in the real world (eg. a computer program) can only ma…

> There is a nuanced but distinct difference in my use of the word Proof as used in Program as a Proof and Proof in a Mathematical Algebraic System which you have missed. They are isomorphic but not exact (hence my using the phrase it depends and scare-quotes around "proving").

A proof of a program's correctness is mathematical in nature, it doesn't stand apart in some distinct non-mathematical realm. (Whether we call it computer science is of little consequence here.) The tools for generating such proofs tend to use SMT solvers.

It's true that C's int type, for instance, does not correspond to the mathematical integers, despite the name. It has its own arithmetic rules. So what? It's still mathematical in nature.

I think this is really a disagreement on phraseology though, nothing deeper.

> The reason is because Mathematics deals with ideal and abstract objects whereas objects in the real world (eg. a computer program) can only map to aspects of the ideal world and not in its entirety.

Programming languages can be modelled mathematically. Programs can be modelled mathematically. That's much of the point of formal methods.

Real computers are finite state machines. So what?

> any proof which uses the axiom of associativity for signed integers in a computer can never be as absolute and general as its counterpart in pure mathematics

Modular arithmetic is mathematics, just as arithmetic over integers is mathematics. Formal analysis of floating-point arithmetic, or of C-style signed integer arithmetic, may be of less interest to pure mathematicians, but both can be (and have been) analysed with proper mathematical rigour.

If someone really mistakes C's int type for the mathematical integers, or the float type for the reals, then they don't understand the first thing about programming.

> In general, mathematics uses exact Analytical Techniques while computers use approximate Numerical Techniques to solve a problem which is reflected in the nature of their proofs.

Sometimes we need to approximate the reals, sure, but there's nothing approximate about, say, mergesort. Similarly a proof of its correctness (whether in the abstract, or of a particular implementation in a programming language) isn't in any way approximate.

> Coming to DbC, since it is based on Hoare Logic (i.e. an algebra with axioms/inference rules), a Program is written as a series of Preconditions/Postconditions/Invariants with the Programmer acting as the Proof deriver.

As I understand it, in typical design-by-contract software development, there is no formal proving of anything, there's just runtime checking.

It's possible to mistakenly believe we've come up with a model that is guaranteed to always preserve its postconditions and invariants. A decent introductory course on formal methods allows students to discover this for themselves, perhaps using Z Notation [0] or one of its derivatives. There's no substitute for proving your model correct.

If your starting point really is a proper formal model with a proof of correctness, what you're doing isn't typical design-by-contract software development.

> Thus if a series of pre/post/inv holds at a certain stage in the program (i.e. proof) the next post will hold (barring external cataclysms).

We only know that's the case if we've formally proven that the program is correct. If you're doing runtime checking, it's presumably because you don't know whether the program always does as you hope in all possible states.

> The fact that the proof obligation is discharged dynamically at runtime is immaterial. But we may not want that in certain categories of real world programs since the question of what to do when the proof obligation is not met at runtime becomes a problem [...] prove it through a verifier statically thus guaranteeing invalid states can never arise at runtime. But note that this is merely an incidental distinction due to the needs of the real world but the essential DbC guarantees remain the same.

It's not mere detail, it's an entirely different software engineering outcome. As you've just acknowledged, proving the absence of bugs from a codebase may be of life-and-death practical importance, and typically this cannot be achieved using runtime checks. A proof of correctness is a powerful assurance to have, and the tools needed to deliver it are radically different from runtime checks. It's in no way incidental, it's a whole different game.

Even if you were able to test your program on all possible inputs, which you can't, you still probably haven't achieved the equivalent of a formal proof of correctness. There are plenty of issues that runtime assertions are likely unable to provide assurances for. Does the code have a subtle concurrency bug, or read-before-write bug, or some other form of nondeterministic behaviour, such that it might have failed to arrive at the correct outputs, but we just got lucky this time? Absence of undefined behaviour? Absence of sensitivity to platform-specific or implementation-defined behaviours or aspects of the programming language, such as the maximum value that can be held in an unsigned int?

On the plus side, many of those issues can be mitigated by a well-designed programming language, or by compiler-generated runtime checks. The SPARK Ada language closes the door of many of them, for instance, whereas in C those sorts of issues are pervasive.

More generally, testing and runtime checking are able to discover bugs, but are typically incapable of proving the absence of bugs. This is much of the motivation for formal methods in the first place.

> when you map concepts from mathematical to computing domain you need to understand how the same names like "Integer", "Set/Type", "Algebra", "Axiom", "Proof" map from one to the other (though not exactly) and how you can leverage their isomorphism

Again I don't think it's helpful to phrase it as if there are 2 worlds here, one mathematical and one not. Program behaviour can be modelled mathematically. It's not math-vs-programming, it's just a matter of applying the correct math.

I'm not sure it's quite right to call it isomorphism, on account of computers being finite state machines. As you indicated earlier, computers can, roughly speaking, only cope with a subset of reality.

[0] https://en.wikipedia.org/wiki/Z_notation

Re: Mathematics for Computer Science (2024)

#109

Earlier quoted context omitted.

There is a nuanced but distinct difference in my use of the word Proof as used in Program as a Proof and Proof in a Mathematical Algebraic System which you have missed. They are isomorphic but not exact (hence my using the phrase it depends and scare-quotes around "proving" ). The reason is because Mathematics deals with ideal and abstract objects whereas objects in the real world (eg. a computer program) can only ma…

Correction: In the 4th para above replace set N (set of natural numbers) with set Z (set of all positive and negative integers).

Don't forget zero!

Re: Mathematics for Computer Science (2024)

#110

Earlier quoted context omitted.

Correction: In the 4th para above replace set N (set of natural numbers) with set Z (set of all positive and negative integers).

Don't forget zero!

The set Z includes zero. Only when annotated eg. Z+, Z* etc. (often differently by different authors) are various subsets denoted.
Post reply on HN