June 19, 2019

Week 3 ends.. - Week 3 of the first phase of this coding period is coming to an end. The week started with a bad note, given that I had fallen sick due to travelling. But the work in Week 2, and the meeting with Sartaj on 11th of June helped me to progress...

June 17, 2019

The third week has ended and a good amount of work has been done on polycyclic groups PR here. The collection algorithm has been implemented, from the beginning of the week, I started with understanding the algorithm which took some time and then finally it was implemented, still we are facing a problem in type conversion(here) but that will be sorted out soon!

Even though only two weeks were alloted for polycyclic group implementation but it seems we need one more week or maybe more than a week to implement more functionalities for pc groups. But it’s completely fine because we started work early and according to the proposed timeline we still have one week.

Few of the issues with the current implementation which needs to be sorted out are:

  • firstly to compute uncollected subwords the word is manipulated using its array_form which eventually leads to change in the type of the subwords computed and it creates a problem in processing these subwords further.
  • Some more issues were pointed out by Kalevi and can be seen in the comments of the PR.

The complete week was spent implementing collection of words so a lot of tasks targeted last week were not completed, I’ll try to cover those tasks in the upcomming week.

  • Solve the issues with collection of words.
  • Get ready with the pc presentation.

Till then, Good byee..!

The third week of coding period has ended and as I already stated in the last blog, I couldn’t be much productive this week. Nevertheless, I tried to wrap-up some unfinished works. PR #16956 is ready to merge, just waiting for some last reviews. This PR needs to be supplemented with some fixes in the code of Add class to handle all the issues over Relationals. PR #16978 had one major failing test from the stats module. I tried to debug it ,but due to my unfamiliarity with that part of code I took help from Gagandeep and as his comment suggests, the result this PR is giving is correct and more intuitive. At least, one less issue to handle 😌.

Over the end of the week, I shifted my focus towards New Assumptions. One of my major tasks for this summer is to speed up the satask module. As suggested by Aaron, I searched the repository for issues and PRs over this, and I found a number of such unfinished work. I would need to study these ideas and profile the results before working ahead. I would create a issue-tree over it connecting all such PRs and there respective benchmarks.

For this week, I would focus on the above mentioned task only. Since the first phase is about to end, I would have to speed things up.

June 16, 2019

Hello, the third week ends! I am a little bit too busy to keep contributing on my GSoC project as the first two weeks. Fortunately, thank to the work of the past 2 weeks and the help of my mentors, I become more productive which compensates, more or less, the lack of time.

  • Overview

The task about sparse arrays nearly comes to an end which is the main goal for the first phase. I still have one case to be fixed but most of them are merged in to Sympy’s master and are ready to be used. I started as well preparing for the next task: implementing more data structure for sparse arrays. This would be started in the next week and is supposed to be ended by the begining of phase 2.

  • PRs

Several PR are merged this week for sparse arrays operations. #16937 is finally merged with a code style much simpler than its first version. #16994 about __mul__ and __rmul__ is closed and replaced by #17014 due to a mistake about rebase. #17026 about __div__ and __neg__ operators for sparse arrays is opened and merged. #17035 about permutedims and transpose for sparse arrays is opened and reviewed by my mentor.

  • Issues

No specific issue opened. The list in #16941 is continously being updated.

  • Reviews

No review due to the lack of time.

  • Related works

Pratice of rebasing and merging for a specific case: updated local repository from the upstream master after opening a PR. Even though I have broken the PR #16994, I am still happy to learn some new tricks that I didn’t know before.

Preparing a blog about presenting sparse array associated with my work in SymPy so that my contribution can indeed help people when they need to use this class but don’t really know how to do it and what the advantage would be .

This week started with working on PR #17001. The algorithm was extended to handle concave polygons as well. I came up with a new method which I have explained in the wiki page that I have created. It has to be tested against some symbolic coordinates to make it a complete method.

The API of the CrossSection class has been changed as discussed in the last week. The documentation of the class has been completed.

There were some discussions being done on the necessity and the importance of the CrossSection class. Despite the CrossSection class providing some very useful functionalities of calculating the section modulus, the first moment of area and polar modulus, is there really a need for such a class? After getting some pros and cons listed out we got to a conclusion, that it would probably be better to add these functionalities directly to the geometry module.

But the question of complex geometries like T-shape and I-shape still remains. The alternative to this that we came up with in the discussion was Boolean operations on simple polygons. There are some clipping algorithms like Vatti algorithm and Greiner Hormann algorithm which might be helpful in implementing these.

In short, this is what is left to be done:

  • Transferring the cross-sectional properties defined in the CrossSection class to the geometry module
  • Making the beam class to accept any geometry instead of the second moment that is currently accepted from the user.

In later stages, I might try to work on the Boolean operations as currently there is a limitation of time and the implementation of the stage -II awaits.

After this, the stage-I would end and I will have to start with the next implementation i.e. the column buckling calculations

Next Week:

  • Completing leftovers of the previous week
  • Starting off with stage-II

The work and the progress during the stage-I were full of ups and downs. Will try to make it smoother this time. Will try to discuss the implementations with the mentors and the members in even more detail. Hope to have a good coding week.

Will keep you updated!


Week 3 has ended and we are moving towards phase 1 evaluations by entering the fourth week. Let me tell you what all has been done during the previous week to make the last step smooth.

The basic structure of stochastic process has been added with the merging of the PR #16981 and I am currently working on adding more features like, joint_distribution, expectation and may be some more according to the suggestions recieved from the community. You can read more about it, here. So this was about some processes, now lets move to the case of symbolic dimensions. Well, I made a comment and the members showed agreement to that. I have made some updates to the PR #16962 and the summary is available at this comment. I also discovered that docs of SymPy weren’t being updated at https://docs.sympy.org for the stats module and therefore I modified the PR #16934. For preparation of phase 2, I have created the issue #17039 for discussion on random matrices.

So, what I learnt? Premature optimization is bad for the health of the code. Yes, while reviewing PRs I learnt that concept. I also got to know why some imports cannot be put at the top of the file, all due to a concept called, circular imports. Sounds intuitive and faced a lot earlier but wasn’t aware of the exact term. Thanks to leosartaj for this. I also tried the coverage tests on my local system with the help of oscarbenjamin. Read this comment.

That’s it for now, bye!!

This was the third week meeting with the GSoC mentors which was scheduled on Sunday 16th June, 2019 between 12:00 - 01:00 PM (IST). Me, Amit, Yathartha and Shekhar were the attendees of the meeting. In this meeting mainly it was discussed to improve the code quality and make routine of independent working code.

  • Code quality

Every programmer should master this skill to write a good quality code. Everything from naming, documentation to make routines includes in this skill.

And we discussed mainly the code for the PR #16890 and realising that a new function power_list to be made to return all the powers of symbols present in an expression.

Learning new skills!!

“How did it get so late so soon?” ― Dr. Seuss Welcome everyone, this is your host Nikhil Maan aka Sc0rpi0n101 and we’re running late on everything this week. This time we will talk about some operating system stuff along with the week’s work. I will have more blogs on operating systems and that type of stuff soon. For now, let’s talk about what’s happening. Why so Late?

June 13, 2019

The second week of official coding period has concluded. I will give you a brief summary of the week’s work.

I started this week with working on PR #16956, the PR is now passing tests. I will try to get it merged soon. Later this week, I tried to include complex -> finite in the assumptions system. I started PR #16978 over this. This PR changes the assumptions system to work over the complex -> finite clause. All the instances of use of is_complex call has to be modified. As suggested by Aaron, the is_complex call was changed with a disjunction of is_complex and is_infinite calls. Luckily for me, the usage of complex assumption was not much in the codebase 😌. Though it meant less test failures to handle, the core assumptions system (in the old system) is quite complex to understand and debug, and hence handling all the failing tests proved quite difficult. Also, I tried to work on it without including any new assumptions to the system. One important result of this is, zoo.is_complex returns False now.

Apart from that I have worked on to sync these changes in the new assumptions system as well and I will be sending PR over it soon.

For the coming week,

  • I will start to work on SAT solver and to speed it up. As suggested by Aaron, I will first look into the other unfinished PRs over this.
  • I will sync the new assumptions with the recent developments in the old system.

With enough said, these PRs made me realize how much the codebase can break with small changes in the assumptions. Also, I know this post is a little bit late(because of bad health). I have some pending work over from the last week and I will try to catch speed as soon as possible.

June 11, 2019

Hello world, The second week of coding period has been ended and for the complete week we worked on the presentation of polycyclic groups. I’ve created a WIP PR for the basic structure of PcGroups here but it seems like there are a lot of things that needs to be changed or enhanced in this presentation.

Initially I thought of representing PcGroups with just the generators of the given permutation group and then from the last week we already have composition-series(here) so we can easily compute the generating sequence(pcgs) for the polycyclic group. But, finally we realised that the composition-series will be too big to do all the computations for the PcGroup. Also, in the presentation we can’t ignore the relators.

So, after all this we thought of computing the smaller version of subnormal series with cyclic factors and finally we realised that collection algorithm is something that we need. Can’t say more about this because I have to look into the rewriting code which looks like a tough task for me but let’s hope for the best.

For the next week I’m setting these milestones for me:

  • Get ready with the presentation of PcGroups(still I’m not sure if collection algorithm is what we need!).
  • Implement exponent-vector which may further help in HallSubgroup computation.
  • Include more methods in the PcGroup class.

Will try my best to execute things in order mentioned above. With this, sign out for the next week.

June 09, 2019

Hello everyone! I am glad to present some of my progress during this past week.

  • Overview

I was mainly working on the sparse aray issue over this week. A sparse array is, by a brief definition, an array in which most of the elements are zero. In order to save the memory cost, sparse array is distinguished from the dense array(which means most of elements are non-zero) and then is stored and manipulated in a different way. The default data format in SymPy for sparse array is called Dictionary of keys (DOK), where the non-zero value is stored in a dictionary.

However, the sparse array is cast to dense array in various ways. So what I am trying to do is to free these sparse arrays and nake good use of them for cases like large scale sparse array operations.

  • PRs

The PR about derive_by_array #16937 is not yet merged. Thank to the guidance of my mentor Francesco, the PR is being ameliorated and now has satisfactory result. Besides the operation of derive_by_array, I have updated as well the way Array module perform a equality test and apply function. To show the result of these changes, let’s see what the behavior of derive_by_array was:

>>> a = MutableSparseNDimArray.zeros(10000, 20000)
>>> a[1, 1] = i
>>> a[1, 2] = j
>>> d = derive_by_array(a, i)
>>> d = derive_by_array(a, (i, j))

The sparse array is cast to a list which leads to the MemoryError. Now, we can have:

>>> a = MutableSparseNDimArray.zeros(10000, 20000)
>>> a[1, 1] = i
>>> derive_by_array(a, i) = ImmutableSparseNDimArray({20001:1},(10000, 20000))
>>> a[1, 2] = j
>>> derive_by_array(a, (i, j)) == ImmutableSparseNDimArray({20001: 1, 200020002: 1},(2, 10000, 20000))

The operation is much more rapid and can save a lot of spaces of memory.

Francesco also helped to improve the quality of codes. For example, to perform the deriative of a sparse array, he suggested me to use a dictionary comprehension instead of a for loop, so an extra function is replaced by one single line of code.

A new PR #16994 about __mul__ and__rmul__ is opened, which solves the problem of casting in these operators. Same as another new PR #17000 for tensorproduct. However, these PRs cannot pass the test for now because the issue about equality test is not yet fixed and merged into master of SymPy.

A new PR #16969 about adding functions and tests for ArrayComprehension is merged, which added functions like .tomatrix(), .tolist() for this class.

  • Issues

I have opened a issue #16984 about equality test of Dict and dict objects. I ran into this case while comparing the dictionaries of sparse array. Fortunately, this issue is recently fixed.

  • Reviews

No reviews for other contributors’ PR. I have participated in the review of my own PRs since there are some errors have been found after the creation of PR.

  • Related works

I have participated in the discussion about the nature of ArrayComprehension in the community this week. Comprehension is a new class that I implemented last week(See last post for more details) This discussion helped me better understand the difference between a multipledimensional list and an array: an array is suppposed to perform vectorized operations while list is mosyly element-wise.

The second week has ended and here I am to give you a brief about the week’s work!

The week started with the opening of a PR #16964 which intended to define a class CrossSection as planned. Discussions have been done in this PR regarding its API and its need. All these discussions lead to a conclusion of making a slight change in the API to make it accept any arbitrary cross-section which the user can define using the geometry module. So now the CrossSection class will take the input of a pre-defined object of the geometry module and calculate its corresponding properties. This will make the CrossSection class much simpler and generalized. I will be updating the same in the PR soon.

I had also researched some of the previous works done in this area. PR #14434, which intends to implement a shape class, giving functionality to cut an ellipse or a parabola via a line and determine the properties of the newly formed segment. I have tried to implement a similar concept to the Polygon class via a method cut_section() in PR #17001.

Also since one of the major issues also was to determine the first moment of area, this PR would further help in the calculation of the first moment of area. It intends to give the Polygon class functionality to return a new Polygon segment formed when a given line intersects the Polygon. Although, an alternative method of Polygon triangulation also has been discussed in this PR, to determine the first moment. I will have to do a bit of research for this to get this implemented.

Next Week:

  • Implementing a method to determine the first moment of area
  • Completing the CrossSection class along with its documentation and testing
  • Linking it with the beam module
  • Working over the implementation of Stage-II

I will try to make the CrossSection class fully functional, by the end of the coming week.

Will keep you updated!


Week 2 ends.. - Week 2 of the Coding Period (Phase 1) is coming to an end. This week was mostly devoted towards polishing the existing PRs, and bringing them to a mergeable condition. And this week resulted in the merge of 2 PRs. Yayy !!! Here are the deliverables which have been completed...

This week involved a lot of work and reviews. I worked on three PRs this week which were started for the purpose of, Markov chains, symbolic dimensions and symbolic conditions for finite RVs. Let me tell you how I managed all this.

The most important and the most demanding PR from all the said topics was that of Markov chain. I told you that we were discussing API for the same. Fortunately the discussion concluded and I started implementation with the starting of the second week, by opeining #16981. Infact, the basic structure is ready and I am vary happy, that the code is able to handle probability queries and is generating desirable results. Out of curiosity, I started work on symbolic dimensions for helping one of my fellow students. Infact, it’s also going to be completed, see #16962. The work for symbolic conditions which started for the purpose of correcting @XFAIL tests is also almost complete, take a look at #16908. I have observed that still there are some issues with sympy.stats.frv which need to be handled in a different set of PRs. Hopefully, I am planning to make some of those this week if time permits. I also aim to add more features to StochasticProcess like joint_distribution, and adding more properties to DiscreteMarkovChain like, whether it’s absorbing, transient. Adding, ContinuousMarkovChain will also be on my list.

Apart from a lot of work there was a lot of learning too. I got many of my concepts cleared, like, inherit Basic only when the instance of the class is going to be a part of SymPy expression. Thanks to Ondřej Čertík for this. I also realized the worth of sympy.stats.symbolic_probability while working on symbolic dimensions. Francesco used to suggest that we should use it wherever necessary, but now I completely understand his view.

That’s all, thanks for reading. Bye!!

June 08, 2019

This was the second week meeting with the GSoC mentors which was scheduled on Saturday 8th June, 2019 between 12:00 - 01:00 PM (IST). Me, Amit, Yathartha and Harsh were the attendees of the meeting. It was a surprise having Harsh on this meeting. In this meeting we mainly discussed about how to integrate lambert another way because the existing method in PR #16890 is not trustworthy and upto the mark. So this week I will try to implement the method or approach told by Yathartha. Important lesson learned in this meeting was that the method that I implement should have these following qualities to be a better software developer:-

  • Proof Of Correctness

This is very important because I should have a plan before I get to code. Many things already get straightened up while planning for what to implement and it ultimately reduces coding time and let us get a more accurate and concrete code.

  • Clean and Understandable Code

This factor is also very important to write a code that is easily understandable. It is better for us as well as it also persuade new contributors easily who are willing to contribute.

  • Extensible Code

A well written code is always extensible. Proper techniques should be learned to write an extensible code rather than a code that looks like patch.

In this week I also started a PR #16976 to handle modular equations.
It was a worth it meeting because I got to learn various important and necessary qualities from all of the mentors. Harsh was also glad that we were trying to focus on well written clean code.

A lot more to learn and implement :) !!

Welcome everyone, this is your host Nikhil Maan aka Sc0rpi0n101 and this time we will talk about the Week 2 of the coding period for GSoC 2019 and the story of the elusive pull requests which people had to wait almost the whole week for. The Weekend after the Meeting A Bad Start Finally, the Pull Request The Meeting for the Week The Next Week The Weekend after the Meeting The plan for the week was discussed in the meeting held on May 30 which was to post a PR with the Clang work and get on track with LFortran with the developer examples in the developer tutorial and post a PR if possible.

June 07, 2019

Posted on June 7, 2019 by Ankit Pandey

See the previous post for Week 1.

For this week, I’ve continued working on adding support for LFortran to SymPy’s code generation capabilities. This week mostly involved getting the infrastructure for testing the functionality of the new code generator working. I also extended the number of expressions the generator can handle, in addition to adding to LFortran’s ability to parse numbers upstream.

More Expressions

I’ve added support for four more expression types that the generator can handle: Float, Rational, Pow and Function. Since our base translation class was already in place from last week, implementing these was relatively straightforward and involved just defining the node visitors for each expression type (The commit that implements this can be found here). Here’s a demonstration showing the abstract syntax tree generated from translating the expression (43)x\left(\frac{4}{3}\right)^{x}:

However, the translator fails for expressions that should in theory work. Right now, we can’t add an integer to a symbol because symbols default to real numbers, resulting in a type mismatch:

Fortran allows the implicit conversion of a float to a real, and the expression shouldn’t generate an error. This is functionality that will hopefully be implemented by the time I come back to this project close to the end of the summer.

Testing the LFortran Converter

I also added the initial infrastructure for testing the new code generation functions, with the starting commit available here. As Aaron mentioned in one of our meetings, the plan right now is for code generated by the LFortran backend to be equivalent to the output generated by the existing fcode at the AST level. Each test should be in the form of an assertion that tests the (parsed) output of fcode applied to a SymPy expression against the same AST generated by our newly implemented sympy_to_lfortran. The LFortran project already has code to check generated ASTs against expected values, so I adapted this to the testing library of our code generator (I’m also not sure how this works in terms of licensing, since both SymPy and LFortran use the BSD-3 license).

One problem that immediately became apparent was the way that LFortran represents numbers. Looking at the expression tree above, the real numbers are actually stored as strings. On the parser side, LFortran stores a real number as the string used to represent that number. This means that the ASTs of two expressions that represent the same number in different ways are not identical (for example, 1.0_dp and 1.d0 both represent the same double precision floating point number, but the strings stored by LFortran will be different). It’s only at the “annotation” stage of evaluation that LFortran canonicalizes floating point representations. For now, the tests use the annotation function of this stage, and I filed a merge request on the LFortran project to add support for parsing numbers in the way that fcode generates them.

While the initial infrastructure is in place, I haven’t added any tests yet. Since the LFortran project is still in early alpha, the functionality needed to compare the syntax tree made by the builder API against the syntax tree parsed from the output of fcode hasn’t been implemented yet. Again, this is something that will hopefully be implemented in LFortran near the end of the summer when I start on this portion of the project again.

Contributing Upstream

After I filed the merge request to add the functionality I needed to LFortran, Ondřej (the creator of LFortran and one of my mentors) mentioned that he was planning on eventually removing the module I contributed to. The merge request I filed actually wasn’t the one I had in mind at first. I thought about adding support for canonicalizing number nodes right after they’re created in the builder API, but I decided against this because I felt that any changes I made would have to be minimally invasive. In retrospect, this was probably a misplaced concern, since it’s important to consider the development stage of a project when deciding how much of it should be changed. Because of this, LFortran will probably end up with something I opted at the moment to not implement.

Next Steps

There’s still some work left to be done with LFortran, such as filing issues I encountered and preparing the pull request for a merge (though it’ll probably remain a work in progress for some time). After that, I’ll be finished with LFortran for the time being and move on to extending support for matrix expressions in the Python code generator. The Python code generator can already convert (most) matrix expressions through NumPy, though there are still some bugs owing to an incomplete implementation. For next week, I’ll have to figure out what this missing functionality is how it can be implemented.

June 05, 2019

Welcome everyone, this is your host Nikhil Maan aka Sc0rpi0n101 and today I would like to tell you about the Community Bonding Period of GSoC 2019 and also talk about my project and organization in detail. GSoC My Project The Organizations Community Bonding Period GSoC Google Summer of Code (GSoC) is a 12-week program, sponsored by Google to promote open-source among various college students around the world, where the people selected are assigned to projects from different open-source organizations working over the summer contributing to open-source software.

June 04, 2019

The coding period has been started from 27 may 2019 and the first week went well. We worked on the composition series computation for solvable groups. I was waiting for the PR to get merged so, that I can include a fully completed PR here 🙂. Kalevi helped a lot in reviewing and helping me with the algorithm. The PR link is here.

Till now, everything is going as it was planned. The abelian invariants PR has been already merged in the community bonding period itself, may be some other time I’ll discuss about the details of it but for the time being one can look into the PR of abelian invariants here.

Composition series of a group G is defined as the subnormal series G = H_0 > H_1 > H_2 \ldots > H_k = 1 where every factor group H(i+1)/H(i) is simple. The algorithm is described in the implementation itself. We wanted to make sure, the implemeted method work as expected so, I wrote a good amount of tests and examples in the docs.

The tasks that I’m hopping to accomplish in the next week are:

  • Discuss with Kalevi about the Polycyclic group implementation.
  • In the end of the week get ready with WIP PR on pc groups.

Hopping I’ll be able to execute things as planned! Till then good bye, keep learning.

The first week of official Coding Period is over and it went well 😄.

As proposed, I created a branch over #7608 and went through it locally. I have made certain improvements and I will create appropriate PR for them this week. I intend to get that merged in this week only, if everything goes well. Also, as suggested by Aaron, I looked for profiling tools for optimizing slow parts in the codebase. I will be using pyinstrument and the profiler of PyCharm for this purpose.

Later in this week, I started the PR #16956 which fixes issues #16915 and #16582. Both these issues are related to assumptions handling in Relationals. It broke more code than expected 😅. This shows how embedded the old assumptions are in the codebase. I will try to fix them ASAP.

With the first week wrapped up, in the next week :

  • I will create an experimental PR to include complex -> finite in the old assumptions. This is going to break zoo.is_complex overall. I will try to do it without including new facts. #16666 shows how difficult such proceedings can be.
  • I will also create a PR to include complex -> finite in the new assumptions. This should be easier than the former. The new assumptions is still not used much in the codebase 😌.

I will try to shift my focus more towards the new assumptions. But I will also look for any major inconsistency between the assumptions systems.

With this, sign out for the next week.

June 02, 2019

Hello everyone! Here comes the end of the first coding week. This blog is dedicated to present the progress that I have had during the past week.

  • PRs

This week the PR about ArrayComprehension is merged. #16845. This class is designed as an extension of list comprehension in Python, which enables the list comprehension with symbolic dimensions.

A new PR #16937 about the sparse array being cast to dense array in the case of derive_by_array is opened. But somes improvements are still needed. The challenge is to find an approriate method to override and perform a derivative correctly.

  • Issues

An issue #16911 is opened. It is in fact a discussion about implementing a NumPy-Like behavior in Array module. It is interesting because my mentor was, at first, not in favor of this implementation. But some differences of behavior between the Array module in SymPy and the one in NumPy did change his mind. So this implementation can be kept in my proposal and will be my tasks for the next phase.

Another issue #16941 whose aim is to list out all cases where a sparse array is cast to dense arrays is opened this week. Not only as a discussion, this issue would also be a overview of the problems so that the PRs like #16937 can refer to it. A checklist is being updated to show the avancement.

Please feel free to comment on the issues or the PRs that I opened. I would love to listen to your opinions.

  • Reviews

After the merge of ArrayComprehension, another student Gagandeep Singh opened a new PR to ameliorate the code quality of this class. I have also participated as a reviewer to offer some help. I have also leant a lot from the discussion.

  • Related works

Not much, due to the burden of projects in college.

The GSoC timeline started as soon as the projects were announced and so did the work on projects.

The Community bonding period ended last week. There wasn’t much work in the community bonding period. All I had to do was to extend my knowledge base related to the project and to familiarize with the development flow.

I started with going through the geometry module, which has a major role to play in the implementation of the Stage-I i.e. the implementation of CrossSection module. Also, I studied about the different properties of cross-sections, like, the first moment of area, polar modulus, section modulus, etc.

So the coding period started on 27th May and now the first week is completed. My task in the first week was to start the implementation of the CrossSection module. It majorly comprised of defining a new class CrossSection.

Major tasks inside the CrossSection class were:

  • Defining the different geometries using the geometry module:
    • Circle: A circular cross-section was easily defined by using class sympy.geometry.ellipses.Circle
    • Rectangle, I-section, T-section, triangle: These four shapes were defined using class sympy.geometry.polygons.Polygon. These geometries were defined using point to point mapping in the counter-clockwise direction in such a way that it starts at the origin and joins all the given points or vertices of the polygon in the given sequence.
    • All these geometries were defined in a way that they lie in the first quadrant, in order to get correct values of the centroid.
  • Defining different properties of the above cross-sections:
    • Area
    • Centroid
    • Second moment
    • Polar modulus
    • Section Modulus
    • First moment

Implementing these was not that difficult as area, centroid, the second moment are already implemented in the geometry module. On the other hand, polar modulus and section modulus were specifically defined in the CrossSection module separately for each geometry.

The problem of defining the first moment of area:

The way the first moment of area is calculated can be seen from here. And since the first moment of area is required majorly to calculate the Transverse shear stress on a beam, we are interested only in the first moment along the x-axis (or the horizontal axis).

But just a day pondering over it I realized that the first moment calculated as above calculates it for the extreme layer of the beam. Probably, we will have to return it in terms of y, so that the shear stress at any layer could be calculated.

where “y” is the distance of the layer of the beam from the neutral axis

So, I will be opening an issue-cum-discussion regarding the above problem to discuss it with the mentors. Also, I will soon be opening a work-in-progress PR regarding what has been implemented.

Next Week:

  • Completing the CrossSection class and linking it with the beam module via an add_cross_section() function.
  • Adding tests to the CrossSection module and in the Beam module
  • Completing documentation of the CrossSection module.

Since I had to travel this weekend there was a bit of delay in the progress. But I am positive that I will be able to compensate for it in the next week. Also, I will try to keep the work a bit in advance.

Will keep you updated!


Week 1 ends.. - Week 1 of the Coding Period (Phase 1) is coming to an end. It was a hectic week for me, as I had to travel in the initial days of the week, but the work done in Community Bonding Period, helped me to progress faster. I also had a meeting...

The first week of official coding phase is over and it’s time to tell you about what I did and what I learnt. So here it goes.

I started discussion with my mentor about API design of Markov chain. We have more clarity about the same than before. The final API will be somewhat closer to the one mentioned in this comment. The discussion about probability space of stochastic process is under way. We will conclude that soon.

I also made some PRs during this week for improving the distributions which I added during the bonding period. The PR #16914 allowed the possibility of symbolic dimensions in MultivariateEwens. We earlier decided that we will use ArrayComprehension which one of my fellow students developed. However, currently it needs a lot of improvements before being put to use. I have made an attempt to optimise the code of ArrayComprehension via PR #16929. It also covers some cases which were left during the inital merge. I have also tried to allow symbolic conditions to finite probability spaces. I have two approaches for review. One of them is in the diff of PR #16908 and the other one is in this comment. I have also made some minor improvements like changing namespace of joint_rv_types via PR #16919, enhancement of P in PR #16907 and some general bug fixes in MarginalDistribution at PR #16934.

Doing all this I learnt a lot of things. The most important was that API design matters the most. Without it, it’s not possible to develop a good class structure. Thanks to Francesco for making me learn this fact. The other thing is, how sometimes even to make small changes in a large code base, it takes hours to get it right. Another fact which I learnt is how small optimisations in a large of code base can improve the performance.

See you next week with some more progress. :)

This was the first week meeting with the GSoC mentors which was scheduled on Sunday 2nd June, 2019 between 11:30 AM - 12:30 PM (IST). Me, Amit and Yathartha were the attendees of the meeting. In this meeting we mainly discussed about the problems and implementation for my pull request #16890 to complete the lambert solver.
As Amit requested changes at the pull request to describe the problem in detail, to give proof of correctness and describe the plan more briefly. So here below are the all details for what I am trying to achieve and how I am trying to achieve this:-

Current Implementation

Let me show here code from _lambert function to show the current implementation so that I could describe the problem in detail:-

u = Dummy('rhs')
sol = []
# check only real solutions:
for k in [-1, 0]:
    l = LambertW(d/(a*b)*exp(c*d/a/b)*exp(-f/a), k)
    # if W's arg is between -1/e and 0 there is
    # a -1 branch real solution, too.
    if k and not l.is_real:
    rhs = -c/b + (a/d)*l

    solns = solve(X1 - u, x)
    for i, tmp in enumerate(solns):
        solns[i] = tmp.subs(u, rhs)
return sol

Explanation of for loop:

  1. k == -1 :- In this case all the real solutions are considered due to not l.is_real.
  2. k == 0 :- In this case all the solutions come out to be real as always.

What solutions are missed?

The solutions are missed due to the argument inside the LambertW function of value

l = LambertW(d/(a*b)*exp(c*d/a/b)*exp(-f/a), k)

While converting all lambert solvable equations to this form F(X, a..f) = a*log(b*X + c) + d*X + f = 0 some solutions get missed.

For eg: Consider the equation (a/x + exp(x/2)).diff(x) = 0 which is -a/x**2 + exp(x/2)/2 = 0(Please take note of the x**2 in denominator of a). And we can also write this equation as -a/(-x)**2 + exp(x/2)/2 = 0. What sympy do is to convert this equation to this form:

F(X, a..f) = a*log(b*X + c) + d*X + f = 0

which will be 2*log(x) + x/2 - log(a) = 0 and 2*log(-x) + x/2 - log(a) = 0 respectively: So solutions corresponding to both equations are:

2*log(x) + x/2 - log(a) = 0 --> [4*LambertW(sqrt(2)*sqrt(a)/4)] --> this is currently included
2*log(-x) + x/2 - log(a) = 0 --> [4*LambertW(-sqrt(2)*sqrt(a)/4)] --> this is missed

What type of lambert type equation it is for?

This is for the equations where the changing of cofficients of the target equation doesn’t change the original equation just like the above case.

What’s the current algorithm to solve such type of equation and what’s wrong with current logic?

Current implementation is shown above and what is wrong is that it is not considering the other logarithm equations which are originated from the original equation. 2*log(-x) + x/2 - log(a) = 0 in case of (a/x + exp(x/2)).diff(x) = 0.

What’s the proposed solution?

This problem can be solved by two methods as follows:

  • Combining all the logarithm forms generated by the original equation(by taking abs)
    2*log(x) + x/2 - log(a) = 0 + 2*log(-x) + x/2 - log(a) = 0
                          \      /
                           \    /
                            \  /
              2*log(abs(x)) + x/2 - log(a) = 0                     

    I think this method is not viable at this time as it will be very complex to solve the equation invloving abs with log.

  • This method I propose to solve this problem i.e considering all solutions and eliminating by substitution. For example for this equation (1/x + exp(x/2)).diff(x) = 0 Possible solutions considered [4*LambertW(-sqrt(2)*sqrt(a)/4), 4*LambertW(sqrt(2)*sqrt(a)/4), \ 4*LambertW(-sqrt(2)*sqrt(a)/4, -1), 4*LambertW(sqrt(2)*sqrt(a)/4, -1)] Solutions after filtering from checksol [4*LambertW(-sqrt(2)*sqrt(a)/4), 4*LambertW(sqrt(2)*sqrt(a)/4)].

Why is the proposed solution better and how it won’t effect the other equations (no side effects)?

This method involves less computation to solve this problem i.e considering all solutions and eliminating by substitution rather than first converting the given equation to target equation in which we doesn’t know about coffecient of logarithmic equation and solving it again by making different equations from it in case of abs taken.

This doesn’t effect other equation because the only thing we are doing is considering all solutions and not changing code for other type of equations. And we are using checksol to check the correct solutions.

What is the testing strategy to verify that the proposed solution works?

Testing strategy should be to involve the cases where current implementation is missing other logarithmic equations.

Which examples/equations are we going to use to make sure that those are necessary and sufficient for testing purposes?

According to me these tests are sufficient test this strategy:

assert solve((a/x + exp(x/2)).diff(x), x) == \
        [4*LambertW(-sqrt(2)*sqrt(a)/4), 4*LambertW(sqrt(2)*sqrt(a)/4)]
assert solve(x*log(x) + 3*x + 1, x) == \
        [exp(-3 + LambertW(-exp(3))), exp(-3 + LambertW(-exp(3), -1))]
assert solve((1/x + exp(x/2)).diff(x, 2), x) == \
            [6*LambertW((-1)**(S(1)/3)/3), 6*LambertW((-1)**(S(1)/3)/3, -1)]
assert solve(-x**2 + 2**x, x) == [2, 4, -2*LambertW(log(2)/2)/log(2)]
# issue 4271
assert solve((a/x + exp(x/2)).diff(x, 2), x) == \
            6*LambertW(-(-1)**(S(1)/3)*a**(S(1)/3)/3, -1),
            6*LambertW((-1)**(S(1)/3)*a**(S(1)/3)/3, -1)]
assert solve(x**2 - y**2/exp(x), x, y, dict=True) == \
                [{x: 2*LambertW(-y/2)}, {x: 2*LambertW(y/2)}]

Some test cases that fail due to some other reasons

  • assert solve((1/x + exp(x/2)).diff(x), x) == \
    [4*LambertW(-sqrt(2)/4), 4*LambertW(sqrt(2)/4), 4*LambertW(-sqrt(2)/4, -1)]
    assert solve(x**2 - 2**x, x) == [2, 4]

    These tests are failing because checksol returns false but expected to return true Although _lambert is returning correct solutions of equation.

  • assert solve(a/x + exp(x/2), x) == [2*LambertW(-a/2), 2*LambertW(a/2)] In this case 2*LambertW(a/2) which is not a solution is included because checksol returns none.

  • >>>solve((1/x + exp(x/2)).diff(x, 2), x)
    [6*LambertW((-1)**(1/3)/3), 6*LambertW((-1)**(1/3)/3, -1)]

    here (-1)**1/3 can have these values -1, 1/6(1 - I*3**1/3), 1/6(1 + I*3**1/3) but sympy only take (-1)**1/3 to be 1/6(1 - I*3**1/3) whereas real solutions are [6*LambertW(-1/3), 6*LambertW(-1/3, -1)]

Why including checksol in _solve_lambert ?

Due to this test case:

p = symbols('p', positive=True)
eq = 4*2**(2*p + 3) - 2*p - 3
assert _solve_lambert(eq, p, _filtered_gens(Poly(eq), p)) == [
    -S(3)/2 - LambertW(-4*log(2))/(2*log(2))]

To remove the solutions which were supposed to be checked by checksol later in solve.

Pardon me if I missed a thing!!

May 31, 2019

Posted on May 31, 2019 by Ankit Pandey

For the past week, I’ve been working on adding support for LFortran to SymPy’s code generation capabilities. My current goal is to emulate SymPy’s fcode, which converts a SymPy expression to an equivalent expression in Fortran, utilizing only LFortran as a backend. This post is an outline of what I’ve done (and learned) over last week.


LFortran is a Fortran (with some extensions) to LLVM compiler. One advantage that this design provides is that it enables interactive execution of Fortran code. LFortran can also be used as a Jupyter kernel, which means it can be used in a Jupyter notebook environment (you can even find an online interactive demo here).

In addition to being able to parse code, LFortran also provides the functionality of traversing a parse tree and generating the equivalent Fortran code. This means that if we want to generate Fortran code from a SymPy expression, the only work that we have to do is convert the SymPy expression tree to its LFortran equivalent.

LFortran Builder

