Skip to content

Conversation

jverzani
Copy link
Contributor

@jverzani jverzani commented Apr 2, 2025

In #260 a promote rule for true or false is setup. Currently this would promote true to a symbolic 1 and false to a symbolic 0 as Bool <: Integer. This provides an alternatative by promoting to a symbolic True and symbolic False.

I don't know which is a better choice, this is just meant to provide an option.

If this option is better, it might be nice to have some means to convert True or False to 1 or 0 with the N function.

@jverzani
Copy link
Contributor Author

jverzani commented Apr 3, 2025

One option for N could be

@@ -124,7 +125,12 @@ end
 function N(::Val{<:Any}, b::Basic)
     is_constant(b) ||
         throw(ArgumentError("Object can have no free symbols"))
-    out = evalf(b)
+
+    # replace any True/False with 1/0
+    m = CMapBasicBasic()
+    m[True] = Basic(1); m[False] = Basic(0)
+
+    out = evalf(subs(b, m))
     imag(out) == Basic(0.0) ? N(real(out)) : N(out)
 end

It adds some allocations, but isn't too costly performance wise.

@isuruf
Copy link
Member

isuruf commented Apr 3, 2025

Add a specialized N(::Val{:BooleanAtom}, b::Basic) ?

@jverzani
Copy link
Contributor Author

jverzani commented Apr 3, 2025

That is here, it is when a BooleanAtom is part of an expression (like Basic(2)+True) that N falls back to calling evalf which doesn't treat True as numeric, as happens in Julia.

@jverzani
Copy link
Contributor Author

jverzani commented Apr 3, 2025

Oops, I hadn't pushed all the changes I had locally. What is there now is one way that booleans could be handled.

src/numerics.jl Outdated
Comment on lines 16 to 17
m = CMapBasicBasic()
m[True] = ONE; m[False] = ZERO
Copy link
Member

Choose a reason for hiding this comment

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

Can we make this map a global variable instead of creating it every time?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I need your help with that. I was trying, but kept getting segfaults. The construction of Basic objects is a bit different than that of CMapBasicBasic, so I was having issue initializing the map in __init__.

One thing about what I have here that bothers me is I'd like to cheaply test if an expression has a BooleanAtom and then try to evaluate that expression after substitution with evalf, but it seemed easier to do the substitution and then compare the result to the original. I wasn't sure if substituting in a map with no matches would always return the original expression, as the test has that assumption.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I just checked in what I thought I'd tried earlier and it seems to not cause an issue. I'll add a direct test to be sure.

@jverzani jverzani mentioned this pull request Apr 5, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants