Extracting common terms with MathNet Symbolics - c#

I'm using MathNet Symbolics to handle the symbolic algebra portion of a program I'm working on. The general use is create a pair of symbolic formulas, and then divide those two formulas. This works quite well most of the time. However, sometimes, it does not want to do more complex simplification. For example:
(512*r*t*w + 2048*r*t^2*w)
-----------------------------------------------------------------------
(512*r*t*w + 512*r^2*t*w + 3072*r*t^2*w + 3072*r^2*t^2*w + 1024*r*t^3*w)
With some work, I've been able to have it eliminate w from the equation, as it is in all terms top and bottom:
(512*r*t + 2048*r*t^2)
--------------------------------------------------------------
(512*r*t + 512*r^2*t + 3072*r*t^2 + 3072*r^2*t^2 + 1024*r*t^3)
However, I cannot figure out how to make it find common terms:
(512*r*t)*(1 + 4*t)
--------------------------------------
(512*r*t)(1 + r + 6*t + 6*r*t + 2*t^2)
And eliminate these terms:
(1 + 4*t)
-----------------------------
(1 + r + 6*t + 6*r*t + 2*t^2)
I've been using Wolfram Alpha as my gold standard for checking my work. The code from LinqPad I've been working on most of the afternoon, that gets my the elimination of w:
var h1 = MathNet.Symbolics.Infix.ParseOrUndefined("(1/8)*r*t*w + (1/2)*r*t^2*w");
var h2 = MathNet.Symbolics.Infix.ParseOrUndefined("(1/8)*r*t*w + (1/8)*r^2*t*w + (3/4)*r*t^2*w + (3/4)*r^2*t^2*w + (1/4)*r*t^3*w");
Infix.Print(Rational.Expand(h1/h2)).Dump(); //Prints (512*r*t*w + 2048*r*t^2*w)/(512*r*t*w + 512*r^2*t*w + 3072*r*t^2*w + 3072*r^2*t^2*w + 1024*r*t^3*w)
var tot = Rational.Expand(h1 / h2);
var simplified = true;
do
{
simplified=false;
foreach (var v in Rational.Variables(tot))
{
var result = Polynomial.Divide(v, h1, h2);
if (!result.Item1.Equals(MathNet.Symbolics.Expression.Zero))
{
simplified = true;
tot = result.Item1;
break;
}
}
}while(simplified);
tot = Rational.Expand(tot);
Infix.Print(tot).Dump(); //Prints (512*r*t + 2048*r*t^2)/(512*r*t + 512*r^2*t + 3072*r*t^2 + 3072*r^2*t^2 + 1024*r*t^3)
Can someone give me pointers to how to proceed with MathNet? I've tried various combinations of functions from Rational and Polynomial, and have not been able to move past this point.

I've just published a new Math.NET Symbolics release v0.6.0 which includes a new Rational.Reduce routine that removes such common simple factors (also executed as part of Rational.Expand):
var h1 = Infix.ParseOrThrow("(1/8)*r*t*w + (1/2)*r*t^2*w");
var h2 = Infix.ParseOrThrow("(1/8)*r*t*w + (1/8)*r^2*t*w + (3/4)*r*t^2*w + (3/4)*r^2*t^2*w + (1/4)*r*t^3*w");
var q1 = h1/h2;
Infix.Print(q1);
// returns: ((1/8)*r*t*w + (1/2)*r*t^2*w)/((1/8)*r*t*w + (1/8)*r^2*t*w + (3/4)*r*t^2*w + (3/4)*r^2*t^2*w + (1/4)*r*t^3*w)
var q2 = Rational.Expand(q1);
Infix.Print(q2);
// returns: (1 + 4*t)/(1 + r + 6*t + 6*r*t + 2*t^2)
Unfortunately quite a few of the univariate polynomial and rational routines like the new square-free factorization do not have a multivariate counterpart yet. Univariate routines expect one symbol parameter, while multivariate ones expect a symbol set.

Related

Program writes out chars as ascii codes, but only sometimes

I was bored so I decided to create a little rock paper scissors game. It isn't complete because I only wanted to include necessary code. It looks like this:
class Program
{
static void Main(string[] args)
{
char[] enemyznak = new char[9];
char[] znak = enemyznak;
char input;
Console.WriteLine("A as in pAper, D as in Diorite, S as in Scissors");
Random random = new Random();
while (true)
{
Input:
input = Console.ReadLine()[0];
switch (input)
{
case 'A': znak = Paper(znak);
break;
case 'D': znak = Rock(znak);
break;
case 'S': znak = Scissors(znak);
break;
default: Console.WriteLine("Unknown Character"); goto Input;
}
switch (random.Next(0,3))
{
case 0: enemyznak = Paper(enemyznak);
break;
case 1: enemyznak = Rock(enemyznak);
break;
case 2: enemyznak = Scissors(enemyznak);
break;
}
Console.WriteLine(znak[0] + znak[1] + znak[2] + " " + enemyznak[0] + enemyznak[1] + enemyznak[2]);
Console.WriteLine(znak[3] + znak[4] + znak[5] + " " + enemyznak[3] + enemyznak[4] + enemyznak[5]);
Console.WriteLine(znak[6] + znak[7] + znak[8] + " " + enemyznak[6] + enemyznak[7] + enemyznak[8]);
}
}
static char[] Rock(char[] znak)
{
// just like Scissors except different characters
}
static char[] Scissors(char[] znak)
{
znak[0] = 'o';
znak[1] = ' ';
znak[2] = '/';
znak[3] = ' ';
znak[4] = '¤';
znak[5] = ' ';
znak[6] = 'o';
znak[7] = ' ';
znak[8] = '\\';
return znak;
}
static char[] Paper(char[] znak)
{
// just like Scissors except different characters
}
}
During the printing out phase, it shows the player's symbol as weird numbers (such as 190 228 235 for Scissors). However, enemy symbol is written out as it should be, in characters. I tried comparing the segments but they seem the same to me, so what causes this inconsistency?
You bumped into C# operator priority and its implicit behavoiur.
To fully understand the behaviour, let us start from three things:
what your code is actually calling
how the + operator works
what is char type
1. What your code is actually calling
Let us focus on the given line:
Console.WriteLine(znak[0] + znak[1] + znak[2] + " " + enemyznak[0] + enemyznak[1] + enemyznak[2]);
Once you step in while debigging, you will see that the signature of this method is: public static void WriteLine(string? value)
2. How the + operator works
See documentation: + and += operators (C# reference)
In short:
When one or both operands are of type string, the + operator concatenates the string
3. What is char type
See documentation: char (C# reference)
In short:
Moreover, for char operands, arithmetic and bitwise logical operators perform an operation on the corresponding character codes and produce the result of the int type.
We can gather all those details to find out what is going on:
We are calling Console.WriteLine(znak[0] + znak[1] + znak[2] + " " + enemyznak[0] + enemyznak[1] + enemyznak[2]); (so WriteLine(string? value))
2, Program to be able to call WriteLine(string? value) will create a variable of type string? with the following value: znak[0] + znak[1] + znak[2] + " " + enemyznak[0] + enemyznak[1] + enemyznak[2]
As we now from 2, adding char and char with + operator will result in int:
znak[0] 111 'o' char
znak[1] 32 ' ' char
znak[2] 47 '/' char
...
so znak[0] + znak[1] = 143, 143 + znak[2] = 190 (such as 190 228 235 for Scissors)
Now as we now from 3 When one or both operands are of type string, the + operator concatenates the string so: 190 + " " = "190" + " " = "190 ".
Now on the left hand side we have a string. So (as we know from 3) "190 " + + enemyznak[0] + enemyznak[1] + enemyznak[2] will result in string.
You can run the following experiment:
add empty string at the very beginning:
Console.WriteLine("" + znak[0] + znak[1] + znak[2] + " " + enemyznak[0] + enemyznak[1] + enemyznak[2]);
Console.WriteLine("" + znak[3] + znak[4] + znak[5] + " " + enemyznak[3] + enemyznak[4] + enemyznak[5]);
Console.WriteLine("" + znak[6] + znak[7] + znak[8] + " " + enemyznak[6] + enemyznak[7] + enemyznak[8]);
See what will happen. As you have string + char, it will result in string.

Unity export create new .txt files

I'm currently working on a thesis for high school in Germany. My topic is to figure out how we can make traffic intersections more efficient through automation. For this, I'm building a small simulation in Unity3D and right now I'm working on the script and settings for the car. In order to compare multiple settings, I would like to export some data in order to analyze it with NumPy and Matplotlib. But to do so I have to export the data out of Unity.
Right now the car is driving through some waypoints and I would like to get the time when the car is reaching those points.
So now I only have to save them outside of Unity in a format so I could easily import it inside of my jupyter notebook in order to analyze it.
So how would I do this? I know this might be a simple question but most guides are for game objects or characters. So they've saved it for a different purpose.
Update:
Thanks for the help. I got it fixed and now it is writing into a txt file.
Code
Is there a possibility that Unity is creating a new txt file every single time when I run the script. I'm not quite sure if this is even possible at all since I'm technical starting the whole system again and there is no information from last time. As an example that now it's called data1.txt and the next time I'm starting the code it is now saving it into data2.txt.
This is the current output just for some reference.
Data.txt
void FixedUpdate()
{
speed = Engine.currentSpeed;
time = Time.time;
node = Engine.node;
xPos = Auto.transform.position.x;
zPos = Auto.transform.position.z;
if (IsRunning == true)
{
StartCoroutine(Wait());
}
}
public IEnumerator Wait()
{
IsRunning = false;
yield return new WaitForSeconds(WaitTimer);
Output();
IsRunning = true;
}
void Output()
{
print("[" + motorTorque + "," + maxSpeed + "," + steerAngle + "," + node + "," + time + "," + speed + "," + xPos + "," + zPos + "]");
StreamWriter writer = File.AppendText(#"C:\Users\kaykl\Documents\Schule\Info\Data\CarControle\data.txt");
writer.WriteLine("[" + motorTorque + "," + maxSpeed + "," + steerAngle + "," + node + "," + time + "," + speed + "," + xPos + "," + zPos + "]");
writer.Close();
if (IsRunning == true)
{
StartCoroutine(Wait());
}
if (node == 0 && cancel == false)
{
cancel = true;
}
else if (node == 0 && cancel == true)
{
writer.Close();
}
}
An easy way will be save what you need to a file:
https://forum.unity3d.com/threads/how-to-write-a-file.8864/
And for coding a different file every time, just include a time-stamp in the filename.
And alternative will be to use Unity Analytics:
https://unity3d.com/unity/features/analytics
It comes with some nice graphs that could be useful when presenting your thesis.
Good luck!

Selenium c# loop through local variables

I need to loop through some local variables which are used to drive a class that gets data from an excel sheet.
Basically I have 18 questions with radio button answers so I want to be able to loop through these and based on the value in the excel data select the right radio button. My thinking is I would loop through question 1 to 18 and then use a split to set the right radio button.
Here is my code
//Loops questions 1 through 18
int i = 0;
int ex = 1;
do
{
var Answer = userData + (".Question" + ex);
Console.WriteLine(Answer);
switch (Answer)
{
case "Strongly Agree":
driver.FindElement(By.XPath("//*[#id='ctl00_MainBody_Client_lvRiskProfileQuestions_ctrl" + i + "_radAnswerID_" + 4 + "']")).Click();
break;
case "Agree":
driver.FindElement(By.XPath("//*[#id='ctl00_MainBody_Client_lvRiskProfileQuestions_ctrl" + i + "_radAnswerID_" + 3 + "']")).Click();
break;
case "Neither Agree nor Disagree":
driver.FindElement(By.XPath("//*[#id='ctl00_MainBody_Client_lvRiskProfileQuestions_ctrl" + i + "_radAnswerID_" + 2 + "']")).Click();
break;
case "Disagree":
driver.FindElement(By.XPath("//*[#id='ctl00_MainBody_Client_lvRiskProfileQuestions_ctrl" + i + "_radAnswerID_" + 1 + "']")).Click();
break;
case "Strongly Disagree":
driver.FindElement(By.XPath("//*[#id='ctl00_MainBody_Client_lvRiskProfileQuestions_ctrl" + i + "_radAnswerID_" + 0 + "']")).Click();
break;
}
i++;
ex++;
} while (i < 18);
My problem appears to be that the Answer variable is not being set to the value in excel but rather the link its self. The output from the write line is OnlineStore.TestDataAcess.ExcelTestDataParser.Question1
and so on.
Any suggestions of how to get this working will be greatly received
You could try getting the fields of the ParserObject and then getting their value dynamically. For example:
var questionNumber = "Question" + i;
var field = userData.GetType().GetField(questionNumber);
var userResponse = field.GetValue(userData);
var Answer = userResponse + (".Question" + ex);
This should give you the value of whichever question you pass to GetField. Note that GetField returns null of the method is not found so you might want to wrap the field.GetValue in a try-catch.
Also this will only work for member variables not auto-implemented properties i.e. those defined like public string Question1 {get; set;}.
If the questions are added as auto-implemented properties, you can do this instead:
var questionNumber = "Question" + i;
var property= userData.GetType().GetProperty(questionNumber);
var userResponse = property.GetValue(userData);
var Answer = userResponse + (".Question" + ex);
This also assumes a lot about your Parser object, how is each question represented in the parser class?

c# Fractional Calculator - Working out Box?

I'm working on a project where I need to develop a fractional calculator.
I want to add something extra to it, such as having a working out box that displays how the user got their answer.
For example, say I enter 1 1/2 + 1 1/2 into the calculate and press "Calculate", it would then display the answer and how it got the answer such as:
= 3/2 + 3/2
= ((3 × 2) + (3 × 2)) / (2 × 2)
= (6 + 6) / 4
= 12/4
= 3/1
= 3
Here is my basic, crappy looking, program: http://gyazo.com/1dc27b531873c48cdb198baa40b3af9a
I want it to display the working out in the 'Calculations' box below.
How am I able to do this?
Your question is missing some details, so here is a simple answer to begin with.
(I guess your GUI is winforms, and you have a trigger for the calculate OnClick)
To add text into your "Calculations" textbox the code you need is (for your example):
private void calculateButton_Click(object sender, EventArgs e)
{
int common_den = denumerator1*denumerator2;
int new_enumerator1 = enumerator1 * denumerator2;
int new_enumerator2 = enumerator2 * denumerator1;
string myCalculations = " = " + enumerator1.ToString() + "/" + denumerator1.ToString() + " + " + enumerator2.ToString() + "/" + denumerator2.ToString();
string myCalculations += " = " + new_enumerator1.ToString() + "/" + common_den.ToString() + " + " + new_enumerator2.ToString() + "/" + common_den.ToString();
string myCalculations += " = " + (new_enumerator1 + new_enumerator2).ToString() + "/" + common_den.ToString();
calculationsTextBox.Text = myCalculations;
}
If you are looking for the code that will build the calculation string - you need to ask for it explicitly

Count the number of rows in each column

How can I count number of rows in specified column in a Excel sheet?
For example I have 2 columns in a spreadsheet:
A B
--- -----
abc hi
fff hello
ccc hi
hello
The result should look like:
count of A column is 3
count of B column is 4
How can I do this using Microsoft Interop?
The approach suggested by Doug Glancy is accurate and simple to be implemented. You can write the function and retrieve the value from a cell not seenable by the user (ZZ1000, for example). The code is straightforward:
Range notUsed = curSheet.get_Range("ZZ1000", "ZZ1000");
string targetCol = "A";
notUsed.Value2 = "=COUNTA(" + targetCol + ":" + targetCol + ")";
int totRows = Convert.ToInt32(notUsed.Value2);
notUsed.Value2 = "";
UPDATE ---
From your example I understood that you were looking for the total number of non-empty cells, what COUNTA delivers. But, apparently, this is not the case: you want the row number of the last non-empty cell; that is, by using a more descriptive example:
C
---
abc
fff
ccc
hello
You don't want to count the number of non-empty cells (4 in this case; what COUNTA delivers), but the position of "hello", that is, 5.
I don't like relying on Excel formulae too much, unless for clearly-defined problems (like yours, as I understood it initially). Excel formulae deliver still the best solution for what you really want (although its complexity is right "in the limit"). To account for the situation as described above, you can rely on MATCH. If your cells contain text (at least one letter per cell), the code can be changed into:
notUsed.Value2 = "=MATCH(REPT(\"z\",255)," + targetCol + ":" + targetCol + ")";
In case of having numeric values (not a single letter in the cell):
notUsed.Value2 = "=MATCH(LOOKUP(" + Int32.MaxValue.ToString() + "," + targetCol + ":" + targetCol + ")," + targetCol + ":" + targetCol + ")";
If you want to account for both options, you would have to combine these equations: you can create a new formula including both; or you might rely on C# code (e.g., get the values from both equations and consider only the bigger one).
Bear also in mind that you have to account for cases where no matches are found. Here you have a code accounting for both situations (letters and numbers via C# code) and for no matches:
notUsed.Value2 = "=MATCH(REPT(\"z\",255)," + targetCol + ":" + targetCol + ")";
int lastLetter = Convert.ToInt32(notUsed.Value2);
if (lastLetter == -2146826246)
{
lastLetter = 0;
}
totRows = lastLetter;
notUsed.Value2 = "=MATCH(LOOKUP(" + Int32.MaxValue.ToString() + "," + targetCol + ":" + targetCol + ")," + targetCol + ":" + targetCol + ")";
int lastNumber = Convert.ToInt32(notUsed.Value2);
if (lastNumber == -2146826246)
{
lastNumber = 0;
}
if (lastNumber > totRows)
{
totRows = lastNumber;
}
This should do it:
private static int GetRowsInColumnOnWorkSheetInWorkbook(string workbookName, int worksheetNumber, int workSheetColumn)
{
return new Excel.Application().Workbooks.Open(workbookName)
.Sheets[worksheetNumber]
.UsedRange
.Columns[workSheetColumn]
.Rows
.Count;
}
You could have the following override also:
private static int GetRowsInColumnOnWorkSheetInWorkbook(string workbookName, string worksheetName, int workSheetColumn)
{
return new Excel.Application().Workbooks.Open(workbookName)
.Sheets[worksheetName]
.UsedRange
.Columns[workSheetColumn]
.Rows
.Count;
}
It's slightly longer than the other answer, but I think this is more readable, and simpler.

Categories

Resources