Storing fewer shapes in model files

With the plans for more turtle shapes and support for vector graphics (see https://forum.netlogo.org/t/making-turtle-shapes/578 and https://forum.netlogo.org/t/logoshapes-a-library-of-netlogo-vector-graphics/713), it seems a good moment to reduce the number of shapes stored in model files.

Would it be possible to store only those shapes (turtle and link) that have been edited or added?
Most models use just a few shapes and then mostly only standard shapes.
The NetLogo program knows all standard shapes already, so why store them in model files?

The shapes editors could still show all available shapes with operations as before (and probably extended with new functionality). Additionally, non-standard shapes could be indicated by a star or another indicator.

Hi Mark,

Thank you for the suggestion, it definitely does have a significant impact on the size of the model file. We have discussed this in the past, but we decided that it’s best to leave them in, because it could break the model if we change the shape library. For example, if a model uses the wolf shape and we then decide to remove the wolf shape from the library, that model would no longer function unless the wolf shape was included in the model itself. This is the current reasoning for retaining all the default shapes in the model file, but if you come up with any potential solutions, we would be happy to hear them!

Isaac B.

1 Like

Hi Isaac,

Interesting to hear that you have discussed this already, and what the reason is for storing all shapes.

The easy solution against removed shapes is simply not removing shapes from the library (on maybe only in major releases?).
But this leaves the potential problem of changing shape definitions. At least, this would not technically break existing models. I have no idea how many models implicitly rely on details of the shapes – I have never encountered such models myself.
So, this seems a reasonable option.

Before posting this feature request, I had also thought about only storing shapes that are “in use”, but that cannot be decided in all cases.
In my experience, more than 99% of models only use literals for setting shapes (in set shape or set-default-shape), and most other models use a static value passed as a parameter to a procedure.
Still, for dynamic values for shapes – for example from a string input box – NetLogo itself would not be able to determine which shapes are in use.
It might be an option if NetLogo performs the static check on “in use” and leaves the dynamic case to the user – who would be an advanced user in that case anyway.
All aspects considered, I think this approach burdens NetLogo as well as some users, which makes it less attractive.

For the user, forcing a shape to be stored would be easy: edit the shape to let it count as “edited”.

I don’t think it’s a good decision to permanently prohibit any further changes to the shape library, especially since the implementation of SVG support will likely lead to more user and developer shape contributions. You make a good point, though, that most models don’t rely that heavily on details of specific shapes, especially since the turtles are usually pretty small compared to the whole view. So I agree that allowing minor edits and additions but prohibiting removals is most likely a satisfactory solution. We’ll discuss this soon and see what we can work out.

Isaac B.

1 Like

The solution of adding only the shapes currently in use to the model seems like a reasonable approach. I don’t see how this would be problematic.

If I understand correctly, NetLogo would only store shapes that are identified in the code, importing standard shapes from the NetLogo Shape Library when needed, while leaving any additional shapes or shape edits in the file untouched. Even if assignments are made dynamically, I imagine that NetLogo’s check procedure could easily identify them.

@danielvartan Feel free to suggest a solution if you have one, but as far as I know, it’s not possible to infer shape usage from a model. For example, what if the model prompts the user for a shape, with user-input or an input widget? What if the model uses an extension (or in the near future, a library/module) that defines some sort of shape usage? Or what if the shape is programmatically determined or read from some sort of external source? All this variability makes it quite difficult to reliably determine the shapes used by a model, so I don’t think that can be the solution. Let me know your thoughts!

Isaac B.

@ERSUCC please don’t get me wrong, I’m just wondering.

The three scenarios you posed could be resolved with a routine embedded in NetLogo that checks the NetLogo library while changing the shape. A similar routine already exists for extensions: when an extension is missing but available in the extension manager, NetLogo offers to download it.

As I said before, I think trying to resolve “in use” for shapes is too much burden.

The comparison with the extensions manager does not hold. References to extensions are static references, so there is a direct way to check them.

While most references to shapes are static as well, the dynamic ones are the problem for checking “in use”.

Why would a dynamic check be a problem? Couldn’t a routine scan the NetLogo library for matches, even in a dynamic setting?

Yes, it would be slower, but that cost is on the developer for not embedding the shapes into the model. As you said, this is an edge case, but I still don’t see why the routine above wouldn’t work.

OK, What should NetLogo do when it detects a shape “in use” but not in the model file?

If the answer is to get it from the standard shapes, this comes down to the first solution.
With the issue that Isaac raised in his first answer.

If the answer is to give an error message, the problem was not solved after all.
This approach is definitely not as easy as for extensions, while it is still open-ended.
With still an error message if all else fails, it would work of course.
If I were to do the development, I would say it is not worth the effort.

If the answer is to get it from the standard shapes, this comes down to the first solution. With the issue that Isaac raised in his first answer.

I believe you’re referring to this quote from Isaac:

For example, if a model uses the wolf shape and we then decide to remove the wolf shape from the library, that model would no longer function unless the wolf shape was included in the model itself.

If that’s the concern, the solution is straightforward: maintain support for legacy shapes by not removing them from the NetLogo library. What’s the challenge with this approach?

I trust the judgment of the NetLogo developers, but it’s important to open—or reopen—discussions like this one from time to time. Forcing 99% of users to clutter their model files doesn’t seem like a good solution.

1 Like

Thank you both for the thoughtful discussion! As I thought about it more, I realized that although we’ve been retaining these shapes in case we ever change the default shapes or remove shapes from the library, this is realistically never going to happen. So I’ve come around to the idea that we can probably remove these shapes from the default model file. I’ll bring this up in our next meeting and see what people think!

2 Likes

I do agree that it’s wasteful for us to dump every single default shape into each .nlogox file, and I’d like to avoid that. But it’s not really safe for us to skip writing default shapes into .nlogox files, across the board.

The issue isn’t that we could remove things from NetLogo’s collection of default shapes. I’m not sure that’s ever actually happened in the history of NetLogo. More so, it’s that we can change the default appearance of the shapes, and we have done this before. To me, the canonical example of this is the Wolf Sheep Predation model. If you look up old versions of the model, those “wolf” and “sheep” shapes look pretty different.

If default shapes never get stored into your model, changes that we make on our end can cause your model to start looking different, without any input from you. Maybe you wouldn’t like that—I probably wouldn’t.

Consequently, I think it’s wise for us to snapshot only the default shapes that you use in your model. I think that this would be substantially difficult to do with 100% correctness, since shapes are just strings, and people can do something like set shape (word "wo" "lf") or set shape input-field, but we could do a low-effort scan of the model’s code for any string matching a default shape’s name, and solve this issue in ~98% cases.

And, in those other 2% of cases… then, I guess their model changes its appearance, if we change the default shape (which isn’t often at all). If someone is insistent that they really want the old, default shape, they always have the option of preventing this problem on their end, by making a copy of the default shape and saving it directly into their model.

The problems seem rare enough (and workaround-able enough) that it would be worth doing the imperfect, easy fix.

2 Likes

Hi Jason,

If you think it is worth the effort to do this static analysis, I think it is a very nice solution!