Get intersection of two NFA - intersection

So i have this problem where I have to find the intersection of two NFA and I don't find any solution.
So you have two automatons m1 and m2 with m1=(Q1, Σ1, Δ1, q1, F1) and m2=(Q2, Σ2, Δ2, q2, F2).
I think that Q is formed by a combination of states of Q1 and Q2, so that any state of m is made of every possible combination of states of m1 and m2.
Then Σ is formed by the union of Σ1 and Σ2 I suppose.
Then the begin end end state is made of the combination of begin and end state of m1 and m2.
Buth my question is: how are F and Δ formed. Is it just the cartesian product or is it something special?
Does anyone know if there is a difference or am i totally wrong with the other parts?
So i had this excercise and found the following solution. So the excercise is to make an intersection of these two NFA's:
Excercise
This is my reduced solution:
Final solution
Can anyone let me know if i'm right?

F is formed by the union of F1 and F2 as we have the "or" condition and again any given string of F1 should be accept in F so we have F as union of set of final states in F1 and F2 and i suppose this would be minimizable depending on the set of alphabets, the transitions depend on the transition of both F1 and F2 and should be converted to other form as F1 cannot transit for any input of F2 so again no. of transitions is cartesian product of F1 and F2.

Related

MySQL - Cannot reference result of a subquery

Hit a roadblock and hoping someone here is able to help please?
edit: DB<>FIDDLE : https://dbfiddle.uk/?rdbms=mysql_5.5&fiddle=c73f8ec9a60f530fe4ad489dc743f9b9
I have 3 tables:
marks - which uses grades;
target - which also uses grades;
grades - a lookup for grades to points.
What I am trying to do is calculate the total points for grades within the marks table, then calculate the total target points by multiplying the points value for the target by the number of grades within the marks table for a given person (adno).
I'm able to sum and count the points values from the marks table without a problem, but as I've used an inner joint for the marks to grades already I cannot add a further one for target to grades so I've used a subquery.
However when I try to use the result of subquery (EDIT single_target_points , not target_points as I originally posted) in the calculation in the line straight after it I get the error :
[Err] 1054 - Unknown column 'single_target_points' in 'field list'
This is the query I am trying:
SELECT
marks.adno,
Sum(grades.points) AS total_points,
Count(grades.points) AS no_of_subjects,
(SELECT grades.points FROM targets INNER JOIN grades ON targets.grade = grades.grade WHERE targets.adno = marks.adno GROUP BY grades.points) AS single_target_points,
single_target_points*no_of_subjects AS target_points
FROM
marks
INNER JOIN grades ON marks.resultvalue = grades.grade
INNER JOIN targets ON targets.adno = marks.adno
GROUP BY
marks.adno
This will resolve the query for you, but not sure what you are doing is completely accurate. I took your in-line query and made it a subquery including the "adno" (person id) to get all distinct points. Using that and JOINING based on the person like the others.
SELECT
m.adno,
Sum(g.points) AS total_points,
Count(g.points) AS no_of_subjects,
SUM( TP.single_target_points * g.points) AS target_points
FROM
marks m
JOIN grades g
ON m.resultvalue = g.grade
JOIN students s
ON m.adno = s.adno
JOIN targets t
ON m.adno = t.adno
JOIN
( SELECT distinct
t2.adno,
t2.grade,
g2.points single_target_points
FROM
targets t2
JOIN grades g2
ON t2.grade = g2.grade ) TP
on t.adno = TP.adno
and t.grade = TP.grade
GROUP BY
m.adno
Now, that being said, it looks like you are trying to compute a person's GPA (grade point average). If you can EDIT your existing post and provide samples of data (use spaces to align, not tabs) even if fictional names (but not necessary since things here are all ID values and otherwise not private). It would help to see the basis of what computations are going on. If not done correctly, you will get Cartesian results and skew your points due to multiple entries * multiple entries = oversized expected answer values.
Also, I Updated your dbfiddle. You inserted into adno instead of students the sample records, inserted into targets the grades, so those tables were blank. I had to correct that. Then changed grades to integer since doing math (via sum( g.points)). Best to use proper data types vs everything as character.
At least the queries are now working, but does not make sense if this is GPA calculations -- as far as I know and have done for U.S. college transcript purposes.

How to improve performance on large left outer join?

These are my tables:
Source_Artikelen - columns: article - description (1.438.171 records)
Source_LevArt - columns: article - manufacturer part number (1.751.801 records)
... and this is the query I'm performing
SELECT a.Artikel,a.Omschrijving, l.Artikel_Leverancier
FROM Source_Artikelen AS a
LEFT OUTER JOIN Source_LevArt AS l
ON a.Artikel Like l.Artikel
This query was running tonight for more than 20 hours before I cancelled it manually.
So what am I trying to do?
I want to list down all articles from my table Source_Artikelen. Then I would like to see if there are manufacturer part numbers available in Source_LevArt.
not every article from Source_Artikelen is present in Source_LevArt
sometimes there are multiple manufacturer part numbers in Source_LevArt for one article
That's why I need to use a LEFT OUTER JOIN.
I've tried some things with indexes, but it's not really helping. Possibly I'm doing something wrong.
I can really use some help, as this is only the beginning of the query I'm writing.
I will have to add 2 other (large) tabes as left outer join later...
UPDATE 19/12/2016 16:24:
Hi piet.t
SELECT TOP(20) a.Artikel,a.Omschrijving, l.Artikel_Leverancier
FROM Source_Artikelen AS a
LEFT JOIN Source_LevArt AS l
ON a.Artikel LIKE l.Artikel
this takes 9 seconds
SELECT TOP(20) a.Artikel,a.Omschrijving, l.Artikel_Leverancier
FROM Source_Artikelen AS a
LEFT JOIN Source_LevArt AS l
ON a.Artikel = l.Artikel
this takes 1 second!
I really didn't know there was a difference as I'm not using wildcards.
This is covered by Paul White here :Dynamic Seeks and Hidden Implicit Conversions
using like even when there is exact match tends to do a dynamic seek..which means knowing the column to be seeked at execution time,not at compilation time..
below is how .,column is derived for the tables in below example of mine..
[Expr1005] = Scalar Operator(CONVERT_IMPLICIT(varchar(12),[Aegon_X].[Sales].[Orders].[custid] as [o].[custid],0)),
[Expr1006] = Scalar Operator(LikeRangeStart(CONVERT_IMPLICIT(varchar(12),[Aegon_X].[Sales].[Orders].[custid] as [o].[custid],0))),
[Expr1007] = Scalar Operator(LikeRangeEnd(CONVERT_IMPLICIT(varchar(12),[Aegon_X].[Sales].[Orders].[custid] as [o].[custid],0))),
[Expr1008] = Scalar Operator(LikeRangeInfo(CONVERT_IMPLICIT(varchar(12),[Aegon_X].[Sales].[Orders].[custid] as [o].[custid],0)))
below is what Paul describes ,how those are derived
The upper tooltip shows that the Compute Scalar uses three internal functions, LikeRangeStart, LikeRangeEnd, and LikeRangeInfo.
The first two functions describe the range as an open interval. The third function returns a set of flags encoded in an integer, that are used internally to define certain seek properties for the Storage Engine. The lower tooltip shows the seek on the open interval described by the result of LikeRangeStart and LikeRangeEnd, and the application of the residual predicate ‘LIKE #Like’.
So in summary ,using like SQL uses dynamic seek to derive seek properties at compile time ..
Examples below showing different plans
using like :
I really didn't know there was a difference as I'm not using wildcards.
select top 10* from sales.orders o
join
sales.customers c
on c.custid like o.custid
plan:
Now when using exact match..
select top 10* from sales.orders o
join
sales.customers c
on c.custid =o.custid
You can see merge join plan
Use = instead of like.
These 2 indexes should give you the best performance for a Select.
CREATE INDEX idx ON Source_Artikelen(Artikel) INCLUDE(Omschrijving);
CREATE INDEX idx ON Source_LevArt(Artikel) INCLUDE(Artikel_Leverancier);
If you implement them and try your SELECT again, can you please upload a copy of your execution plan?

Choosing none in set

I have two tables:
Invariant (UniqueID, characteristic1, characteristic2)
Variant (VariantID, UniqueID, specification1, specification2)
Each project has its own unchanging characteristics between implementations. Each implementation also has its own individual properties.
So, I use queries like this to find projects with the given characteristics and specifications:
SELECT *
FROM `Invariants`
LEFT JOIN (`Variants`) ON (`Variants`.`UniqueID`=`Invariants`.`UniqueID`)
WHERE char2='y' and spec1='x'
GROUP BY `Invariant`.`UniqueID`;
I'm looking for a query that will return all projects that have never satisfied a given specification. So, if one of project 100's variants had spec1='bad', then I don't want project 100 to be included, regardless if it had variants where spec1='good'.
select *
from Invariants iv
where not exists (
select 1
from Variants v
where v.UniqueId = iv.UniqueId and v.spec1 = 'bad'
)
The queries below do not address your question, I probably read to fast and thought you wanted to pick up only the invariant properties of a particular type. But I will note that you shouldn't use a left join and then filter, in the where clause, against columns from the right table (except for checking nulls). People make that mistake all the time and that's what jumped out to me at first glance.
The whole purpose of a left join is that some of the rows will not match and will thus have filler null values in the columns for the right-hand table. This join logic happens first and then after that the where clause is applied. When you have a condition like where spec1 = 'x' it will always evaluate to false against a null value. So you end up eliminating all the rows you wanted to keep.
This happens a lot with these invariant/custom values tables. You're only interested in one of the properties but if you don't filter prior to joining or inside the join condition, you end up dropping rows because the value didn't exist and you didn't have a value left to compare once it tried to apply a where-clause condition on the property name.
Hope that made sense. See below for examples:
select iv.UniqueId, ...
from
Invariants iv left outer join
Variants
on v.UniqueId = vi.UniqueId and v.spec1 = 'x'
or
select iv.UniqueId, ...
from
Invariants iv left outer join
(
select
from Variants
where spec1 = 'x'
) v
on v.UniqueId = vi.UniqueId

Natural join of table (A) with itself

I came across this question in an interview and I have been wondering if what I did was right. Let's say I have a table 'A' with the following attributes:
R S T
-----------
a1 b1 c1
a1 b2 c2
a1 b3 c3
a4 b4 c4
and lets say I need to calculate the Relational Algebra for given B = {[(projection)R,S (A) NATURAL JOIN (projection) S,T (A) ] NATURAL JOIN (projection)R,T (A)}
what would be the result?
This is what I tried:
-We know (A) NATURAL JOIN (A) = A
-I did the first set of join within the square bracket. Since we had attribute 'S' in common I just yielded the result to be a table of (R S T) with the same 4 rows of tuples.
-Finally, I joined (R S T) with the second set of join where attributes 'R' and 'T' are common which I assumed will yield R S T again with 4 rows of tuples.
Meaning, with the way I did it, I ended up getting B = A.
I did not consider the tuples at all, I just did a natural join based on the common attributes between two projections.
I know that's very stupid.. but I am trying to execute it in MySQL and for some reason I am getting errors when I try to execute such a query:
select A,B from dbt2.relationalalgebra as r1 NATURAL JOIN (select B, C from dbt2.relationalalgebra as r2); and I am getting an error saying every derived table must have its own aliases!
Please help me clarify on how Natural join works on same table.
Thanks in advance for any help.
What you did is correct. And it's correct that you obtained B = A -- given that content for A.
This is a question about the functional dependencies between the values in the data. (So you might not get B = A, if the data was different.)
For attributes S and T, there's a different value in each tuple. IoW given a value for S (or T), you know which row it's from, so you know the value for the other two attributes in that tuple. The functional dependencies are S -> R, T; T -> R, S. (You might say that S or T are each keys for A.)
The pairs of attributes in the projections you give each include at least one key, so uniquely determine which 'missing' attribute gets joined. You're seeing a lossless join decomposition, as per Heath's Theorem. http://en.wikipedia.org/wiki/Functional_dependency
A natural join is a shorthand for joining two tables (or subqueries) on all columns that have the same name.
A natural join of a table to itself could have several consequences. The most common would be the table itself -- if none of the values are NULL and the rows are unique. If each row had a NULL value in some column, then the natural join would return no rows at all. If rows are duplicated, then multiple rows might appear.
I do not recommend ever using natural join. A small change to an underlying table structure could break a query.

Help me figure out a MySQL query

These are tables I have:
Class
- id
- name
Order
- id
- name
- class_id (FK)
Family
- id
- order_id (FK)
- name
Genus
- id
- family_id (FK)
- name
Species
- id
- genus_id (FK)
- name
I'm trying to make a query to get a list of Class, Order, and Family names that does not have any Species under them. You can see that the table has some form of hierarchy from Order all the way down to Species. Each table has Foreign Key (FK) that relates to the immediate table above itself on the hierarchy.
Trying to get this at work, but I am not doing so well.
Any help would be appreciated!
Meta-answer (comment on the two previous answers):
Using IN tends to degrade to something very like an OR (a disjunction) of all terms in the IN. Bad performance.
Doing a left join and looking for null is an improvement, but it's obscurantist. If we can say what we mean, let's say it in a wau that's clossest to how we'd say it in natural language:
select f.name
from family f left join genus g on f.id = g.family_id
WHERE NOT EXISTS (select * from species c where c.id = g.id);
We want where something doesn't exist, so if we can say "where not exists" all the better. And, the select * in the subquery doesn't mean it's really bringing back a whole row, so it's not an "optimization" to replace select * with select 1, at least not on any modern RDBMS.
Further, where a family has many genera (and in biology, most families do), we're going to get one row per (family, genus) when all we care about is the family. So let's get one row per family:
select DISTINCT f.name
from family f left join genus g on f.id = g.family_id
WHERE NOT EXISTS (select * from species c where c.id = g.id);
This is still not optimal. Why? Well it fulfills the OP's requirement, in that it finds "empty" genera, but it fails to find families that have no genera, "empty" families. Can we make it do that too?
select f.name
from family f
WHERE NOT EXISTS (
select * from genus g
join species c on c.id = g.id
where g.id = f.id);
We can even get rid of the distinct, because we're not joining family to anything. And that is an optimization.
Comment from OP:
That was a very lucid explanation. However, I'm curious as to why using IN or disjunctions is bad for performance. Can you elaborate on that or point me to a resource where I can learn more about the relative performance cost of different DB operations?
Think of it this way. Say that there was not IN operator in SQL. How would you fake an IN?
By a series of ORs:
where foo in (1, 2, 3)
is equivalent to
where ( foo = 1 ) or ( foo = 2 ) or (foo = 3 )
Ok, you say, but that still doesn't tell me why it's bad. It's bad because there's often no decent way to use a key or index to look this up. So what you get is either a) a table scan, where for each disjunction (or'd predicate or element of an IN list), the row gets tested, until a test is true or the list is exhausted. Or b) you get a table scan for each of these disjunctions. The second case (b) may actually be better, which is why you sometimes see a select with an OR turned into one select for each leg of the OR union'd together:
select * from table where x = 1 or x = 3 ;
select * from table where x = 1
union select * from table where x = 3 ;
Now this is not to say you can never use an OR or an IN list. And in some cases, the query optimizer is smart enough to turn an IN list into a join -- and the other answers you were given are precisely the cases where that's most likely.
But if we can explicitly turn our query into a join, well, we don't have to wonder if the query optimizer is smart. And in general, joins are what the databse is best at doing.
Well, just giving this a quick and dirty shot, I'd write something like this. I spend most of my time using Firebird so the MySQL syntax may be a little different, but the idea should be clear
select f.name
from family f left join genus g on f.id = g.family_id
left join species s on g.id = species.genus_id
where ( s.id is null )
if you want to enforce there being a genus then you just remove the "left" portion of the join from family to genus.
I hope I'm not misunderstanding the question and thus, leading you down the wrong path. Good luck!
edit: Actually, re-reading this I think this will just catch families where there's no species within a genus. You could add a " and ( g.id is null )" too, I think.
Sub-select to the rescue...
select f.name from family as f, genus as g
where
f.id == g.family_id and
g.id not in (select genus_id from species);
SELECT f.name
FROM family f
WHERE NOT EXISTS (
SELECT 1
FROM genus g
JOIN species s
ON g.id = s.genus_id
WHERE g.family_id = f.id
)
Note, than unlike pure LEFT JOIN solutions, this is more efficient.
It does not select ALL rows filtering out those with NOT NULL values, but instead selects at most one row from genus and species.