Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve trigonometric abstractions #1272

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open

Improve trigonometric abstractions #1272

wants to merge 7 commits into from

Conversation

stilscher
Copy link
Member

@stilscher stilscher commented Nov 23, 2023

This PR improves the abstraction of the cos function if the argument is neither nan nor inf by

  • storing also the inverted relationship between arguments of math functions and (assigned variable, math function) in the tmpSpecial analysis
  • being more precise in the abstraction of cos(x) in case one can assure that variables representing isInf(x) and isNaN are definitely false

@michael-schwarz
Copy link
Member

This yields 4 more successful tasks, I'll start it on the server.

@michael-schwarz michael-schwarz added this to the SV-COMP 2024 milestone Nov 23, 2023
@michael-schwarz michael-schwarz marked this pull request as ready for review November 23, 2023 15:21
@sim642 sim642 self-requested a review November 23, 2023 18:40
@@ -907,8 +929,16 @@ module FloatIntervalImplLifted = struct
let acos = lift (F1.acos, F2.acos)
let asin = lift (F1.asin, F2.asin)
let atan = lift (F1.atan, F2.atan)
let cos = lift (F1.cos, F2.cos)
let sin = lift (F1.sin, F2.sin)
let cos ?(asPreciseAsConcrete=BoolDomain.MustBool.top ()) ?(notInf_notNaN=BoolDomain.MustBool.top ()) = function
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
let cos ?(asPreciseAsConcrete=BoolDomain.MustBool.top ()) ?(notInf_notNaN=BoolDomain.MustBool.top ()) = function
let cos ?(asPreciseAsConcrete=false) ?(notInf_notNaN=false) = function

BoolDomain.MustBool.top () is false.

| F64 a -> F64 (F2.cos ~asPreciseAsConcrete:true ~notInf_notNaN a)
| FLong a -> FLong (F2.cos ~notInf_notNaN a)
| FFloat128 a -> FFloat128 (F2.cos ~notInf_notNaN a)
let sin ?(asPreciseAsConcrete=BoolDomain.MustBool.top ()) ?(notInf_notNaN=BoolDomain.MustBool.top ()) = function
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
let sin ?(asPreciseAsConcrete=BoolDomain.MustBool.top ()) ?(notInf_notNaN=BoolDomain.MustBool.top ()) = function
let sin ?(asPreciseAsConcrete=false) ?(notInf_notNaN=false) = function

map { f1= (fun (type a) (module F : FloatDomain with type t = a) -> F.cos); }
let sin =
map { f1= (fun (type a) (module F : FloatDomain with type t = a) -> F.sin); }
let cos ?(asPreciseAsConcrete=BoolDomain.MustBool.top ()) ?(notInf_notNaN=BoolDomain.MustBool.top ()) =
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
let cos ?(asPreciseAsConcrete=BoolDomain.MustBool.top ()) ?(notInf_notNaN=BoolDomain.MustBool.top ()) =
let cos ?(asPreciseAsConcrete=false) ?(notInf_notNaN=false) =

map { f1= (fun (type a) (module F : FloatDomain with type t = a) -> F.sin); }
let cos ?(asPreciseAsConcrete=BoolDomain.MustBool.top ()) ?(notInf_notNaN=BoolDomain.MustBool.top ()) =
map { f1= (fun (type a) (module F : FloatDomain with type t = a) -> F.cos ~asPreciseAsConcrete ~notInf_notNaN); }
let sin ?(asPreciseAsConcrete=BoolDomain.MustBool.top ()) ?(notInf_notNaN=BoolDomain.MustBool.top ()) =
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
let sin ?(asPreciseAsConcrete=BoolDomain.MustBool.top ()) ?(notInf_notNaN=BoolDomain.MustBool.top ()) =
let sin ?(asPreciseAsConcrete=false) ?(notInf_notNaN=false) =

@@ -791,8 +791,30 @@ module FloatIntervalImpl(Float_t : CFloatType) = struct
let acos = eval_unop eval_acos
let asin = eval_unop eval_asin
let atan = eval_unop eval_atan
let cos = eval_unop eval_cos
let sin = eval_unop eval_sin
let cos ?(asPreciseAsConcrete=false) ?(notInf_notNaN=false) op =
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like we should be able to get some reuse here for sin and cos.