LFortran provides a number of convenience functions for building a Fortran AST. Since LFortran is still in early alpha, there are currently only about a dozen builder functions. However, these few basic functions are enough for constructing simple expressions in the Fortran AST. As an example, if we wanted to construct the expression represented by c = a + b, where each variable involved is an integer, we could do something like:

LFortran also provides functionality to visualize what the expression tree looks like:

>>> import lfortran.asr.pprint as pprint
>>> pprint.pprint_asr(expr)

Sympy to LFortran Converter

I’ve started with the implementation of a basic SymPy to LFortran converter utilizing the AST builder described above, with the current pull request available on the SymPy GitHub. The converter follows the same node visitor class structure as all of the other code printers (it even inherits the CodePrinter class, despite the methods not producing strings but rather AST nodes). Here’s a simple example that demonstrates the conversion of a simple expression to an equivalent in LFortran:

There are two things to notice here. The first is that I had to replace all the newlines in the generated expression, since a bug in LFortran causes too many newlines to be printed. The second is that there are a number of redundant parentheses in the printed expression. While this isn’t an outright bug, it’s another aspect of LFortran that is currently being improved upon.

I’ve also add another function, sympy_to_lfortran_wrapped, which wraps an expression in a function definition, (poorly) emulating the wrapping part of autowrap:

>>> from sympy.codegen.lfort import sympy_to_lfortran_wrapped
>>> e_wrapped = sympy_to_lfortran_wrapped(e)
>>> print(lfortran.ast_to_src(lfortran.asr_to_ast(e_wrapped)))
integer function f(x) result(ret)
integer, intent(in) :: x
ret = 1 + x
end function

Since LFortran can directly compile the AST to an LLVM intermediate representation, a future implementation of autowrap might be implemented by compiling the output of this function (instead of first completely generating the code and then feeding it to gfortran as it’s done right now).

Next Steps

For the next couple of days, I will try to extend the types of SymPy expressions that may be converted. One thing to note is that there isn’t a perfect correspondence between SymPy and LFortran AST nodes. LFortran supports nodes for operations like unary subtraction and division, which SymPy converts into multiplication and division respectively. On top of this, I’ll also add some tests for the functionality that I have implemented so far. After that, I’ll start with work on SymPy’s matrix expression code generation (the second part of my GSoC project) and pick LFortran up again close to the end of the summer.

Welcome everyone, I am your host Nikhil Maan aka Sc0rpi0n101 and I will be barraging you with blogs of my progress with my GSoC project. This is the blog for the first week of work. The official coding started May 27. Today is May 31, it’s been 5 days of work and I’ve had some progress since Monday and had the meeting for the first week yesterday. The week has not been as productive as I would’ve liked to be but I managed to get in some work.

May 29, 2019

Community bonding period has concluded. Due to my exams and travelling, I was not able to devote much of my time over this. But I managed to review PR #16666 and helped it get merged. With this PR, SymPy comes one step closer to unifying both the Assumption systems. Also, with this I realized how difficult reviewing can be 😅.

I had my first meeting with my mentors, Aaron and Kalevi, on Monday where we decided about the timings of weekly meetings. It was also decided to use gitter as a medium for these meetings. Aaron also gave me some directions about the overall project.

Since the official coding period has begun, I will try to stick to my proposal. These are my plans for the coming week:

  • As per my proposal, I have to include First Order Logic into SymPy. There is already a PR on this ( #7608). During this week I will work on to improve over it.
  • Also as suggested by Aaron, I will look into some known performance issues with assumptions.

Along with this, I will also be looking for inconsistencies between the two Assumptions systems.

Sign out for the next week 😄

May 27, 2019

So, here I am with another set of experiences to share with you, i.e., the Community Bonding of GSoC. After discussing with my fellow developers, and my mentors, we reframed our timeline. I will be working on very interesting topics in statistics, including, joint distributions, Markov chains, random matrices, assumptions of dependence and simplifying the results of the stats module. For a head start, I started working on adding multivariate distributions and the good news is that I have completed majority of the work, apart from some technical constraints which will be solved by another project very soon. If you are interested in seeing the code, take a look at the PRs #16576, #16808, #16825. Infact, apart from the stats module, I also had an opportunity to work on other modules of SymPy, like, I improved the API of Sum in sympy.concrete, allowing Range to be passed as limits and that too while working on discrete joint distributions. You can check the PR #16810 for the details. Thanks to Christopher Smith for helping me with this. Still there are issues like, #16833 which require a lot of discussion before concrete implementation, will update you on this if some progress takes place. Apart from coding, we had discussions on design of Markov chain and random matrices. I also made two prototypes at PR #16852, and #16866 . We are currently having more to think on this part, like API, class structure, etc. Overall, the bonding period was very a great learning experience about how various modules affect each other and bring the best out of SymPy. See you soon in the next blog. :)

May 26, 2019

The Journey will begin now !! - The all-important Community Bonding Period ends!! During these three weeks, I have come to learn a lot more things about SymPy, and especially its Series module, the module I would be improving this summer. The first week of the CBP was wasted since I had college exams going on, and...

Older blog entries

Planet SymPy is made from the blogs of SymPy's contributors. The opinions it contains are those of the contributor. This site is powered by Rawdog and Rawdog RSS. Feed readers can read Planet SymPy with RSS, FOAF or OPML.