
My automated planner can now render its plans as gifs! Here it is trying to solve a block-pushing puzzle where the goal is to push the block to the top right corner:

Sokoban next?

What’s that?

Classic push a block game.


Oooo that’s perfect

I believe it’s very much a standard task for testing planners amongst the AI planning researchers.

The original sokoban starts with easier levels I believe.

I’ll put that on my list of examples to include in the docs

my next task is to get these gifs to show up in the scribble docs

For a semi-random reference showing that planners use Sokoban, see e.g. https://webdocs.cs.ualberta.ca/~holte/Publications/ijcai2016-subset-selection.pdf (linked from https://webdocs.cs.ualberta.ca/~holte/Publications/index.html), which was found by searching for the name of the researcher who taught me the little I know about planning, combined with Sokoban - it’s one of the example domains they use to test the performance of their planner design.

I think AI stuff is really hard to visualize if all you’ve got is static diagrams

@jcoo092 This is great! Thank you very much

Glad to help :slightly_smiling_face:

If you’re interested I can share a bit more about the planner I’m writing

Yes, please. I am definitely interested (not that I’m an expert on planning in the slightest) :slightly_smiling_face:

I was reading some textbooks on planning and thought it was awesome, so I started working on a planner. Along the way I decided I really didn’t like the state-variable representation that the textbooks used - it was difficult to translate to actual code and didn’t really match how I model data in normal code. I also happen to have this other project, Rebellion, which defines lots of useful collection libraries and data type libraries. So I decided to make a planner where the state of the world is represented by some sort of collection, like a list, set, multiset, or hash table.

That block world problem is using the hash table representation. The planner sees the state of the world as a hash from keys (which are row+column numbers) to values (which are objects), and I give it a list of hash-action
values that describe the ways it can insert and remove from the hash.

I’m hoping that this lets me come up with good heuristics that are still very general-purpose, since the action model exposes a lot of structure to the planner.

For example, using multiset actions looks like this: (define make-water
(multiset-action
#:preconditions (hash 'hydrogen (at-least-range 2)
'oxygen (at-least-range 1))
#:additions (multiset 'water)
#:deletions (multiset 'hydrogen 'hydrogen 'oxygen)))
> (multiset-act (multiset 'hydrogen 'hydrogen 'oxygen 'carbon) make-water)
(multiset 'carbon 'water)

:thinking_face:

Certainly looks good from here :slightly_smiling_face:

(A multiset is like a set, except it can have duplicates. They’re great for modeling things where order doesn’t matter but quantity does, like an inventory.)

More details on planning with multisets: https://docs.racket-lang.org/planning/The_Multiset_State_Representation.html

Was the data representation in the book PDDL? (https://en.wikipedia.org/wiki/Planning_Domain_Definition_Language) It seems pretty likely to have been inspired by LISP (most likely because the people who created it used a LISP a lot).

Yup, it was that.

The syntax and notation weren’t the problem.

Yeah, PDDL seems to be the standard for planners in the research community. Which is certainly not to say its perfect. I only used it very briefly to complete a couple of uni assignments, planning is not my area at all.

I think if I wanted to take this planner seriously, I’d be more interested in implementing it.

It’s odd.

PDDL represents states and actions in terms of logical statements about fluents, which makes total sense if you’re coming from a classical computational logic background. But it makes no sense at all if you’re coming from a classical programming background. I want to make a planner that’s easy to use for people who aren’t planning researchers.

In large part because I’m not a planning researcher and the textbook’s explanations of fluents are complicated enough, and they’re not even trying to describe them in enough detail to implement them.

TIL Sussman anomaly

@notjack If you want to write a simple planner, I highly recommend Iterative Deepening Depth First Search as the search procedure. No need for complicated state representation, all you need actions that mutate the state (and either save the previous state, or be able mutate the state back). It’s very simple to implement, doesn’t require much memory (compared to A* and such) and can be good enough in many cases. https://en.wikipedia.org/wiki/Iterative_deepening_depth-first_search

and then you can move on to IDA* when you want to introduce heuristics: https://en.wikipedia.org/wiki/Iterative_deepening_A*

If you’re happy with making copies of your state instead of using mutation, the implementation is even simpler

Try DeepLearning, then you’d hope you’d have a least as much detail as in planning ;)

Racket news issue 31, I think there might be an error…. Does someone here look after that?

What kind of error? (also @pmatos)

‘’’rs(src/pkg) is a live coding tool that lets you sequence MIDI using Racket. fuzzy-search(src/pkg) is a live coding tool that lets you sequence MIDI using Racket. planning(src/pkg) is a live coding tool that lets you sequence MIDI using Racket.’’’

Bah! iPhone

There are 3 new packages wit the same blurb :)

Ah! I see it now.


@pocmatos looks after racket news

I’d search for a repo and do a PR but I’m on childcare duty today :)

Just read the bottom where is has an email :)

@chris613 Thanks for pointing out the error! :slightly_smiling_face: Fixed. Site is regenerating, should be up in a few minutes.

No probs. Just emailed as well, sorry for the multiple channels spam :)

Currently I’m just using BFS. I’m probably going to switch to some combination of A* and greedy best-first search.

Complex search algorithms are fine with me, since that’s all hidden from the API user’s point of view.

It’s the representation of states and actions that I wanted to keep simple.

Also I have a very neat book of planning algorithms to implement :)

I implemented prop:convertible
for my animation snips so they can be converted to gifs. Any idea if that pasteboard representation selection code uses that protocol?

it looks like it doesn’t, but I wonder if it could

All good… definitely punish me if you see a mistake in racket news. :wink:

If you’re happy with more complicated algorithms but want some stronger theoretical guarantees over A*, you may be interested in this shamelessly self promoted paper: https://arxiv.org/abs/1907.13062 (ijcai 2019) And if you want some more fun planning algorithms to play with, and see some unreadable Racket plots on sokoban, here’s another one: https://arxiv.org/abs/1811.10928 (NeurIPS 2018)

Ooo nice, thank you!

Once planning
has more docs and is generally easier to play around with, would you be interested in trying to implement one of these search algorithms within the library?


Sure, if/when I have time, but yes in principle :slightly_smiling_face:

Oh hey disposables got mentioned

I’ll give you a poke once the docs are written and include pretty animations :)

Cool

Is it meant to be fast? If so, I might use it for my papers (and thus advertise it) :wink:

oh god no

ah too bad :slightly_smiling_face:

It is meant to enable good heuristics, so measurements of how much of the state space is explored are more interesting to me than actual runtimes

Being fast would be nice, that’s just not something I’m good at

I agree with that, but unfortunately speed can still make a huge difference

Sure, no worries

Yeah it’s a really valuable feature. Maybe if the docs are flashy enough I’ll magically attract help from an optimization wizard or two.

To make a fast library, we usually need to work with bare data structures and not use fancy features

So it’s usually not easy (read: frustrating) to optimize bits and pieces of an existing library

Also you (really) need to disable all contracts, they are a sucker for time

Honestly I think this could gain a lot of perf by using generics

For the collections

I think the biggest problem with contracts is redundant checks. I even encountered cases where it made my algorithm O(n^2) instead of O(n), (ormap proc l1 l2
inside another loop, when I’ve already checked before the main loop that l1 and l2 are of the same length, and the ormap terminates almost always after just a few items)

To be fair, I blame that one on linked lists, not contracts

I’m trying a different approach to dict/c
again, and I’m wondering whether I should use prop:impersonator-of
in the wrapper struct. Is there a proper way to use prop:impersonator-of
so that I can define a wrapper to be an impersonator of the wrapped dict?

What do you mean?

checking if two lists are the same size should be a fast constant-time operation

Something weird I’ve noticed is that prop:impersonator-of
can actually make impersonator-of?
return false in cases where it would have returned true if gen:equal+hash
is implemented for the wrapper: ;; (wrapper [Listof Blame] Any)
(struct wrapper [blames value]
#:methods gen:equal+hash
[(define (equal-proc self other rec)
(eq? (wrapper-value self) (wrapper-value other)))
(define (hash-proc self rec)
(eq-hash-code (wrapper-value self)))
(define (hash2-proc self rec)
(eq-hash-code (wrapper-value self)))])
If I try to add a prop:impersonator-of
on top of this, like if I want (wrapper (list blame2 blame1) X)
to be an impersonator of (wrapper (list blame1) X)
, then impersonator-of?
will return false with prop:impersonator-of
there, but true without it. So should I be using that or not? If not then when would it be a good idea to use it?

ah right, but even with that I think there’s a fundamental redundancy problem with contracts. It should be possible to alleviate with a smart(er) compiler, but things would be a lot nicer if expression were tagged as pure-functional?

I don’t think it’s much of a compilation thing. I actually think more runtime info would help.

If you can avoid runtime, it’s better. But having more info at runtime and avoiding checks then, or maybe JIT would certainly help

For example, in rebellion/base/comparator
I wrap comparison functions in a comparator
struct and this lets me skip a lot of higher order contract wrappers. Instead of wrapping the input to every comparator-accepting function with (-> any/c any/c (or/c '< '= '>)
, I can just test for comparator?
and rely on the make-comparator
constructor to apply the contract once.

for length
at least that would clearly help

for length
, we just shouldn’t be using linked lists…

Yeah, I was thinking that every piece of data could come with guarantees that are just a number of predicates it satisfies (or not), so that checking a guarantee a second time amounts to checking the polarity of the guarantee

For length, I’m not sure I agree

I don’t understand what you mean here. Can you provide the full example?

can you use emoji in DrRacket?

:wink: Try copy pasting this.

I get : : wink : Try copy pasting this.

and then :wink:: unbound identifier in: :wink:

You need to click on “copy image” in the context menu

(works for me)

😄 😃 😀 😊 😎️ 👍

I see what you are getting at.

I’m after the characters

I can’t insert emoji from the Font Book.

Unicode I presume

If you open Font Book and enter emoji in the search bar, you can copy paste characters.

(Slack does something odd).

font book gives me blanks

Ditto.

I think it might be because emoji are a different font. I’m wondering if the situation is the same on DrRacket for Windows and Linux

Emoji don’t draw on Mac OS because a different text-drawing function at the CoreText(?) level is needed than the one that Pango uses (last I looked). I think they work on Windows and other Unixes.

thanks

I just use nominal types to get those kinds of guarantee predicates

let’s me turn contracts for complex higher order properties into simple type tests

as for the length
thing, I just want a good generic collections framework

think of nominal types as the class name, and properties as implemented interfaces

So the full example with my attempt at dict/c
is very large, but I suppose I can give you more on the simplified wrapper
version ;; (wrapper [Listof Blame] Any)
(struct wrapper [blames value]
#:property prop:impersonator-of
(λ (self)
(and (cons? (wrapper-blames self))
(wrapper (rest (wrapper-blames self)) (wrapper-value self))))
#:methods gen:equal+hash
[(define (equal-proc self other rec)
(eq? (wrapper-value self) (wrapper-value other)))
(define (hash-proc self rec)
(eq-hash-code (wrapper-value self)))
(define (hash2-proc self rec)
(eq-hash-code (wrapper-value self)))])
;; wrap-blame : Blame Any -> Wrapper
(define (wrap-blame blame value)
(match value
[(wrapper bs v) (wrapper (cons blame bs) v)]
[v (wrapper (list blame) v)]))
(define x1 (make-hash))
(define x2 (wrap-blame 1 x1))
(define x3 (wrap-blame 2 x2))
(impersonator-of? x3 x2)
So here with prop:impersonator-of
, it returns false, but if I delete that property, it returns true.

I’m using it in a project right now. I was going to have a connection pool mechanism (maybe later), but the with-disposable
form and the disposable values let me abstract annoying setup and teardown bits.

Oh cool! I’m glad it worked

I forgot how much work I put into that project, especially the docs

Yup, I see what you mean

did you see the PLT paper about how nominality can be used to fix the performance problems of sound gradual typing and contracts? extremely valuable research

sounds cool, do you remember the name of the paper?

Ok… Yes: adding prop:impersonator-of
can introduce impersonator-of?
distinctions that aren’t there without prop:impersonator-of
. Making those distinctions is the point. For x3
to impersonate x2
, it generally needs to preserve x2
— not make another value that that’s similar/equal to x2
but that isn’t x2
. So, maybe impersonators are not the tool you’re looking for.

I was poking around the benchmarks game site, and was a bit surprised at the performance of Racket CS vs. BC on a few: https://benchmarksgame-team.pages.debian.net/benchmarksgame/fastest/racket-racketcs.html an order of magnitude slower on some. Is anyone familiar with those particular benchmarks and why CS is so much slower than BC?

I looks like pango (a year ago) changed something that suggests it should work now: https://gitlab.gnome.org/GNOME/pango/-/merge_requests/40

My initial thought is that it’s compilation time; the maintainer has been very difficult about adding a raco make
call before running the program.

Could it be floating point related too?

that’s also possible

I was suspecting floating point

If so, that’s really sad :disappointed:

Macros are used creatively in the benchmarks, so sam’s hunch is probably it.

might be due to parallelism too, since both mandelbrot and spectral-norm use that

I guess I can run my own benchmarks to get a better feel for it. I would probably shell out to Julia for intensive number crunching, but I’m not thrilled with the idea of CS going backwards in performance from BC.

So maybe needs some tweaking for CS?

@laurent.orseau the cpu load looks comparable between them - at least on mandelbrot and spectral-norm. BC utilizes the processors a little more fully, but not 10x

indeed

looking at which benchmarks are slow, it’s probably floating point

@samth do you have a feel for how solvable the fp issues are?

@samth The outputs say they do use some make rules. Can’t this be used to run raco make? (Or maybe they just don’t want Racket to have an edge?)

Chez Scheme is slow on floating-point operations because it doesn’t unbox intermediate float values. @mflatt said a couple days ago that it’s next on his list

@laurent.orseau yes, it should be easy. but …

erf

Cool. I don’t have a current need for fp, so as long as there’s a path to get there (i.e. Chez isn’t fundamentally broken in this regard), I’m fine :slightly_smiling_face:

And while my personality loves the idea of one language to rule them all, I’m comfortable with the compromise of using Racket for 90+% of my code and Julia for the minority of mathy stuff I’ll be doing soon. It’s hard to compete in that area with something purposely designed to crunch numbers.

Okay

actually, now that I look at least some are using raco make

I think there’s some programs that will be faster in Julia, but Racket CS with unboxed FP ops should be plenty fast in most cases.

this is so exciting!

@samth I agree - Racket’s performance in general is amazingly good. I think I’ll only need to delegate the really large and time consuming stuff that makes use of linear algebra libraries, etc.


Is there a Ubuntu PPA for Racket CS? Someone is asking on the discord.

Yes, nice to have that available, but the Julia ecosystem is pretty rich since scientific/numerical computing is the main reason for its existence :slightly_smiling_face:

I love a recursive and functional approach to computing, but I have to reluctantly admit that a more loopy and mutative approach is extremely convenient for numerical stuff.

(I’ll be the first to admit I don’t know what a Ppa is or why it is so important)

That PPA seems to exist, and be by @asumu, but hasn’t been updated recently. The regular PPA does not have Racket CS.

personal package archive, facilitates installation via apt
, without needing to be integrated into the ubuntu project structure

Thanks

Thanks

would integrating Racket into Ubuntu so the ppa isn’t necessary be a good idea? (I don’t know anything about package management on Ubuntu so I have no idea)

I think Ubuntu takes the debian package which is probably really old.

it might be in there already, not sure (i use Arch, and there is an official Racket package). i think the original question was about Racket-CS.

This is from Ubuntu 20.04 (just released) Package: racket
Architecture: amd64
Version: 7.2+dfsg1-2ubuntu3

PPAs are a way for there to be a semi supported way for packages to be added to ubuntu without Canonical (or debian) having to do any additional effort. It’s up to the PPA owner to keep it up to date.

Sound Gradual Typing is Nominally Alive and Well


Could/should this be considered a bug in Racket CS?
~> racket
Welcome to Racket v7.7.0.5 [cs].
> (current-inexact-milliseconds)
1.589918178396419e+12
~> racketbc
Welcome to Racket v7.6.
> (current-inexact-milliseconds)
1589918194811.886

It definitely caught me off guard when I was debugging something today…

What would the bug be? Those two values are only ~16s apart.

Sorry, I should’ve been more clear. I’m referring to the representations of the numbers. current-inexact-milliseconds
was just an easy way to get large reals to demonstrate the issue.

Scientific notation is used on CS and standard on BC.

It looks like the macro-stepper has had some issues with the following code since version 7.6 #lang racket
(module untyped racket
(provide foo?)
(define (foo? x) x))
(module typed typed/racket
(require/typed (submod ".." untyped)
[foo? (-> Number Number)])
(provide foo?))
The error message is Internal error:
rename: different contours!
contour-diff: (#s(DIFF #%app begin) #s(DIFF apply-contract (define-values (lifted/2) (quote-module-name))) #s(DIFF lifted/1 (#%app apply-contract lifted/1 foo? (quote (interface for foo?)) lifted/2 (quote foo?) (#%app kernel:srcloc (quote "/Users/capfredf/code/racket-extra-pkgs/typed-racket/test.rkt") (quote 9) (quote 5) (quote 151) (quote 4)) (quote #f))) . #s(DIFF (foo? (quote (interface for foo?)) lifted/2 (quote foo?) (#%app kernel:srcloc (quote "/Users/capfredf/code/racket-extra-pkgs/typed-racket/test.rkt") (quote 9) (quote 5) (quote 151) (quote 4)) (quote #f)) ()))
pre: #<syntax:...racket-installers/Racket v7.6/share/pkgs/typed-racket-lib/typed-racket/utils/require-contract.rkt:59:16 (#%app apply-contract lifted/1 foo? (quote (interface for foo?)) lifted/2 (quote foo?) (#%app kernel:srcloc (quote "/Users/capfredf/code/racket-extra-pkgs/typed-racket/test.rkt") (quote 9) (quote 5) (quote 151) (quote 4)) (quote #f))>
post: #<syntax (begin (define-values (lifted/2) (quote-module-name)) (#%app apply-contract lifted/1 foo? (quote (interface for foo?)) lifted/2 (quote foo?) (#%app kernel:srcloc (quote "/Users/capfredf/code/racket-extra-pkgs/typed-racket/test.rkt") (quote 9) (quote 5) ...>

I’ve tried the steppers of 7.4, 7.5, 7.6, 7.7 and the latest build on macOS 10.14.16

7.4’s and 7.5’s worked well.

@mflatt Does this look like a regression? By the way, I looked through the issues on github. Seems nobody has reported this problem.

v7.6 may have been Ryan’s overhaul of the macro stepper, so I’d file a bug report there

Thanks!

Cool. I am gonna file an issue there

Yes, that was the version with the rewrite

That seems like a bug to me

I’ll open an issue

Thanks for the report! I’ll try to take a look soon.

So I’ve got this animation-snip%
class that implements prop:convertible
and supports conversion to GIFs. I want to set things up so when example code in Scribble returns an animation snip, it automatically gets converted to a GIF and embedded in the document. Right now this doesn’t work: trying to evaluate examples that construct animation snips raises the error racket/gui: cannot instantiate in a non-main place on Mac OS
. What do I need to do to make this happen? Do I need to do something with prop:serializable
? Or do I need to skip the snip step entirely in Scribble example evaluators and use an alternate implementation that saves the animation to a file or something?

Is there any reason why errortrace
doesn’t use custom-load
so that there’s no need to clear compiled
directory manually?

You need to avoid racket/gui
— but the racket/snip
library by itself doesn’t depend on racket/gui
. Are you depending on something else that requires racket/gui
?

Loading everything from source would take a long time. Not loading everything from source requires errortrace
to know about some distinction that you have in mind. Currently, that distinction is declared by not having compiled files. That’s not the only way of making the distinction, of course, just the one that’s currently implemented.

There are two bindings that I need from racket/gui/base
: timer%
and get-the-snip-class-list
.

I’m using the timer to make the animation refresh in the DrRacket REPL, and I’m using get-the-snip-class-list
to add a snip class when the module defining animation-snip%
is instantiated.

Oh also, here’s a link to the code: https://github.com/jackfirth/planning/blob/master/private/animation.rkt

FWIW, in my symbolic error tracer for Rosette, I use existing zo
from installed packages (in a sense that path->pkg
returns non-#f
) and from those in (find-collects-dir)
. The rest will be loaded from source. Of course, sometimes you do want to instrument a package, so there’s an option to instrument a given list of packages. We find that this works really well in practice.

You could use gui-available?
to decide whether to get and call get-the-snip-class-list
via gui-dynamic-require
. Maybe the same for timer%
.

That would work. I’m also considering adding a headless
submodule that defines most of the logic and making the enclosing module responsible for setting up the snip class list and timers. I like that because it keeps the module dependency logic static. What do you think?

That does sound better.

The idea I had in the back of my head when I wrote custom-load
was that users could configure custom-load
with a predicate that represented the code they cared about at the moment and then run a tool like errortrace, cover, etc. I never wrote any high-level utilities for that, though. It might make a good DSL. BTW, this division into “my code” vs “the platform” occurs in the macro stepper too, for macro hiding.

In my overall impression, Racket BS is still outperforms Racket CS in many ways, and it takes up less memory and less startup time.

This worked but it turns out Scribble only tries to convert things to png or svg, it doesn’t support gifs :disappointed:


@longfellow has joined the channel

I wrote my own in-range
that is just like Racket’s in-range
, but supports (in-range 1 #:to n)
which will be an inclusive range. Is this something that would benefit other people?

I think something like that could be useful, but 1) keyword arguments that read like positional arguments are weird to me and 2) what do you think about the name in-inclusive-range
?

I found myself writing (in-range 1 (add1 n))
a few times, so I would like an inclusive in-range
too, my own preference would be (in-range 1 n #:inclusive? #t)

Exactly. I want to avoid this add1
. Though the word inclusive
(in both @notjack’s and @alexharsanyi’s) is kinda long.

I would much rather read a slightly longer expression than wonder whether a range is inclusive or exclusive

both in-inclusive-range
and (in-range 1 n #:inclusive #t)
would tell anyone what they do without consulting the documentation. (in-range 1 #:to n)
is shorter, but I would have no idea what it does unless I lookup the documentation

also if you want to query ranges instead of iterate over them, you might be interested in this: https://docs.racket-lang.org/rebellion/Ranges.html