Comment on lines +2383 to +2385
let isNotNan = Q.MLInv.exists (fun (y, ml) -> matchnan ml && isFalse y) s in
let isNotInf = Q.MLInv.exists (fun (y, ml) -> matchinf ml && isFalse y) s in
isNotInf && isNotNan)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might make sense to restructure so the lookup for isNotInf doesn't always happen.

Comment on lines +2378 to +2380
match Queries.ID.to_bool v with
| Some b -> not b
| None -> false)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
match Queries.ID.to_bool v with
| Some b -> not b
| None -> false)
Queries.ID.to_bool v = Some false)

@@ -2355,6 +2355,40 @@ struct
| _ -> failwith ("non-integer argument in call to function "^f.vname)
end
in
let apply_better_trig fk (float_fun : ?asPreciseAsConcrete:bool -> ?notInf_notNaN:bool -> FD.t -> FD.t) x =
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the type annotation needed, it looks a bit clunky.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Possibly, because the type inference of optional arguments is not principal: https://dev.realworldocaml.org/variables-and-functions.html#inference-of-labeled-and-optional-arguments.

D.add (v, Offset.Exp.of_cil offs) ((ML.lift fun_args, Deps.of_list ((Lval lv)::arglist))) d
else (
if M.tracing then M.trace "tmpSpecialInv" "build tmpSpecial Entry for Lval %s\n" v.vname;
let d1 = MM.add (v, Offset.Exp.of_cil offs) ((ML.lift fun_args, Deps.of_list ((Lval lv)::arglist))) (fst d) in
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think some parens are unneeded here...

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also Deps.of_list ((Lval lv)::arglist)) is constructed twice here.

Comment on lines +131 to +136
let mlv = MInvEntrySet.fold (fun (v, ml, deps) acc -> Queries.MLInv.add (v,ml) acc) es (Queries.MLInv.empty ())
|> Queries.MLInv.filter (fun (v,ml) ->
match ml, v with
| `Bot, _ -> false
| _, `Lifted exp -> true
| _ -> false) in
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This way of doing looks as if it may be in a figure of speech potentially trying to achieve the goal in a way that might be described as roundabout. You might want to do the filtering right in place. 😉


(* arg maps to (x, mathf(arg), deps) if x = mathf(arg) *)
module ExpFlat = Lattice.Flat (CilType.Exp) (Printable.DefaultNames)
module MInvEntry = Lattice.Prod3 (ExpFlat) (ML) (Deps)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have you tried this type:

module MInvEntry = Printable.Prod3 (CilType.Exp) (LibraryDesc.MathPrintable) (SetDomain.Make(CilType.Exp))

Might make it easier on the inside to give up on the lattice structure that is unused anyway.

@sim642 sim642 modified the milestones: SV-COMP 2024, v2.4.0 Nov 24, 2023
@sim642
Copy link
Member

sim642 commented Nov 24, 2023

Since this is still in need of refactoring/cleanup, it's too late to include for SV-COMP 2024. Four additional tasks out of ~32000 is not worth the risk for a possible regression.

@michael-schwarz
Copy link
Member

Four additional tasks out of ~32000 is not worth the risk for a possible regression.

There is no regression, we ran it overnight on all tasks with full timeouts.

@sim642
Copy link
Member

sim642 commented Nov 24, 2023

It's not just about SV-COMP though. It will be the representative version of Goblint for the entire year to come. If something doesn't yet meet our own standards, then it's not ready for such release. This is just too last minute, considering the freezing deadline we set for ourselves.

@michael-schwarz
Copy link
Member

Ok. I think it would've been nice for Sarah's work this past week to be reflected in that version, but I won't push too hard.

@sim642
Copy link
Member

sim642 commented Nov 27, 2023

Why is the TmpSpecialInv query needed? TmpSpecial itself already is a certain inverse (for refining the argument based on the return value), so TmpSpecialInv is some kind of inverse of the inverse. Is that not just normal forward evaluation? The new query is also used in eval not invariant.

Comment on lines +2370 to +2371
let matchinf = function
| `Lifted LibraryDesc.Isnan _ -> true
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
let matchinf = function
| `Lifted LibraryDesc.Isnan _ -> true
let matchinf = function
| `Lifted LibraryDesc.Isinf _ -> true

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants